O tom, ako napísať a zverejniť inteligentnú zmluvu v Telegram Open Network (TON)

O tom, ako napísať a zverejniť smart kontrakt v TON

O čom je tento článok?

V článku budem hovoriť o tom, ako som sa zúčastnil prvej (z dvoch) blockchainovej súťaže Telegram, nezískal cenu a rozhodol sa zaznamenať svoju skúsenosť do článku, aby neupadol do zabudnutia a možno aj pomohol niekto.

Keďže som nechcel písať abstraktný kód, ale robiť niečo funkčné, pre článok som napísal inteligentnú zmluvu na okamžitú lotériu a webovú stránku, ktorá zobrazuje dáta inteligentnej zmluvy priamo z TON bez použitia medziskladu.

Článok bude užitočný pre tých, ktorí chcú uzavrieť svoj prvý smart kontrakt v TON, ale nevedia, kde začať.

Na príklade lotérie prejdem od inštalácie prostredia k zverejneniu inteligentnej zmluvy, interakcii s ňou a napísaniu webovej stránky na prijímanie a zverejňovanie údajov.

O účasti v súťaži

Minulý október Telegram oznámil blockchainovú súťaž s novými jazykmi Fift и FunC. Bolo potrebné vybrať si zo spísania ľubovoľného z piatich navrhovaných smart kontraktov. Myslel som si, že by bolo fajn urobiť niečo iné, naučiť sa jazyk a niečo vyrobiť, aj keď už v budúcnosti nemusím písať nič iné. Navyše, téma je neustále na perách.

Stojí za to povedať, že som nemal žiadne skúsenosti s vývojom inteligentných zmlúv.

Plánoval som sa zúčastniť až do úplného konca, kým budem môcť a potom napísať recenziu, no hneď na prvý som neuspel. ja napísal peňaženku so zapnutým viacnásobným podpisom FunC a vo všeobecnosti to fungovalo. Bral som to ako základ smart kontrakt na Solidity.

Vtedy som si myslel, že to určite stačí na to, aby som obsadil aspoň nejaké miesto. Výsledkom bolo, že asi 40 zo 60 účastníkov sa stalo víťazmi a ja som medzi nimi nebol. Vo všeobecnosti na tom nie je nič zlé, ale jedna vec mi vadila. V čase vyhlásenia výsledkov ešte nebola urobená kontrola testu na moju zmluvu, pýtal som sa účastníkov chatu, či je ešte niekto, kto ho nemá, neboli.

Keď som si dával pozor na moje správy, o dva dni neskôr porotcovia zverejnili komentár a ja stále nechápem, či náhodou pri posudzovaní neprehliadli moju smart zmluvu, alebo si jednoducho mysleli, že je to také zlé, že to nepotrebuje komentár. Položil som otázku na stránke, ale nedostal som odpoveď. Hoci nie je tajomstvom, kto to súdil, považoval som za zbytočné písať osobné správy.

Veľa času sa venovalo porozumeniu, a tak bolo rozhodnuté napísať článok. Keďže zatiaľ nie je veľa informácií, tento článok pomôže ušetriť čas všetkým záujemcom.

Koncept smart kontraktov v TON

Predtým, ako niečo napíšete, musíte zistiť, z ktorej strany k tejto veci pristupovať. Preto vám teraz poviem, z akých častí sa systém skladá. Presnejšie, aké časti potrebujete vedieť, aby ste mohli spísať aspoň nejakú pracovnú zmluvu.

Zameriame sa na spísanie smart kontraktu a prácu s TON Virtual Machine (TVM), Fift и FunC, takže článok je skôr popisom vývoja bežného programu. Nebudeme sa tu venovať tomu, ako samotná platforma funguje.

Vo všeobecnosti o tom, ako to funguje TVM a jazyk Fift existuje dobrá oficiálna dokumentácia. Počas účasti v súťaži a teraz pri písaní aktuálnej zmluvy som sa na ňu často obracal.

Hlavným jazykom, v ktorom sú písané smart kontrakty, je FunC. Momentálne k tomu nie je žiadna dokumentácia, takže ak chcete niečo napísať, musíte si naštudovať príklady inteligentných zmlúv z oficiálneho úložiska a implementáciu samotného jazyka tam, plus si môžete pozrieť príklady inteligentných zmlúv z posledných dvoch súťaže. Odkazy na konci článku.

Povedzme, že sme už spísali smart kontrakt pre FunC, potom kód skompilujeme do Fift assembleru.

Zostavený smart kontrakt zostáva ešte zverejniť. Ak to chcete urobiť, musíte napísať funkciu Fift, ktorý prevezme kód inteligentnej zmluvy a niektoré ďalšie parametre ako vstup a výstupom bude súbor s príponou .boc (čo znamená „vrecko buniek“) a v závislosti od toho, ako to napíšeme, aj súkromný kľúč a adresu, ktorá sa generuje na základe kódu inteligentnej zmluvy. Gramy už môžete posielať na adresu smart kontraktu, ktorý ešte nebol zverejnený.

