Kuidas kirjutada ja avaldada nutikat lepingut TON-is
Millest see artikkel räägib?
Selles artiklis räägin teile, kuidas osalesin esimesel (kahest) Telegrami plokiahela võistlusel, auhinda ei võitnud ja otsustasin kogemuse artiklis jäädvustada, et see unustuse hõlma ei vajuks ja ehk kedagi aitaks.
Kuna ma ei tahtnud kirjutada abstraktset koodi, vaid midagi toimivat panna, siis kirjutasin artikli jaoks nutika lepingu kiirloterii ja veebilehe, mis näitab nutika lepingu andmeid otse TON-ist ilma vahemälu kasutamata.
Artikkel on kasulik neile, kes soovivad sõlmida oma esimese nutika lepingu TON-is, kuid ei tea, kust alustada.
Kasutades näitena loteriid, liigun keskkonna loomisest nutika lepingu avaldamise, sellega suhtlemise ning andmete vastuvõtmiseks ja avaldamiseks veebisaidi kirjutamiseni.
Võistlusel osalemise kohta
Eelmise aasta oktoobris kuulutas Telegram välja plokiahela võistluse uute keeltega Fift и FunCPidin valima viie nutika lepingu vahel. Mõtlesin, et oleks hea mõte teha midagi ebatavalist, õppida keel ja teha midagi, isegi kui ma ei pea tulevikus midagi muud kirjutama. Lisaks on see teema alati kõigi huulil.
Väärib märkimist, et mul polnud nutikate lepingute väljatöötamise kogemust.
Plaanisin osaleda kuni lõpuni, kuniks saan, ja siis kirjutada arvustusartikli, aga esimesel korral kukkusin läbi. mitme allkirjaga FunC ja see üldiselt toimis. Võtsin selle aluseks .
Sel hetkel arvasin, et sellest kindlasti piisab, et vähemalt mingi auhinnaline koht võita. Lõpuks said auhinnaliste kohtade võitjateks umbes 40 osalejat 60-st ja mind nende hulgas polnud. Üldiselt pole selles midagi kohutavat, aga üks asi häiris mind. Kui ülevaatuse tulemused välja kuulutati, kuna minu leping polnud veel testiga tehtud, küsisin vestluses osalejatelt, kas on veel kedagi, kellel seda pole, aga neid polnud.
Ilmselt märgates mu sõnumeid, avaldasid kohtunikud kaks päeva hiljem kommentaari ja ma ei saa siiani aru, kas nad jätsid hindamise ajal kogemata mu nutika lepingu kahe silma vahele või arvasid nad lihtsalt, et see on nii halb, et kommentaari pole vaja. Esitasin lehel küsimuse, aga vastust ei saanud. Kuigi pole saladus, kes hindas, pidasin isiklike sõnumite kirjutamist tarbetuks.
Selle mõistmiseks kulus palju aega, seega otsustati kirjutada artikkel. Kuna infot pole veel palju, aitab see artikkel kõigi huviliste aega kokku hoida.
Nutikate lepingute kontseptsioon TON-is
Enne millegi kirjutamist tuleb välja mõelda, millisest küljest sellele asjale läheneda. Seega nüüd ma räägin teile, millistest osadest süsteem koosneb. Täpsemalt, milliseid osi peate teadma, et kirjutada vähemalt mingisugune tööleping.
Keskendume nutika lepingu kirjutamisele ja koostööle TON Virtual Machine (TVM), Fift и FunC, seega on artikkel pigem tavalise programmi arenduse kirjeldus. Me ei hakka siinkohal pikemalt peatuma sellel, kuidas platvorm ise töötab.
Üldiselt sellest, kuidas see toimib TVM ja keel Fift Olemas on korralik ametlik dokumentatsioon. Viitasin sellele tihti nii konkursi ajal kui ka praegust lepingut kirjutades.
Peamine keel, milles nutikad lepingud kirjutatakse, on FunCPraegu puudub selle kohta dokumentatsioon, seega millegi kirjutamiseks peate uurima ametlikust repositooriumist pärit nutikate lepingute näiteid ja sealset keele implementatsiooni, lisaks saate vaadata kahe viimase võistluse nutikate lepingute näiteid. Lingid artikli lõpus.
Oletame, et oleme juba nutika lepingu kirjutanud FunC, pärast seda kompileerime koodi Fifti assemblerisse.
Koostatud nutikas leping tuleb veel avaldada. Selleks peate kirjutama funktsiooni Fift, mis sisendina aktsepteerib nutika lepingu koodi ja mõningaid muid parameetreid ning väljundiks on fail laiendiga .boc (mis tähendab "rakkude kotti") ja olenevalt kirjutamisviisist privaatvõti ja aadress, mis genereeritakse nutika lepingu koodi põhjal. Nutika lepingu aadressile saab juba gramme saata, kuid seda pole veel avaldatud.
TON-is nutika lepingu avaldamiseks saime .boc Fail tuleb plokiahelasse saata valguskliendi abil (sellest lähemalt allpool). Enne avaldamist tuleb aga genereeritud aadressile grammid edastada, vastasel juhul nutilepingut ei avaldata. Pärast avaldamist saab nutilepinguga suhelda, saates sellele sõnumeid väljastpoolt (näiteks valguskliendi abil) või seestpoolt (näiteks saadab üks nutileping teisele sõnumi TON-i sees).
Kui oleme aru saanud, kuidas kood avaldatakse, muutub see lihtsamaks. Me teame umbes, mida me kirjutada tahame ja kuidas meie programm töötab. Kirjutamise ajal otsime, kuidas see on juba olemasolevates nutikates lepingutes rakendatud või uurime implementatsioonikoodi. Fift и FunC ametlikust repositooriumist või vaadake ametlikku dokumentatsiooni.
Väga tihti otsisin märksõnu Telegrami vestlusest, kuhu kogunesid kõik võistluse osalejad ja Telegrami töötajad, juhtus nii, et võistluse ajal kogunesid kõik sinna ja hakkasid Fifti ja FunC-d arutama. Link artikli lõpus.
On aeg liikuda teooriast praktikasse.
TON-iga töötamise keskkonna ettevalmistamine
Tegin kõik, mida MacOS-i artiklis kirjeldatakse, ja kontrollisin seda puhtalt üle. Ubuntu 18.04 LTS Dockeril.
Esimene asi, mida pead tegema, on alla laadida ja installida lite-client millega saate TON-ile päringuid saata.
Ametliku veebisaidi juhised kirjeldavad installiprotsessi üsna põhjalikult ja selgelt, jättes mõned detailid välja. Siin järgime juhiseid, paigaldades kõik puuduvad sõltuvused. Ma ei kompileerinud iga projekti ise ja installisin ametlikust repositooriumist. Ubuntu (macOS-is kasutasin brew).
apt -y install git
apt -y install wget
apt -y install cmake
apt -y install g++
apt -y install zlib1g-dev
apt -y install libssl-dev Kui kõik sõltuvused on installitud, saate installida lite-client, Fift, FunC.
Esmalt kloonime TON-repositooriumi koos sõltuvustega. Mugavuse huvides teeme kõik kaustas. ~/TON.
cd ~/TON
git clone https://github.com/ton-blockchain/ton.git
cd ./ton
git submodule update --init --recursiveRepositoorium salvestab ka implementatsioone. Fift и FunC.
Nüüd oleme valmis projekti ehitama. Repositooriumi kood on kloonitud kausta. ~/TON/ton. Sisse ~/TON loo kaust build ja me kogume sinna projekti.
mkdir ~/TON/build
cd ~/TON/build
cmake ../tonKuna me hakkame kirjutama nutikat lepingut, ei pea me mitte ainult lite-clientkuid Fift с FunC, seega kompileerime kõik. See pole kiire protsess, seega ootame.
cmake --build . --target lite-client
cmake --build . --target fift
cmake --build . --target funcJärgmisena laadime alla konfiguratsioonifaili, mis sisaldab andmeid sõlme kohta, kuhu lite-client loob ühenduse.
wget https://test.ton.org/ton-lite-client-test1.config.jsonEsimeste taotluste esitamine TON-ile
Nüüd käivitame lite-client.
cd ~/TON/build
./lite-client/lite-client -C ton-lite-client-test1.config.jsonKui ehitamine õnnestus, näete pärast käivitamist valguskliendi ühenduse logi sõlmega.
[ 1][t 2][1582054822.963129282][lite-client.h:201][!testnode] conn ready
[ 2][t 2][1582054823.085654020][lite-client.cpp:277][!testnode] server version is 1.1, capabilities 7
[ 3][t 2][1582054823.085725069][lite-client.cpp:286][!testnode] server time is 1582054823 (delta 0)
...Saate käsku täita help ja vaata, millised käsud on saadaval.
helpLoetleme käsud, mida me selles artiklis kasutame.
list of available commands:
last Get last block and state info from server
sendfile <filename> Load a serialized message from <filename> and send it to server
getaccount <addr> [<block-id-ext>] Loads the most recent state of specified account; <addr> is in [<workchain>:]<hex-or-base64-addr> format
runmethod <addr> [<block-id-ext>] <method-id> <params>... Runs GET method <method-id> of account <addr> with specified parameterslast получает последний созданный блок с сервера.
sendfile <filename> отправляет в TON файл с сообщением, именно с помощью этой команды публикуется смарт-контракт и запрсосы к нему.
getaccount <addr> загружает текущее состояние смарт-контракта с указанным адресом.
runmethod <addr> [<block-id-ext>] <method-id> <params> запускает get-методы смартконтракта. Nüüd oleme valmis lepingut ise kirjutama.
Реализация
Mõte
Nagu ma eespool kirjutasin, on meie kirjutatav nutikas leping loterii.
Pealegi pole see loterii, kus peate pileti ostma ja tund, päev või kuu ootama, vaid hetkeline loterii, mille käigus kasutaja kannab raha üle lepingujärgsele aadressile. N grammi ja saab selle koheselt tagasi 2 * N gramme või kaotab. Võidu tõenäosus on umbes 40%. Kui maksmiseks pole piisavalt gramme, loeme tehingu konto täiendamiseks.
Lisaks on oluline, et panuseid saaks näha reaalajas ja mugavas vormis, et kasutaja saaks kohe aru, kas ta võitis või kaotas. Seetõttu on vaja luua veebisait, mis kuvab panuseid ja tulemust otse TON-ist.
Nutika lepingu kirjutamine
Mugavuse huvides tegin FunC jaoks koodi esiletõstmise, plugina saab leida ja installida Visual Studio koodiotsingus, kui äkki tahad midagi lisada, siis postitasin plugina avalikku omandisse. Samuti tegi keegi varem Fiftiga töötamiseks plugina, selle saab ka VSC-st installida ja leida.
Loome kohe hoidla, kuhu me vahetulemused salvestame.
Meie elu lihtsamaks tegemiseks kirjutame nutika lepingu ja testime seda lokaalselt, kuni see on valmis. Alles seejärel avaldame selle TON-is.
Nutilepingul on kaks välist meetodit, mida saab välja kutsuda. Esimene, recv_external() See funktsioon täidetakse siis, kui lepingule esitatav päring tuleb välismaailmast, st mitte näiteks TON-ist, kui me ise moodustame sõnumi ja saadame selle lite-clienti kaudu. Teine, recv_internal() See on siis, kui mõni TON-i sees olev leping viitab meie omale. Mõlemal juhul saab funktsioonile parameetreid edastada.
Alustame lihtsa näitega, mis töötab avaldatuna, kuid ei paku mingit funktsionaalsust.
() recv_internal(slice in_msg) impure {
;; TODO: implementation
}
() recv_external(slice in_msg) impure {
;; TODO: implementation
}Siin peame selgitama, mis see on sliceKõik TON-i plokiahelas talletatud andmed on kogum. TVM cell või lihtsalt cell, selline lahter mahutab kuni 1023 bitti andmeid ja kuni 4 viidet teistele lahtritele.
TVM cell slice või slice see on osa olemasolevast cell kasutatakse selle parsimiseks, see selgub hiljem. Meie jaoks on peamine see, et saame üle minna nutikale lepingule slice ja olenevalt sõnumi tüübist töötle andmeid recv_external() või recv_internal().
impure — märksõna, mis näitab, et funktsioon muudab nutika lepingu andmeid.
Salvestame lepingu koodi sisse lottery-code.fc ja kompileerida.
~/TON/build/crypto/func -APSR -o lottery-compiled.fif ~/TON/ton/crypto/smartcont/stdlib.fc ./lottery-code.fc Lippude tähendust saab vaadata käsuga
~/TON/build/crypto/func -helpSaime kompileeritud Fifti assembleri koodi kätte lottery-compiled.fif:
// lottery-compiled.fif
"Asm.fif" include
// automatically generated from `/Users/rajymbekkapisev/TON/ton/crypto/smartcont/stdlib.fc` `./lottery-code.fc`
PROGRAM{
DECLPROC recv_internal
DECLPROC recv_external
recv_internal PROC:<{
// in_msg
DROP //
}>
recv_external PROC:<{
// in_msg
DROP //
}>
}END>cSeda saab kohapeal käitada, selleks valmistame ette keskkonna.
Pane tähele, et esimene rida ühendub Asm.fif, see on Fifti assembleri jaoks Fiftis kirjutatud kood.
Kuna me tahame nutikat lepingut lokaalselt käivitada ja testida, loome faili lottery-test-suite.fif ja kopeeri kompileeritud kood sinna, asendades selle viimase rea, mis kirjutab nutika lepingu koodi konstanti code, et saaksite selle seejärel virtuaalmasinasse üle kanda:
"TonUtil.fif" include
"Asm.fif" include
PROGRAM{
DECLPROC recv_internal
DECLPROC recv_external
recv_internal PROC:<{
// in_msg
DROP //
}>
recv_external PROC:<{
// in_msg
DROP //
}>
}END>s constant code
Siiani tundub kõik selge, nüüd lisame samasse faili koodi, mida me TVM-i käivitamiseks kasutame.
0 tuple 0x076ef1ea , // magic
0 , 0 , // actions msg_sents
1570998536 , // unix_time
1 , 1 , 3 , // block_lt, trans_lt, rand_seed
0 tuple 100000000000000 , dictnew , , // remaining balance
0 , dictnew , // contract_address, global_config
1 tuple // wrap to another tuple
constant c7
0 constant recv_internal // to run recv_internal()
-1 constant recv_external // to invoke recv_external()В c7 Me salvestame konteksti, st andmed, millega TVM käivitatakse (või võrgu olek). Isegi võistluse ajal näitas üks arendajatest, kuidas luua c7 ja ma kopeerisin selle. Selles artiklis peame võib-olla muutma rand_seed kuna juhusliku arvu genereerimine sõltub sellest ja seda ei saa muuta, tagastatakse iga kord sama arv.
recv_internal и recv_external Konstandid väärtustega 0 ja -1 vastutavad vastavate funktsioonide kutsumise eest nutikas lepingus.
Nüüd oleme valmis looma oma tühja nutilepingu esimese testi. Selguse huvides lisame kõik testid esialgu samasse faili. lottery-test-suite.fif.
Loome muutuja storage ja kirjuta sinna tühi cell, see on nutika lepingu salvestuskoht.
message See on sõnum, mille edastame nutikale kontaktile väljastpoolt. Jätame selle ka praegu tühjaks.
variable storage
<b b> storage !
variable message
<b b> message ! Pärast konstantide ja muutujate ettevalmistamist käivitame TVM-i käsuga runvmctx ja edastage loodud parameetrid sisendile.
message @
recv_external
code
storage @
c7
runvmctx Lõpuks õnnestub meil vahekood peal Fift.
Nüüd saame tulemuseks saadud koodi käivitada.
export FIFTPATH=~/TON/ton/crypto/fift/lib // выполняем один раз для удобства
~/TON/build/crypto/fift -s lottery-test-suite.fif Programm peaks töötama ilma vigadeta ja väljundis näeme täitmislogi:
execute SETCP 0
execute DICTPUSHCONST 19 (xC_,1)
execute DICTIGETJMPZ
execute DROP
execute implicit RET
[ 3][t 0][1582281699.325381279][vm.cpp:479] steps: 5 gas: used=304, max=9223372036854775807, limit=9223372036854775807, credit=0Suurepärane, oleme kirjutanud nutika lepingu esimese toimiva versiooni.
Nüüd peame lisama funktsionaalsuse. Esiteks tegeleme välismaailmast tulevate sõnumitega. recv_external()
Arendaja ise valib sõnumivormingu, mida leping aktsepteerib.
Aga tavaliselt,
- Esiteks tahame kaitsta oma lepingut välismaailma eest ja muuta selle nii, et ainult lepingu omanik saab sellele väliseid sõnumeid saata.
- Teiseks, kui saadame TON-ile kehtiva sõnumi, tahame, et see juhtuks täpselt üks kord ja kui saadame sama sõnumi uuesti, lükkab nutileping selle tagasi.
Seega lahendab peaaegu iga leping need kaks probleemi, kuna meie leping võtab vastu väliseid sõnumeid, peame ka selle eest hoolitsema.
Teeme seda vastupidises järjekorras. Esmalt lahendame kordusprobleemi – kui leping on sellise sõnumi juba saanud ja töödelnud, siis teist korda seda ei teostata. Seejärel lahendame probleemi nii, et nutilepingule saab sõnumeid saata ainult teatud ring inimesi.
Topeltsõnumite probleemi saab lahendada mitmel viisil. Teeme seda järgmiselt. Nutikas lepingus initsialiseerime vastuvõetud sõnumite loenduri algväärtusega 0. Igasse nutilepingu sõnumisse lisame loenduri praeguse väärtuse. Kui sõnumi loenduri väärtus ei vasta nutilepingu väärtusele, siis me seda ei töötle; kui vastab, siis töötleme seda ja suurendame nutilepingu loendurit 1 võrra.
Me naaseme lottery-test-suite.fif ja lisa sellele teine test. Saada sobimatu number, kood peaks viskama erandi. Näiteks oletame, et lepingu andmed salvestavad 166 ja meie saadame 165.
<b 166 32 u, b> storage !
<b 165 32 u, b> message !
message @
recv_external
code
storage @
c7
runvmctx
drop
exit_code !
."Exit code " exit_code @ . cr
exit_code @ 33 - abort"Test #2 Not passed"Käivitame.
~/TON/build/crypto/fift -s lottery-test-suite.fif Ja näeme, et test käivitatakse veaga.
[ 1][t 0][1582283084.210902214][words.cpp:3046] lottery-test-suite.fif:67: abort": Test #2 Not passed
[ 1][t 0][1582283084.210941076][fift-main.cpp:196] Error interpreting file `lottery-test-suite.fif`: error interpreting included file `lottery-test-suite.fif` : lottery-test-suite.fif:67: abort": Test #2 Not passedPraeguses etapis lottery-test-suite.fif peaks välja nägema nagu .
Nüüd lisame nutikale lepingule loenduri loogika lottery-code.fc.
() recv_internal(slice in_msg) impure {
;; TODO: implementation
}
() recv_external(slice in_msg) impure {
if (slice_empty?(in_msg)) {
return ();
}
int msg_seqno = in_msg~load_uint(32);
var ds = begin_parse(get_data());
int stored_seqno = ds~load_uint(32);
throw_unless(33, msg_seqno == stored_seqno);
}В slice in_msg peitub sõnum, mida me saadame.
Esimese asjana kontrollime, kas sõnumis on andmeid, kui ei, siis lihtsalt väljume.
Järgmisena analüüsime sõnumit. in_msg~load_uint(32) laadib numbri 165, 32-bitine unsigned int edastatud sõnumist.
Järgmisena laadime nutika lepingu salvestusruumist 32 bitti. Kontrollime, kas laaditud number vastab edastatud arvule, kui mitte, siis viskame erandi. Meie puhul, kuna edastame mittevastavust, peaks tekkima erand.
Nüüd kompileerime.
~/TON/build/crypto/func -APSR -o lottery-compiled.fif ~/TON/ton/crypto/smartcont/stdlib.fc ./lottery-code.fc Kopeeri saadud kood sisse lottery-test-suite.fif, unustamata viimast rida asendada.
Kontrollime, kas test läbib:
~/TON/build/crypto/fift -s lottery-test-suite.fifNäete vastavat commit'i koos praeguste tulemustega.
Pane tähele, et nutika lepingu kompileeritud koodi pidev kopeerimine testidega faili on ebamugav, seega kirjutame skripti, mis kirjutab koodi meie eest konstanti, ja ühendame kompileeritud koodi lihtsalt oma testidega, kasutades "include".
Loo projektikaustas fail build.sh järgmise sisuga.
#!/bin/bash
~/TON/build/crypto/func -SPA -R -o lottery-compiled.fif ~/TON/ton/crypto/smartcont/stdlib.fc ./lottery-code.fcTeeme selle käivitatavaks.
chmod +x ./build.shNüüd piisab lepingu kompileerimiseks meie skripti käivitamisest. Aga lisaks sellele peame selle kirjutama konstanti codeSeega loome uue faili lotter-compiled-for-test.fif, mille me faili lisame lottery-test-suite.fif.
Lisame sh-skripti koodi, mis lihtsalt dubleerib kompileeritud faili lotter-compiled-for-test.fif ja muuda selle viimast rida.
# copy and change for test
cp lottery-compiled.fif lottery-compiled-for-test.fif
sed '$d' lottery-compiled-for-test.fif > test.fif
rm lottery-compiled-for-test.fif
mv test.fif lottery-compiled-for-test.fif
echo -n "}END>s constant code" >> lottery-compiled-for-test.fifNüüd kontrollimiseks käivitame saadud skripti ja fail genereeritakse lottery-compiled-for-test.fif, mille me oma lottery-test-suite.fif
В lottery-test-suite.fif kustuta lepingukood ja lisa rida "lottery-compiled-for-test.fif" include.
Teeme teste, et kontrollida nende läbimist.
~/TON/build/crypto/fift -s lottery-test-suite.fifSuurepärane, nüüd testide automatiseerimiseks loome faili test.sh, mis esineb esmalt build.shja seejärel käivitage testid.
touch test.sh
chmod +x test.shMe kirjutame sees
./build.sh
echo "nCompilation completedn"
export FIFTPATH=~/TON/ton/crypto/fift/lib
~/TON/build/crypto/fift -s lottery-test-suite.fifTeeme ära test.sh ja käivitage see, et veenduda testide toimimises.
chmod +x ./test.sh
./test.shKontrollime lepingu koostamist ja testide käivitamist.
Suurepärane, nüüd käivitamisel test.sh testid kompileeritakse ja käivitatakse kohe. Siin on link .
Olgu, enne kui jätkame, teeme mugavuse huvides veel ühe asja.
Loome kausta build kuhu me salvestame kompileeritud lepingu ja selle klooni, mis on kirjutatud konstanti lottery-compiled.fif, lottery-compiled-for-test.fifSamuti loome kausta test kuhu testfail salvestatakse lottery-test-suite.fif ja potentsiaalselt ka teisi tugifaile. .
Jätkame nutika lepingu väljatöötamist.
Järgmisena peaks olema test, mis kontrollib, kas sõnum on vastu võetud ja loendur poes uueneb, kui saadame õige numbri. Aga seda teeme hiljem.
Mõelgem nüüd, millist andmestruktuuri ja milliseid andmeid tuleb nutikas lepingus salvestada.
Ma kirjeldan kõike, mida me salvestame.
`seqno` 32-х битное целое положительное число счетчик.
`pubkey` 256-ти битное целое положительное число публичный ключ, с помощью которого, мы будем проверять подпись отправленного извне сообщения, о чем ниже.
`order_seqno` 32-х битное целое положительное число хранит счетчик количества ставок.
`number_of_wins` 32-х битное целое положительное число хранит количество побед.
`incoming_amount` тип данных Gram (первые 4 бита отвечает за длину), хранит общее количество грамов, которые были отправлены на контртакт.
`outgoing_amount` общее количество грамов, которое было отправлено победителям.
`owner_wc` номер воркчейна, 32-х битное (в некоторых местах написано, что 8-ми битное) целое число. В данный момент всего два -1 и 0.
`owner_account_id` 256-ти битное целое положительное число, адрес контракта в текущем воркчейне.
`orders` переменная типа словарь, хранит последние двадцать ставок. Järgmisena peate kirjutama kaks funktsiooni. Kutsume esimest välja pack_state(), mis pakib andmed edasiseks salvestamiseks nutika lepingu salvestusruumi. Teiseks nimetame unpack_state() loeb ja tagastab andmeid salvestusruumist.
_ pack_state(int seqno, int pubkey, int order_seqno, int number_of_wins, int incoming_amount, int outgoing_amount, int owner_wc, int owner_account_id, cell orders) inline_ref {
return begin_cell()
.store_uint(seqno, 32)
.store_uint(pubkey, 256)
.store_uint(order_seqno, 32)
.store_uint(number_of_wins, 32)
.store_grams(incoming_amount)
.store_grams(outgoing_amount)
.store_int(owner_wc, 32)
.store_uint(owner_account_id, 256)
.store_dict(orders)
.end_cell();
}
_ unpack_state() inline_ref {
var ds = begin_parse(get_data());
var unpacked = (ds~load_uint(32), ds~load_uint(256), ds~load_uint(32), ds~load_uint(32), ds~load_grams(), ds~load_grams(), ds~load_int(32), ds~load_uint(256), ds~load_dict());
ds.end_parse();
return unpacked;
}Lisame need kaks funktsiooni nutika lepingu algusesse. Saame vahetulemus.
Andmete salvestamiseks peate kutsuma sisseehitatud funktsiooni set_data() ja see salvestab andmed pack_state() nutika lepingu salvestusruumis.
cell packed_state = pack_state(arg_1, .., arg_n);
set_data(packed_state);Nüüd, kui meil on mugavad funktsioonid andmete kirjutamiseks ja lugemiseks, saame edasi liikuda.
Peame kontrollima, kas väljastpoolt saabuv sõnum on allkirjastatud lepingu omaniku (või mõne muu kasutaja, kellel on juurdepääs privaatvõtmele) poolt.
Nutika lepingu avaldamisel saame selle initsialiseerida vajalike andmetega salvestusruumis, mis salvestatakse edaspidiseks kasutamiseks. Kirjutame sinna avaliku võtme, et saaksime kontrollida, kas sissetuleva sõnumi allkiri tehti vastava privaatvõtmega.
Enne jätkamist loome privaatvõtme ja kirjutame selle üles test/keys/owner.pkSelleks käivitame Fifti interaktiivses režiimis ja täidame neli käsku.
`newkeypair` генерация публичного и приватного ключа и запись их в стек.
`drop` удаления из стека верхнего элемента (в данном случае публичный ключ)
`.s` просто посмотреть что лежит в стеке в данный момент
`"owner.pk" B>file` запись приватного ключа в файл с именем `owner.pk`.
`bye` завершает работу с Fift. Loome kausta keys kausta sees test ja me kirjutame sinna privaatvõtme.
mkdir test/keys
cd test/keys
~/TON/build/crypto/fift -i
newkeypair
ok
.s
BYTES:128DB222CEB6CF5722021C3F21D4DF391CE6D5F70C874097E28D06FCE9FD6917 BYTES:DD0A81AAF5C07AAAA0C7772BB274E494E93BB0123AA1B29ECE7D42AE45184128
drop
ok
"owner.pk" B>file
ok
byeNäeme faili praeguses kaustas owner.pk.
Eemaldame avaliku võtme pinust ja saame selle vajadusel privaatvõtmest kätte.
Nüüd peame kirjutama allkirjakontrolli. Alustame testiga. Esmalt loeme failist privaatvõtme funktsiooni abil file>B ja kirjuta see muutujasse owner_private_key, seejärel funktsiooni abil priv>pub teisendage privaatvõti avalikuks võtmeks ja kirjutage tulemus owner_public_key.
variable owner_private_key
variable owner_public_key
"./keys/owner.pk" file>B owner_private_key !
owner_private_key @ priv>pub owner_public_key !Me vajame mõlemat võtit.
Initsialiseeri nutika lepingu salvestusruum suvaliste andmetega samas järjekorras nagu funktsioonis pack_state()ja kirjuta see muutujasse storage.
variable owner_private_key
variable owner_public_key
variable orders
variable owner_wc
variable owner_account_id
"./keys/owner.pk" file>B owner_private_key !
owner_private_key @ priv>pub owner_public_key !
dictnew orders !
0 owner_wc !
0 owner_account_id !
<b 0 32 u, owner_public_key @ B, 0 32 u, 0 32 u, 0 Gram, 0 Gram, owner_wc @ 32 i, owner_account_id @ 256 u, orders @ dict, b> storage !Järgmisena koostame allkirjastatud sõnumi, mis sisaldab ainult allkirja ja loenduri väärtust.
Esmalt loome andmed, mida soovime edastada, seejärel allkirjastame need privaatvõtmega ja lõpuks moodustame allkirjastatud sõnumi.
variable message_to_sign
variable message_to_send
variable signature
<b 0 32 u, b> message_to_sign !
message_to_sign @ hashu owner_private_key @ ed25519_sign_uint signature !
<b signature @ B, 0 32 u, b> <s message_to_send ! Selle tulemusel kirjutatakse nutikale lepingule saadetav sõnum muutujasse message_to_send, funktsioonide kohta hashu, ed25519_sign_uint sa oskad lugeda .
Ja testi käivitamiseks kutsume seda uuesti välja.
message_to_send @
recv_external
code
storage @
c7
runvmctxTestfail peaks selles etapis välja nägema selline.
Käivitame testi ja see ebaõnnestub, seega muudame nutikat lepingut nii, et see saaks sellises vormingus sõnumeid vastu võtta ja allkirja kontrollida.
Esmalt loeme sõnumist 512 bitti allkirja ja kirjutame need muutujasse, seejärel loeme loenduri muutuja 32 bitti.
Kuna meil on funktsioon andmete lugemiseks nutika lepingu salvestusruumist, siis me seda ka kasutame.
Järgmisena kontrollige salvestusruumiga edastatud loendurit ja signatuuri. Kui midagi ei ühti, visake vastava koodiga erand.
var signature = in_msg~load_bits(512);
var message = in_msg;
int msg_seqno = message~load_uint(32);
(int stored_seqno, int pubkey, int order_seqno, int number_of_wins, int incoming_amount, int outgoing_amount, int owner_wc, int owner_account_id, cell orders) = unpack_state();
throw_unless(33, msg_seqno == stored_seqno);
throw_unless(34, check_signature(slice_hash(in_msg), signature, pubkey));Vastav commit .
Käivitame testid ja vaatame, et teine test ebaõnnestub. Kahel põhjusel on sõnumis ja salvestusruumis bitid otsas, seega koodi parsimine ebaõnnestub. Peame saadetavale sõnumile lisama allkirja ja kopeerima salvestusruumi eelmisest testist.
Teises testis lisame sõnumi allkirja ja muudame nutika lepingu salvestusruumi. Nii näeb testfail hetkel välja.
Kirjutame neljanda testi, milles saadame kellegi teise privaatvõtmega allkirjastatud sõnumi. Loome uue privaatvõtme ja salvestame selle faili. not-owner.pkMe allkirjastame sõnumi selle privaatvõtmega. Me käivitame testid ja veendume, et kõik testid läbivad. praegusel hetkel.
Nüüd saame lõpuks edasi liikuda nutika lepingu loogika rakendamise juurde.
В recv_external() Võtame vastu kahte tüüpi sõnumeid.
Kuna meie leping akumuleerib mängijate kaotused, tuleb see raha üle kanda loterii loojale. Loterii looja rahakoti aadress kirjutatakse lepingu loomisel salvestusruumi.
Igaks juhuks vajame võimalust muuta aadressi, kuhu kaotajate grammid saata. Samuti peame saama lotogrammid saata omaniku aadressile.
Alustame esimesest. Esmalt kirjutame testi, mis kontrollib, kas pärast sõnumi saatmist on nutileping salvestanud uue aadressi mällu. Pane tähele, et lisaks loendurile ja uuele aadressile saadame ka action 7-bitine mittenegatiivne täisarv, olenevalt sellest valime, kuidas sõnumit nutilepingus töödelda.
<b 0 32 u, 1 @ 7 u, new_owner_wc @ 32 i, new_owner_account_id @ 256 u, b> message_to_sign !Testis näete, kuidas toimub nutika lepingu salvestusruumi deserialiseerimine. storage Muutujate deserialiseerimist on kirjeldatud Fifti dokumentatsioonis.
taigna lisamisega.
Käivitame testi ja veendume, et see jookseb kokku. Nüüd lisame loogika loto omaniku aadressi muutmiseks.
Nutikas lepingus jätkame parsimist message, me lugesime sisse actionTuletame teile meelde, et meil on kaks action: aadressi muutmine ja grammide saatmine.
Seejärel loeme lepingu omaniku uue aadressi ja salvestame selle salvestusse.
Käivitame testid ja näeme, et kolmas test ebaõnnestub. See ebaõnnestub, kuna leping parsib nüüd sõnumist lisaks 7 bitti, mis testis puuduvad. Lisame olematu actionTeeme testid läbi ja vaatame, kas need kõik läbivad. Pühendu muutustele. Suurepärane.
Nüüd kirjutame loogika määratud arvu grammide saatmiseks eelnevalt salvestatud aadressile.
Esmalt kirjutame testi. Kirjutame kaks testi, ühe siis, kui saldo pole piisav, ja teise siis, kui kõik peaks hästi minema. Teste näete. .
Nüüd lõpetame koodi. Esmalt kirjutame kaks abimeetodit. Esimene get-meetod on nutika lepingu praeguse saldo leidmiseks.
int balance() inline_ref method_id {
return get_balance().pair_first();
}Ja teine on grammide saatmiseks teise nutilepingusse. Kopeerisin selle meetodi täielikult teisest nutilepingust.
() send_grams(int wc, int addr, int grams) impure {
;; int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool src:MsgAddress -> 011000
cell msg = begin_cell()
;; .store_uint(0, 1) ;; 0 <= format indicator int_msg_info$0
;; .store_uint(1, 1) ;; 1 <= ihr disabled
;; .store_uint(1, 1) ;; 1 <= bounce = true
;; .store_uint(0, 1) ;; 0 <= bounced = false
;; .store_uint(4, 5) ;; 00100 <= address flags, anycast = false, 8-bit workchain
.store_uint (196, 9)
.store_int(wc, 8)
.store_uint(addr, 256)
.store_grams(grams)
.store_uint(0, 107) ;; 106 zeroes + 0 as an indicator that there is no cell with the data.
.end_cell();
send_raw_message(msg, 3); ;; mode, 2 for ignoring errors, 1 for sender pays fees, 64 for returning inbound message value
}Lisame need kaks meetodit nutilepingusse ja kirjutame loogika. Esmalt parsime sõnumist grammide arvu. Seejärel kontrollime saldot, kui seda pole piisavalt, viskame erandi. Kui kõik on korras, saadame grammid salvestatud aadressile ja uuendame loendurit.
int amount_to_send = message~load_grams();
throw_if(36, amount_to_send + 500000000 > balance());
accept_message();
send_grams(owner_wc, owner_account_id, amount_to_send);
set_data(pack_state(stored_seqno + 1, pubkey, order_seqno, number_of_wins, incoming_amount, outgoing_amount, owner_wc, owner_account_id, orders));Nii näeb nutikas leping hetkel välja. Teeme testid läbi ja veendume, et need läbivad.
Muide, iga kord, kui nutileping sõnumit töötleb, kantakse maha vahendustasu. Selleks, et nutileping saaks päringu täita, peate pärast põhikontrolle helistama accept_message().
Nüüd sisemiste sõnumite juurde. Tegelikult aktsepteerime ainult gramme ja saadame mängijale võidu korral tagasi topeltsumma ning kaotuse korral kolmandiku omanikule.
Esmalt kirjutame lihtsa testi. Selleks vajame nutika lepingu test-aadressi, millelt me gramme nutikale lepingule saadame.
Nutika lepingu aadress koosneb kahest numbrist: 32-bitisest täisarvust, mis vastutab tööahela eest, ja 256-bitisest mittenegatiivsest täisarvust, mis on selle tööahela unikaalne kontonumber. Näiteks -1 ja 12345, see aadress ja salvesta faili.
Kopeerisin funktsiooni aadressi salvestamiseks .
// ( wc addr fname -- ) Save address to file in 36-byte format
{ -rot 256 u>B swap 32 i>B B+ swap B>file } : save-addressVaatame, kuidas funktsioon töötab, see annab arusaama Fifti toimimisest. Käivitage Fift interaktiivses režiimis.
~/TON/build/crypto/fift -i Esmalt paneme pinu -1, 12345 ja tulevase faili nime "sender.addr":
-1 12345 "sender.addr" Järgmine samm on funktsiooni käivitamine -rot, mis nihutab pinu nii, et unikaalne nutika lepingu number on pinu ülaosas:
"sender.addr" -1 12345256 u>B Teisendab 256-bitise mittenegatiivse täisarvu baitideks.
"sender.addr" -1 BYTES:0000000000000000000000000000000000000000000000000000000000003039swap vahetab virna kaks ülemist elementi omavahel.
"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 -132 i>B Teisendab 32-bitise täisarvu baitideks.
"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 BYTES:FFFFFFFFB+ ühendab kaks baitide jada.
"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFFJälle swap.
BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF "sender.addr" Ja lõpuks kirjutatakse baidid faili. B>filePärast seda on meie pinu tühi. Stopp FiftPraegusesse kausta on loodud fail. sender.addrLiigutame faili loodud kausta. test/addresses/.
Kirjutame lihtsa testi, mis saadab grammid nutikale lepingule. .
Nüüd aga loterii loogika juurde.
Esimene asi, mida me teeme, on sõnumi kontrollimine bounced või mitte, kui bounced, siis me ignoreerime seda. bounced tähendab, et leping tagastab grammid vea ilmnemisel. Me ei tagasta gramme vea ilmnemisel.
Kontrollime, kui jääk on alla poole grammi, siis lihtsalt aktsepteerime teate ja ignoreerime seda.
Järgmisena parsime selle nutika lepingu aadressi, kust sõnum tuli.
Loeme andmeid salvestusruumist ja kustutame seejärel ajaloost vanad panused, kui neid on rohkem kui kakskümmend. Mugavuse huvides kirjutasin kolm lisafunktsiooni pack_order(), unpack_order(), remove_old_orders().
Järgmisena vaatame, et kui saldost makse tegemiseks ei piisa, siis arvame, et see pole panus, vaid täiendamine ja salvestame täiendamise sisse orders.
Nüüd lõpuks nutika lepingu olemus.
Esiteks, kui mängija kaotab, salvestame selle panustamisajalukku ja kui summa on suurem kui 3 grammi, saadame 1/3 nutika lepingu omanikule.
Kui mängija võidab, saadame kahekordistatud summa mängija aadressile ja salvestame seejärel panuseinfo ajalukku.
() recv_internal(int order_amount, cell in_msg_cell, slice in_msg) impure {
var cs = in_msg_cell.begin_parse();
int flags = cs~load_uint(4); ;; int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
if (flags & 1) { ;; ignore bounced
return ();
}
if (order_amount < 500000000) { ;; just receive grams without changing state
return ();
}
slice src_addr_slice = cs~load_msg_addr();
(int src_wc, int src_addr) = parse_std_addr(src_addr_slice);
(int stored_seqno, int pubkey, int order_seqno, int number_of_wins, int incoming_amount, int outgoing_amount, int owner_wc, int owner_account_id, cell orders) = unpack_state();
orders = remove_old_orders(orders, order_seqno);
if (balance() < 2 * order_amount + 500000000) { ;; not enough grams to pay the bet back, so this is re-fill
builder order = pack_order(order_seqno, 1, now(), order_amount, src_wc, src_addr);
orders~udict_set_builder(32, order_seqno, order);
set_data(pack_state(stored_seqno, pubkey, order_seqno + 1, number_of_wins, incoming_amount + order_amount, outgoing_amount, owner_wc, owner_account_id, orders));
return ();
}
if (rand(10) >= 4) {
builder order = pack_order(order_seqno, 3, now(), order_amount, src_wc, src_addr);
orders~udict_set_builder(32, order_seqno, order);
set_data(pack_state(stored_seqno, pubkey, order_seqno + 1, number_of_wins, incoming_amount + order_amount, outgoing_amount, owner_wc, owner_account_id, orders));
if (order_amount > 3000000000) {
send_grams(owner_wc, owner_account_id, order_amount / 3);
}
return ();
}
send_grams(src_wc, src_addr, 2 * order_amount);
builder order = pack_order(order_seqno, 2, now(), order_amount, src_wc, src_addr);
orders~udict_set_builder(32, order_seqno, order);
set_data(pack_state(stored_seqno, pubkey, order_seqno + 1, number_of_wins + 1, incoming_amount, outgoing_amount + 2 * order_amount, owner_wc, owner_account_id, orders));
}Nii see on. .
Nüüd on see lihtne: loome get-meetodid, et saaksime välismaailmast lepingu oleku kohta teavet (tegelikult loeksime andmeid nutika lepingu salvestusruumist).
Allpool kirjutame sellest, kuidas saada teavet nutika lepingu kohta.
Unustasin ka lisada koodi, mis hakkab tegelema kõige esimese päringuga, mis tekib nutika lepingu avaldamisel. Ja palju muud Viga 1/3 summast omaniku kontole saatmisega.
Nüüd jääb üle vaid nutikas leping avaldada. Loome kausta. requests.
Võtsin aluseks avaldamiskoodi который ametlikus hoidlas.
Millele tasub tähelepanu pöörata. Moodustame nutika lepingu salvestusruumi ja sisendsõnumi. Pärast seda genereeritakse nutika lepingu aadress, see tähendab, et aadress on teada juba enne TON-is avaldamist. Seejärel tuleb sellele aadressile saata mitu grammi ja alles pärast seda tuleb saata fail koos nutika lepinguga ise, kuna võrk võtab nutika lepingu ja selles tehtud toimingute salvestamise eest vahendustasu (valideerijad, kes salvestavad ja täidavad nutikaid lepinguid). .
Järgmisena käivitame avaldamiskoodi ja saame lottery-query.boc nutika lepingu fail ja aadress.
~/TON/build/crypto/fift -s requests/new-lottery.fif 0Ärge unustage loodud faile salvestada: lottery-query.boc, lottery.addr, lottery.pk.
Muuhulgas näeme täitmislogides nutika lepingu aadressi.
new wallet address = 0:044910149dbeaf8eadbb2b28722e7d6a2dc6e264ec2f1d9bebd6fb209079bc2a
(Saving address to file lottery.addr)
Non-bounceable address (for init): 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd
Bounceable address (for later access): kQAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8KpFYLõbu pärast esitame TON-ile palve
$ ./lite-client/lite-client -C ton-lite-client-test1.config.json
getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8KsydJa me näeme, et selle aadressiga konto on tühi.
account state is emptySaadame aadressile 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd 2 Grammi ja mõne sekundi pärast käivitan sama käsu. Grammide saatmiseks kasutan ja sa võid vestlusest kelleltki testgramme küsida, millest ma artikli lõpus räägin.
> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8KsydPaistab, et võrku on ilmunud initsialiseerimata (state:account_uninit) nutikas leping sellise aadressi ja 1 000 000 000 nanogrammi jäägiga.
account state is (account
addr:(addr_std
anycast:nothing workchain_id:0 address:x044910149DBEAF8EADBB2B28722E7D6A2DC6E264EC2F1D9BEBD6FB209079BC2A)
storage_stat:(storage_info
used:(storage_used
cells:(var_uint len:1 value:1)
bits:(var_uint len:1 value:103)
public_cells:(var_uint len:0 value:0)) last_paid:1583257959
due_payment:nothing)
storage:(account_storage last_trans_lt:3825478000002
balance:(currencies
grams:(nanograms
amount:(var_uint len:4 value:2000000000))
other:(extra_currencies
dict:hme_empty))
state:account_uninit))
x{C00044910149DBEAF8EADBB2B28722E7D6A2DC6E264EC2F1D9BEBD6FB209079BC2A20259C2F2F4CB3800000DEAC10776091DCD650004_}
last transaction lt = 3825478000001 hash = B043616AE016682699477FFF01E6E903878CDFD6846042BA1BFC64775E7AC6C4
account balance is 2000000000ngNüüd avaldame nutika lepingu. Käivitame lite-clienti ja täidame selle.
> sendfile lottery-query.boc
[ 1][t 2][1583008371.631410122][lite-client.cpp:966][!testnode] sending query from file lottery-query.boc
[ 3][t 1][1583008371.828550100][lite-client.cpp:976][!query] external message status is 1 Kontrollime, kas leping on avaldatud.
> last
> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8KsydMuuhulgas saame me kätte.
storage:(account_storage last_trans_lt:3825499000002
balance:(currencies
grams:(nanograms
amount:(var_uint len:4 value:1987150999))
other:(extra_currencies
dict:hme_empty))
state:(account_activeMe näeme seda account_active.
Vastav muudatustega commit .
Nüüd loome päringud nutika lepinguga suhtlemiseks.
Täpsemalt öeldes jätame esimese aadressi muutmise iseseisvaks tööks ja teise teeme grammide saatmiseks omaniku aadressile. Tegelikult peame tegema sama, mis grammide saatmise testis.
See on sõnum, mille saadame nutikale lepingule, kus msg_seqno 165 action 2 ja 9.5 grammi saatmiseks.
<b 165 32 u, 2 7 u, 9500000000 Gram, b>Ära unusta sõnumit privaatvõtmega allkirjastada lottery.pk, mis genereeriti varem nutika lepingu loomisel. .
Nutika lepingu teabe hankimine get-meetodite abil
Nüüd vaatame, kuidas käivitada nutikaid lepingu võtmise meetodeid.
Käivitamine lite-client ja käivitage meie kirjutatud get-meetodid.
$ ./lite-client/lite-client -C ton-lite-client-test1.config.json
> runmethod 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd balance
arguments: [ 104128 ]
result: [ 64633878952 ]
...В result sisaldab funktsiooni tagastatavat väärtust balance() meie nutikast lepingust.
Teeme sama veel mitme meetodi puhul.
> runmethod 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd get_seqno
...
arguments: [ 77871 ]
result: [ 1 ] Küsime kihlvedude ajalugu.
> runmethod 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd get_orders
...
arguments: [ 67442 ]
result: [ ([0 1 1583258284 10000000000 0 74649920601963823558742197308127565167945016780694342660493511643532213172308] [1 3 1583258347 4000000000 0 74649920601963823558742197308127565167945016780694342660493511643532213172308] [2 1 1583259901 50000000000 0 74649920601963823558742197308127565167945016780694342660493511643532213172308]) ] Nutika lepingu kohta teabe kuvamiseks saidil kasutame lite-client ja get-meetodeid.
Nutikate lepingute andmete kuvamine veebisaidil
Kirjutasin lihtsa Pythoni veebisaidi, et kuvada nutikate lepingute andmeid mugaval viisil. Ma ei hakka siin detailidesse laskuma ja avaldan veebisaidi. .
TON-ile esitatakse päringuid aadressilt Python abiga lite-clientMugavuse huvides on sait pakendatud Dockerisse ja avaldatud Google Cloudis. .
Proovin
Proovime nüüd sinna gramme saata, et neid täiendada Saadame 40 grammi. Ja teeme selguse huvides paar panust. Näeme, et sait näitab panustamisajalugu, praegust võiduprotsenti ja muud kasulikku teavet.
, et me võitsime esimese ja kaotasime teise.
järelsõna
Artikkel osutus palju pikemaks, kui ma ootasin, võib-olla oleks see võinud olla lühem või on see lihtsalt mõeldud inimesele, kes TONist midagi ei tea ja soovib kirjutada ja avaldada mitte just väga lihtsa nutika lepingu, millel on võimalus sellega suhelda. Võib-olla oleks mõnda asja saanud lihtsamalt selgitada.
Võib-olla oleks mõningaid teostuse aspekte saanud teha tõhusamalt ja elegantsemalt, aga siis oleks artikli ettevalmistamine võtnud veelgi rohkem aega. Samuti on võimalik, et tegin kuskil vea või ei saanud millestki aru, seega kui teete midagi tõsist, peate toetuma ametlikule dokumentatsioonile või ametlikule repositooriumile koos TON-koodiga.
Tuleb märkida, et kuna TON ise on alles aktiivses arendusjärgus, võib esineda muudatusi, mis rikuvad mõnda selle artikli sammu (mis juhtus minu kirjutamise ajal, olen selle juba parandanud), kuid üldine lähenemisviis tõenäoliselt ei muutu.
Ma ei hakka TONi tuleviku üle spekuleerima. Võib-olla saab platvormist midagi suuremat ja peaksime praegu aega pühendama selle uurimisele ning oma toodetega niši hõivamisele.
Samuti on olemas Facebooki Libra, mille potentsiaalne kasutajate sihtrühm on suurem kui TONil. Ma ei tea Librast peaaegu mitte midagi, aga foorumi põhjal otsustades on seal palju rohkem aktiivsust kui TONi kogukonnas. Kuigi arendajad ja TONi kogukond on pigem underground, mis on samuti lahe.
Viited
- TON-i ametlik dokumentatsioon:
- TON-i ametlik hoidla:
- Ametlik rahakott erinevatele platvormidele:
- Nutikas lepingute hoidla sellest artiklist:
- Link nutika lepingu veebisaidile:
- Visual Studio koodi laienduste hoidla FunC jaoks:
- Vestlus TON-ist Telegramis, mis aitas mul algstaadiumis palju aru saada. Ma arvan, et pole viga, kui ütlen, et kõik, kes TON-i jaoks midagi kirjutasid, on seal olemas. Samuti saate sealt test-gramme küsida.
- Veel üks vestlus TONi kohta, kust leidsin kasulikku infot:
- Võistluse esimene etapp:
- Võistluse teine etapp:
Allikas: www.habr.com
