Oor hoe om 'n slim kontrak in die Telegram Open Network (TON) te skryf en te publiseer

Oor hoe om 'n slim kontrak in TON te skryf en te publiseer

Waaroor gaan hierdie artikel?

In die artikel sal ek praat oor hoe ek aan die eerste (van twee) Telegram blockchain-kompetisie deelgeneem het, nie 'n prys ontvang het nie en besluit het om die ervaring in die artikel op te teken sodat dit nie in die vergetelheid wegsink nie en miskien help iemand.

Aangesien ek nie abstrakte kode wou skryf nie, maar om iets te doen wat werk, het ek vir die artikel 'n kitslotery-slimkontrak geskryf en 'n webwerf wat slimkontrakdata direk vanaf TON wys sonder om tussenberging te gebruik.

Die artikel sal nuttig wees vir diegene wat hul eerste slim kontrak in TON wil maak, maar nie weet waar om te begin nie.

Deur die voorbeeld van 'n lotery te gebruik, gaan ek van die opstel van die omgewing na die publikasie van 'n slim kontrak, interaksie daarmee, en die skryf van 'n webwerf vir die ontvangs en publisering van data.

Oor deelname aan die kompetisie

Verlede Oktober het Telegram 'n blokkettingkompetisie met nuwe tale aangekondig Fift и FunC. Dit was nodig om te kies om enige van die vyf voorgestelde slim kontrakte te skryf. Ek het gedink dit sal lekker wees om iets buitengewoon te doen, 'n taal te leer en iets te doen, al hoef ek in die toekoms niks anders te skryf nie. Boonop is die onderwerp voortdurend aan die hoor.

Dit is die moeite werd om te sê dat ek geen ondervinding gehad het in die ontwikkeling van slim kontrakte nie.

Ek het beplan om tot die einde toe deel te neem, solank dit blyk en dan ’n resensieartikel te skryf, maar ek het dadelik by die eerste een misluk. ek beursie geskryf met multi-handtekening aan FunC en hy het oor die algemeen gewerk. As basis geneem slim kontrak op Solidity.

Op daardie tydstip het ek gedink dit is beslis genoeg om ten minste 'n pryswennerplek in te neem. Gevolglik het sowat 40 uit 60 deelnemers wenners geword en ek was nie onder hulle nie. Oor die algemeen is dit niks vreesliks nie, maar een ding het my gespanne. Ten tyde van die aankondiging van die uitslae was 'n hersiening met 'n toets vir my kontrak nie gedoen nie, ek het die deelnemers aan die chat gevra of daar nog iemand is wat dit nie gehad het nie, daar was geen.

Blykbaar, nadat hulle aandag aan my boodskappe gegee het, het die beoordelaars twee dae later 'n opmerking gepubliseer en ek het steeds nie verstaan ​​nie, hulle het per ongeluk my slim kontrak tydens beoordeling gemis, of bloot gedink dat dit so erg is dat dit nie kommentaar nodig het nie. Ek het 'n vraag op die blad gevra, maar nie 'n antwoord gekry nie. Alhoewel wie geoordeel het nie 'n geheim is nie, het ek dit oorbodig geag om persoonlike boodskappe te skryf.

Baie tyd is aan begrip bestee, daarom is besluit om 'n artikel te skryf. Aangesien daar nog nie veel inligting is nie, sal die artikel help om tyd te bespaar vir almal wat belangstel.

Die konsep van slim kontrakte in TON

Voordat jy iets skryf, moet jy uitvind watter kant jy enigsins hierdie ding moet benader. Daarom sal ek nou vir jou sê uit watter dele die stelsel bestaan. Meer presies, watter dele moet jy weet om ten minste 'n soort werkkontrak te skryf.

Ons sal daarop fokus om 'n slim kontrak te skryf en saam te werk TON Virtual Machine (TVM), Fift и FunC, so die artikel is meer soos 'n beskrywing van die ontwikkeling van 'n konvensionele program. Ons sal nie hier stilstaan ​​oor hoe die platform self werk nie.

Oor die algemeen oor hoe dit werk TVM en taal Fift daar is goeie amptelike dokumentasie. Tydens my deelname aan die kompetisie en nou tydens die skryf van die huidige kontrak, het ek my gereeld tot haar gewend.

Die hooftaal waarin slim kontrakte geskryf word, is FunC. Daar is tans geen dokumentasie daaroor nie, so om iets te skryf, moet jy voorbeelde van slim kontrakte van die amptelike bewaarplek en die taalimplementering self daar bestudeer, plus jy kan na voorbeelde van slim kontrakte vir die afgelope twee kompetisies kyk. Skakels aan die einde van die artikel.

Gestel ons het reeds 'n slim kontrak geskryf vir FunC, daarna stel ons die kode saam in Fift assembler.

Die saamgestelde slimkontrak moet nog gepubliseer word. Om dit te doen, moet jy 'n funksie skryf vir Fift, wat die slimkontrakkode en 'n paar ander parameters as invoer sal neem, en die uitvoer sal 'n lêer met die uitbreiding wees .boc (wat "sak selle" beteken), en, afhangend van hoe ons dit skryf, 'n private sleutel en 'n adres wat gegenereer word op grond van die slimkontrakkode. Grams kan reeds na 'n slimkontrakadres gestuur word wat nog nie gepubliseer is nie.