Na zverejnenie smart kontraktu v TON prijatých .boc súbor bude potrebné odoslať do blockchainu pomocou ľahkého klienta (viac o tom nižšie). Pred zverejnením je ale potrebné preniesť gramy na vygenerovanú adresu, inak nebude smart kontrakt zverejnený. Po zverejnení môžete komunikovať s inteligentným kontraktom tak, že mu budete posielať správy zvonku (napríklad pomocou ľahkého klienta) alebo zvnútra (napríklad jeden inteligentný kontrakt pošle druhému správu v TON).

Keď pochopíme, ako je kód zverejnený, bude to jednoduchšie. Zhruba vieme, čo chceme napísať a ako bude náš program fungovať. A pri písaní hľadáme, ako je to už implementované v existujúcich smart kontraktoch, prípadne nahliadneme do implementačného kódu Fift и FunC v oficiálnom úložisku alebo si pozrite oficiálnu dokumentáciu.

Veľmi často som hľadal kľúčové slová v telegramovom chate, kde sa zišli všetci účastníci súťaže a zamestnanci Telegramu a stalo sa, že počas súťaže sa tam všetci zišli a začali diskutovať o Fift a FunC. Odkaz na konci článku.

Je čas prejsť od teórie k praxi.

Príprava prostredia pre prácu s TON

Urobil som všetko, čo bude popísané v článku o MacOS a dvakrát som to skontroloval v čistom Ubuntu 18.04 LTS na Docker.

Prvá vec, ktorú musíte urobiť, je stiahnuť a nainštalovať lite-client pomocou ktorého môžete posielať požiadavky do TON.

