O tom, jak napsat a publikovat chytrou smlouvu v Telegram Open Network (TON)

O tom, jak napsat a zveřejnit smart contract v TONu

O čem je tento článek?

V článku budu mluvit o tom, jak jsem se zúčastnil první (ze dvou) blockchainové soutěže Telegram, nezískal cenu a rozhodl se zaznamenat svou zkušenost do článku, aby neupadl v zapomnění a možná pomohl někdo.

Protože jsem nechtěl psát abstraktní kód, ale udělat něco funkčního, pro článek jsem napsal chytrou smlouvu na okamžitou loterii a web, který zobrazuje data o chytrých smlouvách přímo z TON bez použití meziúložiště.

Článek bude užitečný pro ty, kteří chtějí uzavřít svůj první chytrý kontrakt v TON, ale nevědí, kde začít.

Na příkladu loterie přejdu od instalace prostředí k publikování chytré smlouvy, interakci s ní a napsání webu pro příjem a publikování dat.

O účasti v soutěži

Loni v říjnu Telegram oznámil blockchainovou soutěž s novými jazyky Fift и FunC. Bylo nutné si vybrat ze sepsání libovolné z pěti navrhovaných smart kontraktů. Říkal jsem si, že by bylo fajn udělat něco jiného, ​​naučit se jazyk a něco vyrobit, i když v budoucnu nebudu muset psát nic jiného. Navíc je téma neustále na rtech.

Stojí za to říci, že jsem neměl žádné zkušenosti s vývojem chytrých kontraktů.

Plánoval jsem se zúčastnit až do úplného konce, dokud to půjde, a pak napsat recenzi, ale hned u prvního jsem neuspěl. já napsal peněženku se zapnutým vícenásobným podpisem FunC a obecně to fungovalo. Vzal jsem to jako základ chytrý kontrakt na Solidity.

Tehdy jsem si říkal, že to rozhodně stačí na to, abych si odnesl alespoň nějaké místo. Výsledkem bylo, že asi 40 ze 60 účastníků se stalo vítězi a já mezi nimi nebyl. Obecně na tom není nic špatného, ​​ale jedna věc mi vadila. V době vyhlášení výsledků ještě nebyla provedena revize testu na mou smlouvu, ptal jsem se účastníků chatu, zda je ještě někdo, kdo ho nemá, nebyl.

Když jsem si dával pozor na své zprávy, o dva dny později uveřejnili porotci komentář a já stále nechápu, zda náhodou při posuzování nepropásli mou smart smlouvu nebo si prostě mysleli, že je to tak špatné, že to nepotřebuje komentář. Položil jsem otázku na stránce, ale nedostal jsem odpověď. I když není tajemstvím, kdo soudil, považoval jsem za zbytečné psát osobní zprávy.

Hodně času bylo věnováno porozumění, a tak bylo rozhodnuto napsat článek. Vzhledem k tomu, že informací zatím není mnoho, pomůže tento článek ušetřit čas všem zájemcům.

Koncept chytrých kontraktů v TON

Než něco napíšete, musíte si rozmyslet, z jaké strany k této věci přistupovat. Proto vám nyní řeknu, z jakých částí se systém skládá. Přesněji, jaké části potřebujete znát, abyste sepsali alespoň nějakou pracovní smlouvu.

Zaměříme se na sepsání chytré smlouvy a práci s TON Virtual Machine (TVM), Fift и FunC, takže článek je spíše popisem vývoje běžného programu. Nebudeme se zde zabývat tím, jak samotná platforma funguje.

Obecně o tom, jak to funguje TVM a jazyk Fift existuje dobrá oficiální dokumentace. Při účasti v soutěži a nyní při psaní aktuální smlouvy jsem se na ni často obracel.

Hlavním jazykem, ve kterém jsou psány smart kontrakty, je FunC. V tuto chvíli k tomu není žádná dokumentace, takže abyste mohli něco napsat, musíte si prostudovat příklady smart kontraktů z oficiálního úložiště a implementaci samotného jazyka tam, plus se můžete podívat na příklady smart kontraktů z posledních dvou soutěže. Odkazy na konci článku.

Řekněme, že jsme již sepsali smart kontrakt pro FunC, poté kód zkompilujeme do pátého assembleru.