Om 'n slim kontrak te publiseer in TON ontvang .boc die lêer sal met 'n ligte kliënt na die blokketting gestuur moet word (meer daaroor hieronder). Maar voordat u publiseer, moet u gram na die gegenereerde adres oordra, anders sal die slim kontrak nie gepubliseer word nie. Na publikasie sal dit moontlik wees om met 'n slim kontrak te kommunikeer deur boodskappe van buite (byvoorbeeld deur gebruik te maak van 'n ligte kliënt) of van binne (byvoorbeeld, een slim kontrak stuur 'n boodskap na 'n ander binne TON) daaraan te stuur.

Nadat ons verstaan ​​het hoe die kode gepubliseer word, word dit verder makliker. Ons weet ongeveer wat ons wil skryf en hoe ons program sal werk. En terwyl ons skryf, soek ons ​​hoe dit reeds in bestaande slim kontrakte geïmplementeer is, of ons kyk na die implementeringskode Fift и FunC in die amptelike bewaarplek, of kyk in die amptelike dokumentasie.

Ek het baie gereeld na sleutelwoorde in die Telegram-klets gesoek waar al die deelnemers van die kompetisie en Telegram-werknemers, insluitend, bymekaargekom het, dit het so gebeur dat tydens die kompetisie almal daar bymekaargekom het en Fift en FunC begin bespreek het. Skakel aan die einde van die artikel.

Dit is tyd om van teorie na praktyk te beweeg.

Berei die omgewing voor om met TON te werk

Alles wat beskryf sal word in die artikel wat ek op MacOS gedoen het en dubbel gekontroleer het in 'n skoon Ubuntu 18.04 LTS op Docker.

Die eerste ding om te doen is om af te laai en te installeer lite-client waarmee jy versoeke aan TON kan stuur.