Pokyny na oficiálnej stránke popisujú proces inštalácie pomerne podrobne a jasne a vynechávajú niektoré detaily. Tu postupujeme podľa pokynov a nainštalujeme chýbajúce závislosti. Nekompiloval som každý projekt sám a nainštaloval som ho z oficiálneho úložiska Ubuntu (na MacOS som používal 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 

Po nainštalovaní všetkých závislostí môžete nainštalovať lite-client, Fift, FunC.

Najprv naklonujeme úložisko TON spolu s jeho závislosťami. Pre pohodlie urobíme všetko v priečinku ~/TON.

cd ~/TON
git clone https://github.com/ton-blockchain/ton.git
cd ./ton
git submodule update --init --recursive

V úložisku sú uložené aj implementácie Fift и FunC.

Teraz sme pripravení zostaviť projekt. Kód úložiska sa naklonuje do priečinka ~/TON/ton. V ~/TON vytvorte priečinok build a zhromaždiť v ňom projekt.

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

Keďže ideme napísať inteligentnú zmluvu, potrebujeme nielen lite-clientavšak Fift с FunC, tak poďme všetko skompilovať. Nie je to rýchly proces, takže čakáme.

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

Ďalej si stiahnite konfiguračný súbor, ktorý obsahuje údaje o uzle, do ktorého lite-client sa pripojí.

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

Zadávanie prvých požiadaviek na TON

Teraz poďme spustiť lite-client.

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

Ak bolo zostavenie úspešné, po spustení uvidíte protokol pripojenia ľahkého klienta k uzlu.

[ 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)
...

Príkaz môžete spustiť help a uvidíte, aké príkazy sú k dispozícii.

help

Uveďme si zoznam príkazov, ktoré použijeme v tomto článku.

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-методы смартконтракта. 

Teraz sme pripravení spísať samotnú zmluvu.

Реализация

Nápad

Ako som písal vyššie, smart kontrakt, ktorý píšeme, je lotéria.

Navyše nejde o lotériu, v ktorej si musíte kúpiť tiket a čakať hodinu, deň alebo mesiac, ale o okamžitú lotériu, v ktorej sa používateľ prenesie na zmluvnú adresu. N gramov a okamžite to dostane späť 2 * N gramov alebo stratí. Pravdepodobnosť výhry dosiahneme asi 40%. Ak nie je dostatok gramov na platbu, transakciu budeme považovať za dobitie.

Okrem toho je dôležité, aby stávky bolo možné vidieť v reálnom čase a vo vhodnej forme, aby používateľ okamžite pochopil, či vyhral alebo prehral. Preto musíte urobiť web, ktorý bude zobrazovať stávky a výsledky priamo z TON.

Spísanie inteligentnej zmluvy

Pre pohodlie som zvýraznil kód pre FunC, plugin sa dá nájsť a nainštalovať vo vyhľadávaní kódu Visual Studio, ak zrazu chcete niečo pridať, plugin som sprístupnil verejnosti. Tiež niekto predtým vytvoril plugin pre prácu s Fift, môžete si ho tiež nainštalovať a nájsť vo VSC.

Okamžite si vytvoríme úložisko, kde budeme odovzdávať medzivýsledky.

Aby sme si uľahčili život, napíšeme inteligentnú zmluvu a budeme ju testovať lokálne, kým nebude pripravená. Až potom to zverejníme v TON.

Inteligentná zmluva má dve externé metódy, ku ktorým je možné pristupovať. Najprv, recv_external() táto funkcia sa vykoná, keď príde požiadavka na zmluvu z vonkajšieho sveta, teda nie od TON, napríklad keď si sami vygenerujeme správu a pošleme ju cez lite-clienta. po druhé, recv_internal() vtedy sa v rámci samotnej spoločnosti TON akákoľvek zmluva odvoláva na našu. V oboch prípadoch môžete funkcii odovzdať parametre.

Začnime jednoduchým príkladom, ktorý bude fungovať, ak bude zverejnený, ale nie je v ňom žiadna funkčná záťaž.

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

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

Tu musíme vysvetliť, čo to je slice. Všetky údaje uložené v TON Blockchain sú kolekciou TVM cell alebo jednoducho cell, v takejto bunke môžete uložiť až 1023 bitov dát a až 4 odkazy na ďalšie bunky.

TVM cell slice alebo slice toto je súčasť existujúceho cell sa používa na analýzu, neskôr sa to vyjasní. Pre nás je hlavné, že vieme prestupovať slice a v závislosti od typu správy spracovať údaje v recv_external() alebo recv_internal().

impure — kľúčové slovo, ktoré označuje, že funkcia upravuje údaje inteligentnej zmluvy.

Uložme kód zmluvy lottery-code.fc a zostaviť.

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

Význam príznakov je možné zobraziť pomocou príkazu

~/TON/build/crypto/func -help

Kompilovali sme päťkový assemblerový kód 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

Dá sa spustiť lokálne, na to pripravíme prostredie.

Všimnite si, že prvý riadok spája Asm.fif, toto je kód napísaný v Fift pre assembler Fift.

Keďže chceme inteligentnú zmluvu spustiť a otestovať lokálne, vytvoríme súbor lottery-test-suite.fif a skopírujte tam skompilovaný kód a nahraďte v ňom posledný riadok, ktorý zapíše kód inteligentnej zmluvy do konštanty codea potom ho preniesť do virtuálneho počítača:

"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

Zatiaľ sa to zdá jasné, teraz do toho istého súboru pridáme kód, ktorý použijeme na spustenie TVM.

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 zaznamenávame kontext, teda údaje, s ktorými sa TVM (alebo stav siete) spustí. Aj počas súťaže jeden z vývojárov ukázal, ako sa tvorí c7 a skopíroval som. V tomto článku možno budeme musieť niečo zmeniť rand_seed pretože generovanie náhodného čísla závisí od toho a ak sa nezmení, vždy sa vráti rovnaké číslo.

recv_internal и recv_external konštanty s hodnotami 0 a -1 budú zodpovedné za volanie zodpovedajúcich funkcií v inteligentnom kontrakte.

Teraz sme pripravení vytvoriť prvý test pre náš prázdny smart kontrakt. Pre prehľadnosť zatiaľ všetky testy pridáme do toho istého súboru lottery-test-suite.fif.

Vytvorme premennú storage a napíšte do nej prázdnu cell, toto bude úložisko inteligentných zmlúv.

message Toto je správa, ktorú prenesieme do inteligentného kontaktu zvonku. Tiež ho zatiaľ vyprázdnime.

variable storage 
<b b> storage ! 

variable message 
<b b> message ! 

Keď máme pripravené konštanty a premenné, spustíme TVM pomocou príkazu runvmctx a odovzdať vytvorené parametre na vstup.

message @ 
recv_external 
code 
storage @ 
c7 
runvmctx 

Nakoniec sa nám to podarí takto medzikód pre Fift.

Teraz môžeme spustiť výsledný kód.

export FIFTPATH=~/TON/ton/crypto/fift/lib // выполняем один раз для удобства 
~/TON/build/crypto/fift -s lottery-test-suite.fif 

Program by mal bežať bez chýb a vo výstupe uvidíme protokol vykonania:

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

Skvelé, napísali sme prvú pracovnú verziu smart kontraktu.

Teraz musíme pridať funkčnosť. Najprv sa poďme zaoberať správami, ktoré prichádzajú z vonkajšieho sveta recv_external()

Samotný vývojár si vyberie formát správy, ktorý môže zmluva akceptovať.

Ale obyčajne

  • po prvé, chceme chrániť našu zmluvu pred vonkajším svetom a urobiť ju tak, aby do nej mohol posielať externé správy iba jej vlastník.
  • po druhé, keď pošleme platnú správu do TON, chceme, aby sa to stalo presne raz a keď tú istú správu pošleme znova, smart kontrakt ju odmietne.

Takmer každá zmluva teda rieši tieto dva problémy, keďže naša zmluva akceptuje externé správy, musíme sa postarať aj o to.

Urobíme to v opačnom poradí. Najprv vyriešme problém s opakovaním, ak zmluva už takúto správu dostala a spracovala, druhýkrát ju nevykoná. A potom problém vyriešime tak, aby správy do smart kontraktu mohol posielať len určitý okruh ľudí.

Existujú rôzne spôsoby, ako vyriešiť problém s duplicitnými správami. Takto to urobíme. V smart kontrakte inicializujeme počítadlo prijatých správ s počiatočnou hodnotou 0. V každej správe do smart kontraktu pripočítame aktuálnu hodnotu počítadla. Ak sa hodnota počítadla v správe nezhoduje s hodnotou v inteligentnom kontrakte, tak ho nespracujeme, ak áno, tak ho spracujeme a zvýšime počítadlo v inteligentnom kontrakte o 1.

Vráťme sa k lottery-test-suite.fif a pridajte k tomu druhý test. Ak pošleme nesprávne číslo, kód by mal vyvolať výnimku. Nechajte napríklad údaje zmluvy uložiť 166 a my pošleme 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"

Poďme spustiť.

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

A uvidíme, že test sa vykoná s chybou.

[ 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

V tejto fáze lottery-test-suite.fif by mal vyzerať по ссылке.

Teraz pridajte logiku počítadla do inteligentnej zmluvy 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 leží správa, ktorú posielame.

Prvá vec, ktorú urobíme, je skontrolovať, či správa obsahuje údaje, ak nie, jednoducho skončíme.

Ďalej analyzujeme správu. in_msg~load_uint(32) načíta číslo 165, 32-bit unsigned int z prenášanej správy.

Ďalej načítame 32 bitov z úložiska inteligentnej zmluvy. Skontrolujeme, či sa načítané číslo zhoduje s odovzdaným, ak nie, vyvoláme výnimku. V našom prípade, keďže prihrávame nesúlad, treba hodiť výnimku.

Teraz poďme skompilovať.

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

Skopírujte výsledný kód do lottery-test-suite.fif, nezabudnite nahradiť posledný riadok.

Skontrolujeme, či test prešiel:

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

Práve tu Môžete vidieť zodpovedajúce odovzdanie s aktuálnymi výsledkami.

Všimnite si, že je nepohodlné neustále kopírovať skompilovaný kód smart kontraktu do súboru s testami, preto napíšeme skript, ktorý nám kód zapíše do konštanty a skompilovaný kód jednoducho pripojíme k našim testom pomocou "include".

Vytvorte súbor v priečinku projektu build.sh s nasledujúcim obsahom.

#!/bin/bash

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

Urobme to spustiteľné.

chmod +x ./build.sh

Teraz stačí spustiť náš skript na zostavenie zmluvy. Ale okrem toho to musíme zapísať do konštanty code. Vytvoríme teda nový súbor lotter-compiled-for-test.fif, ktorý zaradíme do súboru lottery-test-suite.fif.

Pridajme kód skirpt do sh, ktorý jednoducho duplikuje skompilovaný súbor lotter-compiled-for-test.fif a zmeňte v ňom posledný riadok.

# 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

Teraz pre kontrolu spustite výsledný skript a vygeneruje sa súbor lottery-compiled-for-test.fif, ktorý zaradíme do nášho lottery-test-suite.fif

В lottery-test-suite.fif vymažte kód zmluvy a pridajte riadok "lottery-compiled-for-test.fif" include.

Vykonávame testy, aby sme skontrolovali, či prešli.

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

Skvelé, teraz, aby sme zautomatizovali spustenie testov, vytvorte súbor test.sh, ktorý sa najskôr vykoná build.sha potom spustite testy.

touch test.sh
chmod +x test.sh

Píšeme dovnútra

./build.sh 

echo "nCompilation completedn"

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

Urobme to test.sh a spustite ho, aby ste sa uistili, že testy fungujú.

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

Skontrolujeme, či je zmluva zostavená a testy sú vykonané.

Skvelé, teraz na štarte test.sh Testy budú zostavené a okamžite spustené. Tu je odkaz na zaviazať sa.

Dobre, než budeme pokračovať, urobme ešte jednu vec pre pohodlie.

Vytvorme priečinok build kde uložíme skopírovanú zmluvu a jej klon zapísaný do konštanty lottery-compiled.fif, lottery-compiled-for-test.fif. Vytvorme si aj priečinok test kde bude uložený testovací súbor? lottery-test-suite.fif a potenciálne ďalšie podporné súbory. Odkaz na príslušné zmeny.

Pokračujme vo vývoji inteligentnej zmluvy.

Ďalej by mal nasledovať test, ktorý skontroluje, či je správa prijatá a počítadlo sa v obchode aktualizuje, keď pošleme správne číslo. Ale to urobíme neskôr.

Teraz sa zamyslime nad tým, aká dátová štruktúra a aké dáta musia byť uložené v smart kontrakte.

Popíšem všetko, čo skladujeme.

`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` переменная типа словарь, хранит последние двадцать ставок. 

Ďalej musíte napísať dve funkcie. Zavolajme prvému pack_state(), ktorý zabalí dáta pre následné uloženie do úložiska smart kontraktov. Zavolajme tomu druhému unpack_state() bude čítať a vracať dáta z úložiska.

_ 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;
}

Tieto dve funkcie pridávame na začiatok smart kontraktu. Vyjde to takto medzivýsledok.

Na uloženie údajov budete musieť zavolať vstavanú funkciu set_data() a bude zapisovať dáta z pack_state() v úložisku inteligentných zmlúv.

cell packed_state = pack_state(arg_1, .., arg_n); 
set_data(packed_state);

Teraz, keď máme pohodlné funkcie na zápis a čítanie dát, môžeme pokračovať.

Musíme skontrolovať, či správa prichádzajúca zvonku je podpísaná vlastníkom zmluvy (alebo iným používateľom, ktorý má prístup k súkromnému kľúču).

Keď zverejníme inteligentnú zmluvu, môžeme ju inicializovať s údajmi, ktoré potrebujeme v úložisku, ktoré sa uložia pre budúce použitie. Verejný kľúč tam zaznamenáme, aby sme si mohli overiť, či bola prichádzajúca správa podpísaná príslušným súkromným kľúčom.

Pred pokračovaním si vytvorte súkromný kľúč a zapíšme ho test/keys/owner.pk. Ak to chcete urobiť, spustite Fift v interaktívnom režime a vykonajte štyri príkazy.

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

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

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

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

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

Vytvorme priečinok keys vnútri priečinka test a napíšte tam súkromný kľúč.

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

Vidíme súbor v aktuálnom priečinku owner.pk.

Odstránime verejný kľúč zo zásobníka a v prípade potreby ho môžeme získať zo súkromného.

Teraz musíme napísať overenie podpisu. Začnime testom. Najprv pomocou funkcie načítame súkromný kľúč zo súboru file>B a zapíšte ho do premennej owner_private_key, potom pomocou funkcie priv>pub previesť súkromný kľúč na verejný kľúč a zapísať výsledok 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 !

Budeme potrebovať oba kľúče.

Úložisko smart kontraktov inicializujeme ľubovoľnými údajmi v rovnakom poradí ako vo funkcii pack_state()a zapíšte ho do premennej 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 !

Ďalej vytvoríme podpísanú správu, bude obsahovať iba podpis a hodnotu počítadla.

Najprv vytvoríme údaje, ktoré chceme preniesť, potom ich podpíšeme súkromným kľúčom a nakoniec vygenerujeme podpísanú správu.

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 !  

V dôsledku toho sa správa, ktorú pošleme do smart kontraktu, zaznamená do premennej message_to_send, o funkciách hashu, ed25519_sign_uint môžeš čítať v dokumentácii Piaty.

A na spustenie testu zavoláme znova.

message_to_send @ 
recv_external 
code 
storage @
c7
runvmctx

Páči sa ti to Súbor s testami by mal v tejto fáze vyzerať takto.

Spustíme test a zlyhá, takže zmeníme smart kontrakt tak, aby mohol prijímať správy v tomto formáte a overovať podpis.

Najprv spočítame 512 bitov podpisu zo správy a zapíšeme ho do premennej, potom spočítame 32 bitov premennej čítača.

Keďže máme funkciu na čítanie údajov z úložiska smart kontraktov, využijeme ju.

Nasleduje kontrola preneseného počítadla s úložiskom a kontrola podpisu. Ak sa niečo nezhoduje, vyhodíme výnimku s príslušným kódom.

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

Príslušný záväzok tu.

Spustite testy a uvidíme, že druhý test zlyhá. Z dvoch dôvodov nie je v správe dostatok bitov a v úložisku nie je dostatok bitov, takže kód pri analýze padá. Do správy, ktorú posielame, musíme pridať podpis a skopírovať úložisko z posledného testu.

V druhom teste pridáme podpis správy a zmeníme úložisko smart kontraktov. Páči sa ti to súbor s testami vyzerá momentálne.

Napíšme štvrtý test, v ktorom pošleme správu podpísanú cudzím súkromným kľúčom. Vytvorme ďalší súkromný kľúč a uložíme ho do súboru not-owner.pk. Správu podpíšeme týmto súkromným kľúčom. Spustite testy a uistite sa, že všetky testy prejdú. Zaviazať sa v tejto chvíli.

Teraz môžeme konečne prejsť k implementácii logiky inteligentnej zmluvy.
В recv_external() budeme akceptovať dva typy správ.

Keďže naša zmluva bude kumulovať straty hráčov, tieto peniaze musia byť prevedené na tvorcu lotérie. Adresa peňaženky tvorcu lotérie je zaznamenaná v úložisku pri vytvorení zmluvy.

Pre každý prípad potrebujeme možnosť zmeniť adresu, na ktorú posielame gramy porazených. Mali by sme byť tiež schopní poslať gramy z lotérie na adresu majiteľa.

Začnime tým prvým. Napíšme najprv test, ktorý preverí, že po odoslaní správy smart kontrakt uložil novú adresu do úložiska. Upozorňujeme, že v správe okrem prepážky a novej adresy prenášame aj action 7-bitové celé nezáporné číslo, v závislosti od neho si vyberieme spôsob spracovania správy v smart kontrakte.

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

V teste môžete vidieť, ako sa deserializuje úložisko smartcontract storage v Piatej. Deserializácia premenných je popísaná v dokumentácii Fift.

Potvrdiť odkaz s pridaným cestom.

Spustite test a uistite sa, že zlyhá. Teraz pridajme logiku na zmenu adresy majiteľa lotérie.

V inteligentnej zmluve pokračujeme v analýze message, prečítajte si action. Pripomeňme, že budeme mať dve action: zmeniť adresu a odoslať gramy.

Potom načítame novú adresu vlastníka zmluvy a uložíme ju na sklad.
Spustíme testy a uvidíme, že tretí test zlyhá. Padá kvôli tomu, že zmluva teraz dodatočne analyzuje 7 bitov zo správy, ktoré v teste chýbajú. Pridajte do správy neexistujúcu action. Urobme testy a uvidíme, že všetko prejde. tu zaviazať sa k zmenám. Skvelé.

Teraz napíšme logiku na odoslanie určeného počtu gramov na predtým uloženú adresu.

Najprv si napíšeme test. Budeme písať dva testy, jeden, keď nie je dostatočná rovnováha, druhý, keď by malo všetko úspešne prejsť. Testy je možné zobraziť v tomto záväzku.

Teraz pridajme kód. Najprv si napíšme dve pomocné metódy. Prvou metódou získania je zistiť aktuálny zostatok inteligentnej zmluvy.

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

A druhý je na posielanie gramov na ďalší smart kontrakt. Túto metódu som úplne skopíroval z inej inteligentnej zmluvy.

() 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
}

