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 mat Multi-ĂnnerschrĂ«ft op FunC an et huet allgemeng geschafft. Ech hunn et als Basis geholl .
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 duebel an engem propperen Test iwwerpréift. Ubuntu 18.04 LTS op Docker.
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 zimlech grëndlech a kloer, a vergiessen e puer Detailer. Hei verfollege mir d'Instruktiounen a installéiere all fehlend OfhÀngegkeeten ënnerwee. Ech hunn net all Projet selwer kompilléiert an aus dem offiziellen Repository installéiert. Ubuntu (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 --recursiveDe 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 ../tonWell 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 funcAls 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.jsonMaachen 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.jsonWann 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.
helpLoosst 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 parameterslast ĐżĐŸĐ»ŃŃĐ°Đ”Ń ĐżĐŸŃĐ»Đ”ĐŽĐœĐžĐč ŃĐŸĐ·ĐŽĐ°ĐœĐœŃĐč Đ±Đ»ĐŸĐș Ń ŃĐ”ŃĐČĐ”Ńа.
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 -helpMir 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>cEt 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 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=0Great, 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 passedAn dëser Phase lottery-test-suite.fif soll ausgesinn .
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.fifDir 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.fcLoosst eis et ausféierbar maachen.
chmod +x ./build.shElo, 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.fifElo, 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.fifSuper, 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.shMir schreiwen bannen
./build.sh
echo "nCompilation completedn"
export FIFTPATH=~/TON/ton/crypto/fift/lib
~/TON/build/crypto/fift -s lottery-test-suite.fifLoosst eis et maachen test.sh a lafen et fir sécherzestellen datt d'Tester funktionnéieren.
chmod +x ./test.sh
./test.shMir 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 .
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. .
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 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
byeMir 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 .
A fir den Test ze lafen, ruffe mir nach eng Kéier.
message_to_send @
recv_external
code
storage @
c7
runvmctxDen 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 .
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. 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. 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.
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. 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 .
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));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 .
// ( wc addr fname -- ) Save address to file in 36-byte format
{ -rot 256 u>B swap 32 i>B B+ swap B>file } : save-addressLoosst 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 12345256 u>B konvertéiert en 256-Bit net-negativ Ganzt op Bytes.
"sender.addr" -1 BYTES:0000000000000000000000000000000000000000000000000000000000003039swap wiesselt déi iewescht zwee Elementer vum Stack.
"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 -132 i>B konvertéiert en 32-Bit Ganzt op Bytes.
"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 BYTES:FFFFFFFFB+ verbënnt zwou Sequenzen vu Bytes.
"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFFErë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. .
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. .
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).
. 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. . A weider 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 wat 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). .
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 0Vergiesst 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): kQAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8KpFYJust for fun, loosst eis eng Ufro un TON maachen
$ ./lite-client/lite-client -C ton-lite-client-test1.config.json
getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8KsydA mir wÀerte gesinn datt de Kont mat dëser Adress eidel ass.
account state is emptyMir schécken op d'Adress 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd 2 Gramm an no e puer Sekonnen fuere mir datselwecht Kommando aus. Ze schécken Gramm benotzen ech , an Dir kënnt een aus dem Chat fir Testgramm froen, iwwer déi ech um Enn vum Artikel schwÀtzen.
> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8KsydGesÀ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 2000000000ngLoosst 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 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8KsydMir 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_activeMir gesinn dat account_active.
Entspriechend Verpflichtung mat Ănnerungen .
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. .
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 .
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. .
Loosst eis probéieren
Loosst eis elo probéieren Gramm dohinner ze schécken fir Ersatz vun . 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.
datt 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
- Offiziell TON Dokumentatioun:
- Offiziell TON Repository:
- Offiziell Portemonnaie fir verschidde Plattformen:
- Smart Kontrakt Repository aus dësem Artikel:
- Link op d'Smart Kontrakt WebsÀit:
- Repository fir d'Extensioun fir Visual Studio Code fir FunC:
- 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.
- En aneren Chat iwwer TON an deem ech nëtzlech Informatioun fonnt hunn:
- Ăischt Etapp vum Concours:
- Zweet Etapp vum Concours:
Source: will.com