Sestavená smart smlouva zbývá zveřejnit. Chcete-li to provést, musíte napsat funkci Fift, který převezme kód inteligentní smlouvy a některé další parametry jako vstup a výstupem bude soubor s příponou .boc (což znamená „pytel buněk“) a v závislosti na tom, jak jej napíšeme, soukromý klíč a adresu, která je generována na základě kódu chytré smlouvy. Gramy již můžete posílat na adresu chytré smlouvy, která ještě nebyla zveřejněna.

Ke zveřejnění smart kontraktu v TONu přijato .boc soubor bude nutné odeslat do blockchainu pomocí lehkého klienta (více o tom níže). Před zveřejněním je ale potřeba přenést gramy na vygenerovanou adresu, jinak nebude smart kontrakt zveřejněn. Po zveřejnění můžete s inteligentní smlouvou interagovat tak, že jí budete posílat zprávy zvenčí (například pomocí lehkého klienta) nebo zevnitř (například jedna inteligentní smlouva posílá další zprávu uvnitř TON).

Jakmile pochopíme, jak je kód publikován, bude to jednodušší. Zhruba víme, co chceme napsat a jak bude náš program fungovat. A při psaní hledáme, jak je to již implementováno ve stávajících smart kontraktech, případně nahlížíme do implementačního kódu Fift и FunC v oficiálním úložišti nebo se podívejte do oficiální dokumentace.

Velmi často jsem hledal klíčová slova v chatu Telegram, kde se sešli všichni účastníci soutěže a zaměstnanci Telegramu, a stalo se, že se tam během soutěže všichni sešli a začali diskutovat o Fift a FunC. Odkaz na konci článku.

Je čas přejít od teorie k praxi.

Příprava prostředí pro práci s TON

Udělal jsem vše, co bude popsáno v článku na MacOS a dvakrát jsem to zkontroloval v čistém Ubuntu 18.04 LTS na Dockeru.

První věc, kterou musíte udělat, je stáhnout a nainstalovat lite-client pomocí kterého můžete odesílat požadavky do TON.

Pokyny na oficiálních stránkách popisují proces instalace poměrně podrobně a jasně a vynechávají některé detaily. Zde postupujeme podle pokynů a instalujeme chybějící závislosti. Nekompiloval jsem každý projekt sám a nainstaloval jsem z oficiálního úložiště Ubuntu (na MacOS jsem použil 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 

Jakmile jsou všechny závislosti nainstalovány, můžete nainstalovat lite-client, Fift, FunC.

Nejprve naklonujeme úložiště TON spolu s jeho závislostmi. Pro pohodlí uděláme vše ve složce ~/TON.

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

V úložišti jsou také uloženy implementace Fift и FunC.

Nyní jsme připraveni projekt sestavit. Kód úložiště je naklonován do složky ~/TON/ton. V ~/TON vytvořit složku build a shromáždit v něm projekt.

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

Protože se chystáme sepsat chytrou smlouvu, potřebujeme nejen lite-clientAle Fift с FunC, tak pojďme vše zkompilovat. Není to rychlý proces, takže čekáme.

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

Dále si stáhněte konfigurační soubor, který obsahuje data o uzlu, ke kterému lite-client se připojí.

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

Odeslání prvních požadavků na TON

Nyní spustíme lite-client.

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

Pokud bylo sestavení úspěšné, po spuštění uvidíte protokol připojení lehké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)
...

Příkaz můžete spustit help a podívejte se, jaké příkazy jsou k dispozici.

help

Uveďme si seznam příkazů, které v tomto článku použijeme.

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

Nyní jsme připraveni sepsat samotnou smlouvu.

uskutečnění

Nápad

Jak jsem psal výše, chytrá smlouva, kterou sepisujeme, je loterie.

Navíc se nejedná o loterii, ve které si musíte koupit tiket a čekat hodinu, den nebo měsíc, ale o okamžitou loterii, ve které se uživatel přenese na smluvní adresu N gramů a okamžitě je dostane zpět 2 * N gramů nebo ztrácí. Uděláme pravděpodobnost výhry asi 40 %. Pokud není dostatek gramů na platbu, budeme transakci považovat za dobití.

Kromě toho je důležité, aby sázky bylo možné vidět v reálném čase a ve vhodné formě, aby uživatel okamžitě pochopil, zda vyhrál nebo prohrál. Proto musíte udělat web, který bude zobrazovat sázky a výsledky přímo z TON.

Sepsání chytré smlouvy