Die instruksies op die amptelike webwerf beskryf die installasieproses in 'n mate en duidelik en laat 'n paar besonderhede weg. Hier volg ons die instruksies langs die pad en installeer die ontbrekende afhanklikhede. Ek het nie elke projek self saamgestel en vanaf die amptelike Ubuntu-bewaarplek geïnstalleer nie (op MacOS wat ek gebruik het 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 

Sodra alle afhanklikhede geïnstalleer is, kan jy installeer lite-client, Fift, FunC.

Eerstens kloon ons die TON-bewaarplek saam met die afhanklikhede. Gerieflikheidshalwe sal ons alles in 'n gids doen ~/TON.

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

Die bewaarplek stoor ook implementerings Fift и FunC.

Nou is ons gereed om die projek te bou. Bewaarplekkode in vouer gekloneer ~/TON/ton. In ~/TON skep 'n gids build en versamel die projek daarin.

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

Aangesien ons 'n slim kontrak gaan skryf, hoef ons nie net lite-clientMaar Fift с FunC, so ons stel alles saam. Nie 'n vinnige proses nie so ons wag.

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

Laai dan die konfigurasielêer af, wat data bevat oor die nodus waarnatoe lite-client sal verbind.

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

Maak die eerste versoeke in TON

Nou kom ons hardloop lite-client.

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

As die bou suksesvol was, sal jy na bekendstelling die ligte kliëntverbindingslog na die nodus sien.

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

Jy kan die opdrag uitvoer help en kyk watter opdragte beskikbaar is.

help

Kom ons lys die opdragte wat ons in hierdie artikel sal gebruik.

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

Nou is ons gereed om die kontrak self te skryf.

Implementering

Idee

Soos ek hierbo geskryf het, is die slim kontrak wat ons skryf 'n lotery.

Boonop is dit nie 'n lotery waarin u 'n kaartjie moet koop en 'n uur, 'n dag of 'n maand moet wag nie, maar 'n onmiddellike een waarin die gebruiker na die adres van die kontrak oorskakel. N gram, en kom dadelik terug 2 * N gram of verloor. Ons sal die waarskynlikheid om te wen ongeveer 40% maak. As daar nie genoeg gram vir betaling is nie, sal ons die transaksie as 'n aanvulling beskou.

Boonop is dit belangrik dat die weddenskappe intyds en op 'n gerieflike manier gesien kan word, sodat die gebruiker dadelik kan verstaan ​​of hy gewen of verloor het. Daarom moet jy 'n webwerf maak wat die tariewe en die resultaat direk vanaf TON sal wys.

Skryf 'n slim kontrak

Gerieflikheidshalwe het ek kode-uitligting vir FunC gemaak, die inprop kan gevind en geïnstalleer word in die Visual Studio Code-soektog, as jy skielik iets wil byvoeg, dan het ek die inprop in die publieke domein geplaas. Ook, iemand het voorheen 'n inprop gemaak om met Fift te werk, jy kan dit ook installeer en dit in VSC vind.

Skep onmiddellik 'n bewaarplek waar ons tussentydse resultate sal verbind.

Om ons lewe makliker te maak, sal ons 'n slim kontrak skryf en dit plaaslik toets totdat dit gereed is. Eers daarna sal ons dit in TON publiseer.

Die slimkontrak het twee eksterne metodes waartoe toegang verkry kan word. Eerstens, recv_external() hierdie funksie word uitgevoer wanneer 'n versoek na die kontrak van die buitewêreld af kom, dit wil sê nie van TON nie, byvoorbeeld wanneer ons self 'n boodskap vorm en dit via 'n lite-kliënt stuur. Tweedens, recv_internal() dit is wanneer, binne die TON self, enige kontrak na ons s'n verwys. In beide gevalle kan u parameters aan die funksie deurgee.

Kom ons begin met 'n eenvoudige voorbeeld wat sal werk as dit gepubliseer word, maar wat geen funksionele lading bevat nie.

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

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

Hier is dit nodig om te verduidelik wat slice. Alle gestoor data in TON Blockchain is 'n versameling TVM cell of bloot cell, kan so 'n sel tot 1023 bisse data en tot 4 verwysings na ander selle stoor.

TVM cell slice of slice is deel van die bestaande cell vir die ontleding daarvan gebruik word, sal dit verder duidelik wees. Die belangrikste ding vir ons is dat ons na 'n slim kontrak kan oorgaan slice en, afhangende van die tipe boodskap, verwerk die data in recv_external() of recv_internal().

impure — 'n sleutelwoord wat aandui dat die funksie die slimkontrakdata verander.

Stoor die kontrakkode in lottery-code.fc en saamstel.

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

Die waarde van die vlae kan met die opdrag bekyk word

~/TON/build/crypto/func -help

Ons het Fift assembler kode saamgestel in 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

Dit kan plaaslik bestuur word, hiervoor sal ons die omgewing voorberei.

Let daarop dat die eerste reël verbind Asm.fif, dit is kode geskryf in Fift for Fift assembler.

Aangesien ons die slim kontrak wil hardloop en toets, sal ons 'n lêer plaaslik skep lottery-test-suite.fif en kopieer die saamgestelde kode daarheen, vervang die laaste reël daarin, wat die slimkontrakkode in 'n konstante skryf codeom dit dan na die virtuele masjien oor te dra:

"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

Alhoewel dit duidelik lyk, laat ons nou die kode byvoeg wat ons sal gebruik om TVM te begin by dieselfde lêer.

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 ons skryf die konteks, dit wil sê die data waarmee die TVM (of netwerkstaat) geloods sal word. Selfs tydens die kompetisie het een van die ontwikkelaars gewys hoe om te skep c7 en ek het gekopieer. In hierdie artikel moet ons dalk verander rand_seed aangesien die generering van 'n ewekansige getal daarvan afhang en nie verander nie, sal dieselfde getal elke keer teruggestuur word.

recv_internal и recv_external konstantes met 'n waarde van 0 en -1 sal verantwoordelik wees vir die oproep van die toepaslike funksies in die slimkontrak.

Ons is nou gereed om die eerste toets vir ons leë slimkontrak te skep. Vir duidelikheid, vir nou, sal ons al die toetse by dieselfde lêer voeg. lottery-test-suite.fif.

Kom ons skep 'n veranderlike storage en skryf 'n leë cell, sal dit die stoor van die slim kontrak wees.

message dit is die boodskap wat ons van buite aan die slim kontak sal stuur. Kom ons maak dit vir eers leeg.

variable storage 
<b b> storage ! 

variable message 
<b b> message ! 

Nadat ons die konstantes en veranderlikes voorberei het, begin ons TVM deur die opdrag te gebruik runvmctx en gee die geskep parameters na die invoer.

message @ 
recv_external 
code 
storage @ 
c7 
runvmctx 

Op die ou end sal ons kan so intermediêre kode na Fift.

Nou kan ons die gevolglike kode laat loop.

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

Die program behoort sonder foute te werk en in die uitvoer sal ons die uitvoeringslogboek sien:

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

Wonderlik, ons het die eerste werkende weergawe van die slim kontrak geskryf.

Nou moet ons funksionaliteit byvoeg. Kom ons handel eers oor die boodskappe wat van die buitewêreld af na recv_external()

Die ontwikkelaar kies self die boodskapformaat wat die kontrak kan aanvaar.

Maar gewoonlik

  • Eerstens wil ons ons kontrak van die buitewêreld beskerm en dit so maak dat slegs die eienaar van die kontrak eksterne boodskappe daaraan kan stuur.
  • tweedens, wanneer ons 'n geldige boodskap aan TON stuur, wil ons hê dit moet presies een keer gebeur en wanneer dieselfde boodskap weer gestuur word, verwerp die slimkontrak dit.

Daarom word hierdie twee probleme in byna elke kontrak opgelos, aangesien ons kontrak eksterne boodskappe aanvaar, moet ons ook hiervoor sorg.

Ons sal dit in omgekeerde volgorde doen. Eerstens los ons die probleem op met herhaling, as die kontrak reeds so 'n boodskap ontvang en verwerk het, dan sal dit dit nie 'n tweede keer uitvoer nie. En dan sal ons die probleem oplos sodat net 'n sekere kring mense boodskappe na die slim kontrak kan stuur.

Daar is verskillende maniere om die probleem met herhaalde boodskappe op te los. Ons sal dit op hierdie manier doen. In die slimkontrak inisialiseer ons die teller van ontvangde boodskappe met 'n beginwaarde van 0. In elke boodskap by die slimkontrak sal ons die huidige waarde van die teller byvoeg. As die waarde van die teller in die boodskap nie ooreenstem met die waarde in die slim kontrak nie, dan verwerk ons ​​dit nie, indien wel, dan verwerk en verhoog ons die teller in die slim kontrak met 1.

Ons keer terug na lottery-test-suite.fif en voeg die tweede toets daarby. Kom ons stuur 'n ongeldige nommer, die kode moet 'n uitsondering gee. Byvoorbeeld, kom ons sê 166 word in die kontrakdata gestoor, en ons sal 165 stuur.

<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"

Kom ons hardloop.

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

En ons sal sien dat die toets met 'n fout uitgevoer word.

[ 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

Op hierdie stadium lottery-test-suite.fif moet lyk по ссылке.

Kom ons voeg nou die teenlogika by die slim kontrak in 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ê die boodskap wat ons stuur.

Die eerste ding wat ons doen is om te kyk of daar data in die boodskap is, indien nie, dan gaan ons net uit.

Vervolgens ontleed ons die boodskap. in_msg~load_uint(32) laai nommer 165, 32-bis unsigned int van die oorgedra boodskap.

Vervolgens laai ons 32 bisse vanaf die slim kontrakberging. Ons kyk of die gelaaide nommer ooreenstem met die geslaagde een, indien nie, gooi ons 'n uitsondering. In ons geval, aangesien ons in 'n wanverhouding verbygaan, moet 'n uitsondering gegooi word.

Kom ons stel nou saam.

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

Kopieer die resulterende kode na lottery-test-suite.fif, nie vergeet om die laaste reël te vervang nie.

Kontroleer of die toets slaag:

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

Net hier jy kan die ooreenstemmende commit sien met huidige resultate.

Let daarop dat dit ongerieflik is om voortdurend die saamgestelde slimkontrakkode na die toetslêer te kopieer, so ons sal 'n skrip skryf wat die kode na 'n konstante vir ons sal skryf, en ons sal eenvoudig die saamgestelde kode aan ons toetse koppel met "include".

Skep 'n lêer in die projekgids build.sh met die volgende inhoud.

#!/bin/bash

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

Kom ons maak dit uitvoerbaar.

chmod +x ./build.sh

Nou is dit genoeg om ons skrif te laat loop om die kontrak saam te stel. Maar behalwe dit, moet ons dit in 'n konstante skryf code. Ons sal dus 'n nuwe lêer skep lotter-compiled-for-test.fif, wat ons by die lêer sal insluit lottery-test-suite.fif.

Kom ons voeg kode by sh script wat eenvoudig die saamgestelde lêer in sal dupliseer lotter-compiled-for-test.fif en verander die laaste reël daarin.

# 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

Nou, om na te gaan, voer die resulterende skrip uit en ons sal 'n lêer genereer lottery-compiled-for-test.fifwat ons in ons sal insluit lottery-test-suite.fif

В lottery-test-suite.fif verwyder die kontrakkode en voeg die reël by "lottery-compiled-for-test.fif" include.

Doen toetse om te sien of hulle slaag.

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

Wonderlik, kom ons skep nou 'n lêer om die bekendstelling van die toetse te outomatiseer test.sh, wat eers sal uitvoer build.shen voer dan toetse uit.

touch test.sh
chmod +x test.sh

Ons skryf binne

./build.sh 

echo "nCompilation completedn"

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

Kom ons doen test.sh en hardloop om seker te maak die toetse werk.

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

Ons kyk of die kontrak saamgestel is en die toetse uitgevoer word.

Fantasties, nou aan die begin test.sh die toetse sal saamgestel en onmiddellik uitgevoer word. Hier is 'n skakel na pleeg.

Goed, voor ons voortgaan, laat ons nog een ding doen vir gerief.

Kom ons skep 'n gids build waar ons die gekopieerde kontrak en sy kloon geskryf in 'n konstante sal stoor lottery-compiled.fif, lottery-compiled-for-test.fif. Ons sal ook 'n gids skep test waar sal die toetslêer gestoor word lottery-test-suite.fif en moontlik ander ondersteuningslêers. Skakel na verwante veranderinge.

Kom ons gaan voort om die slim kontrak te ontwikkel.

Volgende moet 'n toets wees wat kontroleer dat die boodskap ontvang is en die teller in die winkel opgedateer is wanneer ons die korrekte nommer stuur. Maar ons sal dit later doen.

Kom ons dink nou oor watter datastruktuur en watter data in 'n slim kontrak gestoor moet word.

Ek sal alles beskryf wat ons het.

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

Die volgende stap is om twee funksies te skryf. Kom ons noem die eerste pack_state(), wat die data vir daaropvolgende berging in die slimkontrakberging sal verpak. Die tweede een, ons sal bel unpack_state() sal data van berging lees en terugstuur.

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

Ons voeg hierdie twee funksies by die begin van die slim kontrak. Dit blyk so intermediêre resultaat.

Om die data te stoor, sal jy die ingeboude funksie moet bel set_data() en dit sal data van skryf pack_state() in die slim kontrakberging.

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

Noudat ons gerieflike funksies het om data te skryf en te lees, kan ons aanbeweeg.

Ons moet seker maak dat die inkomende boodskap onderteken is deur die eienaar van die kontrak (wel, of 'n ander gebruiker wat toegang tot die private sleutel het).

Wanneer ons 'n slim kontrak publiseer, kan ons dit inisialiseer met die data wat ons in die winkel benodig, wat gestoor sal word vir toekomstige gebruik. Ons sal die publieke sleutel daar skryf sodat ons kan verifieer dat die handtekening van die inkomende boodskap deur die ooreenstemmende private sleutel gemaak is.

Voordat ons voortgaan, laat ons 'n private sleutel skep en dit na skryf test/keys/owner.pk. Om dit te doen, begin Fift in interaktiewe modus en voer vier opdragte uit.

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

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

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

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

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

Kom ons skep 'n gids keys binne 'n gids test en skryf die private sleutel daar.

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

Ons sien die lêer in die huidige gids owner.pk.

Ons verwyder die publieke sleutel uit die stapel, wanneer ons dit nodig het, kan ons dit van die private een af ​​kry.

Nou moet ons die handtekeningverifikasie skryf. Kom ons begin met 'n toets. Eerstens lees ons die private sleutel uit die lêer met die funksie file>B en skryf dit na 'n veranderlike owner_private_key, gebruik dan die funksie priv>pub omskep die private sleutel na publiek en skryf die resultaat na 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 !

Ons het albei sleutels nodig.

Ons inisialiseer die slim kontrakberging met arbitrêre data in dieselfde volgorde as in die funksie pack_state()en skryf na 'n veranderlike 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 !

Vervolgens sal ons 'n getekende boodskap saamstel, dit sal slegs die handtekening en die waarde van die teller bevat.

Eerstens skep ons die data wat ons wil oordra, dan teken ons dit met 'n private sleutel, en uiteindelik vorm ons 'n getekende boodskap.

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 !  

Gevolglik word die boodskap wat ons na die slim kontrak sal stuur na die veranderlike geskryf message_to_send, oor funksies hashu, ed25519_sign_uint jy kan lees in die Fift-dokumentasie.

En ons bel weer om die toets uit te voer.

message_to_send @ 
recv_external 
code 
storage @
c7
runvmctx

Hier so die toetslêer moet op hierdie stadium lyk.

Kom ons voer die toets uit en dit sal misluk, so ons sal die slim kontrak verander sodat dit boodskappe van hierdie formaat kan ontvang en die handtekening kan verifieer.

Eerstens lees ons 512 bisse van die handtekening van die boodskap en skryf dit na 'n veranderlike, dan lees ons 32 bisse van die tellerveranderlike.

Aangesien ons 'n funksie het om data vanaf die slim kontrakberging te lees, sal ons dit gebruik.

Verdere kontrole van die toonbank oorgedra met berging en verifikasie van die handtekening. As iets nie ooreenstem nie, gooi ons 'n uitsondering met die ooreenstemmende kode.

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

Relevante commit hier.

Kom ons voer die toetse uit en sien dat die tweede toets misluk. Om twee redes, die gebrek aan stukkies in die boodskap en die gebrek aan stukkies in die berging, sodat die kode ineenstort wanneer dit ontleed word. Ons moet die handtekening van die boodskap wat ons stuur byvoeg en die berging van die laaste toets kopieer.

In die tweede toets sal ons 'n boodskaphandtekening byvoeg en die stoor van die slimkontrak verander. Hier so lyk soos 'n lêer met toetse op die oomblik.

Kom ons skryf die vierde toets, waarin ons 'n boodskap sal stuur wat deur iemand anders se private sleutel onderteken is. Kom ons skep nog 'n private sleutel en stoor dit in 'n lêer not-owner.pk. Kom ons teken die boodskap met hierdie private sleutel. Kom ons doen die toetse en maak seker dat al die toetse slaag. pleeg op hierdie oomblik.

Nou kan ons uiteindelik voortgaan met die implementering van die slim kontraklogika.
В recv_external() ons sal twee tipes boodskappe ontvang.

Aangesien ons kontrak die verliese van die spelers sal ophoop, moet hierdie geld aan die skepper van die lotery oorgedra word. Die beursie-adres van die lottoskepper word na die kluis geskryf wanneer die kontrak geskep word.

Net vir ingeval, ons het die vermoë nodig om die adres te verander waarheen die gram van die verloorders gestuur moet word. Ons behoort ook gram van die lotery na die adres van die eienaar te kan stuur.

Kom ons begin met die eerste een. Kom ons skryf eers 'n toets wat sal kontroleer dat nadat die boodskap gestuur is, die slimkontrak die nuwe adres in die stoor gestoor het. Let daarop dat ons in die boodskap, benewens die toonbank en die nuwe adres, ook stuur action 7-bis nie-negatiewe heelgetal, afhangende daarvan, sal ons kies hoe om die boodskap in die slim kontrak te verwerk.

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

In die toets kan jy sien hoe die de-realisering van die slim kontrakberging plaasvind storage in Fift. Veranderlike deserialisering word in die Fift-dokumentasie beskryf.

Skakel na die commit met bykomende toets.

Kom ons voer die toets uit en kyk of dit misluk. Laat ons nou logika byvoeg om die adres van die lotery-eienaar te verander.

In die slim kontrak gaan ons voort om te ontleed message, lees in action. Onthou dat ons twee het action: verander adres en stuur gram.

Dan lees ons die nuwe adres van die kontrakeienaar en stoor dit in die stoor.
Ons doen die toetse en sien dat die derde toets misluk. Omval as gevolg van die feit dat die kontrak nou addisioneel 7 bisse van die boodskap ontleed, wat in die toets ontbreek. Kom ons voeg 'n nie-bestaande boodskap by die boodskap action. Kom ons doen die toetse en kyk dat alles slaag. Hier verbind tot veranderinge. Groot.

Kom ons skryf nou die logika vir die stuur van die gespesifiseerde aantal gram na die voorheen gestoorde adres.

Kom ons skryf eers 'n toets. Ons sal twee toetse skryf, een wanneer die balans nie genoeg is nie, die tweede wanneer alles suksesvol behoort te slaag. Toetse kan besigtig word in hierdie verbintenis.

Kom ons voeg nou 'n paar kode by. Kom ons skryf eers twee helpermetodes. Die eerste kry-metode is om die huidige balans van die slim kontrak uit te vind.

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

En die tweede een is om gram na 'n ander slim kontrak te stuur. Ek het hierdie metode heeltemal van 'n ander slim kontrak gekopieer.

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

Kom ons voeg hierdie twee metodes by die slim kontrak en skryf die logika. Eerstens ontleed ons die aantal gram van die boodskap. Dan gaan ons die balans na, indien nie genoeg nie, gooi ons 'n uitsondering. As alles goed is, stuur ons gram na die gestoorde adres en werk die teller op.

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

Hier so lyk op die oomblik na 'n slim kontrak. Kom ons doen die toetse en maak seker hulle slaag.

Terloops, 'n kommissie word elke keer vir 'n verwerkte boodskap van 'n slimkontrak gedebiteer. Om die slim kontrakboodskappe die versoek uit te voer, moet jy na basiese kontrole bel accept_message().

Kom ons gaan nou met interne boodskappe. Trouens, ons sal net gram aanvaar en 'n dubbele bedrag aan die speler terugstuur as hy wen en 'n derde aan die eienaar as hy verloor.

Kom ons skryf eers 'n eenvoudige toets. Om dit te doen, benodig ons 'n toetsadres van die slimkontrak waarvandaan ons gram na die slimkontrak stuur.

Die slimkontrakadres bestaan ​​uit twee nommers, 'n 32-bis heelgetal verantwoordelik vir die werkketting en 'n 256-bis nie-negatiewe heelgetal unieke rekeningnommer in hierdie werkketting. Byvoorbeeld, -1 en 12345, hierdie adres sal in 'n lêer gestoor word.

Ek het die adres stoor funksie van gekopieer 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

Kom ons kyk na hoe die funksie werk, dit sal 'n begrip gee van hoe Fift werk. Begin Fift in interaktiewe modus.

~/TON/build/crypto/fift -i 

Eers druk ons ​​-1, 12345 en die naam van die toekomstige lêer "sender.addr" op die stapel:

-1 12345 "sender.addr" 

Die volgende stap is om die funksie uit te voer -rot, wat die stapel skuif sodat die unieke nommer van die slimkontrak bo-aan die stapel is:

"sender.addr" -1 12345

256 u>B skakel 'n 256-bis nie-negatiewe heelgetal om na grepe.

"sender.addr" -1 BYTES:0000000000000000000000000000000000000000000000000000000000003039

swap ruil die boonste twee elemente van die stapel.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 -1

32 i>B skakel 'n 32-bis heelgetal om na grepe.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 BYTES:FFFFFFFF

B+ verbind twee reekse grepe.

 "sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF

weer swap.

BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF "sender.addr" 

En uiteindelik word die grepe na die lêer geskryf B>file. Daarna is ons stapel leeg. Stop Fift. Lêer geskep in huidige vouer sender.addr. Skuif die lêer na die geskepte vouer test/addresses/.

Kom ons skryf 'n eenvoudige toets wat gram na 'n slim kontrak sal stuur. Hier is die commit.

Kom ons gaan nou oor die logika van die lotery.

Die eerste ding wat ons doen is om die boodskap na te gaan bounced of nie as bounced, dan ignoreer ons dit. bounced beteken dat die kontrak gram sal terugstuur as een of ander fout voorkom. Ons sal nie gram terugstuur as 'n fout voorkom nie, ons sal nie.

Ons kyk of die balans minder as 'n halwe gram is, dan aanvaar ons eenvoudig die boodskap en ignoreer dit.

Vervolgens ontleed ons die adres van die slim kontrak waaruit die boodskap gekom het.

Ons lees die data van die stoor af en vee dan die ou weddenskappe uit die geskiedenis uit as daar meer as twintig van hulle is. Gerieflikheidshalwe het ek drie bykomende funksies geskryf pack_order(), unpack_order(), remove_old_orders().

Dan kyk ons ​​of die balans nie genoeg is vir die uitbetaling nie, dan neem ons in ag dat dit nie 'n weddenskap is nie, maar 'n aanvulling en stoor die aanvulling in orders.

Dan uiteindelik die essensie van die slim kontrak.

Eerstens, as die speler verloor het, stoor ons dit in die geskiedenis van weddenskappe en as die bedrag meer as 3 gram is, stuur ons 1/3 aan die eienaar van die slim kontrak.

As die speler gewen het, stuur ons 'n dubbele bedrag na die speler se adres en stoor dan die inligting oor die weddenskap in die geskiedenis.

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

Dis alles. Relevante commit.

Nou bly dit eenvoudig, ons sal kry metodes maak sodat inligting oor die stand van die kontrak van die buitewêreld verkry kan word (lees trouens die data van die slim kontrakberging).

Voeg Kry-metodes by. Ons sal hieronder skryf oor hoe om inligting oor 'n slim kontrak te ontvang.

Ek het ook vergeet om die kode by te voeg wat die heel eerste versoek sal verwerk wat plaasvind wanneer die slim kontrak gepubliseer word. Relevante commit. En verder gekorrigeer fout met die stuur van 1/3 van die bedrag na die eienaar se rekening.

Die volgende stap is om die slim kontrak te publiseer. Kom ons skep 'n gids requests.

Ek het die publikasiekode as basis geneem simple-wallet-code.fc wat kan vind in die amptelike bewaarplek.

Waaraan is die moeite werd om aandag te gee. Ons vorm die stoor van die slimkontrak en die toegangsboodskap. Hierna word die adres van die slim kontrak gegenereer, dit wil sê, die adres is bekend selfs voor publikasie in TON. Dan moet jy 'n paar gram na hierdie adres stuur, en eers daarna moet jy 'n lêer met die slimkontrak self stuur, aangesien die netwerk 'n kommissie neem om die slimkontrak en bedrywighede daarin te stoor (valideerders wat slim stoor en uitvoer kontrakte). Die kode kan hier gesien word.

Vervolgens voer ons die publikasiekode uit en kry lottery-query.boc lêer en slim kontrak adres.

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

Moenie vergeet om die gegenereerde lêers te stoor nie: lottery-query.boc, lottery.addr, lottery.pk.

Ons sal onder meer in die uitvoeringslogboeke die adres van die slim kontrak sien.

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

Interessantheidshalwe sal ons 'n versoek aan TON rig

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

En ons sal sien dat die rekening met hierdie adres leeg is.

account state is empty

Ons stuur na die adres 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd 2 Gram en na 'n paar sekondes voer ons dieselfde opdrag uit. Om gram te stuur gebruik ek amptelike beursie, en jy kan toetsgramme van iemand in die klets vra, waaroor ek aan die einde van die artikel sal praat.

> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Soek vir 'n ongeinitialiseerde (state:account_uninit) 'n slim kontrak met hierdie adres en 'n balans van 1 000 000 000 nanogram.

account state is (account
  addr:(addr_std
    anycast:nothing workchain_id:0 address:x044910149DBEAF8EADBB2B28722E7D6A2DC6E264EC2F1D9BEBD6FB209079BC2A)
  storage_stat:(storage_info
    used:(storage_used
      cells:(var_uint len:1 value:1)
      bits:(var_uint len:1 value:103)
      public_cells:(var_uint len:0 value:0)) last_paid:1583257959
    due_payment:nothing)
  storage:(account_storage last_trans_lt:3825478000002
    balance:(currencies
      grams:(nanograms
        amount:(var_uint len:4 value:2000000000))
      other:(extra_currencies
        dict:hme_empty))
    state:account_uninit))
x{C00044910149DBEAF8EADBB2B28722E7D6A2DC6E264EC2F1D9BEBD6FB209079BC2A20259C2F2F4CB3800000DEAC10776091DCD650004_}
last transaction lt = 3825478000001 hash = B043616AE016682699477FFF01E6E903878CDFD6846042BA1BFC64775E7AC6C4
account balance is 2000000000ng

Kom ons publiseer nou die slim kontrak. Kom ons begin lite-kliënt en voer uit.

> 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 

Kom ons kyk of die kontrak gepubliseer is.

> last
> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Ons kry onder andere

  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

Ons sien dit account_active.

Relevante commit met veranderinge hier.

Kom ons skep nou versoeke om met die slim kontrak te kommunikeer.

Meer presies, ons sal die eerste een vir die verandering van die adres as 'n onafhanklike werk laat, en ons sal die tweede een doen om gram na die eienaar se adres te stuur. Trouens, ons sal dieselfde moet doen as in die toets vir die stuur van gram.

Dit is die boodskap wat ons na die slim kontrak sal stuur, waar msg_seqno 165, action 2 en 9.5 gram om te stuur.

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

Moenie vergeet om die boodskap met jou private sleutel te onderteken nie lottery.pk, wat vroeër gegenereer is toe 'n slim kontrak geskep is. Hier is die relevante commit.

Kry inligting uit 'n slim kontrak met behulp van get-metodes

Kom ons kyk nou na hoe om slim kontrak kry metodes uit te voer.

Begin lite-client en hardloop die get-metodes wat ons geskryf het.

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

В result bevat die waarde wat deur die funksie teruggestuur word balance() uit ons slim kontrak.
Ons sal dieselfde doen vir nog verskeie metodes.

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

Ons sal die geskiedenis van tariewe aanvra.

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

Ons sal lite-kliënt gebruik en metodes kry om inligting oor die slim kontrak op die webwerf te vertoon.

Wys slim kontrakdata op die webwerf

Ek het 'n eenvoudige Python-webwerf geskryf om slim kontrakdata op 'n gerieflike manier te wys. Hier sal ek nie in detail daaroor stilstaan ​​en die webwerf publiseer nie in een commit.

Versoeke aan TON word gemaak van Python met die hulp lite-client. Gerieflikheidshalwe is die webwerf in Docker verpak en op Google Cloud gepubliseer. Skakel.

Probeer

Kom ons probeer nou om gram daarheen te stuur vir aanvulling vanaf beursie. Ons sal 40 gram stuur. En kom ons maak 'n paar weddenskappe vir duidelikheid. Ons sien dat die webwerf die geskiedenis van weddenskappe, die huidige wenpersentasie en ander nuttige inligting toon.

Ons siendat ons die eerste gewen het, die tweede verloor het.

nawoord

Die artikel blyk baie langer te wees as wat ek verwag het, miskien kon dit korter gewees het, of dalk net vir 'n persoon wat niks van TON af weet nie en 'n slim kontrak wil skryf en publiseer wat nie die maklikste is om mee te kommunikeer nie. Miskien kan sommige dinge eenvoudiger verduidelik word.

Miskien kon sommige punte in die implementering meer doeltreffend en elegant gedoen gewees het, maar dan sou die voorbereiding van die artikel nog meer tyd geneem het. Dit is ook moontlik dat ek iewers 'n fout gemaak het of iets nie verstaan ​​het nie, so as jy iets ernstig doen, moet jy staatmaak op die amptelike dokumentasie of die amptelike bewaarplek met die TON-kode.

Daar moet kennis geneem word dat aangesien TON self nog in die aktiewe ontwikkelingstadium is, veranderinge kan voorkom wat enige van die stappe in hierdie artikel sal breek (wat gebeur het terwyl ek geskryf het, ek het dit reeds reggemaak), maar die algemene benadering is onwaarskynlik om te verander.

Ek sal nie oor die toekoms van TON praat nie. Miskien sal die platform iets groots word en ons moet die tyd neem om dit te bestudeer en nou 'n nis met ons produkte te sny.

Daar is ook Weegskaal van Facebook, wat 'n groter potensiële gehoor van gebruikers as TON het. Ek weet omtrent niks van Weegskaal nie, te oordeel aan die aktiwiteitsforum is daar baie meer aktiwiteit as in die TON-gemeenskap. Alhoewel die ontwikkelaars en die TON-gemeenskap meer soos 'n underground is, wat ook cool is.

verwysings

  1. Amptelike dokumentasie oor TON: https://test.ton.org
  2. Amptelike TON-bewaarplek: https://github.com/ton-blockchain/ton
  3. Amptelike beursie vir verskillende platforms: https://wallet.ton.org
  4. Die slim kontrakbewaarplek uit hierdie artikel: https://github.com/raiym/astonished
  5. Skakel na die slimkontrak-webwerf: https://ton-lottery.appspot.com
  6. Bewaarplek vir uitbreiding vir Visual Studio Code for FunC: https://github.com/raiym/func-visual-studio-plugin
  7. Gesels oor TON in Telegram, wat baie gehelp het om dit in die aanvanklike stadium uit te vind. Ek dink dit sal nie 'n fout wees as ek sê daar is almal wat iets vir TON geskryf het nie. Jy kan ook daar vir toetsgramme vra. https://t.me/tondev_ru
  8. Nog 'n geselsie oor TON waarin ek nuttige inligting gevind het: https://t.me/TONgramDev
  9. Die eerste fase van die kompetisie: https://contest.com/blockchain
  10. Tweede rondte van die kompetisie: https://contest.com/blockchain-2

Bron: will.com

Voeg 'n opmerking