Nutika lepingu kirjutamise ja avaldamise kohta Telegrami avatud võrgus (TON)

Nutika lepingu kirjutamise ja avaldamise kohta TONis

Millest see artikkel räägib?

Artiklis räägin sellest, kuidas osalesin esimesel (kahest) Telegrami plokiahela konkursil, ei võtnud auhinda ja otsustasin oma kogemuse artiklisse jäädvustada, et see unustusse ei vajuks ja ehk aitaks keegi.

Kuna ma ei tahtnud kirjutada abstraktset koodi, vaid teha midagi toimivat, kirjutasin artikli jaoks nutika lepingu kiirloterii jaoks ja veebisaidi, mis näitab nutika lepingu andmeid otse TON-ist ilma vahesalvestust kasutamata.

Artikkel on kasulik neile, kes soovivad sõlmida oma esimese nutika lepingu TONis, kuid ei tea, kust alustada.

Loterii näitel liigun keskkonna installimisest nutika lepingu avaldamiseni, sellega suhtlemiseni ning andmete vastuvõtmise ja avaldamise veebilehe kirjutamiseni.

Konkursil osalemisest

Eelmise aasta oktoobris kuulutas Telegram välja uute keeltega plokiahela konkursi Fift и FunC. Viie pakutud nutika lepingu kirjutamise hulgast tuli valida ükskõik milline. Arvasin, et oleks tore teha midagi teistmoodi, õppida keelt ja midagi teha, isegi kui ma ei pea tulevikus midagi muud kirjutama. Lisaks on teema pidevalt huulil.

Tasub öelda, et mul polnud nutikate lepingute väljatöötamise kogemust.

Plaanisin osaleda päris lõpuni, kuni jõuan ja siis ülevaateartikli kirjutan, aga esimesega kukkusin kohe läbi. I kirjutas rahakoti mitme allkirjaga FunC ja üldiselt töötas. Võtsin selle aluseks nutikas leping Solidity kohta.

Tookord arvasin, et sellest kindlasti piisab, et vähemalt mõni auhinnaline koht võtta. Tulemuseks oli, et umbes 40 osalejat 60-st said auhinnasaajateks ja mina nende hulgas ei olnud. Üldiselt pole selles midagi halba, kuid üks asi häiris mind. Tulemuste teatavakstegemise ajaks oli minu lepingu testi ülevaatamine tegemata, küsisin vestluses osalejatelt, kas on veel kellelgi seda ei olnud, ei olnud.

Ilmselt minu sõnumitele tähelepanu pöörates avaldasid kohtunikud kaks päeva hiljem kommentaari ja ma ei saa siiani aru, kas nad jäid kogemata minu nutikale lepingule kohtunike käigus vahele või lihtsalt arvasid, et see on nii halb, et see ei vaja kommentaari. Esitasin lehel küsimuse, kuid vastust ei saanud. Kuigi pole saladus, kes hindas, pidasin isiklike sõnumite kirjutamist ebavajalikuks.

Palju aega kulus mõistmisele, mistõttu otsustati kirjutada artikkel. Kuna infot pole veel palju, aitab see artikkel kõigi huviliste aega kokku hoida.

Nutikate lepingute kontseptsioon TONis

Enne kui midagi kirjutad, pead välja mõtlema, kummalt poolt sellele asjale läheneda. Seetõttu ütlen nüüd teile, millistest osadest süsteem koosneb. Täpsemalt, milliseid osi peab teadma, et vähemalt mingigi töölepingut kirjutada.

Keskendume nutika lepingu kirjutamisele ja sellega töötamisele TON Virtual Machine (TVM), Fift и FunC, seega on artikkel pigem tavalise programmi arendamise kirjeldus. Me ei peatu siinkohal sellel, kuidas platvorm ise töötab.

Üldiselt selle toimimise kohta TVM ja keel Fift on olemas korralik ametlik dokumentatsioon. Konkursil osaledes ja praegu kehtivat lepingut kirjutades pöördusin sageli tema poole.

Peamine keel, milles nutikaid lepinguid kirjutatakse, on FunC. Selle kohta pole hetkel dokumentatsiooni, nii et millegi kirjutamiseks tuleb uurida ametlikust hoidlast nutikate lepingute näiteid ja sealse keele enda juurutamist, lisaks saab vaadata nutikate lepingute näiteid viimasest kahest võistlused. Lingid artikli lõpus.

Oletame, et oleme juba kirjutanud nutika lepingu FunC, pärast seda koostame koodi Fift assemblerisse.