Pro usnadnění jsem zvýraznil kód pro FunC; plugin lze najít a nainstalovat ve vyhledávání kódu Visual Studio; pokud náhle chcete něco přidat, zpřístupnil jsem plugin veřejně. Také někdo dříve vytvořil plugin pro práci s Fiftem, můžete si ho také nainstalovat a najít ve VSC.

Okamžitě vytvoříme úložiště, kde budeme odevzdávat mezivýsledky.

Abychom si usnadnili život, sepíšeme chytrou smlouvu a budeme ji lokálně testovat, dokud nebude připravena. Teprve poté jej zveřejníme v TONu.

Inteligentní smlouva má dvě externí metody, ke kterým lze přistupovat. První, recv_external() tato funkce se provádí, když požadavek na smlouvu přijde z vnějšího světa, tedy ne od TONu, například když sami vygenerujeme zprávu a odešleme ji přes lite-client. Druhý, recv_internal() to je, když v rámci samotné společnosti TON jakákoli smlouva odkazuje na naši smlouvu. V obou případech můžete funkci předat parametry.

Začněme jednoduchým příkladem, který bude fungovat, pokud bude zveřejněn, ale není v něm žádná funkční zátěž.

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

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

Zde musíme vysvětlit, co to je slice. Všechna data uložená v TON Blockchain jsou sbírkou TVM cell nebo jednoduše cell, do takové buňky můžete uložit až 1023 bitů dat a až 4 odkazy na další buňky.

TVM cell slice nebo slice toto je součástí stávajícího cell se používá k jeho analýze, bude jasné později. Pro nás je hlavní, že se umíme přenést slice a v závislosti na typu zprávy zpracovat data v recv_external() nebo recv_internal().

impure — klíčové slovo, které označuje, že funkce upravuje data inteligentní smlouvy.

Uložíme kód smlouvy lottery-code.fc a zkompilovat.

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

Význam příznaků lze zobrazit pomocí příkazu

~/TON/build/crypto/func -help

Zkompilovali jsme kód XNUMX. assembleru 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

Může být spuštěn lokálně, k tomu připravíme prostředí.

Všimněte si, že první řádek spojuje Asm.fif, toto je kód napsaný v Fift pro assembler Fift.

Protože chceme chytrou smlouvu spouštět a testovat lokálně, vytvoříme soubor lottery-test-suite.fif a zkopírujte tam zkompilovaný kód a nahradíte v něm poslední řádek, který zapíše kód inteligentní smlouvy do konstanty codea poté jej přenést na virtuální počítač:

"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

Zatím se to zdá jasné, nyní do stejného souboru přidáme kód, který použijeme ke spuštění 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áváme kontext, tedy data, se kterými bude TVM (nebo stav sítě) spuštěn. I během soutěže jeden z vývojářů ukázal, jak tvořit c7 a zkopíroval jsem. V tomto článku možná budeme muset změnit rand_seed protože na něm závisí generování náhodného čísla, a pokud se nezmění, pokaždé se vrátí stejné číslo.

recv_internal и recv_external konstanty s hodnotami 0 a -1 budou zodpovědné za volání odpovídajících funkcí v inteligentní smlouvě.

Nyní jsme připraveni vytvořit první test pro naši prázdnou inteligentní smlouvu. Pro přehlednost prozatím přidáme všechny testy do stejného souboru lottery-test-suite.fif.

Vytvořme proměnnou storage a napište do něj prázdnou cell, to bude úložiště chytrých smluv.

message Toto je zpráva, kterou předáme chytrému kontaktu zvenčí. Také ho zatím vyprázdníme.

variable storage 
<b b> storage ! 

variable message 
<b b> message ! 

Poté, co jsme připravili konstanty a proměnné, spustíme TVM pomocí příkazu runvmctx a předat vytvořené parametry na vstup.

message @ 
recv_external 
code 
storage @ 
c7 
runvmctx 

Nakonec uspějeme takhle mezikód pro Fift.

Nyní můžeme spustit výsledný kód.

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

Program by měl běžet bez chyb a ve výstupu uvidíme protokol provedení:

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

Skvělé, sepsali jsme první pracovní verzi chytré smlouvy.

Nyní musíme přidat funkcionalitu. Nejprve se pojďme zabývat zprávami, které přicházejí z vnějšího světa recv_external()

Vývojář sám volí formát zprávy, který může smlouva akceptovat.

