O tome kako napisati i objaviti pametni ugovor u Telegram Open Network (TON)

O tome kako napisati i objaviti pametni ugovor u TON-u

O čemu je ovaj članak?

U članku ću govoriti o tome kako sam sudjelovao u prvom (od dva) Telegram blockchain natjecanju, nisam uzeo nagradu i odlučio svoje iskustvo zabilježiti u članku kako ne bi palo u zaborav i možda pomoglo netko.

Budući da nisam želio pisati apstraktni kod, već učiniti nešto što radi, za članak sam napisao pametni ugovor za trenutnu lutriju i web stranicu koja prikazuje podatke pametnog ugovora izravno iz TON-a bez korištenja međupohrane.

Članak će biti koristan onima koji žele napraviti svoj prvi pametni ugovor u TON-u, ali ne znaju odakle početi.

Koristeći lutriju kao primjer, prijeći ću od instaliranja okruženja do objave pametnog ugovora, interakcije s njim i pisanja web stranice za primanje i objavljivanje podataka.

O sudjelovanju u natječaju

Prošlog listopada Telegram je najavio blockchain natjecanje s novim jezicima Fift и FunC. Bilo je potrebno odabrati pisanje bilo kojeg od pet predloženih pametnih ugovora. Mislio sam da bi bilo lijepo raditi nešto drugačije, naučiti jezik i napraviti nešto, čak i ako ne budem morao pisati ništa drugo u budućnosti. Osim toga, tema je stalno na usnama.

Vrijedno je reći da nisam imao iskustva s razvojem pametnih ugovora.

Planirao sam sudjelovati do samog kraja dok ne budem mogao i onda napisati recenzentski članak, ali nisam uspio odmah na prvom. ja napisao novčanik s uključenim višestrukim potpisom FunC i općenito je djelovalo. Uzeo sam to kao osnovu pametni ugovor na Solidityju.

Tada sam mislio da je to sigurno dovoljno da zauzmem barem neko nagradno mjesto. Kao rezultat toga, oko 40 od ​​60 sudionika postali su dobitnici nagrada, a ja nisam bio među njima. Općenito, nema ništa loše u tome, ali me jedna stvar zasmetala. U trenutku objave rezultata nije bio obavljen pregled testa za moj ugovor, pitao sam sudionike chata ima li još netko da ga nema, nije bilo.

Očito obraćajući pažnju na moje poruke, dva dana kasnije suci su objavili komentar i još mi nije jasno je li im slučajno promakao moj pametni ugovor tijekom ocjenjivanja ili su jednostavno mislili da je toliko loš da ne treba komentar. Postavio sam pitanje na stranici, ali nisam dobio odgovor. Iako nije tajna tko je presudio, smatrao sam nepotrebnim pisati osobne poruke.

Potrošeno je puno vremena na razumijevanje, pa je odlučeno napisati članak. Budući da još nema puno informacija, članak će pomoći uštedjeti vrijeme svima zainteresiranima.

Koncept pametnih ugovora u TON-u

Prije nego bilo što napišete, morate shvatiti s koje strane pristupiti ovoj stvari. Stoga ću vam sada reći od kojih se dijelova sastoji sustav. Točnije, koje dijelove trebate znati da biste napisali barem nekakav ugovor o djelu.

Usredotočit ćemo se na pisanje pametnog ugovora i rad s njim TON Virtual Machine (TVM), Fift и FunC, pa je članak više poput opisa razvoja običnog programa. Ovdje se nećemo zadržavati na tome kako sama platforma funkcionira.

Općenito o tome kako to radi TVM i jezik Fift postoji dobra službena dokumentacija. Tijekom sudjelovanja u natječaju i sada dok pišem trenutni ugovor često sam joj se obraćala.

Glavni jezik na kojem su napisani pametni ugovori je FunC. O tome trenutno ne postoji nikakva dokumentacija, pa da biste nešto napisali morate proučiti primjere pametnih ugovora iz službenog repozitorija i implementaciju samog jezika tamo, plus možete pogledati primjere pametnih ugovora iz prošla dva natjecanja. Linkovi na kraju članka.

Recimo da smo već napisali pametni ugovor za FunC, nakon toga kompajliramo kod u Fift asembler.

Sastavljeni pametni ugovor ostaje za objavu. Da biste to učinili, morate napisati funkciju Fift, koji će uzeti kod pametnog ugovora i neke druge parametre kao ulaz, a izlaz će biti datoteka s ekstenzijom .boc (što znači “vrećica ćelija”), te, ovisno o tome kako to napišemo, privatni ključ i adresa, koja se generira na temelju koda pametnog ugovora. Grame već možete poslati na adresu pametnog ugovora koji još nije objavljen.