Pridajme tieto dve metódy do smart kontraktu a napíšme logiku. Najprv analyzujeme počet gramov zo správy. Ďalej skontrolujeme zostatok, ak nestačí, vyvoláme výnimku. Ak je všetko v poriadku, pošleme gramy na uloženú adresu a aktualizujeme počítadlo.

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

Páči sa ti to momentálne vyzerá ako inteligentná zmluva. Spustite testy a uistite sa, že prejdú.

Mimochodom, za každú spracovanú správu sa zo smart kontraktu odpočítava provízia. Aby správy inteligentnej zmluvy vykonali požiadavku, po základných kontrolách musíte zavolať accept_message().

Teraz prejdime k interným správam. V skutočnosti budeme akceptovať iba gramy a hráčovi pošleme späť dvojnásobnú sumu, ak vyhrá, a tretinu majiteľovi, ak prehrá.

Najprv si napíšeme jednoduchý test. Na to potrebujeme testovaciu adresu smart kontraktu, z ktorého vraj posielame gramy do smart kontraktu.

Adresa inteligentnej zmluvy pozostáva z dvoch čísel, 32-bitového celého čísla zodpovedného za pracovný reťazec a 256-bitového nezáporného celočíselného jedinečného čísla účtu v tomto pracovnom reťazci. Napríklad -1 a 12345, toto je adresa, ktorú uložíme do súboru.

