Iwwer wéi een e Smart Kontrakt am Telegram Open Network (TON) schreift a publizéiert

Iwwer wéi e Smart Kontrakt an TON ze schreiwen an ze publizéieren

Iwwer wat geet dësen Artikel?

Am Artikel wäert ech schwätzen iwwer wéi ech un der éischter (vun zwee) Telegram Blockchain Concours deelgeholl hunn, kee Präis geholl hunn an decidéiert hunn meng Erfahrung an engem Artikel opzehuelen sou datt et net an d'Vergiess ënnerzegoen an, vläicht, hëlleft een.

Well ech wollt net abstrakt Code schreiwen, mee eppes ze schaffen schaffen, fir den Artikel geschriwwen ech e Smart Kontrakt fir eng Direktnoriichten Lotterie an eng Websäit déi Smart Kontrakt Daten direkt vun TON weist ouni Zwëschenlagerung benotzt.

Den Artikel wäert nëtzlech sinn fir déi, déi hiren éischte Smart Kontrakt an TON maachen wëllen, awer net wësse wou ufänken.

Mat der Lotterie als Beispill, wäert ech vun der Ëmwelt installéieren fir e Smart Kontrakt ze publizéieren, mat him interagéieren an eng Websäit ze schreiwen fir Daten ze kréien an ze publizéieren.

Iwwer d'Participatioun am Concours

Am leschte Oktober huet Telegram e Blockchain Concours mat neie Sproochen ugekënnegt Fift и FunC. Et war néideg fir eng vun de fënnef proposéierte Smart Kontrakter ze schreiwen. Ech hu geduecht et wier flott eppes anescht ze maachen, eng Sprooch ze léieren an eppes ze maachen, och wann ech an Zukunft näischt méi schreiwen muss. Plus, d'Thema ass permanent op de Lippen.

Et ass derwäert ze soen datt ech keng Erfahrung haten fir intelligent Kontrakter z'entwéckelen.

Ech hu geplangt bis zum Schluss matzemaachen bis ech konnt an dann en Iwwerpréiwungsartikel schreiwen, mee ech hunn direkt bei der éischter gescheitert. ech geschriwwen engem Portmonni mat Multi-Ënnerschrëft op FunC an et huet allgemeng geschafft. Ech hunn et als Basis geholl Smart Kontrakt op Soliditéit.

Deemools hunn ech geduecht datt dëst definitiv genuch wier fir op d'mannst eng Präisplaz ze huelen. Als Resultat sinn ongeféier 40 vun 60 Participanten Präis Gewënner ginn an ech war net ënnert hinnen. Am Allgemengen ass et näischt falsch mat dësem, awer eng Saach huet mech gestéiert. Zu der Zäit vun der Ukënnegung vun de Resultater war d'Iwwerpréiwung vum Test fir mäi Kontrakt net gemaach, ech hunn d'Participanten am Chat gefrot ob et een aneren ass deen et net hat, et waren keng.

Anscheinend oppassen op meng Messagen, zwee Deeg méi spéit hunn d'Riichter e Kommentar verëffentlecht an ech verstinn nach ëmmer net ob se zoufälleg mäi Smart Kontrakt während der Riichterung verpasst hunn oder einfach geduecht hunn datt et sou schlecht wier datt et kee Kommentar brauch. Ech hunn eng Fro op der Säit gestallt, awer keng Äntwert kritt. Och wann et kee Geheimnis ass wien beurteelt huet, hunn ech et onnéideg ugesinn perséinlech Messagen ze schreiwen.

Vill Zäit gouf u Verständnis verbruecht, dofir gouf decidéiert en Artikel ze schreiwen. Well et nach net vill Informatioun ass, hëlleft dësen Artikel Zäit fir jiddereen interesséiert.

D'Konzept vun Smart Kontrakter an TON

Ier Dir eppes schreift, musst Dir erausfannen, vu wéi enger Säit Dir dës Saach unzegoen. Dofir wäert ech Iech elo soen aus wéi enge Deeler de System besteet. Méi präzis, wat Deeler Dir musst wëssen, fir op d'mannst eng Zort Aarbecht Kontrakt ze schreiwen.

Mir konzentréieren eis op e Smart Kontrakt ze schreiwen an ze schaffen mat TON Virtual Machine (TVM), Fift и FunC, Also ass den Artikel méi wéi eng Beschreiwung vun der Entwécklung vun engem normale Programm. Mir wäerten net ophalen wéi d'Plattform selwer hei funktionnéiert.

Am Allgemengen iwwer wéi et funktionnéiert TVM a Sprooch Fift et gëtt gutt offiziell Dokumentatioun. Wärend ech um Concours deelgeholl hunn an elo beim Schreiwen vum aktuelle Kontrakt, hunn ech mech dacks zu hatt gedréint.

D'Haaptsprooch an där Smart Kontrakter geschriwwe sinn ass FunC. Et gëtt keng Dokumentatioun doriwwer am Moment, also fir eppes ze schreiwen musst Dir Beispiller vu Smart Kontrakter aus dem offiziellen Repository studéieren an d'Ëmsetzung vun der Sprooch selwer do, plus Dir kënnt Beispiller vu Smart Kontrakter aus de leschten zwee kucken Concoursen. Linken um Enn vum Artikel.

Loosst eis soen, mir hu schonn e Smart Kontrakt geschriwwen fir FunC, duerno kompiléiere mir de Code an Fift assembler.