Koostatud nutileping jääb avaldada. Selleks peate sisestama funktsiooni Fift, mis võtab sisendiks nutika lepingu koodi ja mõned muud parameetrid ning väljundiks on laiendiga fail .boc (mis tähendab "rakukott") ning sõltuvalt sellest, kuidas me selle kirjutame, privaatvõti ja aadress, mis luuakse nutika lepingu koodi põhjal. Nutilepingu aadressile, mida pole veel avaldatud, saab juba gramme saata.

Targa lepingu avaldamiseks TON-is saadud .boc fail tuleb kerge kliendi abil plokiahelasse saata (sellest lähemalt allpool). Aga enne avaldamist tuleb genereeritud aadressile grammid üle kanda, muidu nutilepingut ei avaldata. Pärast avaldamist saate nutika lepinguga suhelda, saates sellele sõnumeid väljastpoolt (näiteks kergkliendi abil) või seestpoolt (näiteks üks nutileping saadab teisele TON-i sees sõnumi).

Kui mõistame, kuidas kood avaldatakse, muutub see lihtsamaks. Me teame umbkaudu, mida tahame kirjutada ja kuidas meie programm töötab. Ja kirjutamise ajal uurime, kuidas see on juba olemasolevates nutikates lepingutes rakendatud, või uurime juurutuskoodi Fift и FunC ametlikus hoidlas või vaadake ametlikku dokumentatsiooni.

Väga tihti otsisin Telegrami vestlusest, kuhu kogunesid kõik võistlusel osalejad ja Telegrami töötajad, märksõnu ja juhtus nii, et võistluse ajal kogunesid kõik sinna ja hakkasid Fifti ja FunC-i arutama. Link artikli lõpus.

On aeg liikuda teoorialt praktikale.

Keskkonna ettevalmistamine TON-iga töötamiseks

Tegin kõik, mida MacOS-i artiklis kirjeldatakse, ja kontrollisin seda Dockeri puhtas Ubuntu 18.04 LTS-is.

Esimene asi, mida peate tegema, on alla laadida ja installida lite-client millega saate TON-ile päringuid saata.