Skopíroval som funkciu na uloženie adresy z 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

Pozrime sa, ako táto funkcia funguje, vďaka čomu pochopíme, ako funguje Fift. Spustite Fift v interaktívnom režime.

~/TON/build/crypto/fift -i 

Najprv do zásobníka vložíme -1, 12345 a názov budúceho súboru "sender.addr":

-1 12345 "sender.addr" 

Ďalším krokom je vykonanie funkcie -rot, ktorý posunie zásobník tak, že v hornej časti zásobníka je jedinečné číslo smart kontraktu:

"sender.addr" -1 12345

256 u>B konvertuje 256-bitové nezáporné celé číslo na bajty.

"sender.addr" -1 BYTES:0000000000000000000000000000000000000000000000000000000000003039

swap vymení dva horné prvky zásobníka.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 -1

32 i>B konvertuje 32-bitové celé číslo na bajty.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 BYTES:FFFFFFFF

B+ spája dve sekvencie bajtov.

 "sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF

znovu swap.

BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF "sender.addr" 

A nakoniec sa bajty zapíšu do súboru B>file. Potom je náš zásobník prázdny. Zastavujeme Fift. V aktuálnom priečinku bol vytvorený súbor sender.addr. Presuňme súbor do vytvoreného priečinka test/addresses/.