De kompiléierte Smart Kontrakt bleift ze publizéieren. Fir dëst ze maachen, musst Dir eng Funktioun schreiwen Fift, déi de Smart Kontrakt Code an e puer aner Parameteren als Input huelen, an d'Ausgab gëtt e Fichier mat der Extensioun .boc (wat heescht "Täsch vun Zellen"), an, jee wéi mir et schreiwen, e private Schlëssel an Adress, déi op Basis vum Smart Kontrakt Code generéiert gëtt. Dir kënnt scho Gramm op d'Adress vun engem Smart Kontrakt schécken, datt nach net publizéiert gouf.

Fir e Smart Kontrakt ze publizéieren an TON kritt .boc d'Datei muss op de Blockchain geschéckt ginn mat engem Liichtclient (méi doriwwer hei ënnen). Awer ier Dir publizéiert, musst Dir Gramm op déi generéiert Adress transferéieren, soss gëtt de Smart Kontrakt net publizéiert. No der Verëffentlechung kënnt Dir mam Smart Kontrakt interagéieren andeems Dir et Messagen vu baussen schéckt (zum Beispill mat engem Liichtclient) oder vu bannen (zum Beispill, e Smart Kontrakt schéckt engem aneren e Message bannent TON).

Wann mir verstinn wéi de Code publizéiert gëtt, gëtt et méi einfach. Mir wëssen ongeféier wat mir wëllen schreiwen a wéi eise Programm funktionnéiert. A beim Schreiwen kucke mir no wéi dëst schonn an existente Smart Kontrakter ëmgesat gëtt, oder mir kucken an den Implementéierungscode Fift и FunC am offiziellen Repository, oder kuckt an der offizieller Dokumentatioun.

Ganz dacks hunn ech no Schlësselwierder am Telegram Chat gesicht, wou all d'Participanten vun der Konkurrenz an d'Telegram Mataarbechter sech versammelt hunn, an et ass geschitt, datt während dem Concours jidderee sech do versammelt huet an ugefaang huet mat Fift a FunC ze diskutéieren. Link um Enn vum Artikel.

Et ass Zäit vun Theorie op Praxis ze plënneren.

Preparéieren d'Ëmwelt fir mat TON ze schaffen

Ech hunn alles gemaach wat am Artikel iwwer MacOS beschriwwe gëtt an et an der propperer Ubuntu 18.04 LTS op Docker duebel gepréift.

Dat éischt wat Dir maache musst ass eroflueden an z'installéieren lite-client mat deem Dir Demanden op TON schécken kann.