Za objavu pametnog ugovora u TON primljeno .boc datoteka će se morati poslati u blockchain pomoću laganog klijenta (više o tome u nastavku). Ali prije objave morate prenijeti gramove na generiranu adresu, inače pametni ugovor neće biti objavljen. Nakon objave, možete komunicirati s pametnim ugovorom tako da mu šaljete poruke izvana (na primjer, korištenjem laganog klijenta) ili iznutra (na primjer, jedan pametni ugovor šalje drugom poruku unutar TON-a).

Jednom kada shvatimo kako se kod objavljuje, postaje lakše. Otprilike znamo što želimo napisati i kako će naš program raditi. I dok pišemo, tražimo kako je to već implementirano u postojećim pametnim ugovorima ili gledamo implementacijski kod Fift и FunC u službenom repozitoriju, ili pogledajte u službenoj dokumentaciji.

Vrlo često sam tražio ključne riječi u Telegram chatu gdje su se okupljali svi sudionici natjecanja i zaposlenici Telegrama, i dogodilo se da su se tijekom natjecanja svi skupili i počeli raspravljati o Fiftu i FunC-u. Link na kraju članka.

Vrijeme je da prijeđemo s teorije na praksu.

Priprema okruženja za rad s TON-om

Napravio sam sve što će biti opisano u članku o MacOS-u i dva puta provjerio u čistom Ubuntu 18.04 LTS na Dockeru.

Prvo što trebate učiniti je preuzeti i instalirati lite-client s kojim možete slati zahtjeve na TON.