Napíšme si jednoduchý test, ktorý pošle gramy na smart kontrakt. Tu je záväzok.

Teraz sa pozrime na logiku lotérie.

Prvá vec, ktorú urobíme, je skontrolovať správu bounced alebo nie, ak bounced, potom to ignorujeme. bounced znamená, že zmluva vráti gramy, ak sa vyskytne nejaká chyba. Ak sa náhle vyskytne chyba, gramy nevrátime.

Skontrolujeme, ak je zostatok menej ako pol gramu, potom správu jednoducho prijmeme a ignorujeme ju.

Ďalej analyzujeme adresu smart kontraktu, z ktorého prišla správa.

Dáta načítame z úložiska a následne vymažeme staré stávky z histórie, ak ich je viac ako dvadsať. Pre pohodlie som napísal tri ďalšie funkcie pack_order(), unpack_order(), remove_old_orders().

Ďalej sa pozrieme, či zostatok nestačí na platbu, potom zvážime, že nejde o stávku, ale o doplnenie a uložíme doplnenie v orders.

Potom konečne podstata inteligentnej zmluvy.

Najprv, ak hráč prehrá, uložíme ho do histórie stávok a ak je suma vyššia ako 3 gramy, pošleme 1/3 majiteľovi smart kontraktu.

Ak hráč vyhrá, pošleme dvojnásobok sumy na adresu hráča a následne uložíme informácie o stávke do histórie.

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