Ametlikul veebisaidil olevad juhised kirjeldavad installiprotsessi üsna üksikasjalikult ja selgelt ning jätavad mõned üksikasjad välja. Siin järgime juhiseid, installides puuduvad sõltuvused. Ma ei kompileerinud iga projekti ise ja installisin ametlikust Ubuntu hoidlast (kasutasin MacOS-is 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.

Esiteks kloonime TON-i hoidla koos selle 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 --recursive

Hoidlas salvestatakse ka teostused Fift и FunC.

Nüüd oleme valmis projekti kokku panema. Hoidla kood kloonitakse kausta ~/TON/ton. Sisse ~/TON luua kaust build ja koguge projekt sinna.

mkdir ~/TON/build 
cd ~/TON/build
cmake ../ton

Kuna hakkame kirjutama nutikat lepingut, vajame mitte ainult lite-clientkuid Fift с FunC, nii et koostame kõik. See ei ole kiire protsess, nii et me ootame.

cmake --build . --target lite-client
cmake --build . --target fift
cmake --build . --target func

Järgmisena laadige alla konfiguratsioonifail, mis sisaldab andmeid selle sõlme kohta, kuhu lite-client ühendab.

wget https://test.ton.org/ton-lite-client-test1.config.json

Esitame esimesed päringud TON-ile

Nüüd käivitame lite-client.

cd ~/TON/build
./lite-client/lite-client -C ton-lite-client-test1.config.json

Kui ehitamine õnnestus, näete pärast käivitamist kerge kliendi sõlme ühendamise logi.

[ 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äsu käivitada help ja vaadake, millised käsud on saadaval.

help

Loetleme käsud, mida 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 parameters

last получает последний созданный блок с сервера. 

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.

Veelgi enam, see pole loterii, kus peate ostma pileti ja ootama tund, päev või kuu, vaid hetke, kus kasutaja liigub lepingu aadressile. N grammi ja saab selle kohe tagasi 2 * N grammi või kaotab. Teeme võidu tõenäosuseks umbes 40%. Kui grammidest ei jätku maksmiseks, siis käsitleme tehingut täiendusena.

Lisaks on oluline, et panused oleksid reaalajas ja mugaval kujul nähtavad, et kasutaja saaks kohe aru, kas ta võitis või kaotas. Seetõttu peate tegema veebisaidi, mis näitab panuseid ja tulemusi otse TON-ist.

Nutika lepingu kirjutamine

Mugavuse huvides tõstsin esile FunC koodi, plugina leiad ja installid Visual Studio Code otsingust; kui soovid äkki midagi lisada, siis olen teinud plugina avalikult kättesaadavaks. Samuti tegi keegi varem Fiftiga töötamiseks pistikprogrammi, saate selle ka installida ja VSC-st leida.

Loome kohe hoidla, kuhu salvestame vahetulemused.

Oma elu lihtsustamiseks kirjutame nutika lepingu ja testime seda kohapeal, kuni see valmis saab. Alles pärast seda avaldame selle TON-is.

Nutilepingul on kaks välist meetodit, millele pääseb juurde. Esiteks recv_external() see funktsioon täidetakse siis, kui lepingupäring tuleb välismaailmast, st mitte näiteks TON-ist, kui genereerime ise sõnumi ja saadame selle lite-kliendi kaudu. Teiseks recv_internal() see on siis, kui TONis endas viitab mis tahes leping meie omale. Mõlemal juhul saate funktsioonile parameetreid edastada.

Alustame lihtsa näitega, mis töötab avaldamise korral, kuid selles pole funktsionaalset koormust.

() recv_internal(slice in_msg) impure {
    ;; TODO: implementation 
}

() recv_external(slice in_msg) impure {
    ;; TODO: implementation  
}

Siin peame selgitama, mis see on slice. Kõik TON Blockchainis salvestatud andmed on kogumik TVM cell või lihtsalt cell, sellises lahtris saate salvestada kuni 1023 bitti andmeid ja kuni 4 linki teistele lahtritele.

TVM cell slice või slice see on osa olemasolevast cell sõelumiseks kasutatakse, selgub hiljem. Meie jaoks on peamine, et saame üle kanda slice ja olenevalt sõnumi tüübist töödelda andmeid sisse 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 koostada.

~/TON/build/crypto/func -APSR -o lottery-compiled.fif ~/TON/ton/crypto/smartcont/stdlib.fc ./lottery-code.fc 

Lippude tähendust saab vaadata käsu abil

~/TON/build/crypto/func -help

Oleme koostanud Fifti monteerija koodi 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>c

Seda saab käivitada kohapeal, selleks valmistame keskkonna ette.

Pange tähele, et esimene rida ühendab Asm.fif, see on Fifti koostaja jaoks Fiftis kirjutatud kood.

Kuna tahame nutikat lepingut kohapeal käivitada ja testida, loome faili lottery-test-suite.fif ja kopeerige sinna koostatud kood, asendades selle viimase rea, mis kirjutab nutika lepingu koodi konstandile codeet see 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

Seni tundub selge, nüüd lisame samasse faili koodi, mida kasutame TVM-i käivitamiseks.

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 salvestame konteksti, st andmed, millega TVM (või võrgu olek) käivitatakse. Isegi võistluse ajal näitas üks arendajatest, kuidas luua c7 ja ma kopeerisin. Selles artiklis peame võib-olla muutma rand_seed kuna sellest sõltub juhusliku arvu genereerimine ja kui seda ei muudeta, tagastatakse iga kord sama arv.

recv_internal и recv_external konstandid väärtustega 0 ja -1 vastutavad nutilepingu vastavate funktsioonide kutsumise eest.

Nüüd oleme valmis looma oma tühja nutika lepingu jaoks esimese testi. Selguse huvides lisame praegu kõik testid samasse faili lottery-test-suite.fif.

Loome muutuja storage ja kirjutage sinna tühi cell, see on nutikas lepinguline salvestusruum.

message See on sõnum, mille me nutikontaktile väljastpoolt edastame. Teeme selle ka praegu tühjaks.

variable storage 
<b b> storage ! 

variable message 
<b b> message ! 

Kui oleme konstandid ja muutujad ette valmistanud, käivitame käsuga TVM runvmctx ja edastage loodud parameetrid sisendisse.

message @ 
recv_external 
code 
storage @ 
c7 
runvmctx 

Lõpuks õnnestub meil niimoodi vahekood Fift.

Nüüd saame käivitada saadud koodi.

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=0

Suurepärane, oleme kirjutanud nutika lepingu esimese tööversiooni.

Nüüd peame lisama funktsioonid. Kõigepealt käsitleme sõnumeid, mis tulevad välismaailmast recv_external()

Arendaja ise valib sõnumi vormingu, mille leping vastu võtab.

Aga tavaliselt

  • esiteks tahame oma lepingut kaitsta välismaailma eest ja teha nii, et ainult lepingu omanik saaks sellele välisteateid 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 nutikas leping selle tagasi.

Nii et peaaegu iga leping lahendab 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 probleemi kordamisega, kui leping on juba sellise teate saanud ja seda töödeldud, siis teist korda ta seda ei täida. Ja siis lahendame probleemi nii, et nutilepingule saab sõnumeid saata ainult teatud ring inimesi.

Dubleerivate sõnumite probleemi lahendamiseks on erinevaid viise. Teeme seda järgmiselt. Nutilepingus initsialiseerime vastuvõetud sõnumite loenduri algväärtusega 0. Igasse nutika lepingu sõnumisse lisame jooksva loenduri väärtuse. Kui sõnumis olev loenduri väärtus ei ühti nutika lepingu väärtusega, siis me seda ei töötle; kui jah, siis töötleme seda ja suurendame nutika lepingu loendurit 1 võrra.

Tuleme tagasi lottery-test-suite.fif ja lisage sellele teine ​​test. Kui saadame vale numbri, peaks kood tegema erandi. Näiteks jätke lepingu andmetele 166 ja me 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 me näeme, et test sooritatakse 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 passed

Praeguses etapis lottery-test-suite.fif peaks välja nägema по ссылке.

Nüüd lisame nutikale lepingule vastuloogika 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, mille me saadame.

Esimese asjana kontrollime, kas sõnum sisaldab andmeid, kui mitte, 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 laetud number ühtib edastatud numbriga; kui ei, siis teeme erandi. Meie puhul, kuna me läbime mittematši, tuleks teha erand.

Nüüd koostame.

~/TON/build/crypto/func -APSR -o lottery-compiled.fif ~/TON/ton/crypto/smartcont/stdlib.fc ./lottery-code.fc 

Kopeerige saadud kood asukohta lottery-test-suite.fif, unustamata asendada viimast rida.

Kontrollime testi läbimist:

~/TON/build/crypto/fift -s lottery-test-suite.fif

Siin Vastavat kohustust näete praeguste tulemustega.

Pange tähele, et nutika lepingu kompileeritud koodi on ebamugav pidevalt testidega faili kopeerida, seetõttu kirjutame skripti, mis kirjutab koodi meie jaoks konstandiks ja ühendame kompileeritud koodi lihtsalt oma testidega, kasutades "include".

Looge projekti kausta 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.fc

Teeme selle käivitatavaks.

chmod +x ./build.sh

Nüüd lihtsalt käivitage lepingu koostamiseks meie skript. Kuid peale selle peame selle kirjutama konstandiks code. Seega loome uue faili lotter-compiled-for-test.fif, mille lisame faili lottery-test-suite.fif.

Lisame sh-le skirpt-koodi, mis lihtsalt dubleerib kompileeritud faili lotter-compiled-for-test.fif ja muutke selles 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.fif

Nüüd kontrollimiseks käivitame saadud skripti ja fail genereeritakse lottery-compiled-for-test.fif, mille lisame oma lottery-test-suite.fif

В lottery-test-suite.fif kustutage lepingu kood ja lisage rida "lottery-compiled-for-test.fif" include.

Korraldame teste, et kontrollida nende läbimist.

~/TON/build/crypto/fift -s lottery-test-suite.fif

Suurepärane, testide käivitamise automatiseerimiseks loome faili test.sh, mis esmalt käivitatakse build.shja seejärel käivitage testid.

touch test.sh
chmod +x test.sh

Me kirjutame sees

./build.sh 

echo "nCompilation completedn"

export FIFTPATH=~/TON/ton/crypto/fift/lib
~/TON/build/crypto/fift -s lottery-test-suite.fif

Teeme seda test.sh ja käivitage see, et veenduda testide toimimises.

chmod +x ./test.sh
./test.sh

Kontrollime lepingu koostamist ja testide sooritamist.

Suurepärane, nüüd käivitamisel test.sh Testid koostatakse ja käivitatakse kohe. Siin on link aadressile pühenduma.

Olgu, enne kui jätkame, teeme mugavuse huvides veel ühe asja.

Loome kausta build kuhu salvestame kopeeritud lepingu ja selle konstandisse kirjutatud klooni lottery-compiled.fif, lottery-compiled-for-test.fif. Teeme ka kausta test kus testfaili hoitakse? lottery-test-suite.fif ja potentsiaalselt muid toetavaid faile. Link asjakohaste muudatuste juurde.

Jätkame nutika lepingu arendamist.

Järgmiseks peaks olema test, mis kontrollib, kas sõnum on vastu võetud ja loendur uuendatakse poes, kui saadame õige numbri. Aga me teeme seda hiljem.

Nüüd mõelgem, millist andmestruktuuri ja milliseid andmeid tuleb nutikas lepingus salvestada.

Kirjeldan kõike, mida säilitame.

`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. Helistame esimesele pack_state(), mis pakib andmed hilisemaks salvestamiseks nutikasse lepingu salvestusruumi. Helistame teisele 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. See saab korda niimoodi vahetulemus.

Andmete salvestamiseks peate helistama sisseehitatud funktsioonile set_data() ja see kirjutab andmeid 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, et väljastpoolt saabuv sõnum oleks allkirjastatud lepingu omaniku (või mõne muu privaatvõtmele juurdepääsu omava kasutaja) poolt.

Nutilepingu avaldamisel saame selle lähtestada vajalike andmetega laos, mis salvestatakse edaspidiseks kasutamiseks. Salvestame seal avaliku võtme, et saaksime kontrollida, kas sissetulev kiri on allkirjastatud vastava privaatvõtmega.

Enne jätkamist loome privaatvõtme ja kirjutame sellele test/keys/owner.pk. Selleks käivitame interaktiivses režiimis Fifti ja täidame neli käsku.

`newkeypair` генерация публичного и приватного ключа и запись их в стек. 

`drop` удаления из стека верхнего элемента (в данном случае публичный ключ)  

`.s` просто посмотреть что лежит в стеке в данный момент 

`"owner.pk" B>file` запись приватного ключа в файл с именем `owner.pk`. 

`bye` завершает работу с Fift. 

Loome kausta keys kausta sees test ja kirjutage sinna privaatvõti.

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
bye

Näeme praeguses kaustas faili owner.pk.

Eemaldame pinust avaliku võtme ja vajadusel saame selle privaatsest võtmest.

Nüüd peame kirjutama allkirja kinnituse. Alustame testiga. Esmalt loeme funktsiooni abil failist privaatvõtme file>B ja kirjutage see muutujasse owner_private_key, seejärel kasutades funktsiooni priv>pub teisendage privaatvõti avalikuks võtmeks ja kirjutage tulemus sisse 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 !

Meil on vaja mõlemat võtit.

Initsialiseerime nutika lepingu salvestusruumi suvaliste andmetega samas järjestuses nagu funktsioonis pack_state()ja kirjutage 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, see sisaldab ainult allkirja ja loenduri väärtust.

Esiteks loome andmed, mida tahame edastada, seejärel allkirjastame need privaatvõtmega ja lõpuks genereerime 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 tulemusena salvestatakse muutujasse teade, mille saadame nutikale lepingule message_to_send, funktsioonide kohta hashu, ed25519_sign_uint sa oskad lugeda Fifti dokumentatsioonis.

Ja testi käivitamiseks helistame uuesti.

message_to_send @ 
recv_external 
code 
storage @
c7
runvmctx

Siin nii Testidega fail peaks selles etapis välja nägema selline.

Käitame testi ja see ebaõnnestub, seega muudame nutikat lepingut nii, et see saaks selles vormingus sõnumeid vastu võtta ja allkirja kontrollida.

Esiteks loeme kirjast 512 bitti signatuuri ja kirjutame selle muutujasse, seejärel loendame loenduri muutuja 32 bitti.

Kuna meil on nutika lepingu salvestuselt andmete lugemise funktsioon, siis kasutame seda.

Järgmine on salvestusruumiga üle kantud loenduri ja allkirja kontrollimine. Kui midagi ei sobi, siis teeme vastava koodiga erandi.

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));

Asjakohane kohustus siin.

Teeme testid ja vaatame, et teine ​​test ebaõnnestub. Kahel põhjusel pole sõnumis piisavalt bitte ja salvestusruumis pole piisavalt bitte, mistõttu kood jookseb sõelumisel kokku. Peame lisama saadetavale sõnumile allkirja ja kopeerima viimase testi salvestusruumi.

Teises testis lisame sõnumile allkirja ja muudame nutika lepingu salvestusruumi. Siin nii testidega fail näeb hetkel välja selline.

Kirjutame neljanda testi, mille käigus saadame kellegi teise privaatvõtmega allkirjastatud sõnumi. Loome teise privaatvõtme ja salvestame selle faili not-owner.pk. Allkirjastame sõnumi selle privaatvõtmega. Teeme testid ja veendume, et kõik testid läbivad. Pühenduma praegusel hetkel.

Nüüd saame lõpuks liikuda targa lepingu loogika juurutamise juurde.
В recv_external() võtame vastu kahte tüüpi sõnumeid.

Kuna meie lepingule koguneb mängijate kaotus, siis tuleb see raha loosi tegijale üle kanda. Loterii looja rahakoti aadress salvestatakse lepingu sõlmimisel hoiule.

Igaks juhuks vajame võimalust muuta aadressi, kuhu saadame kaotajate grammid. Samuti peaksime saama loteriilt gramme omaniku aadressile saata.

Alustame esimesest. Kirjutame esmalt testi, mis kontrollib, et peale sõnumi saatmist salvestas nutileping uue aadressi salvestusruumi. Pange tähele, et sõnumis edastame lisaks loendurile ja uuele aadressile ka action 7-bitine mittenegatiivne täisarv, sõltuvalt sellest valime nutilepingus sõnumi töötlemise viisi.

<b 0 32 u, 1 @ 7 u, new_owner_wc @  32 i, new_owner_account_id @ 256 u, b> message_to_sign !

Testis on näha, kuidas nutikate lepingute salvestusruumi deserialiseeritakse storage aastal Fift. Muutujate deserialiseerimist kirjeldatakse Fifti dokumentatsioonis.

Kinnita link lisatud taignaga.

Käivitame testi ja veendume, et see ebaõnnestub. Nüüd lisame loogika loosiomaniku aadressi muutmiseks.

Nutikas lepingus jätkame sõelumist message, loe sisse action. Tuletame meelde, et meil on kaks action: muuda aadressi ja saada gramme.

Seejärel loeme lepinguomaniku uue aadressi ja salvestame selle lattu.
Käitame testid ja näeme, et kolmas test ebaõnnestub. See jookseb kokku, kuna leping parsib nüüd täiendavalt sõnumist 7 bitti, mis testis puuduvad. Lisage sõnumile olematu action. Teeme testid ja vaatame, et kõik möödub. Siin muutustele pühenduma. Suurepärane.

Nüüd kirjutame loogika määratud arvu grammide saatmiseks eelnevalt salvestatud aadressile.

Kõigepealt kirjutame testi. Kirjutame kaks testi, ühe siis, kui tasakaalu pole piisavalt, teise, kui kõik peaks edukalt läbima. Teste saab vaadata selles kohustuses.

Nüüd lisame koodi. Kõigepealt kirjutame kaks abimeetodit. Esimene hankimismeetod on nutika lepingu hetkejäägi väljaselgitamine.

int balance() inline_ref method_id {
    return get_balance().pair_first();
}

Ja teine ​​on grammide saatmiseks teisele nutikale lepingule. Kopeerisin selle meetodi täielikult teisest nutikast lepingust.

() 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 nutikale lepingule ja kirjutame loogika. Esiteks analüüsime sõnumist grammide arvu. Järgmisena kontrollime saldot, kui sellest ei piisa, teeme erandi. Kui kõik on korras, siis 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));

Siin nii tundub praegu nutika lepinguna. Teeme testid ja veendume, et need läbivad.

Muide, töödeldud sõnumi eest võetakse nutilepingust iga kord maha vahendustasu. Nutilepingu sõnumite päringu täitmiseks peate pärast põhikontrolli helistama accept_message().

Liigume nüüd sisemiste sõnumite juurde. Tegelikult võtame vastu ainult gramme ja saadame võidu korral mängijale tagasi topeltsumma ja kaotuse korral kolmandiku omanikule.

Kõigepealt kirjutame lihtsa testi. Selleks vajame nutika lepingu testaadressi, kust me väidetavalt gramme nutilepingusse saadame.

Nutika lepingu aadress koosneb kahest numbrist, 32-bitisest täisarvust, mis vastutab tööahela eest, ja 256-bitisest mittenegatiivsest täisarvust unikaalsest kontonumbrist selles tööahelas. Näiteks -1 ja 12345, see on aadress, mille me faili salvestame.

Kopeerisin aadressi salvestamise funktsiooni TonUtil.fif.

// ( wc addr fname -- )  Save address to file in 36-byte format
{ -rot 256 u>B swap 32 i>B B+ swap B>file } : save-address

Vaatame, kuidas funktsioon töötab, see annab ülevaate Fifti toimimisest. Käivitage Fift interaktiivses režiimis.

~/TON/build/crypto/fift -i 

Esmalt lükkame virna -1, 12345 ja tulevase faili nime "sender.addr":

-1 12345 "sender.addr" 

Järgmine samm on funktsiooni täitmine -rot, mis nihutab pinu nii, et virna ülaosas on unikaalne nutika lepingu number:

"sender.addr" -1 12345

256 u>B teisendab 256-bitise mittenegatiivse täisarvu baitideks.

"sender.addr" -1 BYTES:0000000000000000000000000000000000000000000000000000000000003039

swap vahetab virna kaks ülemist elementi.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 -1

32 i>B teisendab 32-bitise täisarvu baitideks.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 BYTES:FFFFFFFF

B+ ühendab kaks baitide jada.

 "sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF

Jälle swap.

BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF "sender.addr" 

Ja lõpuks kirjutatakse failid baidid B>file. Pärast seda on meie virn tühi. Me peatume Fift. Praeguses kaustas on fail loodud sender.addr. Teisaldame faili loodud kausta test/addresses/.

Kirjutame lihtsa testi, mis saadab grammid nutikale lepingule. Siin on kohustus.

Vaatame nüüd loterii loogikat.

Esimese asjana kontrollime sõnumit bounced või mitte, kui bounced, siis ignoreerime seda. bounced tähendab, et mingi vea ilmnemisel tagastab leping gramme. Me ei tagasta gramme, kui ootamatult ilmneb viga.

Kontrollime, kui saldo on alla poole grammi, siis võtame sõnumi lihtsalt vastu ja ignoreerime seda.

Järgmisena sõelume selle nutika lepingu aadressi, kust sõnum tuli.

Loeme andmed salvestusruumist ja kustutame siis ajaloost vanad panused, kui neid on üle kahekümne. Mugavuse huvides kirjutasin kolm lisafunktsiooni pack_order(), unpack_order(), remove_old_orders().

Järgmisena vaatame, kui jäägist makseks ei piisa, siis arvestame, et see pole panus, vaid täiendus ja salvestame täienduse orders.

Siis lõpuks nutika lepingu olemus.

Esiteks, kui mängija kaotab, salvestame selle panuste ajalukku ja kui summa on suurem kui 3 grammi, saadame 1/3 nutika lepingu omanikule.

Kui mängija võidab, saadame mängija aadressile topeltsumma ja salvestame panuse info 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. Vastav kohustus.

Nüüd jääb üle vaid lihtsaks, loome hankimismeetodid, et saaksime välismaailmast lepingu seisu kohta teavet hankida (tegelikult lugeda andmeid nende nutikast lepingute salvestusruumist).

Lisame hankimismeetodid. Sellest, kuidas nutika lepingu kohta infot saada, kirjutame allpool.

Unustasin lisada ka koodi, mis töötleb nutilepingu avaldamisel kõige esimest päringut. Vastav kohustus. Ja edasi parandatud viga 1/3 summast omaniku kontole saatmisega.

Järgmine samm on nutika lepingu avaldamine. Loome kausta requests.

Võtsin aluseks avaldamiskoodi simple-wallet-code.fc который võib leida ametlikus hoidlas.

Midagi, millele tasub tähelepanu pöörata. Loome nutika lepingusalvestuse ja sisendsõnumi. Pärast seda genereeritakse nutika lepingu aadress, see tähendab, et aadress on teada juba enne TONis avaldamist. Järgmisena peate sellele aadressile saatma mitu grammi ja alles pärast seda peate saatma faili nutika lepingu endaga, kuna võrk võtab nutika lepingu ja selles olevate toimingute salvestamise eest vahendustasu (validaatorid, kes salvestavad ja käivitavad nutika lepingu lepingud). Koodi saab vaadata siit.

Järgmisena käivitame avaldamiskoodi ja saame lottery-query.boc nutikas lepingu fail ja aadress.

~/TON/build/crypto/fift -s requests/new-lottery.fif 0

Ärge unustage salvestada loodud faile: 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): kQAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8KpFY

Lõbu pärast esitame TONile taotluse

$ ./lite-client/lite-client -C ton-lite-client-test1.config.json 
getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Ja me näeme, et selle aadressiga konto on tühi.

account state is empty

Saadame aadressile 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd 2 grammi ja mõne sekundi pärast täidame sama käsu. Grammi saatmiseks kasutan ametlik rahakott, ja saate kelleltki vestlusest küsida testgramme, millest räägin artikli lõpus.

> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Näeb välja nagu initsialiseerimata (state:account_uninit) sama aadressiga nutikas leping, mille jääk on 1 000 000 000 nanogrammi.

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 2000000000ng

Nüüd avaldame nutika lepingu. Käivitame lite-kliendi ja käivitame.

> 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 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Muuhulgas saame.

  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_active

Me näeme seda account_active.

Vastav kohustus koos muudatustega siin.

Nüüd loome nutika lepinguga suhtlemise taotlused.

Täpsemalt jätame esimese aadressi muutmise iseseisvaks tööks ja teise teeme grammide saatmise omaniku aadressile. Tegelikult peame tegema sama, mis grammide saatmise testis.

Selle sõnumi saadame nutilepingule, kuhu msg_seqno 165 action Saatmiseks 2 ja 9.5 grammi.

<b 165 32 u, 2 7 u, 9500000000 Gram, b>

Ärge unustage sõnumit oma privaatvõtmega allkirjastada lottery.pk, mis loodi varem nutika lepingu loomisel. Siin on vastav kohustus.

Nutilepingust teabe saamine hankimismeetodite abil

Nüüd vaatame, kuidas käivitada nutikate lepingute hankimise meetodeid.

Käivitamine lite-client ja käivitage meie kirjutatud hankimismeetodid.

$ ./lite-client/lite-client -C ton-lite-client-test1.config.json
> runmethod 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd balance
arguments:  [ 104128 ] 
result:  [ 64633878952 ] 
...

В result sisaldab väärtust, mille funktsioon tagastab balance() meie nutikast lepingust.
Teeme sama veel mitme meetodi puhul.

> runmethod 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd get_seqno
...
arguments:  [ 77871 ] 
result:  [ 1 ] 

Küsime teie panuste 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]) ] 

Kasutame lite-klienti ja hankime meetodid nutika lepingu kohta saidil teabe kuvamiseks.

Nutikate lepingute andmete kuvamine veebisaidil

Nutilepingu andmete mugavaks kuvamiseks kirjutasin Pythonis lihtsa veebisaidi. Siin ma sellel üksikasjalikult ei peatu ja avaldan saidi ühes kohustuses.

Taotlused TON-ile on tehtud Python abiga lite-client. Mugavuse huvides on sait pakitud Dockeri ja avaldatud Google Cloudis. Link.

Proovin

Nüüd proovime saata gramme sinna täiendamiseks rahakott. Saadame 40 grammi. Ja selguse huvides teeme paar panust. Näeme, et sait näitab panuste ajalugu, hetke võiduprotsenti ja muud kasulikku teavet.

Me näemeet võitsime esimese, kaotasime teise.

järelsõna

Artikkel osutus palju pikemaks, kui ma eeldasin, võib-olla oleks see võinud olla lühem või võib-olla lihtsalt inimesele, kes ei tea TONist midagi ja soovib kirjutada ja avaldada mitte nii lihtsat nutikat lepingut, millel on võimalus suhelda seda. Võib-olla oleks mõnda asja saanud lihtsamalt seletada.

Võib-olla oleks mõne teostuse aspekti saanud teha tõhusamalt ja elegantsemalt, kuid siis oleks artikli ettevalmistamine võtnud veelgi rohkem aega. Samuti on võimalik, et ma tegin kuskil vea või ei saanud millestki aru, nii et kui teete midagi tõsist, peate tuginema ametlikule dokumentatsioonile või ametlikule hoidlale TON-koodiga.

Tuleb märkida, et kuna TON ise on alles aktiivses arendusfaasis, siis võib ette tulla muudatusi, mis katkestavad mõne käesoleva artikli sammu (mis juhtus minu kirjutamise ajal, seda on juba parandatud), kuid üldine lähenemine on tõenäoliselt ei muutu.

Ma ei räägi TONi tulevikust. Võib-olla saab platvormist midagi suurt ja me peaksime kulutama aega selle uurimisele ja täitma niši oma toodetega.

Kaalud on ka Facebookist, mille potentsiaalne kasutajate vaatajaskond on suurem kui TON. Ma ei tea Kaaludest peaaegu midagi, foorumi järgi otsustades on seal palju rohkem tegevust kui TONi kogukonnas. Kuigi TONi arendajad ja kogukond on rohkem nagu underground, mis on samuti lahe.

Viited

  1. TON-i ametlik dokumentatsioon: https://test.ton.org
  2. Ametlik TON-i hoidla: https://github.com/ton-blockchain/ton
  3. Ametlik rahakott erinevatele platvormidele: https://wallet.ton.org
  4. Nutikas lepingute hoidla sellest artiklist: https://github.com/raiym/astonished
  5. Link nutika lepingu veebisaidile: https://ton-lottery.appspot.com
  6. FunC Visual Studio Code laienduse hoidla: https://github.com/raiym/func-visual-studio-plugin
  7. Vestelge TONist Telegramis, mis aitas selle algetapis tõesti aru saada. Ma arvan, et pole viga, kui ütlen, et kõik, kes TONile midagi kirjutasid, on seal. Sealt saab ka proovigramme küsida. https://t.me/tondev_ru
  8. Veel üks vestlus TONi kohta, millest leidsin kasulikku teavet: https://t.me/TONgramDev
  9. Võistluse esimene etapp: https://contest.com/blockchain
  10. Võistluse teine ​​etapp: https://contest.com/blockchain-2

Allikas: www.habr.com

Lisa kommentaar