Ale obvykle

  • za prvé, chceme chránit naši smlouvu před vnějším světem a udělat ji tak, aby do ní mohl posílat externí zprávy pouze vlastník smlouvy.
  • za druhé, když pošleme platnou zprávu do TON, chceme, aby se to stalo přesně jednou, a když stejnou zprávu pošleme znovu, smart kontrakt ji odmítne.

Téměř každá smlouva tedy řeší tyto dva problémy, protože naše smlouva přijímá externí zprávy, musíme se postarat i o to.

Uděláme to v obráceném pořadí. Nejprve vyřešme problém s opakováním, pokud smlouva již takovou zprávu obdržela a zpracovala ji, podruhé ji neprovede. A pak problém vyřešíme tak, aby zprávy do smart kontraktu mohl posílat jen určitý okruh lidí.

Problém s duplicitními zprávami lze vyřešit různými způsoby. Zde je návod, jak to uděláme. Ve smart kontraktu inicializujeme počítadlo přijatých zpráv s počáteční hodnotou 0. V každé zprávě do smart kontraktu přičteme aktuální hodnotu počítadla. Pokud se hodnota počítadla ve zprávě neshoduje s hodnotou v chytré smlouvě, pak ji nezpracujeme, pokud ano, zpracujeme ji a zvýšíme počítadlo v chytré smlouvě o 1.

Vraťme se k lottery-test-suite.fif a přidat k tomu druhý test. Pokud odešleme nesprávné číslo, kód by měl vyvolat výjimku. Nechte například data smlouvy uložit 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"

Pojďme spustit.

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

A uvidíme, že test je proveden 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 této fázi lottery-test-suite.fif by měl vypadat по ссылке.

Nyní přidejte logiku čítače do inteligentní smlouvy 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ží zpráva, kterou posíláme.

První věc, kterou uděláme, je zkontrolovat, zda zpráva obsahuje data, pokud ne, jednoduše skončíme.

Dále analyzujeme zprávu. in_msg~load_uint(32) načte číslo 165, 32-bit unsigned int z přenášené zprávy.

Dále načteme 32 bitů z úložiště inteligentních kontraktů. Zkontrolujeme, zda se načtené číslo shoduje s předaným, pokud ne, vyvoláme výjimku. V našem případě, protože procházíme neshodou, by měla být vyvolána výjimka.

Nyní pojďme zkompilovat.

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

Výsledný kód zkopírujte do lottery-test-suite.fif, nezapomeňte nahradit poslední řádek.

Zkontrolujeme, zda test prošel:

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

Zde Můžete vidět odpovídající odevzdání s aktuálními výsledky.

Všimněte si, že je nepohodlné neustále kopírovat zkompilovaný kód chytré smlouvy do souboru s testy, takže napíšeme skript, který nám kód zapíše do konstanty a zkompilovaný kód jednoduše připojíme k našim testům pomocí "include".

Vytvořte soubor ve složce projektu build.sh s následujícím obsahem.

#!/bin/bash

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

Udělejme to spustitelné.

chmod +x ./build.sh

Nyní stačí spustit náš skript a zkompilovat smlouvu. Ale kromě toho to musíme zapsat do konstanty code. Vytvoříme tedy nový soubor lotter-compiled-for-test.fif, který zařadíme do souboru lottery-test-suite.fif.

Pojďme přidat skirpt kód do sh, který jednoduše duplikuje kompilovaný soubor lotter-compiled-for-test.fif a změňte v něm poslední řádek.

# 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

Nyní pro kontrolu spusťte výsledný skript a vygeneruje se soubor lottery-compiled-for-test.fif, kterou zařadíme do našeho lottery-test-suite.fif

В lottery-test-suite.fif odstraňte kód smlouvy a přidejte řádek "lottery-compiled-for-test.fif" include.

Provádíme testy, abychom ověřili, že projdou.

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

Skvělé, nyní pro automatizaci spouštění testů vytvořte soubor test.sh, který se jako první provede build.sha poté spusťte testy.

touch test.sh
chmod +x test.sh

Píšeme dovnitř

./build.sh 

echo "nCompilation completedn"

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

Uděláme to test.sh a spusťte jej, abyste se ujistili, že testy fungují.

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

Zkontrolujeme, že se smlouva zkompiluje a testy jsou provedeny.

Skvělé, nyní na startu test.sh Testy budou sestaveny a okamžitě spuštěny. Zde je odkaz na spáchat.

Dobře, než budeme pokračovat, udělejme pro pohodlí ještě jednu věc.