Upute na službenim stranicama dosta detaljno i jasno opisuju postupak instalacije te izostavljaju neke detalje. Ovdje slijedimo upute, usput instalirajući ovisnosti koje nedostaju. Nisam sam kompajlirao svaki projekt i instalirao iz službenog repozitorija Ubuntu (na MacOS-u koji sam koristio 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 

Nakon što su sve ovisnosti instalirane, možete instalirati lite-client, Fift, FunC.

Prvo, kloniramo TON repozitorij zajedno s njegovim ovisnostima. Radi praktičnosti, sve ćemo raditi u mapi ~/TON.

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

Repozitorij također pohranjuje implementacije Fift и FunC.

Sada smo spremni sastaviti projekt. Kod repozitorija je kloniran u mapu ~/TON/ton. U ~/TON stvoriti mapu build i sakupite projekt u njemu.

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

Budući da ćemo napisati pametni ugovor, ne trebamo samo lite-clientAli Fift с FunC, pa idemo sve kompajlirati. To nije brz proces, pa čekamo.

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

Zatim preuzmite konfiguracijsku datoteku koja sadrži podatke o čvoru na koji lite-client će se povezati.

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

Izrada prvih zahtjeva za TON

Sada pokrenimo lite-client.

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

Ako je izgradnja bila uspješna, nakon pokretanja vidjet ćete zapisnik veze laganog klijenta s čvorom.

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

Možete pokrenuti naredbu help i vidjeti koje su naredbe dostupne.

help

Nabrojimo naredbe koje ćemo koristiti u ovom članku.

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

Sada smo spremni za pisanje samog ugovora.

Provedba

Ideja

Kao što sam već napisao, pametni ugovor koji pišemo je lutrija.

Štoviše, ovo nije lutrija u kojoj treba kupiti listić i čekati sat, dan ili mjesec, već instant lutrija u kojoj korisnik prebacuje na ugovornu adresu N grama, i odmah ga dobije natrag 2 * N grama ili gubi. Napravit ćemo vjerojatnost dobitka na oko 40%. Ako nema dovoljno grama za plaćanje, transakciju ćemo smatrati dopunom.

Štoviše, važno je da se oklade mogu vidjeti u stvarnom vremenu iu prikladnom obliku, tako da korisnik može odmah shvatiti je li dobio ili izgubio. Stoga morate napraviti web stranicu koja će prikazivati ​​oklade i rezultate izravno iz TON-a.

Pisanje pametnog ugovora

Radi praktičnosti, istaknuo sam kôd za FunC; dodatak se može pronaći i instalirati u pretraživanju Visual Studio Code; ako odjednom želite nešto dodati, učinio sam dodatak javno dostupnim. Također, netko je prije napravio plugin za rad s Fiftom, također ga možete instalirati i pronaći u VSC-u.

Kreirajmo odmah spremište u koje ćemo upisati međurezultate.

Kako bismo si olakšali život, napisat ćemo pametni ugovor i testirati ga lokalno dok ne bude spreman. Tek nakon toga ćemo ga objaviti u TON-u.

Pametni ugovor ima dvije vanjske metode kojima se može pristupiti. Prvi, recv_external() ova funkcija se izvršava kada zahtjev na ugovor dolazi iz vanjskog svijeta, odnosno ne iz TON-a, na primjer, kada mi sami generiramo poruku i šaljemo je preko lite-klijenta. Drugi, recv_internal() to je kada se, unutar samog TON-a, bilo koji ugovor odnosi na naš. U oba slučaja možete proslijediti parametre funkciji.

Počnimo s jednostavnim primjerom koji će raditi ako se objavi, ali u njemu nema funkcionalnog opterećenja.

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

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

Ovdje moramo objasniti što je to slice. Svi podaci pohranjeni u TON Blockchainu su zbirka TVM cell ili jednostavno cell, u takvu ćeliju možete pohraniti do 1023 bita podataka i do 4 poveznice na druge ćelije.

TVM cell slice ili slice ovo je dio postojećeg cell koristi se za njegovu analizu, bit će jasno kasnije. Glavno nam je da možemo transferirati slice i ovisno o vrsti poruke, obraditi podatke u recv_external() ili recv_internal().

impure — ključna riječ koja označava da funkcija mijenja podatke pametnog ugovora.

Spremimo kod ugovora lottery-code.fc i sastaviti.

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

Značenje zastavica može se vidjeti pomoću naredbe

~/TON/build/crypto/func -help

Sastavili smo Fift asemblerski kod 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

Može se pokrenuti lokalno, za to ćemo pripremiti okruženje.

Imajte na umu da se prvi red povezuje Asm.fif, ovo je kod napisan u Fiftu za Fift asembler.

Budući da želimo pokrenuti i testirati pametni ugovor lokalno, izradit ćemo datoteku lottery-test-suite.fif i tamo kopirajte kompilirani kod, zamjenjujući zadnji redak u njemu, koji zapisuje kod pametnog ugovora u konstantu codeda biste ga zatim prenijeli na virtualni stroj:

"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

Za sada se čini jasnim, a sada u istu datoteku dodajmo kod koji ćemo koristiti za pokretanje TVM-a.

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 bilježimo kontekst, odnosno podatke s kojima će se pokrenuti TVM (ili stanje mreže). Još tijekom natjecanja jedan od programera pokazao je kako se stvara c7 i kopirao sam. U ovom ćemo članku možda morati promijeniti rand_seed budući da generiranje slučajnog broja ovisi o njemu i ako se ne promijeni, svaki će se put vratiti isti broj.

recv_internal и recv_external konstante s vrijednostima 0 i -1 bit će odgovorne za pozivanje odgovarajućih funkcija u pametnom ugovoru.

Sada smo spremni za izradu prvog testa za naš prazan pametni ugovor. Radi jasnoće, za sada ćemo dodati sve testove u istu datoteku lottery-test-suite.fif.

Kreirajmo varijablu storage i u nju upišite prazan cell, ovo će biti pohrana pametnog ugovora.

message Ovo je poruka koju ćemo prenijeti pametnom kontaktu izvana. Također ćemo ga za sada učiniti praznim.

variable storage 
<b b> storage ! 

variable message 
<b b> message ! 

Nakon što smo pripremili konstante i varijable, naredbom pokrećemo TVM runvmctx i proslijedite kreirane parametre na ulaz.

message @ 
recv_external 
code 
storage @ 
c7 
runvmctx 

Na kraju ćemo uspjeti ovdje je međukod za Fift.

Sada možemo pokrenuti rezultirajući kod.

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

Program bi trebao raditi bez grešaka, au izlazu ćemo vidjeti zapisnik izvršenja:

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

Odlično, napisali smo prvu radnu verziju pametnog ugovora.

Sada moramo dodati funkcionalnost. Najprije se pozabavimo porukama koje dolaze iz vanjskog svijeta recv_external()

Programer sam odabire format poruke koji ugovor može prihvatiti.

Ali obično

  • Prvo, želimo zaštititi naš ugovor od vanjskog svijeta i učiniti ga tako da samo vlasnik ugovora može slati vanjske poruke njemu.
  • drugo, kada pošaljemo valjanu poruku TON-u, želimo da se to dogodi točno jednom, a kada ponovno pošaljemo istu poruku, pametni ugovor je odbija.

Dakle, gotovo svaki ugovor rješava ova dva problema, budući da naš ugovor prihvaća vanjske poruke, moramo voditi računa i o tome.

Učinit ćemo to obrnutim redoslijedom. Prvo riješimo problem s ponavljanjem, ako je ugovor već primio takvu poruku i obradio ju, neće je izvršiti drugi put. A onda ćemo problem riješiti tako da samo određeni krug ljudi može slati poruke na pametni ugovor.

Postoje različiti načini rješavanja problema s dupliciranim porukama. Evo kako ćemo to učiniti. U pametnom ugovoru inicijaliziramo brojač primljenih poruka s početnom vrijednošću 0. U svakoj poruci u pametni ugovor dodat ćemo trenutnu vrijednost brojača. Ako vrijednost brojača u poruci ne odgovara vrijednosti u pametnom ugovoru, tada je ne obrađujemo; ako jest, tada je obrađujemo i povećavamo brojač u pametnom ugovoru za 1.

Vratimo se na lottery-test-suite.fif i tome dodajte drugi test. Ako pošaljemo netočan broj, kôd bi trebao izbaciti iznimku. Na primjer, neka podaci o ugovoru pohrane 166, a mi ćemo poslati 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"

Idemo lansirati.

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

I vidjet ćemo da je test izvršen s greškom.

[ 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

U ovoj fazi lottery-test-suite.fif trebao bi izgledati по ссылке.

Dodajmo sada logiku brojača u pametni ugovor 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ži poruka koju šaljemo.

Prvo što radimo je provjeriti sadrži li poruka podatke, ako ne, jednostavno izlazimo.

Zatim analiziramo poruku. in_msg~load_uint(32) učitava broj 165, 32-bitni unsigned int iz prenesene poruke.

Zatim učitavamo 32 bita iz pohrane pametnog ugovora. Provjeravamo odgovara li učitani broj proslijeđenom; ako ne, bacamo iznimku. U našem slučaju, budući da prolazimo ne-usklađenost, treba baciti iznimku.

Sada kompajlirajmo.

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

Kopirajte dobiveni kod u lottery-test-suite.fif, ne zaboravljajući zamijeniti posljednji redak.

Provjeravamo je li test prošao:

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

Upravo ovdje Možete vidjeti odgovarajuću predaju s trenutnim rezultatima.

Imajte na umu da je nezgodno stalno kopirati kompajlirani kod pametnog ugovora u datoteku s testovima, pa ćemo napisati skriptu koja će umjesto nas zapisivati ​​kod u konstantu, a kompajlirani kod ćemo jednostavno povezati s našim testovima pomoću "include".

Stvorite datoteku u mapi projekta build.sh sa sljedećim sadržajem.

#!/bin/bash

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

Učinimo to izvršnim.

chmod +x ./build.sh

Sada samo pokrenite našu skriptu za sastavljanje ugovora. Ali osim ovoga, trebamo ga zapisati u konstantu code. Stoga ćemo stvoriti novu datoteku lotter-compiled-for-test.fif, koje ćemo uključiti u datoteku lottery-test-suite.fif.

Dodajmo skirpt kod u sh, koji će jednostavno duplicirati kompajliranu datoteku lotter-compiled-for-test.fif i promijenite posljednji redak u njemu.

# 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

Sada, da provjerimo, pokrenimo rezultirajuću skriptu i datoteka će se generirati lottery-compiled-for-test.fif, koje ćemo uključiti u naš lottery-test-suite.fif

В lottery-test-suite.fif obrišite šifru ugovora i dodajte redak "lottery-compiled-for-test.fif" include.

Provodimo testove kako bismo provjerili prolaze li.

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

Sjajno, sada da bismo automatizirali pokretanje testova, kreirajmo datoteku test.sh, koji će se prvi izvršiti build.sh, a zatim pokrenite testove.

touch test.sh
chmod +x test.sh

Pišemo unutra

./build.sh 

echo "nCompilation completedn"

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

Učinimo to test.sh i pokrenite ga da provjerite rade li testovi.

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

Provjeravamo da je ugovor sastavljen i da li su testovi izvršeni.

Odlično, sada na pokretanju test.sh Testovi će se odmah sastaviti i pokrenuti. Ovdje je poveznica na počiniti.

U redu, prije nego što nastavimo, učinimo još jednu stvar radi praktičnosti.

Kreirajmo mapu build gdje ćemo pohraniti kopirani ugovor i njegov klon zapisan u konstantu lottery-compiled.fif, lottery-compiled-for-test.fif. Kreirajmo i mapu test gdje će testna datoteka biti pohranjena? lottery-test-suite.fif i potencijalno druge prateće datoteke. Link na relevantne promjene.

Nastavimo razvijati pametni ugovor.

Zatim bi trebao postojati test koji provjerava je li poruka primljena i ažurira li se brojač u trgovini kada pošaljemo točan broj. Ali to ćemo učiniti kasnije.

Razmislimo sada o tome koju strukturu podataka i koji podaci trebaju biti pohranjeni u pametnom ugovoru.

Opisat ću sve što skladištimo.

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

Zatim trebate napisati dvije funkcije. Pozovimo prvu pack_state(), koji će pakirati podatke za naknadno spremanje u pohranu pametnog ugovora. Nazovimo drugu unpack_state() čitat će i vraćati podatke iz pohrane.

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

Ove dvije funkcije dodajemo na početak pametnog ugovora. Sredit će se ovdje je međurezultat.

Za spremanje podataka morat ćete pozvati ugrađenu funkciju set_data() i zapisivat će podatke iz pack_state() u pohrani pametnih ugovora.

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

Sada kada imamo prikladne funkcije za pisanje i čitanje podataka, možemo krenuti dalje.

Moramo provjeriti je li poruku koja dolazi izvana potpisao vlasnik ugovora (ili drugi korisnik koji ima pristup privatnom ključu).

Kada objavimo pametni ugovor, možemo ga inicijalizirati podacima koji su nam potrebni u pohrani, a koji će biti spremljeni za buduću upotrebu. Tamo ćemo zabilježiti javni ključ kako bismo mogli provjeriti je li dolazna poruka potpisana odgovarajućim privatnim ključem.

Prije nastavka stvorimo privatni ključ i upišimo ga test/keys/owner.pk. Da bismo to učinili, pokrenimo Fift u interaktivnom načinu rada i izvršimo četiri naredbe.

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

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

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

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

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

Kreirajmo mapu keys unutar mape test i tamo napišite privatni ključ.

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

Vidimo datoteku u trenutnoj mapi owner.pk.

Javni ključ uklanjamo sa steka i po potrebi ga možemo dobiti iz privatnog.

Sada moramo napisati ovjeru potpisa. Počnimo s testom. Prvo čitamo privatni ključ iz datoteke pomoću funkcije file>B i zapišite ga u varijablu owner_private_key, zatim pomoću funkcije priv>pub pretvoriti privatni ključ u javni ključ i upisati rezultat 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 !

Trebat će nam oba ključa.

Pohranu pametnog ugovora inicijaliziramo proizvoljnim podacima u istom slijedu kao u funkciji pack_state()i zapišite ga u varijablu 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 !

Zatim ćemo sastaviti potpisanu poruku, sadržavat će samo potpis i protuvrijednost.

Prvo kreiramo podatke koje želimo prenijeti, zatim ih potpišemo privatnim ključem i na kraju generiramo potpisanu poruku.

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 !  

Kao rezultat toga, poruka koju ćemo poslati pametnom ugovoru bilježi se u varijabli message_to_send, o funkcijama hashu, ed25519_sign_uint možeš čitati u dokumentaciji Fift.

I ponovno zovemo da izvršimo test.

message_to_send @ 
recv_external 
code 
storage @
c7
runvmctx

Ovdje tako Datoteka s testovima trebala bi izgledati ovako u ovoj fazi.

Pokrenimo test i neće uspjeti, pa ćemo promijeniti pametni ugovor tako da može primati poruke ovog formata i verificirati potpis.

Prvo izbrojimo 512 bita potpisa iz poruke i zapišemo ga u varijablu, zatim izbrojimo 32 bita varijable brojača.

Budući da imamo funkciju za čitanje podataka iz pohrane pametnih ugovora, koristit ćemo se njome.

Sljedeća je provjera brojača prenesenog sa pohranom i provjera potpisa. Ako nešto ne odgovara, onda bacamo iznimku s odgovarajućim kodom.

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

Relevantno predanje ovdje.

Pokrenimo testove i vidimo da drugi test pada. Iz dva razloga, nema dovoljno bitova u poruci i nema dovoljno bitova u pohrani, pa se kod ruši prilikom parsiranja. Moramo dodati potpis poruci koju šaljemo i kopirati pohranu iz posljednjeg testa.

U drugom testu ćemo dodati potpis poruke i promijeniti pohranu pametnog ugovora. Ovdje tako datoteka s testovima trenutno izgleda ovako.

Napišimo četvrti test, u kojem ćemo poslati poruku potpisanu tuđim privatnim ključem. Stvorimo još jedan privatni ključ i spremimo ga u datoteku not-owner.pk. Poruku ćemo potpisati ovim privatnim ključem. Pokrenimo testove i pobrinimo se da svi testovi prođu. Počiniti u ovom trenutku.

Sada konačno možemo prijeći na implementaciju logike pametnog ugovora.
В recv_external() prihvatit ćemo dvije vrste poruka.

Budući da će naš ugovor akumulirati gubitke igrača, ovaj novac mora biti prebačen tvorcu lutrije. Adresa novčanika kreatora lutrije bilježi se u pohrani prilikom kreiranja ugovora.

Za svaki slučaj treba nam mogućnost promjene adrese na koju šaljemo grame gubitnika. Također bismo trebali moći slati grame s lutrije na adresu vlasnika.

Počnimo s prvim. Napišimo prvo test koji će provjeriti je li pametni ugovor nakon slanja poruke spremio novu adresu u pohranu. Napominjemo da u poruci osim šaltera i nove adrese prenosimo i action 7-bitni cijeli broj koji nije negativan, ovisno o njemu ćemo odabrati kako ćemo obraditi poruku u pametnom ugovoru.

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

U testu možete vidjeti kako je pohrana pametnog ugovora deserijalizirana storage u Petici. Deserijalizacija varijabli opisana je u Fift dokumentaciji.

Potvrdi vezu s dodanim tijestom.

Pokrenimo test i uvjerimo se da ne uspijeva. Sada dodajmo logiku da promijenimo adresu vlasnika lutrije.

U pametnom ugovoru nastavljamo analizirati message, čitaj u action. Podsjetimo, imat ćemo dva action: promijeni adresu i pošalji grame.

Zatim čitamo novu adresu vlasnika ugovora i spremamo je u pohranu.
Pokrećemo testove i vidimo da treći test pada. Ruši se zbog činjenice da ugovor sada dodatno analizira 7 bitova iz poruke, koji nedostaju u testu. Dodajte nepostojeći u poruku action. Provedimo testove i vidimo da sve prolazi. ovdje posvetiti se promjenama. Sjajno.

Sada napišimo logiku za slanje navedenog broja grama na prethodno spremljenu adresu.

Prvo, napišimo test. Napisat ćemo dva testa, jedan kada nema dovoljno ravnoteže, drugi kada sve treba uspješno proći. Testovi se mogu pogledati u ovom obvezi.

Sada dodajmo kod. Prvo, napišimo dvije pomoćne metode. Prva metoda dobivanja je saznati trenutno stanje pametnog ugovora.

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

A drugi je za slanje grama na drugi pametni ugovor. U potpunosti sam kopirao ovu metodu iz drugog pametnog ugovora.

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

Dodajmo ove dvije metode pametnom ugovoru i napišimo logiku. Prvo analiziramo broj grama iz poruke. Zatim provjeravamo ravnotežu, ako nije dovoljna bacamo iznimku. Ako je sve u redu, šaljemo grame na spremljenu adresu i ažuriramo brojač.

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

Ovdje tako izgleda kao pametni ugovor u ovom trenutku. Pokrenimo testove i uvjerimo se da prolaze.

Inače, provizija se odbija od pametnog ugovora svaki put za obrađenu poruku. Kako bi poruke pametnog ugovora izvršile zahtjev, nakon osnovnih provjera potrebno je nazvati accept_message().

Sada prijeđimo na interne poruke. Zapravo, prihvatit ćemo samo grame i vratiti dvostruki iznos igraču ako pobijedi i trećinu vlasniku ako izgubi.

Prvo, napišimo jednostavan test. Da bismo to učinili, potrebna nam je testna adresa pametnog ugovora s koje navodno šaljemo gramove pametnom ugovoru.

Adresa pametnog ugovora sastoji se od dva broja, 32-bitnog cijelog broja odgovornog za radni lanac i 256-bitnog nenegativnog cijelog broja jedinstvenog broja računa u ovom radnom lancu. Na primjer, -1 i 12345, ovo je adresa koju ćemo spremiti u datoteku.

Kopirao sam funkciju za spremanje adrese iz 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

Pogledajmo kako funkcija radi, to će vam dati razumijevanje kako radi Fift. Pokrenite Fift u interaktivnom načinu rada.

~/TON/build/crypto/fift -i 

Prvo gurnemo -1, 12345 i naziv buduće datoteke "sender.addr" na stog:

-1 12345 "sender.addr" 

Sljedeći korak je izvršavanje funkcije -rot, koji pomiče stog na takav način da se na vrhu stoga nalazi jedinstveni broj pametnog ugovora:

"sender.addr" -1 12345

256 u>B pretvara 256-bitni nenegativan cijeli broj u bajtove.

"sender.addr" -1 BYTES:0000000000000000000000000000000000000000000000000000000000003039

swap mijenja gornja dva elementa snopa.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 -1

32 i>B pretvara 32-bitni cijeli broj u bajtove.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 BYTES:FFFFFFFF

B+ povezuje dva niza bajtova.

 "sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF

opet swap.

BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF "sender.addr" 

I na kraju se bajtovi zapisuju u datoteku B>file. Nakon ovoga naš stog je prazan. Zaustavljamo se Fift. Datoteka je stvorena u trenutnoj mapi sender.addr. Premjestimo datoteku u stvorenu mapu test/addresses/.

Napišimo jednostavan test koji će poslati gramove na pametni ugovor. Evo obveze.

Pogledajmo sada logiku lutrije.

Prvo što radimo je provjeriti poruku bounced ili ne ako bounced, onda ga ignoriramo. bounced znači da će ugovor vratiti grame ako se dogodi neka greška. Nećemo vratiti grame ako iznenada dođe do pogreške.

Provjeravamo, ako je stanje manje od pola grama, tada jednostavno prihvaćamo poruku i ignoriramo je.

Zatim analiziramo adresu pametnog ugovora s kojeg je poruka stigla.

Očitavamo podatke iz pohrane i brišemo stare oklade iz povijesti ako ih ima više od dvadeset. Radi praktičnosti, napisao sam tri dodatne funkcije pack_order(), unpack_order(), remove_old_orders().

Zatim gledamo ako saldo nije dovoljan za isplatu, tada smatramo da ovo nije oklada, već nadopuna i spremamo nadopunu u orders.

Zatim konačno bit pametnog ugovora.

Prvo, ako igrač izgubi, to spremamo u povijest klađenja, a ako je iznos veći od 3 grama, šaljemo 1/3 vlasniku pametnog ugovora.

Ako igrač pobijedi, tada šaljemo dvostruki iznos na adresu igrača, a potom podatke o okladi spremamo u povijest.

() 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 to. Odgovarajuće preuzimanje.

Sada sve što preostaje je jednostavno, kreirajmo get-metode kako bismo mogli dobiti informacije o stanju ugovora iz vanjskog svijeta (u stvari, pročitati podatke iz njihove pohrane pametnih ugovora).

Dodajmo get metode. U nastavku ćemo pisati o tome kako dobiti informacije o pametnom ugovoru.

Također sam zaboravio dodati kod koji će obraditi prvi zahtjev koji se pojavi prilikom objave pametnog ugovora. Odgovarajuće preuzimanje. I dalje ispravljeno bug sa slanjem 1/3 iznosa na račun vlasnika.

Sljedeći korak je objava pametnog ugovora. Kreirajmo mapu requests.

Za osnovu sam uzeo kod objave simple-wallet-code.fc koji mogu naći u službenom repozitoriju.

Nešto vrijedno pažnje. Generiramo pohranu pametnog ugovora i ulaznu poruku. Nakon toga se generira adresa pametnog ugovora, odnosno adresa je poznata i prije objave u TON-u. Zatim je potrebno poslati nekoliko grama na ovu adresu, a tek nakon toga poslati datoteku sa samim pametnim ugovorom, budući da mreža uzima proviziju za pohranu pametnog ugovora i operacije u njemu (validatori koji pohranjuju i izvršavaju pametne ugovore ). Kod možete pogledati ovdje.

Zatim izvršavamo kod za objavljivanje i dobivamo lottery-query.boc datoteku i adresu pametnog ugovora.

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

Ne zaboravite spremiti generirane datoteke: lottery-query.boc, lottery.addr, lottery.pk.

Između ostalog, u zapisnicima izvršenja vidjet ćemo adresu pametnog ugovora.

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

Samo zabave radi, uputimo zahtjev TON-u

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

I vidjet ćemo da je račun s ovom adresom prazan.

account state is empty

Šaljemo na adresu 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd 2 Gram i nakon nekoliko sekundi izvršavamo istu naredbu. Za slanje grama koristim službeni novčanik, a za probne grame možete pitati nekoga s chata o čemu ću govoriti na kraju članka.

> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Izgleda kao neinicijalizirano (state:account_uninit) pametni ugovor s istom adresom i stanjem od 1 nanograma.

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

Sada objavimo pametni ugovor. Pokrenimo lite-client i izvršimo.

> 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 

Provjerimo je li ugovor objavljen.

> last
> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Između ostalog dobivamo.

  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 vidimo account_active.

Odgovarajuće uvrštavanje s promjenama ovdje.

Kreirajmo sada zahtjeve za interakciju s pametnim ugovorom.

Točnije, prvu za promjenu adrese ostavit ćemo kao samostalan rad, a drugu za slanje grama na adresu vlasnika. Zapravo, morat ćemo učiniti isto što i u testu za slanje grama.

Ovo je poruka koju ćemo poslati pametnom ugovoru, gdje msg_seqno 165, action 2 i 9.5 grama za slanje.

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

Ne zaboravite potpisati poruku svojim privatnim ključem lottery.pk, koji je generiran ranije prilikom izrade pametnog ugovora. Ovdje je odgovarajući commit.

Primanje informacija iz pametnog ugovora korištenjem metoda get

Sada pogledajmo kako pokrenuti metode dobivanja pametnog ugovora.

Pokreni lite-client i pokrenite get metode koje smo napisali.

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

В result sadrži vrijednost koju funkcija vraća balance() iz našeg pametnog ugovora.
Isto ćemo učiniti za još nekoliko metoda.

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

Zamolimo vas za povijest oklada.

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

Koristit ćemo lite-client i dobiti metode za prikaz informacija o pametnom ugovoru na web mjestu.

Prikaz podataka pametnog ugovora na web stranici

Napisao sam jednostavnu web stranicu u Pythonu za prikaz podataka iz pametnog ugovora na prikladan način. Ovdje se neću detaljno zadržavati na tome i objavit ću stranicu u jednom predanju.

Zahtjevi za TON šalju se od Python uz pomoć lite-client. Radi praktičnosti, stranica je upakirana u Docker i objavljena na Google Cloudu. Veza.

Težak

Sada pokušajmo tamo poslati grame za nadopunu torbica. Poslat ćemo 40 grama. I uložimo nekoliko oklada radi jasnoće. Vidimo da stranica prikazuje povijest oklada, trenutni postotak dobitaka i druge korisne informacije.

Mi vidimoda smo prvo dobili, drugo izgubili.

pogovor

Članak je ispao puno duži nego što sam očekivao, možda je mogao biti i kraći, ili možda samo za osobu koja ne zna ništa o TON-u i želi napisati i objaviti ne tako jednostavan pametni ugovor s mogućnošću interakcije s to. Možda su se neke stvari mogle jednostavnije objasniti.

Možda su neki aspekti implementacije mogli biti odrađeni učinkovitije i elegantnije, ali bi onda za pripremu članka trebalo još više vremena. Također je moguće da sam negdje pogriješio ili nešto nisam razumio, pa ako radite nešto ozbiljno, morate se osloniti na službenu dokumentaciju ili službeni repozitorij s kodom TON.

Treba napomenuti da budući da je sam TON još uvijek u aktivnoj fazi razvoja, može doći do promjena koje će prekinuti bilo koji od koraka u ovom članku (što se dogodilo dok sam pisao, već je ispravljeno), ali opći pristup je malo je vjerojatno da će se promijeniti.

Neću govoriti o budućnosti TON-a. Možda će platforma postati nešto veliko i trebali bismo provesti vrijeme proučavajući je i ispuniti nišu s našim proizvodima sada.

Tu je i Libra s Facebooka, koja ima potencijalnu publiku korisnika veću od TON. O Libri ne znam skoro ništa, sudeći po forumu tamo je puno više aktivnosti nego u TON zajednici. Iako su programeri i zajednica TON-a više nalik undergroundu, što je također cool.

reference

  1. Službena TON dokumentacija: https://test.ton.org
  2. Službeni TON repozitorij: https://github.com/ton-blockchain/ton
  3. Službeni novčanik za različite platforme: https://wallet.ton.org
  4. Repozitorij pametnih ugovora iz ovog članka: https://github.com/raiym/astonished
  5. Link na web mjesto pametnog ugovora: https://ton-lottery.appspot.com
  6. Repozitorij za proširenje za Visual Studio Code za FunC: https://github.com/raiym/func-visual-studio-plugin
  7. Razgovarajte o TON-u u Telegramu, što je stvarno pomoglo da to shvatite u početnoj fazi. Mislim da neće pogriješiti ako kažem da su tu svi koji su nešto napisali za TON. Tamo možete zatražiti i testne grame. https://t.me/tondev_ru
  8. Još jedan chat o TON-u u kojem sam pronašao korisne informacije: https://t.me/TONgramDev
  9. Prva faza natjecanja: https://contest.com/blockchain
  10. Druga faza natjecanja: https://contest.com/blockchain-2

Izvor: www.habr.com

Dodajte komentar