To je všetko. Zodpovedajúci záväzok.

Teraz zostáva už len jednoduché, vytvorme si metódy get, aby sme mohli získať informácie o stave kontraktu z vonkajšieho sveta (v skutočnosti čítať dáta z ich úložiska smart kontraktov).

Pridajme metódy get. O tom, ako získať informácie o smart kontrakte, napíšeme nižšie.

Zabudol som pridať aj kód, ktorý spracuje úplne prvú požiadavku, ktorá nastane pri zverejnení smart kontraktu. Zodpovedajúci záväzok. A ďalej opravené bug s odoslaním 1/3 sumy na účet majiteľa.

Ďalším krokom je zverejnenie inteligentnej zmluvy. Vytvorme priečinok requests.

Ako základ som vzal kód publikácie simple-wallet-code.fc ktorý nájdete v oficiálnom úložisku.

Niečo, čo stojí za pozornosť. Vygenerujeme inteligentné úložisko zmlúv a vstupnú správu. Potom sa vygeneruje adresa smart kontraktu, to znamená, že adresa je známa ešte pred zverejnením v TON. Ďalej musíte na túto adresu poslať niekoľko gramov a až potom musíte odoslať súbor so samotnou inteligentnou zmluvou, pretože sieť berie províziu za uloženie inteligentnej zmluvy a operácií v nej (validátori, ktorí ukladajú a vykonávajú inteligentné zmluvy). Kód si môžete pozrieť tu.

Ďalej spustíme publikačný kód a dostaneme lottery-query.boc súbor a adresu inteligentnej zmluvy.

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

Vygenerované súbory nezabudnite uložiť: lottery-query.boc, lottery.addr, lottery.pk.

V protokoloch vykonávania okrem iného uvidíme adresu smart kontraktu.

new wallet address = 0:044910149dbeaf8eadbb2b28722e7d6a2dc6e264ec2f1d9bebd6fb209079bc2a 
(Saving address to file lottery.addr)
Non-bounceable address (for init): 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd
Bounceable address (for later access): kQAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8KpFY

Len pre zaujímavosť, poďme požiadať TON

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

A uvidíme, že účet s touto adresou je prázdny.

account state is empty

Posielame na adresu 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd 2 Gram a po niekoľkých sekundách vykonáme rovnaký príkaz. Na odoslanie gramov používam oficiálna peňaženka, a môžete požiadať niekoho z chatu o testovacie gramy, o ktorých budem hovoriť na konci článku.

> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Vyzerá to ako neinicializované (state:account_uninit) smart kontrakt s rovnakou adresou a zostatkom 1 000 000 000 nanogramov.

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

Teraz zverejníme smart kontrakt. Poďme spustiť lite-client a spustiť.

> 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 

Skontrolujeme, či bola zmluva zverejnená.

> last
> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Okrem iného dostaneme.

  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

To vidíme account_active.