Vytvoříme složku build kam uložíme zkopírovanou smlouvu a její klon zapsaný do konstanty lottery-compiled.fif, lottery-compiled-for-test.fif. Vytvořme také složku test kde bude uložen testovací soubor? lottery-test-suite.fif a případně další podpůrné soubory. Odkaz na relevantní změny.

Pokračujme ve vývoji chytré smlouvy.

Dále by měl následovat test, který zkontroluje přijetí zprávy a aktualizaci počítadla v obchodě, když odešleme správné číslo. Ale to uděláme později.

Nyní se zamysleme nad tím, jakou datovou strukturu a jaká data je třeba v chytré smlouvě ukládat.

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

Dále musíte napsat dvě funkce. Zavoláme prvnímu pack_state(), který zabalí data pro následné uložení do úložiště smart contract. Zavolejme tomu druhému unpack_state() bude číst a vracet data z úložiště.

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

Tyto dvě funkce přidáme na začátek chytré smlouvy. ono to vyjde takhle mezivýsledek.

Chcete-li uložit data, budete muset zavolat vestavěnou funkci set_data() a bude zapisovat data z pack_state() v úložišti chytrých smluv.

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

Nyní, když máme pohodlné funkce pro zápis a čtení dat, můžeme pokračovat.

Musíme zkontrolovat, zda zprávu příchozí zvenčí podepisuje vlastník smlouvy (nebo jiný uživatel, který má přístup k soukromému klíči).

Když zveřejníme chytrou smlouvu, můžeme ji inicializovat s daty, která potřebujeme v úložišti, která budou uložena pro budoucí použití. Veřejný klíč tam zaznamenáme, abychom mohli ověřit, že příchozí zpráva byla podepsána odpovídajícím soukromým klíčem.

Než budeme pokračovat, vytvořte si soukromý klíč a zapište jej test/keys/owner.pk. Chcete-li to provést, spusťte Pátku v interaktivním režimu a spusťte čtyři příkazy.

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

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

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

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

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

Vytvoříme složku keys uvnitř složky test a napište tam soukromý klíč.

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 soubor v aktuální složce owner.pk.

Odebereme veřejný klíč ze zásobníku a v případě potřeby jej můžeme získat ze soukromého.

Nyní musíme napsat ověření podpisu. Začněme testem. Nejprve načteme privátní klíč ze souboru pomocí funkce file>B a zapište jej do proměnné owner_private_keya poté pomocí funkce priv>pub převést soukromý klíč na veřejný klíč a zapsat výsledek 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 potřebovat oba klíče.

Inicializujeme úložiště smart kontraktů libovolnými daty ve stejném pořadí jako ve funkci pack_state()a zapsat do proměnné 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 !

Dále vytvoříme podepsanou zprávu, bude obsahovat pouze podpis a hodnotu čítače.

Nejprve vytvoříme data, která chceme přenést, pak je podepíšeme privátním klíčem a nakonec vygenerujeme podepsanou zprá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 se zpráva, kterou odešleme do smart kontraktu, zaznamená do proměnné message_to_send, o funkcích hashu, ed25519_sign_uint umí číst v dokumentaci Fift.

A abychom provedli test, zavoláme znovu.

message_to_send @ 
recv_external 
code 
storage @
c7
runvmctx

takhle Soubor s testy by měl v této fázi vypadat takto.

Spustíme test a selže, takže změníme smart kontrakt tak, aby mohl přijímat zprávy tohoto formátu a ověřovat podpis.

Nejprve napočítáme 512 bitů signatury ze zprávy a zapíšeme ji do proměnné, poté napočítáme 32 bitů proměnné čítače.

Jelikož máme funkci pro čtení dat z úložiště chytrých smluv, využijeme ji.

Následuje kontrola počítadla přeneseného s úložištěm a kontrola podpisu. Pokud něco neodpovídá, pak vyvoláme výjimku s příslušným kódem.

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

Příslušný závazek zde.

Spusťte testy a uvidíme, že druhý test selže. Ze dvou důvodů není ve zprávě dostatek bitů a v úložišti je málo bitů, takže kód při analýze padá. Ke zprávě, kterou odesíláme, musíme přidat podpis a zkopírovat úložiště z posledního testu.

Ve druhém testu přidáme podpis zprávy a změníme úložiště chytré smlouvy. takhle soubor s testy vypadá v tuto chvíli.