D'Instruktioune op der offizieller Websäit beschreiwen den Installatiounsprozess ganz detailléiert a kloer an e puer Detailer weg. Hei verfollegen mir d'Instruktioune, installéiert déi fehlend Ofhängegkeete laanscht de Wee. Ech hunn net all Projet selwer kompiléiert an aus dem offiziellen Ubuntu Repository installéiert (op MacOS hunn ech benotzt 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 

Wann all Ofhängegkeeten installéiert sinn, kënnt Dir installéieren lite-client, Fift, FunC.

Als éischt klone mir den TON Repository zesumme mat sengen Ofhängegkeeten. Fir d'Bequemlechkeet wäerte mir alles an engem Dossier maachen ~/TON.

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

De Repository späichert och Implementatiounen Fift и FunC.

Elo si mir prett de Projet ze montéieren. De Repository Code gëtt an en Dossier gekloont ~/TON/ton. d' ~/TON en Dossier erstellen build a sammelen de Projet an et.

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

Well mir e Smart Kontrakt schreiwen, brauche mir net nëmmen lite-clientmee Fift с FunC, also loosst eis alles zesummestellen. Et ass net e séiere Prozess, also mir waarden.

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

Als nächst, luet d'Konfiguratiounsdatei erof déi Daten iwwer den Node enthält lite-client wäert konnektéieren.

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

Maachen déi éischt Demanden zu TON

Loosst eis elo starten lite-client.

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

Wann de Bau erfollegräich war, da gesitt Dir nom Start e Logbuch vun der Verbindung vum Liichtclient zum Node.

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

Dir kënnt de Kommando lafen help a kuckt wéi eng Befehle verfügbar sinn.

help

Loosst eis d'Befehle lëschten déi mir an dësem Artikel benotzen.

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

Elo si mir prett de Kontrakt selwer ze schreiwen.

Ëmsetzung

Idea

Wéi ech uewen geschriwwen hunn, ass de Smart Kontrakt dee mir schreiwen eng Lotterie.

Ausserdeem ass dëst keng Lotterie an där Dir braucht en Ticket ze kafen an eng Stonn, Dag oder Mount ze waarden, awer en Direkt an deem de Benotzer op d'Kontraktadress transferéiert N Gramm, a kritt et direkt zréck 2 * N Gramm oder verléiert. Mir wäerten d'Wahrscheinlechkeet vun enger Victoire iwwer 40% maachen. Wann et net genuch Gramm fir d'Bezuelung gëtt, wäerte mir d'Transaktioun als Top-up betruechten.

Ausserdeem ass et wichteg datt Spillwette an Echtzäit an an enger praktescher Form gesi kënne ginn, sou datt de Benotzer direkt kann verstoen ob hien gewonnen oder verluer huet. Dofir musst Dir eng Websäit maachen déi Spillwette a Resultater direkt vun TON weist.

Schreiwen engem Smart Kontrakt

Fir d'Bequemlechkeet hunn ech de Code fir FunC markéiert; de Plugin kann an der Visual Studio Code Sich fonnt ginn an installéiert ginn; wann Dir op eemol eppes derbäi wëllt, hunn ech de Plugin ëffentlech verfügbar gemaach. Och een huet virdrun e Plugin fir mat Fift ze schaffen, Dir kënnt et och installéieren an et an VSC fannen.

Loosst eis direkt e Repository erstellen wou mir d'Tëscheresultater engagéieren.

Fir eist Liewen méi einfach ze maachen, wäerte mir e Smart Kontrakt schreiwen an et lokal testen bis et fäerdeg ass. Eréischt duerno publizéieren mir et am TON.

De Smart Kontrakt huet zwou extern Methoden déi zougänglech sinn. Éischten, recv_external() dës Funktioun gëtt ausgeführt wann eng Ufro un de Kontrakt vun der Äussewelt kënnt, dat heescht net vum TON, zum Beispill, wa mir selwer e Message generéieren an duerch de Lite-Client schécken. Zweeten, recv_internal() Dëst ass wann, bannent TON selwer, all Kontrakt op eis bezitt. A béide Fäll kënnt Dir Parameteren un d'Funktioun weiderginn.

Fänke mer mat engem einfache Beispill un dat funktionnéiert wann se publizéiert ginn, awer et gëtt keng funktionell Laascht dran.

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

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

Hei musse mir erklären wat et ass slice. All Daten, déi am TON Blockchain gespäichert sinn, sinn eng Sammlung TVM cell oder einfach cell, an esou enger Zell kënnt Dir bis zu 1023 Bits vun Daten a bis zu 4 Linken op aner Zellen späicheren.

TVM cell slice oder slice dëst ass en Deel vun der existéierender cell benotzt gëtt fir et ze analyséieren, wäert et méi spéit kloer ginn. Den Haapt Saach fir eis ass, datt mir kënnen Transfert slice an ofhängeg vun der Aart vu Message, veraarbecht d'Donnéeën an recv_external() oder recv_internal().

impure - e Schlësselwuert dat weist datt d'Funktioun Smart Kontraktdaten ännert.

Loosst eis de Kontraktcode späicheren lottery-code.fc a kompiléieren.

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

D'Bedeitung vun de Fändelen kann mat dem Kommando gekuckt ginn

~/TON/build/crypto/func -help

Mir hunn de Fift Assembler Code zesummegesat 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

Et kann lokal lancéiert ginn, dofir wäerte mir d'Ëmwelt virbereeden.

Bedenkt datt déi éischt Linn verbënnt Asm.fif, Dëst ass Code geschriwwen am Fift fir de Fift Assembler.

Well mir de Smart Kontrakt lokal ausféieren an testen, wäerte mir e Fichier erstellen lottery-test-suite.fif a kopéiert de kompiléierte Code do, ersetzt déi lescht Zeil dran, déi de Smart Kontrakt Code op e konstante schreift codefir se dann op déi virtuell Maschinn ze transferéieren:

"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

Bis elo schéngt et kloer, loosst eis elo dee selwechte Fichier de Code addéieren dee mir benotze fir TVM ze starten.

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 mir Rekord de Kontext, dat ass, d'Donnéeën mat deenen der TVM (oder Reseau Staat) lancéiert ginn. Och während dem Concours huet ee vun den Entwéckler gewisen wéi een erstellt c7 an ech kopéiert. An dësem Artikel musse mir eventuell änneren rand_seed well d'Generatioun vun enger zoufälleger Zuel hänkt dovun of a wann net geännert gëtt, gëtt déi selwecht Zuel all Kéier zréckginn.

recv_internal и recv_external Konstante mat Wäerter 0 an -1 wäerte verantwortlech sinn fir déi entspriechend Funktiounen am Smart Kontrakt ze ruffen.

Elo si mir prett den éischten Test fir eisen eidele Smart Kontrakt ze kreéieren. Fir Kloerheet, fir elo wäerte mir all Tester an déi selwecht Datei derbäi lottery-test-suite.fif.

Loosst eis eng Variabel erstellen storage a schreift eng eidel dran cell, dëst wäert de Smart Kontrakt Stockage ginn.

message Dëst ass de Message dee mir op de Smart Kontakt vu baussen iwwerdroen. Mir wäerten et fir de Moment och eidel maachen.

variable storage 
<b b> storage ! 

variable message 
<b b> message ! 

Nodeems mir d'Konstanten a Variabelen virbereet hunn, starten mir TVM mam Kommando runvmctx a gitt déi erstallt Parameteren un den Input.

message @ 
recv_external 
code 
storage @ 
c7 
runvmctx 

Um Enn wäerte mir et fäerdeg bréngen esou Tëschenzäit Code fir Fift.

Elo kënne mir de resultéierende Code lafen.

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

De Programm soll ouni Feeler lafen an am Output gesi mir den Ausféierungsprotokoll:

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

Great, mir hunn déi éischt Aarbecht Versioun vum Smart Kontrakt geschriwwen.

Elo musse mir Funktionalitéit derbäi. Loosst eis éischt mat Messagen beschäftegen, déi aus der Äussewelt kommen recv_external()

Den Entwéckler selwer wielt de Message Format datt de Kontrakt akzeptéieren kann.

Awer normalerweis

  • éischtens, mir wëllen eise Kontrakt vun der Äussewelt schützen an et esou maachen, datt nëmmen de Besëtzer vum Kontrakt extern Messagen un et schécken kann.
  • zweetens, wann mir eng valabel Message schécken ze TON, mir wëllen dat genee eemol geschéien a wann mir déi selwecht Message schécken erëm, de Smart Kontrakt refuséiert et.

Also bal all Kontrakt léist dës zwee Problemer, well eise Kontrakt extern Messagen akzeptéiert, musse mir eis och dofir këmmeren.

Mir maachen et an ëmgedréint Uerdnung. Als éischt, loosst eis de Problem mat der Widderhuelung léisen; wann de Kontrakt scho sou e Message kritt huet an et veraarbecht huet, gëtt et net eng zweete Kéier ausgefouert. An da wäerte mir de Problem léisen, sou datt nëmmen e bestëmmte Krees vu Leit Messagen un de Smart Kontrakt schécken kann.

Et gi verschidde Weeër fir de Problem mat duplizéierte Messagen ze léisen. Hei ass wéi mir et maachen. Am Smart Kontrakt initialiséieren mir de Compteur vun erhalen Messagen mam initialen Wäert 0. An all Message un de Smart Kontrakt addéiere mir den aktuelle Konterwäert. Wann de Konterwäert an der Noriicht net mam Wäert am Smart Kontrakt entsprécht, da veraarbechte mir et net; wann et geschitt, da veraarbechte mir et an erhéijen de Konter am Smart Kontrakt ëm 1.

Komme mer zréck op lottery-test-suite.fif a füügt en zweeten Test derbäi. Wa mir eng falsch Nummer schécken, soll de Code eng Ausnam werfen. Zum Beispill, loosst de Kontrakt Daten späicheren 166, a mir schécken 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"

Loosst eis starten.

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

A mir wäerte gesinn datt den Test mat engem Feeler ausgefouert gëtt.

[ 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

An dëser Phase lottery-test-suite.fif soll ausgesinn Link.

Loosst eis elo d'Konterlogik zum Smart Kontrakt addéieren 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 läit de Message mir schécken.

Dat éischt wat mir maachen ass kucken ob de Message Daten enthält, wann net, da gi mer einfach eraus.

Als nächst parse mir de Message. in_msg~load_uint(32) lued d'Zuel 165, 32-bëssen unsigned int aus dem iwwerdroe Message.

Als nächst luede mir 32 Bits vun der Smart Kontraktlagerung. Mir kontrolléieren datt déi gelueden Zuel mat der passéierter entsprécht; wann net, werfe mir eng Ausnam. An eisem Fall, well mir en Net-Match passéieren, sollt eng Ausnam geworf ginn.

Loosst eis elo kompiléieren.

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

Kopéiert de resultéierende Code op lottery-test-suite.fif, net vergiessen déi lescht Zeil ze ersetzen.

Mir kontrolléieren ob den Test passéiert:

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

Genau hei Dir kënnt de entspriechende Verpflichtung mat den aktuellen Resultater gesinn.

Notéiert datt et onbequem ass de kompiléierte Code vun engem Smart Kontrakt dauernd an eng Datei mat Tester ze kopéieren, also loosst eis e Skript schreiwen, deen de Code an eng Konstante fir eis schreift, a mir verbannen einfach de kompiléierte Code mat eisen Tester mat "include".

Erstellt eng Datei am Projet Dossier build.sh mat folgendem Inhalt.

#!/bin/bash

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

Loosst eis et ausféierbar maachen.

chmod +x ./build.sh

Elo, lafen just eise Skript fir de Kontrakt ze kompiléieren. Awer nieft dësem musse mir et an eng konstant schreiwen code. Also wäerte mir eng nei Datei erstellen lotter-compiled-for-test.fif, déi mir an de Fichier enthalen lottery-test-suite.fif.

Loosst eis Skirpt Code op sh addéieren, wat d'kompiléiert Datei einfach duplizéiert lotter-compiled-for-test.fif an änneren déi lescht Zeil an et.

# 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

Elo, fir ze kontrolléieren, loosst eis de resultéierende Skript lafen an eng Datei gëtt generéiert lottery-compiled-for-test.fif, déi mir an eisem lottery-test-suite.fif

В lottery-test-suite.fif läschen de Kontrakt Code a füügt d'Linn derbäi "lottery-compiled-for-test.fif" include.

Mir lafen Tester fir ze kontrolléieren ob se passéieren.

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

Super, elo fir de Start vun Tester ze automatiséieren, loosst eis eng Datei erstellen test.sh, déi als éischt ausféieren build.sh, an dann d'Tester lafen.

touch test.sh
chmod +x test.sh

Mir schreiwen bannen

./build.sh 

echo "nCompilation completedn"

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

Loosst eis et maachen test.sh a lafen et fir sécherzestellen datt d'Tester funktionnéieren.

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

Mir kontrolléieren datt de Kontrakt kompiléiert an d'Tester ausgefouert ginn.

Super, elo um Startup test.sh D'Tester ginn zesummegesat an direkt lafen. Hei ass de Link op engagéieren.

Okay, ier mer weidergoen, loosst eis nach eng Saach maachen fir d'Kamoudheet.

Loosst eis en Dossier erstellen build wou mir de kopéierte Kontrakt a säi Klon späicheren an eng Konstant geschriwwe ginn lottery-compiled.fif, lottery-compiled-for-test.fif. Loosst eis och en Dossier erstellen test wou gëtt d'Testdatei gespäichert? lottery-test-suite.fif a potenziell aner ënnerstëtzend Dateien. Link op relevant Ännerungen.

Loosst eis weider de Smart Kontrakt entwéckelen.

Als nächst sollt et en Test ginn, dee kontrolléiert datt de Message kritt gëtt an de Comptoir am Geschäft aktualiséiert gëtt wa mir déi richteg Nummer schécken. Mä mir maachen dat spéider.

Loosst eis elo iwwerdenken wéi eng Datestruktur a wéi eng Daten am Smart Kontrakt gespäichert musse ginn.

Ech wäert alles beschreiwen wat mir späicheren.

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

Als nächst musst Dir zwou Funktiounen schreiwen. Loosst eis déi éischt ruffen pack_state(), déi d'Donnéeën packen fir spéider ze späicheren an der Smart Kontraktspäicherung. Loosst eis déi zweet ruffen unpack_state() wäert Daten aus der Späichere liesen an zréckginn.

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

Mir addéieren dës zwou Funktiounen un den Ufank vum Smart Kontrakt. Et wäert geschéien esou Tëscheresultat.

Fir Daten ze späicheren, musst Dir déi agebaute Funktioun uruffen set_data() an et wäert schreiwen Daten aus pack_state() am Smart Kontrakt Stockage.

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

Elo datt mir praktesch Funktiounen hunn fir Daten ze schreiwen an ze liesen, kënne mir weidergoen.

Mir mussen iwwerpréiwen datt de Message, dee vu baussen erakënnt, vum Besëtzer vum Kontrakt ënnerschriwwe gëtt (oder engem anere Benotzer deen Zougang zum private Schlëssel huet).

Wa mir e Smart Kontrakt publizéieren, kënne mir et initialiséieren mat den Donnéeën déi mir an der Späichere brauchen, déi fir zukünfteg Benotzung gespäichert ginn. Mir wäerten den ëffentleche Schlëssel do notéieren, fir datt mir verifizéiere kënnen datt den erakommende Message mam entspriechende private Schlëssel ënnerschriwwe gouf.

Ier Dir weider geet, loosst eis e private Schlëssel erstellen a schreiwen test/keys/owner.pk. Fir dëst ze maachen, loosst eis Fift am interaktiven Modus starten a véier Kommandoen ausféieren.

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

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

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

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

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

Loosst eis en Dossier erstellen keys am Dossier test a schreift de private Schlëssel do.

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

Mir gesinn e Fichier am aktuellen Dossier owner.pk.

Mir läschen den ëffentleche Schlëssel aus dem Stack a wann néideg kënne mir et vum private kréien.

Elo musse mir eng Ënnerschrëft Verifizéierung schreiwen. Loosst eis mam Test ufänken. Als éischt liesen mir de private Schlëssel aus der Datei mat der Funktioun file>B a schreift et op eng Variabel owner_private_key, dann benotzt d'Funktioun priv>pub konvertéiert de private Schlëssel an en ëffentleche Schlëssel a schreift d'Resultat an 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 !

Mir brauche béid Schlësselen.

Mir initialiséieren de Smart Kontraktlagerung mat arbiträren Donnéeën an der selwechter Sequenz wéi an der Funktioun pack_state()a schreift et an eng Variabel 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 !

Als nächst wäerte mir en ënnerschriwwene Message komponéieren, et enthält nëmmen d'Ënnerschrëft an de Konterwäert.

Als éischt kreéiere mir d'Donnéeën déi mir wëllen iwwerdroen, dann ënnerschreiwen mir se mat engem private Schlëssel a schliisslech generéiere mir eng ënnerschriwwen Noriicht.

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 !  

Als Resultat gëtt de Message, dee mir un de Smart Kontrakt schécken, an enger Variabel opgeholl message_to_send, iwwer Funktiounen hashu, ed25519_sign_uint kann liesen an der Fift Dokumentatioun.

A fir den Test ze lafen, ruffe mir nach eng Kéier.

message_to_send @ 
recv_external 
code 
storage @
c7
runvmctx

Hei ass esou Den Dossier mat Tester soll op dëser Etapp esou ausgesinn.

Loosst eis den Test ausféieren an et wäert versoen, also wäerte mir de Smart Kontrakt änneren, sou datt et Messagen vun dësem Format ka kréien an d'Ënnerschrëft verifizéieren.

Als éischt ziele mir 512 Bits vun der Ënnerschrëft aus dem Message a schreiwen se op eng Variabel, da ziele mir 32 Bits vun der Kontervariabel.

Well mir eng Funktioun hunn fir Daten aus dem Smart Kontraktlagerung ze liesen, wäerte mir se benotzen.

Als nächst gëtt de Konter iwwerpréift mat der Späichere iwwerpréift an d'Ënnerschrëft iwwerpréift. Wann eppes net passt, da werfe mir eng Ausnahm mam passenden Code.

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

Relevant Engagement hei riets.

Loosst eis d'Tester lafen a kucken datt den zweeten Test feelt. Aus zwee Grënn gëtt et net genuch Bits an der Noriicht an et ginn net genuch Bits an der Späichere, sou datt de Code beim Parsing klappt. Mir mussen eng Ënnerschrëft op de Message bäidroen, dee mir schécken an d'Späichere vum leschten Test kopéieren.

Am zweeten Test fügen mir eng Message Ënnerschrëft an änneren de Smart Kontrakt Stockage. Hei ass esou den Dossier mat Tester gesäit am Moment aus.

Loosst eis e véierten Test schreiwen, an deem mir e Message schécken, ënnerschriwwen mat engem anere säi private Schlëssel. Loosst eis en anere private Schlëssel erstellen an en an eng Datei späicheren not-owner.pk. Mir ënnerschreiwen de Message mat dësem private Schlëssel. Loosst eis d'Tester lafen a sécherstellen datt all Tester passéieren. Engagéieren an dësem Moment.

Elo kënne mir endlech weidergoen fir déi intelligent Kontraktlogik ëmzesetzen.
В recv_external() mir wäerten zwou Zorte vu Messagen akzeptéieren.

Well eise Kontrakt d'Verloschter vun de Spiller sammelt, mussen dës Suen un den Ersteller vun der Lotterie transferéiert ginn. D'Portemonnaie Adress vum Lotterie Creator gëtt an der Späichere opgeholl wann de Kontrakt erstallt gëtt.

Just am Fall, mir brauchen d'Fähegkeet d'Adress ze änneren, op déi mir Gramm vun de Verléierer schécken. Mir sollten och fäeg sinn Gramm vun der Lotterie op d'Adress vum Besëtzer ze schécken.

Loosst eis mat deem éischten ufänken. Loosst eis als éischt en Test schreiwen, deen iwwerpréift datt nom Schécken vun der Noriicht de Smart Kontrakt déi nei Adress an der Späichere gerett huet. Notéiert w.e.g. datt mir an der Noriicht, nieft dem Comptoir an der neier Adress, och weiderginn action Eng 7-Bit ganz Zuel net-negativ Zuel, ofhängeg dovun, wäerte mir wielen wéi d'Botschaft am Smart Kontrakt veraarbecht gëtt.

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

Am Test kënnt Dir gesinn wéi d'Smartkontraktlagerung deserialiséiert gëtt storage an fift. Deserialiséierung vu Variabelen gëtt an der Fift Dokumentatioun beschriwwen.

Engagéieren Link mat dobäi Teig.

Loosst eis den Test ausféieren a sécherstellen datt et feelt. Loosst eis elo Logik derbäi fir d'Adress vum Lotteriebesëtzer z'änneren.

Am Smart Kontrakt fuere mir weider message, liesen an action. Loosst eis Iech drun erënneren datt mir zwee wäerten hunn action: Adress änneren a Gramm schécken.

Duerno liesen mir déi nei Adress vum Kontraktbesëtzer a späicheren se an der Lagerung.
Mir lafen d'Tester a gesinn datt den drëtten Test feelt. Et klappt wéinst der Tatsaach datt de Kontrakt elo zousätzlech 7 Bits aus dem Message parséiert, déi am Test fehlen. Füügt en net existent un de Message action. Loosst eis d'Tester lafen a kucken datt alles passéiert. hei engagéieren fir Ännerungen. Super.

Loosst eis elo d'Logik schreiwen fir déi spezifizéiert Zuel vu Gramm op déi virdru gespäichert Adress ze schécken.

Als éischt schreiwen mer en Test. Mir schreiwen zwee Tester, eent wann et net genuch Gläichgewiicht ass, déi zweet wann alles erfollegräich passéiere soll. Tester kënne gekuckt ginn an dësem Engagement.

Loosst eis elo de Code addéieren. Als éischt schreiwen mer zwou Hëllefsmethoden. Déi éischt kréien Method ass déi aktuell Gläichgewiicht vun engem Smart Kontrakt erauszefannen.

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

An déi zweet ass fir Gramm op en anere Smart Kontrakt ze schécken. Ech hunn dës Method komplett vun engem anere Smart Kontrakt kopéiert.

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

Loosst eis dës zwou Methoden zum Smart Kontrakt addéieren a schreiwen d'Logik. Als éischt parse mir d'Zuel vu Gramm aus dem Message. Als nächst kucken mir d'Gläichgewiicht, wann et net genuch ass, werfe mir eng Ausnam. Wann alles gutt ass, da schécken mir d'Gramm op déi gespäichert Adress an aktualiséieren de Comptoir.

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

Hei ass esou gesäit wéi de Smart Kontrakt am Moment. Loosst eis d'Tester lafen a sécherstellen datt se passéieren.

Iwwregens gëtt all Kéiers eng Kommissioun vum Smart Kontrakt fir e veraarbechte Message ofgezunn. Fir datt d'Smart Kontrakt Messagen d'Ufro ausféieren, no Basiskontrollen musst Dir uruffen accept_message().

Loosst eis elo op intern Messagen weidergoen. An Tatsaach, wäerte mir nëmmen Gramm akzeptéieren an zréck duebel Zomm un de Spiller schécken wann hien gewënnt an en Drëttel un de Besëtzer wann hie verléiert.

Als éischt schreiwen mer en einfachen Test. Fir dëst ze maachen, brauche mir eng Testadress vum Smart Kontrakt aus deem mir vermeintlech Gramm un de Smart Kontrakt schécken.

D'Smart Kontrakt Adress besteet aus zwou Zuelen, engem 32-bëssen Ganzt verantwortlech fir d'workchain an eng 256-bëssen net-negativ ganz eenzegaarteg Kont Zuel an dëser workchain. Zum Beispill, -1 an 12345, dëst ass d'Adress déi mir an eng Datei späicheren.

Ech hunn d'Funktioun kopéiert fir d'Adress ze späicheren aus 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

Loosst eis kucken wéi d'Funktioun funktionnéiert, dëst wäert e Verständnis ginn wéi Fift funktionnéiert. Lancéiere Fift am interaktive Modus.

~/TON/build/crypto/fift -i 

Als éischt drécke mir -1, 12345 an den Numm vun der zukünfteger Datei "sender.addr" op de Stack:

-1 12345 "sender.addr" 

De nächste Schrëtt ass d'Funktioun auszeféieren -rot, wat de Stack sou verännert datt am Top vum Stack eng eenzegaarteg Smart Kontrakt Nummer ass:

"sender.addr" -1 12345

256 u>B konvertéiert en 256-Bit net-negativ Ganzt op Bytes.

"sender.addr" -1 BYTES:0000000000000000000000000000000000000000000000000000000000003039

swap wiesselt déi iewescht zwee Elementer vum Stack.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 -1

32 i>B konvertéiert en 32-Bit Ganzt op Bytes.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 BYTES:FFFFFFFF

B+ verbënnt zwou Sequenzen vu Bytes.

 "sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF

Erëm do swap.

BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF "sender.addr" 

A schliisslech ginn d'Bytes an d'Datei geschriwwen B>file. Duerno ass eise Stack eidel. Mir stoppen Fift. E Fichier gouf am aktuellen Dossier erstallt sender.addr. Loosst eis d'Datei an den erstallten Dossier réckelen test/addresses/.

Loosst eis en einfachen Test schreiwen deen Gramm op e Smart Kontrakt schéckt. Hei ass d'Verpflichtung.

Loosst eis elo d'Logik vun der Lotterie kucken.

Dat éischt wat mir maachen ass de Message ze kontrolléieren bounced oder net wann bounced, dann ignoréiere mir et. bounced heescht, datt de Kontrakt Gramm zréck wäert wann e puer Feeler geschitt. Mir ginn net Gramm zréck wann e Feeler op eemol geschitt.

Mir kontrolléieren, wann d'Gläichgewiicht manner wéi en halleft Gramm ass, da akzeptéiere mir einfach de Message an ignoréieren se.

Als nächstes parse mir d'Adress vum Smart Kontrakt, aus deem de Message koum.

Mir liesen d'Donnéeën aus der Stockage an dann al Spillwette aus der Geschicht läschen wann et méi wéi zwanzeg vun hinnen. Fir d'Bequemlechkeet hunn ech dräi zousätzlech Funktiounen geschriwwen pack_order(), unpack_order(), remove_old_orders().

Als nächst kucken mir ob d'Gläichgewiicht net genuch ass fir d'Bezuelung, da betruechte mir datt dëst net eng Wette ass, awer eng Erhuelung a späichert d'Ersatzstéck an orders.

Dann endlech d'Essenz vum Smart Kontrakt.

Als éischt, wann de Spiller verléiert, späichere mir et an der Wettengeschicht a wann de Betrag méi wéi 3 Gramm ass, schécken mir 1/3 un de Besëtzer vum Smart Kontrakt.

Wann de Spiller gewënnt, da schécken mir duebel de Betrag op d'Adress vum Spiller an späichert dann d'Informatioun iwwer d'Wette an der Geschicht.

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

Dat ass alles. Entspriechend Verpflichtung.

Elo alles wat bleift ass einfach, loosst eis Get-Methoden erstellen, fir datt mir Informatioun iwwer den Zoustand vum Kontrakt vun der Äussewelt kréien (tatsächlech liesen d'Donnéeën aus hirem Smart Kontraktlagerung).

Loosst eis Get-Methoden addéieren. Mir schreiwen hei ënnendrënner wéi Dir Informatioun iwwer e Smart Kontrakt kritt.

Ech hunn och vergiess de Code derbäi ze ginn, deen déi éischt Ufro veraarbecht, déi geschitt wann Dir e Smart Kontrakt publizéiert. Entspriechend Verpflichtung. A weider korrigéiert Feeler mat 1/3 vum Betrag op de Kont vum Besëtzer ze schécken.

De nächste Schrëtt ass de Smart Kontrakt ze publizéieren. Loosst eis en Dossier erstellen requests.

Ech hunn de Verëffentlechungscode als Basis geholl simple-wallet-code.fc wat fanne kann am offizielle Repository.

Eppes derwäert opmierksam ze maachen. Mir generéieren e Smart Kontrakt Stockage an en Input Message. Duerno gëtt d'Adress vum Smart Kontrakt generéiert, dat heescht, d'Adress ass och virun der Verëffentlechung am TON bekannt. Als nächst musst Dir e puer Gramm op dës Adress schécken, an nëmmen duerno musst Dir e Fichier mam Smart Kontrakt selwer schécken, well d'Netzwierk eng Kommissioun hëlt fir de Smart Kontrakt an d'Operatiounen dran ze späicheren (Validateuren déi Smart späicheren an ausféieren Kontrakter). De Code kann hei gekuckt ginn.

Als nächst maache mir de Verëffentlechungscode aus a kréien lottery-query.boc Smart Kontrakt Datei an Adress.

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

Vergiesst net déi generéiert Dateien ze späicheren: lottery-query.boc, lottery.addr, lottery.pk.

Ënner anerem wäerte mir d'Adress vum Smart Kontrakt an den Ausféierungsprotokoller gesinn.

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

Just for fun, loosst eis eng Ufro un TON maachen

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

A mir wäerte gesinn datt de Kont mat dëser Adress eidel ass.

account state is empty

Mir schécken op d'Adress 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd 2 Gramm an no e puer Sekonnen fuere mir datselwecht Kommando aus. Ze schécken Gramm benotzen ech offiziell Portemonnaie, an Dir kënnt een aus dem Chat fir Testgramm froen, iwwer déi ech um Enn vum Artikel schwätzen.

> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Gesäit aus wéi eng oninitialiséiert (state:account_uninit) e Smart Kontrakt mat der selwechter Adress an engem Gläichgewiicht vun 1 Nanogramm.

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

Loosst eis elo de Smart Kontrakt publizéieren. Loosst eis Lite-Client starten an ausféieren.

> 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 

Loosst eis kucken ob de Kontrakt publizéiert gouf.

> last
> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Mir kréien ënner anerem.

  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

Mir gesinn dat account_active.

Entspriechend Verpflichtung mat Ännerungen hei riets.

Loosst eis elo Ufroe erstellen fir mam Smart Kontrakt ze interagéieren.

Méi präzis, wäerte mir déi éischt verloossen fir d'Adress als onofhängeg Aarbecht z'änneren, a mir wäerten déi zweet maachen fir Gramm op d'Adress vum Besëtzer ze schécken. Tatsächlech musse mir datselwecht maachen wéi am Test fir Gramm ze schécken.

Dëst ass de Message dee mir un de Smart Kontrakt schécken, wou msg_seqno 165, action 2 an 9.5 Gramm fir schécken.

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

Vergiesst net de Message mat Ärem private Schlëssel z'ënnerschreiwen lottery.pk, déi virdru generéiert gouf beim Schafe vum Smart Kontrakt. Hei ass déi entspriechend Verpflichtung.

Kritt Informatioun vun engem Smart Kontrakt mat Get Methoden

Loosst eis elo kucken wéi Dir Smart Kontrakt Get Methoden ausféiert.

Lancéiere lite-client a lafen d'Get-Methoden déi mir geschriwwen hunn.

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

В result enthält de Wäert deen d'Funktioun zréckginn balance() aus eisem Smart Kontrakt.
Mir wäerten datselwecht fir e puer méi Methoden maachen.

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

Loosst eis fir Är wetten Geschicht froen.

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

Mir benotze Lite-Client a kréien Methoden fir Informatioun iwwer de Smart Kontrakt um Site ze weisen.

Weist Smart Kontrakt Daten op der Websäit

Ech hunn eng einfach Websäit am Python geschriwwen fir d'Donnéeën vum Smart Kontrakt op eng bequem Manéier ze weisen. Hei wäert ech net am Detail op et ophalen a wäert de Site publizéieren an engem Engagement.

Ufro un TON sinn gemaach vun Python mat der Hëllef vun lite-client. Fir d'Bequemlechkeet ass de Site am Docker verpackt a publizéiert op Google Cloud. Link.

Loosst eis probéieren

Loosst eis elo probéieren Gramm dohinner ze schécken fir Ersatz vun Portemonnaie. Mir schécken 40 Gramm. A loosst eis e puer Wette fir Kloerheet maachen. Mir gesinn, datt de Site d'Geschicht vun Spillwette weist, déi aktuell Gewënn Prozentsaz an aner nëtzlech Informatiounen.

Mir gesinndatt mir déi éischt gewonnen hunn, déi zweet verluer.

Afterword

Den Artikel war vill méi laang wéi ech erwaart hunn, vläicht hätt et méi kuerz gewiescht, oder vläicht just fir eng Persoun déi näischt iwwer TON weess an en net sou einfachen Smart Kontrakt mat der Fäegkeet ze interagéieren wëll schreiwen a publizéieren et. Villäicht hätt een e puer Saache méi einfach kënnen erklären.

Vill Aspekter vun der Ëmsetzung hätte vläicht méi effizient an elegant kënne gemaach ginn, mä dann hätt et nach méi Zäit gedauert fir den Artikel virzebereeden. Et ass och méiglech datt ech iergendwou e Feeler gemaach hunn oder eppes net verstanen hunn, also wann Dir eppes sérieux maacht, musst Dir op déi offiziell Dokumentatioun oder den offiziellen Repository mam TON Code vertrauen.

Et sollt bemierkt datt well TON selwer nach ëmmer an der aktiver Etapp vun der Entwécklung ass, Ännerungen kënnen optrieden, déi irgendeng vun de Schrëtt an dësem Artikel briechen (wat geschitt wärend ech geschriwwen hunn, et ass scho korrigéiert), awer déi allgemeng Approche ass onwahrscheinlech ze änneren.

Ech wäert net iwwer d'Zukunft vun TON schwätzen. Vläicht wäert d'Plattform eppes Grousses ginn a mir sollten Zäit verbréngen fir se ze studéieren an elo eng Nisch mat eise Produkter ze fëllen.

Et gëtt och Libra vu Facebook, déi e potenzielle Publikum vu Benotzer méi grouss wéi TON huet. Ech weess bal näischt iwwer Libra, vum Forum beurteelen ass et vill méi Aktivitéit do wéi an der TON Gemeinschaft. Och wann d'Entwéckler an d'Gemeinschaft vun TON méi wéi ënnerierdesch sinn, wat och cool ass.

Referenze

  1. Offiziell TON Dokumentatioun: https://test.ton.org
  2. Offiziell TON Repository: https://github.com/ton-blockchain/ton
  3. Offiziell Portemonnaie fir verschidde Plattformen: https://wallet.ton.org
  4. Smart Kontrakt Repository aus dësem Artikel: https://github.com/raiym/astonished
  5. Link op d'Smart Kontrakt Websäit: https://ton-lottery.appspot.com
  6. Repository fir d'Extensioun fir Visual Studio Code fir FunC: https://github.com/raiym/func-visual-studio-plugin
  7. Chat iwwer TON am Telegram, wat wierklech gehollef huet et an der éischter Etapp erauszefannen. Ech mengen et wäert kee Feeler sinn wann ech soen datt jiddereen deen eppes fir TON geschriwwen huet do ass. Dir kënnt och Testgramm do froen. https://t.me/tondev_ru
  8. En aneren Chat iwwer TON an deem ech nëtzlech Informatioun fonnt hunn: https://t.me/TONgramDev
  9. Éischt Etapp vum Concours: https://contest.com/blockchain
  10. Zweet Etapp vum Concours: https://contest.com/blockchain-2

Source: will.com

Setzt e Commentaire