Zodpovedajúci záväzok so zmenami tu.

Teraz vytvoríme požiadavky na interakciu s inteligentným kontraktom.

Presnejšie, prvý necháme na zmenu adresy ako samostatnú prácu a druhý urobíme na posielanie gramov na adresu majiteľa. V skutočnosti budeme musieť urobiť to isté ako v teste na odosielanie gramov.

Toto je správa, ktorú pošleme do smart kontraktu, kde msg_seqno 165, action 2 a 9.5 gramu na odoslanie.

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

Nezabudnite správu podpísať svojím súkromným kľúčom lottery.pk, ktorý bol vygenerovaný skôr pri vytváraní smart kontraktu. Tu je príslušný commit.

Prijímanie informácií z inteligentnej zmluvy pomocou metód get

Teraz sa pozrime na to, ako spustiť metódy inteligentného získania zmlúv.

Spustiť lite-client a spustite metódy get, ktoré sme napísali.

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

В result obsahuje hodnotu, ktorú funkcia vracia balance() z našej inteligentnej zmluvy.
To isté urobíme pre niekoľko ďalších metód.

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

Spýtajme sa na vašu históriu stávok.

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

Použijeme lite-client a získame metódy na zobrazenie informácií o smart kontrakte na stránke.

Zobrazenie údajov inteligentnej zmluvy na webovej stránke

Napísal som jednoduchú webovú stránku v Pythone, aby som pohodlne zobrazoval údaje zo smart kontraktu. Tu sa tomu nebudem podrobne venovať a stránku zverejním v jednom záväzku.

Požiadavky na TON sú vyrobené z Python skrz lite-client. Pre pohodlie je stránka zabalená v Dockeri a zverejnená v službe Google Cloud. Odkaz.

Pokúša sa

Teraz tam skúsme poslať gramy na doplnenie z peňaženka. Pošleme 40 gramov. A urobme pár stávok pre jasnosť. Vidíme, že stránka zobrazuje históriu stávok, aktuálne percento výhry a ďalšie užitočné informácie.

Vidímeže prvý sme vyhrali, druhý prehrali.

Doslov

Článok sa ukázal byť oveľa dlhší ako som čakal, možno mohol byť kratší, alebo možno len pre človeka, ktorý o TON nič nevie a chce napísať a zverejniť nie práve jednoduchý smart kontrakt s možnosťou interakcie s to. Možno by sa niektoré veci dali vysvetliť jednoduchšie.

Možno by sa niektoré aspekty implementácie dali urobiť efektívnejšie a elegantnejšie, ale potom by príprava článku zabrala ešte viac času. Je tiež možné, že som niekde urobil chybu alebo som niečomu nerozumel, takže ak robíte niečo vážne, musíte sa spoľahnúť na oficiálnu dokumentáciu alebo oficiálny repozitár s TON kódom.

Je potrebné poznamenať, že keďže samotný TON je stále v aktívnom štádiu vývoja, môžu nastať zmeny, ktoré prerušia niektorý z krokov v tomto článku (čo sa stalo počas môjho písania, už je to opravené), ale všeobecný prístup je nepravdepodobné, že sa zmení.

Nebudem hovoriť o budúcnosti TON. Možno sa platforma stane niečím veľkým a mali by sme venovať čas jej štúdiu a vyplniť medzeru našimi produktmi.

Existuje aj Váh od Facebooku, ktorý má potenciálne publikum používateľov väčšie ako TON. O Váhach neviem takmer nič, súdiac podľa fóra je tam oveľa väčšia aktivita ako v komunite TON. Aj keď vývojári a komunita TON sú skôr underground, čo je tiež v pohode.

referencie

  1. Oficiálna dokumentácia TON: https://test.ton.org
  2. Oficiálne úložisko TON: https://github.com/ton-blockchain/ton
  3. Oficiálna peňaženka pre rôzne platformy: https://wallet.ton.org
  4. Úložisko inteligentných zmlúv z tohto článku: https://github.com/raiym/astonished
  5. Odkaz na webovú stránku inteligentnej zmluvy: https://ton-lottery.appspot.com
  6. Úložisko pre rozšírenie pre Visual Studio Code for FunC: https://github.com/raiym/func-visual-studio-plugin
  7. Rozhovor o TON v telegrame, ktorý skutočne pomohol prísť na to v počiatočnej fáze. Myslím, že nebude chybou, ak poviem, že každý, kto niečo napísal pre TON, je tam. Môžete tam požiadať aj o testovacie gramy. https://t.me/tondev_ru
  8. Ďalší rozhovor o TON, v ktorom som našiel užitočné informácie: https://t.me/TONgramDev
  9. Prvá fáza súťaže: https://contest.com/blockchain
  10. Druhá fáza súťaže: https://contest.com/blockchain-2

Zdroj: hab.com

Pridať komentár