Pojďme napsat čtvrtý test, ve kterém pošleme zprávu podepsanou cizím soukromým klíčem. Vytvoříme další soukromý klíč a uložíme jej do souboru not-owner.pk. Tímto soukromým klíčem zprávu podepíšeme. Spusťte testy a ujistěte se, že všechny testy projdou. Spáchat v současné době.

Nyní můžeme konečně přejít k implementaci logiky chytré smlouvy.
В recv_external() přijímáme dva typy zpráv.

Protože naše smlouva bude kumulovat ztráty hráčů, musí být tyto peníze převedeny na tvůrce loterie. Adresa peněženky tvůrce loterie je zaznamenána v úložišti při vytvoření smlouvy.

Pro každý případ potřebujeme možnost změnit adresu, na kterou posíláme gramy poražených. Měli bychom být také schopni posílat gramy z loterie na adresu majitele.

Začněme tím prvním. Pojďme si nejprve napsat test, který prověří, že po odeslání zprávy smart contract uložil novou adresu do úložiště. Upozorňujeme, že ve zprávě kromě přepážky a nové adresy také předáváme action 7bitové celé nezáporné číslo, v závislosti na něm zvolíme způsob zpracování zprávy v chytré smlouvě.

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

V testu můžete vidět, jak je úložiště smartcontract deserializováno storage v Páté. Deserializace proměnných je popsána v dokumentaci Fift.

Potvrdit odkaz s přidaným těstem.

Spusťte test a ujistěte se, že selže. Nyní přidáme logiku pro změnu adresy majitele loterie.

V inteligentní smlouvě pokračujeme v analýze message, přečtěte si action. Připomeňme, že budeme mít dva action: změnit adresu a odeslat gramy.

Poté načteme novou adresu vlastníka smlouvy a uložíme ji do úložiště.
Spustíme testy a uvidíme, že třetí test selže. Padá kvůli tomu, že smlouva nyní dodatečně analyzuje 7 bitů ze zprávy, které v testu chybí. Přidejte do zprávy neexistující action. Udělejme testy a uvidíme, že vše projde. Zde zavázat se ke změnám. Skvělý.

Nyní napíšeme logiku pro odeslání zadaného počtu gramů na dříve uloženou adresu.

Nejprve si napíšeme test. Budeme psát dva testy, jeden, když není dostatečná rovnováha, druhý, když by vše mělo úspěšně projít. Testy lze prohlížet v tomto závazku.

Nyní přidáme kód. Nejprve si napíšeme dvě pomocné metody. První metodou get je zjistit aktuální zůstatek chytré smlouvy.

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

A druhý je pro posílání gramů na další smart kontrakt. Tuto metodu jsem zcela zkopíroval z jiné chytré smlouvy.

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

Přidejme tyto dvě metody do chytré smlouvy a napišme logiku. Nejprve analyzujeme počet gramů ze zprávy. Dále zkontrolujeme zůstatek, pokud nestačí, vyvoláme výjimku. Pokud je vše v pořádku, pak gramy odešleme na uloženou 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));

takhle v tuto chvíli vypadá jako chytrá smlouva. Spusťte testy a ujistěte se, že projdou.

Mimochodem, za zpracovanou zprávu se z chytré smlouvy pokaždé odečítá provize. Aby zprávy smart contract provedly požadavek, po základních kontrolách musíte zavolat accept_message().

Nyní přejdeme k interním zprávám. Ve skutečnosti přijmeme pouze gramy a pošleme zpět dvojnásobek částky hráči, pokud vyhraje, a třetinu majiteli, pokud prohraje.

Nejprve si napíšeme jednoduchý test. K tomu potřebujeme testovací adresu smart kontraktu, ze kterého prý posíláme gramy do smart kontraktu.

Adresa inteligentní smlouvy se skládá ze dvou čísel, 32bitového celého čísla odpovědného za pracovní řetězec a 256bitového nezáporného celočíselného jedinečného čísla účtu v tomto pracovním řetězci. Například -1 a 12345, toto je adresa, kterou uložíme do souboru.

Zkopíroval jsem funkci pro uložení 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

Podívejme se na to, jak funkce funguje, což vám umožní pochopit, jak funguje Fift. Spusťte Fift v interaktivním režimu.

~/TON/build/crypto/fift -i 

Nejprve do zásobníku vložíme -1, 12345 a název budoucího souboru "sender.addr":

-1 12345 "sender.addr" 

Dalším krokem je provedení funkce -rot, který posune zásobník tak, že v horní části zásobníku je jedinečné číslo chytré smlouvy:

"sender.addr" -1 12345

256 u>B převede 256bitové nezáporné celé číslo na bajty.

"sender.addr" -1 BYTES:0000000000000000000000000000000000000000000000000000000000003039

swap prohodí dva horní prvky zásobníku.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 -1

32 i>B převede 32bitové celé číslo na bajty.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 BYTES:FFFFFFFF

B+ spojuje dvě sekvence bajtů.

 "sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF

Opět swap.

BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF "sender.addr" 

A nakonec jsou bajty zapsány do souboru B>file. Poté je náš zásobník prázdný. Zastavujeme Fift. V aktuální složce byl vytvořen soubor sender.addr. Přesuneme soubor do vytvořené složky test/addresses/.

Pojďme si napsat jednoduchý test, který pošle gramy na smart kontrakt. Tady je závazek.

Nyní se podívejme na logiku loterie.

První věc, kterou uděláme, je zkontrolovat zprávu bounced nebo ne pokud bounced, pak to ignorujeme. bounced znamená, že smlouva vrátí gramy, pokud dojde k nějaké chybě. Pokud náhle dojde k chybě, gramy nevrátíme.

Zkontrolujeme, zda je zůstatek menší než půl gramu, pak zprávu jednoduše přijmeme a ignorujeme.

Dále analyzujeme adresu chytré smlouvy, ze které zpráva přišla.

Načteme data z úložiště a poté staré sázky z historie vymažeme, pokud jich je více než dvacet. Pro pohodlí jsem napsal tři další funkce pack_order(), unpack_order(), remove_old_orders().

Dále se podíváme, zda zůstatek nestačí na platbu, pak uvážíme, že se nejedná o sázku, ale o doplnění a doplnění uložíme v orders.

Pak konečně podstata chytré smlouvy.

Nejprve, pokud hráč prohraje, uložíme jej do historie sázek a pokud je částka vyšší než 3 gramy, pošleme 1/3 majiteli smart kontraktu.

Pokud hráč vyhraje, pošleme dvojnásobek částky na adresu hráče a poté uložíme informace o sázce do historie.

() 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šechno. Odpovídající závazek.

Teď už zbývá jen jednoduché, vytvořme get-metody, abychom mohli získat informace o stavu kontraktu z vnějšího světa (ve skutečnosti číst data z jejich úložiště smart kontraktů).

Přidejme metody get. O tom, jak získat informace o smart kontraktu, napíšeme níže.

Ještě jsem zapomněl přidat kód, který zpracuje úplně první požadavek, ke kterému dojde při publikování chytré smlouvy. Odpovídající závazek. A dál opraveno bug s odesláním 1/3 částky na účet majitele.

Dalším krokem je zveřejnění chytré smlouvy. Vytvoříme složku requests.

Jako základ jsem vzal publikační kód simple-wallet-code.fc který může najít v oficiálním úložišti.

Něco, co stojí za pozornost. Vygenerujeme inteligentní úložiště smluv a vstupní zprávu. Poté se vygeneruje adresa smart kontraktu, to znamená, že adresa je známa ještě před zveřejněním v TON. Poté musíte na tuto adresu poslat několik gramů a teprve poté musíte odeslat soubor se samotnou inteligentní smlouvou, protože síť si bere provizi za uložení chytré smlouvy a operací v ní (validátoři, kteří ukládají a provádějí chytré smlouvy ). Kód je k nahlédnutí zde.

Dále spustíme publikační kód a dostaneme lottery-query.boc soubor a adresu inteligentní smlouvy.

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

Vygenerované soubory nezapomeňte uložit: lottery-query.boc, lottery.addr, lottery.pk.

V exekučních protokolech mimo jiné 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

Jen pro zajímavost uveďme požadavek na TON

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

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

account state is empty

Zasíláme na adresu 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd 2 Gram a po několika sekundách provedeme stejný příkaz. K odeslání gramů používám oficiální peněženka, a můžete někoho z chatu požádat o testovací gramy, o kterých budu mluvit na konci článku.

> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Vypadá to jako neinicializované (state:account_uninit) smart kontrakt se stejnou adresou a zůstatkem 1 000 000 000 nanogramů.

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

Nyní zveřejníme smart kontrakt. Spusťte lite-client a spusťte.

> 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 

Zkontrolujeme, zda byla smlouva zveřejněna.

> last
> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Mimo jiné dostáváme.

  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.

Odpovídající potvrzení se změnami zde.

Nyní vytvoříme požadavky na interakci s inteligentní smlouvou.

Přesněji, první necháme pro změnu adresy jako samostatnou práci a druhou uděláme pro zasílání gramů na adresu majitele. Ve skutečnosti budeme muset udělat totéž, co v testu pro odesílání gramů.

Toto je zpráva, kterou odešleme do chytré smlouvy, kde msg_seqno 165, action 2 a 9.5 gramu pro odeslání.

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

Nezapomeňte zprávu podepsat svým soukromým klíčem lottery.pk, který byl vygenerován dříve při vytváření chytré smlouvy. Zde je odpovídající commit.

Příjem informací z chytré smlouvy pomocí metod get

Nyní se podíváme na to, jak spustit metody získávání chytrých kontraktů.

Běh lite-client a spusťte metody get, které jsme napsali.

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

В result obsahuje hodnotu, kterou funkce vrací balance() z naší chytré smlouvy.
Totéž uděláme pro několik dalších metod.

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

Zeptejme se na vaši historii sázek.

> 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ískáme metody pro zobrazení informací o smart kontraktu na webu.

Zobrazení dat inteligentní smlouvy na webu

Napsal jsem jednoduchý web v Pythonu, abych pohodlně zobrazoval data z chytré smlouvy. Zde se tomu nebudu podrobně věnovat a web zveřejním v jednom závazku.

Žádosti na TON se podávají z Python přes lite-client. Pro větší pohodlí je web zabalen v Dockeru a publikován na Google Cloud. Odkaz.

Zkouší

Teď zkusme tam poslat gramy na doplnění z peněženka. Pošleme 40 gramů. A uzavřeme pár sázek pro jasnost. Vidíme, že stránka zobrazuje historii sázek, aktuální procento výher a další užitečné informace.

Vidímeže první jsme vyhráli, druhý prohráli.

Doslov

Článek se ukázal být mnohem delší, než jsem čekal, možná mohl být kratší, nebo možná jen pro člověka, který o TON nic neví a chce sepsat a zveřejnit ne zrovna jednoduchou chytrou smlouvu s možností interakce s to. Možná by se některé věci daly vysvětlit jednodušeji.

Možná by některé aspekty implementace mohly být provedeny efektivněji a elegantněji, ale pak by příprava článku zabrala ještě více času. Je také možné, že jsem někde udělal chybu nebo jsem něčemu nerozuměl, takže pokud děláte něco vážného, ​​musíte se spolehnout na oficiální dokumentaci nebo oficiální úložiště s kódem TON.

Je třeba poznamenat, že vzhledem k tomu, že samotný TON je stále v aktivní fázi vývoje, mohou nastat změny, které překazí některý z kroků v tomto článku (což se stalo během mého psaní, již bylo opraveno), ale obecný přístup je se pravděpodobně nezmění.

Nebudu mluvit o budoucnosti TON. Možná se z platformy stane něco velkého a měli bychom věnovat čas jejímu studiu a zaplnit mezeru našimi produkty.

Existuje také Váha od Facebooku, která má potenciální publikum uživatelů větší než TON. O Vahách nevím skoro nic, soudě podle fóra je tam mnohem větší aktivita než v komunitě TON. I když vývojáři a komunita TON jsou spíš underground, což je taky cool.

reference

  1. Oficiální dokumentace TON: https://test.ton.org
  2. Oficiální úložiště TON: https://github.com/ton-blockchain/ton
  3. Oficiální peněženka pro různé platformy: https://wallet.ton.org
  4. Úložiště inteligentních smluv z tohoto článku: https://github.com/raiym/astonished
  5. Odkaz na web smart contract: https://ton-lottery.appspot.com
  6. Úložiště pro rozšíření pro Visual Studio Code for FunC: https://github.com/raiym/func-visual-studio-plugin
  7. Chat o TON v Telegramu, který opravdu pomohl přijít na to v počáteční fázi. Myslím, že nebude chyba, když řeknu, že jsou tam všichni, kdo něco napsali pro TON. Tam můžete také požádat o testovací gramy. https://t.me/tondev_ru
  8. Další chat o TON, ve kterém jsem našel užitečné informace: https://t.me/TONgramDev
  9. První fáze soutěže: https://contest.com/blockchain
  10. Druhá fáze soutěže: https://contest.com/blockchain-2

Zdroj: www.habr.com

Přidat komentář