Oer hoe't jo in tûk kontrakt skriuwe en publisearje yn it Telegram Open Network (TON)

Oer hoe't jo in tûk kontrakt skriuwe en publisearje yn TON

Wêr giet dit artikel oer?

Yn it artikel sil ik prate oer hoe't ik meidie oan 'e earste (fan twa) Telegram blockchain-kompetysje, gjin priis naam, en besleat myn ûnderfining op te nimmen yn in artikel, sadat it net yn it ferjit sinkt en, miskien, helpt immen.

Sûnt ik woe net skriuwe abstrakte koade, mar te dwaan wat wurkjen, foar it artikel Ik skreau in tûk kontrakt foar in instant lottery en in webside dy't toant smart kontrakt gegevens direkt út TON sûnder gebrûk tuskenlizzende opslach.

It artikel sil nuttich wêze foar dyjingen dy't har earste tûke kontrakt yn TON wolle meitsje, mar net witte wêr't te begjinnen.

Mei de lotterij as foarbyld, sil ik gean fan it ynstallearjen fan de omjouwing nei it publisearjen fan in tûk kontrakt, ynteraksje mei it, en it skriuwen fan in webside foar it ûntfangen en publisearjen fan gegevens.

Oer dielname oan de kompetysje

Ferline oktober kundige Telegram in blockchain-kompetysje oan mei nije talen Fift и FunC. It wie nedich om te kiezen út it skriuwen fan ien fan 'e fiif foarstelde tûke kontrakten. Ik tocht dat it moai wêze soe om wat oars te dwaan, in taal te learen en wat te meitsjen, ek al hoech ik yn de takomst neat mear te skriuwen. Plus, it ûnderwerp is konstant op 'e lippen.

It is it wurdich te sizzen dat ik gjin ûnderfining hie mei it ûntwikkeljen fan tûke kontrakten.

Ik wie fan plan om oant it ein te meidwaan oant ik koe en dan in resinsjeartikel skriuwe, mar ik mislearre direkt by de earste. ik skreau in beurs mei multi-hântekening op FunC en it wurke oer it algemien. Ik naam it as basis smart kontrakt oer Solidity.

Doe tocht ik dat dit grif genôch wie om yn elts gefal wat priisplak yn te nimmen. Dêrtroch waarden sa'n 40 fan de 60 dielnimmers priiswinners en dêr wie ik net ûnder. Yn 't algemien is hjir neat mis mei, mar ien ding stoarde my. Yn 'e tiid fan' e oankundiging fan 'e resultaten wie de beoardieling fan' e test foar myn kontrakt net dien, ik frege de dielnimmers oan 'e petear as d'r immen oars wie dy't it net hie, d'r wiene gjin.

Blykber omtinken foar myn berjochten, twa dagen letter publisearren de rjochters in opmerking en ik begryp noch net oft se myn tûk kontrakt by it oardieljen per ongelok mist hawwe of gewoan tochten dat it sa slim wie dat it gjin kommentaar nedich wie. Ik stelde in fraach op de side, mar krige gjin antwurd. Hoewol it gjin geheim is wa't oardiele, achte ik it net nedich om persoanlike berjochten te skriuwen.

Der waard in soad tiid bestege oan begryp, dus waard besletten om in artikel te skriuwen. Om't d'r noch net in soad ynformaasje is, sil dit artikel helpe om tiid te besparjen foar elkenien dy't ynteressearre is.

It konsept fan tûke kontrakten yn TON

Foardat jo wat skriuwe, moatte jo útfine hokker kant jo dit ding moatte benaderje. Dêrom, no sil ik jo fertelle hokker dielen it systeem bestiet út. Mear krekter, hokker dielen jo moatte witte om op syn minst in soarte fan wurkkontrakt te skriuwen.

Wy sille rjochtsje op it skriuwen fan in tûk kontrakt en wurkje mei TON Virtual Machine (TVM), Fift и FunC, Dus it artikel is mear as in beskriuwing fan 'e ûntwikkeling fan in gewoan programma. Wy sille net dwaen oer hoe't it platfoarm sels hjir wurket.

Yn it algemien oer hoe't it wurket TVM en taal Fift der is goede offisjele dokumintaasje. Wylst ik meidwaan oan 'e konkurrinsje en no by it skriuwen fan it hjoeddeistige kontrakt, kearde ik my faak ta har.

De wichtichste taal wêryn tûk kontrakten wurde skreaun is FunC. D'r is op it stuit gjin dokumintaasje oer, dus om wat te skriuwen moatte jo foarbylden studearje fan tûke kontrakten út it offisjele repository en de ymplemintaasje fan 'e taal sels dêr, plus jo kinne sjen nei foarbylden fan tûke kontrakten fan 'e ôfrûne twa kompetysjes. Links oan 'e ein fan it artikel.

Litte wy sizze dat wy al in tûk kontrakt skreaun hawwe foar FunC, dêrnei kompilearje wy de koade yn Fift assembler.

It gearstalde tûke kontrakt moat noch publisearre wurde. Om dit te dwaan moatte jo in funksje yn skriuwe Fift, dy't de tûke kontraktkoade en guon oare parameters as ynfier nimme, en de útfier sil in bestân wêze mei de útwreiding .boc (wat betsjut "tas fan sellen"), en, ôfhinklik fan hoe't wy skriuwe it, in privee kaai en adres, dat wurdt oanmakke basearre op de smart kontrakt koade. Jo kinne al stjoere gram nei it adres fan in tûk kontrakt dat is noch net publisearre.

Om publisearje in smart kontrakt yn TON ûntfongen .boc it bestân sil nei de blockchain stjoerd wurde moatte mei in ljochtklient (mear oer dat hjirûnder). Mar foardat jo publisearje, moatte jo grammen oerdrage oan it generearre adres, oars sil it tûke kontrakt net publisearre wurde. Nei publikaasje kinne jo ynteraksje mei it tûke kontrakt troch it berjochten fan bûten te stjoeren (bygelyks mei in ljocht kliïnt) of fan binnen (bygelyks, ien tûk kontrakt stjoert in oar in berjocht binnen TON).

Sadree't wy begripe hoe't de koade wurdt publisearre, wurdt it makliker. Wy witte sawat wat wy skriuwe wolle en hoe't ús programma wurket. En by it skriuwen sykje wy nei hoe't dit al ymplementearre is yn besteande tûke kontrakten, of wy sjogge nei de ymplemintaasjekoade Fift и FunC yn it offisjele repository, of sjoch yn 'e offisjele dokumintaasje.

Hiel faak socht ik nei trefwurden yn it Telegram-petear wêr't alle kompetysje-dielnimmers en Telegram-meiwurkers sammele, en it barde sa dat tidens de kompetysje elkenien dêr sammele en begon te besprekken oer Fift en FunC. Link oan 'e ein fan it artikel.

It is tiid om fan teory nei praktyk te gean.

It tarieden fan it miljeu foar it wurkjen mei TON

Ik haw alles dien dat sil wurde beskreaun yn it artikel oer MacOS en dûbel kontrolearre yn skjinne Ubuntu 18.04 LTS op Docker.

It earste ding dat jo moatte dwaan is download en ynstallearje lite-client wêrmei jo fersiken kinne stjoere nei TON.

De ynstruksjes op 'e offisjele webside beskriuwe it ynstallaasjeproses yn frij detail en dúdlik en litte guon details weg. Hjir folgje wy de ynstruksjes, ynstallearje de ûntbrekkende ôfhinklikens ûnderweis. Ik haw net elk projekt sels kompilearre en ynstalleare fanút it offisjele Ubuntu-repository (op MacOS haw ik brûkt 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 

Sadree't alle ôfhinklikens binne ynstallearre kinne jo ynstallearje lite-client, Fift, FunC.

Earst klonen wy it TON-repository tegearre mei syn ôfhinklikens. Foar it gemak sille wy alles yn in map dwaan ~/TON.

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

It repository bewarret ek ymplemintaasjes Fift и FunC.

No binne wy ​​​​klear om it projekt te sammeljen. De repositorykoade wurdt yn in map klone ~/TON/ton. de ~/TON meitsje in map build en sammelje it projekt yn it.

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

Om't wy in tûk kontrakt sille skriuwe, moatte wy net allinich lite-clientmar Fift с FunC, dus litte wy alles kompilearje. It is gjin fluch proses, dus wy wachtsje.

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

Download dan it konfiguraasjetriem dat gegevens befettet oer it knooppunt wêrop lite-client sil ferbine.

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

It meitsjen fan de earste oanfragen oan TON

No litte wy begjinne lite-client.

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

As de bou suksesfol wie, sille jo nei lansearring in log sjen fan 'e ferbining fan' e ljochtklient nei it knooppunt.

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

Jo kinne it kommando útfiere help en sjoch hokker kommando's beskikber binne.

help

Litte wy de kommando's listje dy't wy sille brûke yn dit artikel.

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

No binne wy ​​klear om it kontrakt sels te skriuwen.

Ymplemintaasje

Idea

Lykas ik hjirboppe skreau, is it tûke kontrakt dat wy skriuwe in lotterij.

Boppedat is dit gjin lotterij wêryn jo in kaartsje moatte keapje en in oere, dei of moanne wachtsje, mar in direkte ien wêryn de brûker oerstapt nei it kontraktadres N gram, en daliks krijt it werom 2 * N gram of ferliest. Wy meitsje de kâns om te winnen oer 40%. As d'r net genôch grammen binne foar betelling, dan sille wy de transaksje beskôgje as in opheffing.

Boppedat is it wichtich dat bets kinne wurde sjoen yn it echt tiid en yn in handige foarm, sadat de brûker kin fuortendaliks begripe oft er wûn of ferlern. Dêrom moatte jo meitsje in webside dy't sil sjen litte bets en resultaten direkt út TON.

It skriuwen fan in tûk kontrakt

Foar it gemak haw ik de koade foar FunC markearre; de ​​plugin kin fûn en ynstalleare wurde yn it sykjen fan Visual Studio Code; as jo ynienen wat tafoegje wolle, haw ik de plugin iepenbier beskikber makke. Ek, immen earder makke in plugin foar wurkjen mei Fift, kinne jo ek ynstallearje it en fine it yn VSC.

Litte wy fuortendaliks in repository meitsje wêr't wy de tuskenresultaten sille begean.

Om ús libben makliker te meitsjen, sille wy in tûk kontrakt skriuwe en it lokaal testen oant it klear is. Pas dêrnei sille wy it yn TON publisearje.

It tûke kontrakt hat twa eksterne metoaden dy't tagonklik wurde kinne. Earste, recv_external() dizze funksje wurdt útfierd as in fersyk foar it kontrakt komt fan 'e bûtenwrâld, dat is, net fan TON, bygelyks, as wy sels in berjocht generearje en it fia de lite-kliïnt stjoere. Twadde, recv_internal() dit is wannear't, binnen TON sels, elk kontrakt ferwiist nei ús. Yn beide gefallen kinne jo parameters trochjaan oan de funksje.

Litte wy begjinne mei in ienfâldich foarbyld dat sil wurkje as publisearre, mar d'r is gjin funksjonele lading yn.

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

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

Hjir moatte wy útlizze wat it is slice. Alle gegevens opslein yn TON Blockchain is in kolleksje TVM cell of gewoanlik cell, yn sa'n sel kinne jo oant 1023 bits fan gegevens opslaan en oant 4 keppelings nei oare sellen.

TVM cell slice of slice dit is diel fan 'e besteande cell wurdt brûkt om it te parsearjen, sil it letter dúdlik wurde. It wichtichste ding foar ús is dat wy kinne oerdrage slice en ôfhinklik fan it type berjocht, ferwurkje de gegevens yn recv_external() of recv_internal().

impure - in kaaiwurd dat oanjout dat de funksje smart kontraktgegevens feroaret.

Litte wy de kontraktkoade yn bewarje lottery-code.fc en kompilearje.

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

De betsjutting fan 'e flaggen kin besjoen wurde mei it kommando

~/TON/build/crypto/func -help

Wy hawwe gearstald Fift assembler koade yn 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

It kin lokaal lansearre wurde, dêrfoar sille wy it miljeu tariede.

Tink derom dat de earste line ferbynt Asm.fif, dit is koade skreaun yn Fift foar de Fift-assembler.

Om't wy it tûke kontrakt lokaal wolle útfiere en testen, sille wy in bestân oanmeitsje lottery-test-suite.fif en kopiearje de gearstalde koade dêr, ferfanging fan de lêste rigel dêryn, dy't de tûke kontraktkoade skriuwt nei in konstante codeom it dan oer te setten nei de firtuele masine:

"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

Oant no liket it dúdlik, litte wy no oan itselde bestân de koade tafoegje dy't wy sille brûke om TVM te 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 wy registrearje de kontekst, dat is de gegevens wêrmei de TVM (as netwurk steat) sil wurde lansearre. Sels tidens de konkurrinsje liet ien fan 'e ûntwikkelders sjen hoe't jo meitsje kinne c7 en ik kopiearre. Yn dit artikel moatte wy miskien feroarje rand_seed sûnt de generaasje fan in willekeurich getal hinget ôf fan it en as net feroare, itselde oantal wurdt weromjûn eltse kear.

recv_internal и recv_external konstanten mei wearden 0 en -1 sille ferantwurdlik wêze foar it oproppen fan de oerienkommende funksjes yn it smart kontrakt.

No binne wy ​​​​klear om de earste test te meitsjen foar ús lege smart kontrakt. Foar dúdlikens sille wy no alle tests tafoegje oan itselde bestân lottery-test-suite.fif.

Litte wy in fariabele oanmeitsje storage en skriuw der in lege yn cell, dit sil de smart kontrakt opslach wêze.

message Dit is it berjocht dat wy fan bûten nei it tûke kontakt sille stjoere. Wy meitsje it foarearst ek leech.

variable storage 
<b b> storage ! 

variable message 
<b b> message ! 

Neidat wy hawwe taret de konstanten en fariabelen, wy starte TVM mei help fan it kommando runvmctx en trochjaan de oanmakke parameters nei de ynfier.

message @ 
recv_external 
code 
storage @ 
c7 
runvmctx 

Op it lêst sille wy slagje lykas dit tuskenlizzende koade foar Fift.

No kinne wy ​​de resultearjende koade útfiere.

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

It programma moat sûnder flaters rinne en yn 'e útfier sille wy it útfieringslog sjen:

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

Geweldich, wy hawwe de earste wurkferzje fan it tûke kontrakt skreaun.

No moatte wy funksjonaliteit tafoegje. Earst litte wy omgean mei berjochten dy't komme fan de bûtenwrâld nei recv_external()

De ûntwikkelder kiest sels it berjochtformaat dat it kontrakt akseptearje kin.

Mar meastal

  • foarearst wolle wy ús kontrakt beskermje fan 'e bûtenwrâld en it sa meitsje dat allinich de eigner fan it kontrakt eksterne berjochten nei it stjoere kin.
  • secondly, as wy stjoere in jildich berjocht nei TON, wy wolle dat dit bart krekt ien kear en as wy stjoere itselde berjocht wer, de smart kontrakt fersmyt it.

Dus hast elk kontrakt lost dizze twa problemen op, om't ús kontrakt eksterne berjochten akseptearret, moatte wy dêr ek foar soargje.

Wy sille it yn omkearde folchoarder dwaan. Lit ús earst it probleem oplosse mei werhelling; as it kontrakt al sa'n berjocht hat krigen en it ferwurke, sil it it net in twadde kear útfiere. En dan sille wy it probleem oplosse sadat allinich in bepaalde rûnte fan minsken berjochten stjoere kin nei it tûke kontrakt.

D'r binne ferskate manieren om it probleem op te lossen mei dûbele berjochten. Hjir is hoe't wy it sille dwaan. Yn it tûke kontrakt inisjalisearje wy de teller fan ûntfongen berjochten mei de begjinwearde 0. Yn elk berjocht nei it tûke kontrakt sille wy de hjoeddeistige tellerwearde tafoegje. As de tellerwearde yn it berjocht net oerienkomt mei de wearde yn it tûke kontrakt, dan ferwurkje wy it net; as it docht, dan ferwurkje wy it en ferheegje de teller yn it tûke kontrakt mei 1.

Wy komme werom nei lottery-test-suite.fif en foegje der in twadde test oan. As wy stjoere in ferkeard nûmer, de koade moat smyt in útsûndering. Lit bygelyks de kontraktgegevens 166 opslaan, en wy sille 165 stjoere.

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

Litte wy begjinne.

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

En wy sille sjen dat de test wurdt útfierd mei in flater.

[ 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 dit poadium lottery-test-suite.fif moat lykje link.

Litte wy no de tsjinlogika tafoegje oan it tûke kontrakt yn 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 leit it berjocht dat wy stjoere.

It earste ding dat wy dogge is kontrolearje oft it berjocht gegevens befettet, sa net, dan geane wy ​​gewoan út.

Dan parse wy it berjocht. in_msg~load_uint(32) laadt it getal 165, 32-bit unsigned int út it ferstjoerde berjocht.

Folgjende laden wy 32 bits fan de smart kontrakt opslach. Wy kontrolearje dat it laden nûmer oerienkomt mei it trochjûne; sa net, smyt wy in útsûndering. Yn ús gefal, om't wy in net-wedstriid passe, moat in útsûndering smiten wurde.

No litte wy kompilearje.

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

Kopiearje de resultearjende koade nei lottery-test-suite.fif, net ferjitte te ferfangen de lêste rigel.

Wy kontrolearje dat de test trochgiet:

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

Rjochts hjir Jo kinne de oerienkommende commit sjen mei de hjoeddeistige resultaten.

Tink derom dat it ûngemaklik is om de kompilearre koade fan in tûk kontrakt konstant te kopiearjen yn in bestân mei tests, dus litte wy in skript skriuwe dat de koade yn in konstante foar ús skriuwt, en wy sille de kompilearre koade gewoan ferbine mei ús tests mei "include".

Meitsje in bestân yn 'e projektmap build.sh mei de folgjende ynhâld.

#!/bin/bash

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

Litte wy it útfierber meitsje.

chmod +x ./build.sh

No, gewoan ús skript útfiere om it kontrakt te kompilearjen. Mar njonken dit moatte wy it yn in konstante skriuwe code. Sa sille wy in nij bestân oanmeitsje lotter-compiled-for-test.fif, dy't wy sille opnimme yn 'e triem lottery-test-suite.fif.

Litte wy skirpt-koade tafoegje oan sh, dy't it kompilearre bestân gewoan duplikearje sil yn lotter-compiled-for-test.fif en feroarje de lêste rigel yn it.

# 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

No, om te kontrolearjen, litte wy it resultearjende skript útfiere en in bestân sil wurde generearre lottery-compiled-for-test.fif, dy't wy sille opnimme yn ús lottery-test-suite.fif

В lottery-test-suite.fif wiskje de kontrakt koade en heakje de rigel "lottery-compiled-for-test.fif" include.

Wy rinne tests om te kontrolearjen dat se passe.

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

Geweldich, no om de lansearring fan testen te automatisearjen, litte wy in bestân oanmeitsje test.sh, dy't earst sil útfiere build.sh, en dan de tests útfiere.

touch test.sh
chmod +x test.sh

Wy skriuwe binnen

./build.sh 

echo "nCompilation completedn"

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

Litte wy it dwaan test.sh en rinne it om te soargjen dat de tests wurkje.

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

Wy kontrolearje dat it kontrakt kompilearret en de tests wurde útfierd.

Geweldich, no opstarten test.sh De tests wurde gearstald en daliks útfierd. Hjir is de link nei bedriuwe.

Okee, foardat wy trochgean, litte wy noch ien ding dwaan foar it gemak.

Litte wy in map meitsje build wêr't wy it kopieare kontrakt en syn kloon sille opslaan yn in konstante lottery-compiled.fif, lottery-compiled-for-test.fif. Litte wy ek in map meitsje test wêr sil de test triem wurde opslein? lottery-test-suite.fif en mooglik oare stypjende bestannen. Link nei relevante feroarings.

Litte wy trochgean mei it ûntwikkeljen fan it tûke kontrakt.

Dêrnei moat der in test wêze dy't kontrolearret dat it berjocht is ûntfongen en de teller is bywurke yn 'e winkel as wy it juste nûmer stjoere. Mar dat dogge wy letter.

Litte wy no tinke oer hokker gegevensstruktuer en hokker gegevens moatte wurde opslein yn it tûke kontrakt.

Ik sil alles beskriuwe wat wy opslaan.

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

Folgjende moatte jo twa funksjes skriuwe. Litte wy de earste neame pack_state(), dy't de gegevens sil pakke foar folgjende opslach yn 'e smart kontrakt opslach. Litte wy de twadde neame unpack_state() sil lêze en weromjaan gegevens út opslach.

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

Wy foegje dizze twa funksjes ta oan it begjin fan it tûke kontrakt. It sil slagje lykas dit tuskenresultaat.

Om gegevens te bewarjen moatte jo de ynboude funksje neame set_data() en it sil skriuwe gegevens út pack_state() yn 'e smart kontrakt opslach.

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

No't wy handige funksjes hawwe foar it skriuwen en lêzen fan gegevens, kinne wy ​​trochgean.

Wy moatte kontrolearje dat it berjocht dat fan bûten binnenkomt is tekene troch de eigner fan it kontrakt (of in oare brûker dy't tagong hat ta de privee kaai).

As wy in tûk kontrakt publisearje, kinne wy ​​it inisjalisearje mei de gegevens dy't wy nedich binne yn opslach, dy't wurde bewarre foar takomstich gebrûk. Wy sille dêr de iepenbiere kaai opnimme, sadat wy kinne ferifiearje dat it ynkommende berjocht tekene is mei de oerienkommende priveekaai.

Foardat jo trochgean, litte wy in privee kaai oanmeitsje en it nei skriuwe test/keys/owner.pk. Om dit te dwaan, litte wy Fift yn ynteraktive modus starte en fjouwer kommando's útfiere.

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

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

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

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

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

Litte wy in map meitsje keys binnen de map test en skriuw dêr de privee kaai.

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

Wy sjogge in bestân yn 'e aktuele map owner.pk.

Wy ferwiderje de iepenbiere kaai fan 'e stapel en as it nedich is kinne wy ​​it fan' e privee krije.

No moatte wy in hantekeningferifikaasje skriuwe. Litte wy begjinne mei de test. Earst lêze wy de privee kaai út it bestân mei de funksje file>B en skriuw it nei in fariabele owner_private_key, en brûk dan de funksje priv>pub konvertearje de privee kaai nei in iepenbiere kaai en skriuw it resultaat yn 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 !

Wy sille beide kaaien nedich wêze.

Wy inisjalisearje de smart kontrakt opslach mei willekeurige gegevens yn deselde folchoarder as yn 'e funksje pack_state()en skriuw it yn in fariabele storage.

variable owner_private_key
variable owner_public_key 
variable orders
variable owner_wc
variable owner_account_id

"./keys/owner.pk" file>B owner_private_key !
owner_private_key @ priv>pub owner_public_key !
dictnew orders !
0 owner_wc !
0 owner_account_id !

<b 0 32 u, owner_public_key @ B, 0 32 u, 0 32 u, 0 Gram, 0 Gram, owner_wc @ 32 i, owner_account_id @ 256 u,  orders @ dict, b> storage !

Dêrnei sille wy in tekene berjocht opstelle, it sil allinich de hantekening en de tellerwearde befetsje.

Earst meitsje wy de gegevens dy't wy wolle ferstjoere, dan tekenje wy it mei in privee kaai en as lêste generearje wy in tekene berjocht.

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 !  

As gefolch, it berjocht dat wy sille stjoere nei de tûke kontrakt wurdt opnommen yn in fariabele message_to_send, oer funksjes hashu, ed25519_sign_uint do kinst lêze yn de Fift dokumintaasje.

En om de test út te fieren roppe wy nochris.

message_to_send @ 
recv_external 
code 
storage @
c7
runvmctx

Hjir sa It bestân mei tests soe op dit stadium sa moatte útsjen.

Litte wy de test útfiere en it sil mislearje, dus sille wy it tûke kontrakt feroarje sadat it berjochten fan dit formaat kin ûntfange en de hantekening ferifiearje.

Earst telle wy 512 bits fan 'e hantekening fan it berjocht en skriuwe it nei in fariabele, dan telle wy 32 bits fan 'e tellerfariabele.

Om't wy in funksje hawwe foar it lêzen fan gegevens fan 'e smart kontrakt opslach, sille wy it brûke.

Folgjende is it kontrolearjen fan de teller oerbrocht mei de opslach en kontrolearje de hantekening. As iets net oerienkomt, dan smyt wy in útsûndering mei de passende koade.

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 krekt hjir.

Litte wy de tests útfiere en sjen dat de twadde test mislearret. Om twa redenen binne d'r net genôch bits yn it berjocht en binne d'r net genôch bits yn 'e opslach, sadat de koade crasht by it parsearjen. Wy moatte in hantekening tafoegje oan it berjocht dat wy stjoere en de opslach kopiearje fan 'e lêste test.

Yn 'e twadde test sille wy in berjochthantekening tafoegje en de opslach fan smart kontrakt feroarje. Hjir sa de triem mei tests liket op it stuit.

Litte wy in fjirde test skriuwe, wêryn wy in berjocht stjoere ûndertekene mei de priveekaai fan in oar. Litte wy in oare privee kaai oanmeitsje en dizze opslaan yn in bestân not-owner.pk. Wy sille it berjocht ûndertekenje mei dizze privee kaai. Litte wy de tests útfiere en soargje derfoar dat alle tests passe. Bedriuwe op dit stuit.

No kinne wy ​​einlings trochgean mei it ymplementearjen fan 'e smart kontraktlogika.
В recv_external() wy sille akseptearje twa soarten berjochten.

Sûnt ús kontrakt de ferliezen fan 'e spilers sil sammelje, moat dit jild wurde oerdroegen oan' e makker fan 'e lotterij. It slúfadres fan 'e lotterijmakker wurdt opnommen yn' e opslach as it kontrakt is oanmakke.

Krekt yn gefal, wy moatte de mooglikheid om te feroarjen it adres dêr't wy stjoere gram fan 'e ferliezers. Wy moatte ek kinne stjoere grammen út de lotting nei it adres fan de eigner.

Litte wy begjinne mei de earste. Litte wy earst in test skriuwe dy't sil kontrolearje dat nei it ferstjoeren fan it berjocht it tûke kontrakt it nije adres yn 'e opslach bewarre. Tink derom dat wy yn it berjocht neist de baly en it nije adres ek stjoere action In 7-bit heul getal net-negatyf getal, ôfhinklik fan it, sille wy kieze hoe't jo it berjocht ferwurkje yn it tûke kontrakt.

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

Yn de test kinne jo sjen hoe't smartcontract opslach wurdt deserialized storage yn fift. Deserialization fan fariabelen wurdt beskreaun yn de Fift dokumintaasje.

Ferbine keppeling mei tafoege dough.

Litte wy de test útfiere en soargje derfoar dat it mislearret. Litte wy no logika tafoegje om it adres fan 'e lotterij-eigner te feroarjen.

Yn it tûke kontrakt geane wy ​​troch te parsearjen message,lêze yn action. Lit ús jo herinnerje dat wy twa sille hawwe action: feroarje adres en stjoer gram.

Dan lêze wy it nije adres fan de kontrakteigner en bewarje it yn opslach.
Wy rinne de tests en sjogge dat de tredde test mislearret. It crasht troch it feit dat it kontrakt no ek 7 bits út it berjocht parseart, dy't ûntbrekke yn 'e test. Foegje in net-besteand ta oan it berjocht action. Litte wy de tests útfiere en sjen dat alles trochgiet. hjir ynsette foar feroaringen. Grut.

Litte wy no de logika skriuwe foar it ferstjoeren fan it opjûne oantal grammen nei it earder bewarre adres.

Litte wy earst in test skriuwe. Wy sille twa tests skriuwe, ien as d'r net genôch lykwicht is, de twadde as alles mei sukses passe moat. Tests kinne besjoen wurde yn dizze commit.

Litte wy no de koade tafoegje. Lit ús earst twa helpermetoaden skriuwe. De earste get-metoade is om it hjoeddeistige saldo fan in tûk kontrakt te finen.

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

En de twadde is foar it ferstjoeren fan gram nei in oar tûk kontrakt. Ik haw dizze metoade folslein kopieare fan in oar tûk kontrakt.

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

Litte wy dizze twa metoaden tafoegje oan it tûke kontrakt en de logika skriuwe. Earst parse wy it oantal gram út it berjocht. Folgjende wy kontrolearje it lykwicht, as it is net genôch wy smyt in útsûndering. As alles goed is, stjoere wy de grammen nei it bewarre adres en aktualisearje de teller.

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

Hjir sa liket op it tûke kontrakt op it stuit. Litte wy de tests útfiere en soargje dat se passe.

Trouwens, foar in ferwurke berjocht wurdt elke kear in kommisje ôfrekkene fan it tûke kontrakt. Om de tûke kontraktberjochten it fersyk út te fieren, moatte jo nei basiskontrôles skilje accept_message().

Litte wy no trochgean nei ynterne berjochten. Yn feite, wy sille allinne akseptearje gram en stjoer werom dûbele it bedrach oan de spiler as hy wint en in tredde oan de eigner as hy ferliest.

Litte wy earst in ienfâldige test skriuwe. Om dit te dwaan, hawwe wy in testadres nedich fan it tûke kontrakt wêrfan wy grammen nei it tûke kontrakt stjoere.

De smart kontrakt adres bestiet út twa nûmers, in 32-bit hiel getal ferantwurdlik foar de workchain en in 256-bit net-negatyf hiel getal unyk rekkennûmer yn dizze workchain. Bygelyks, -1 en 12345, dit is it adres dat wy sille bewarje yn in bestân.

Ik haw de funksje kopiearre foar it bewarjen fan it adres fan 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

Litte wy sjen nei hoe't de funksje wurket, dit sil in begryp jaan oer hoe't Fift wurket. Launch Fift yn ynteraktive modus.

~/TON/build/crypto/fift -i 

Earst drukke wy -1, 12345 en de namme fan it takomstige bestân "sender.addr" op 'e stapel:

-1 12345 "sender.addr" 

De folgjende stap is om de funksje út te fieren -rot, dy't de steapel op sa'n manier ferpleatst dat boppe oan 'e steapel in unyk smart kontraktnûmer is:

"sender.addr" -1 12345

256 u>B konvertearret in 256-bit net-negatyf hiel getal nei bytes.

"sender.addr" -1 BYTES:0000000000000000000000000000000000000000000000000000000000003039

swap ruilet de boppeste twa eleminten fan 'e stapel.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 -1

32 i>B konvertearret in 32-bit hiel getal nei bytes.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 BYTES:FFFFFFFF

B+ ferbynt twa sekwinsjes fan bytes.

 "sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF

Wer swap.

BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF "sender.addr" 

En as lêste wurde de bytes nei it bestân skreaun B>file. Hjirnei is ús stapel leech. Wy stopje Fift. In triem is makke yn de aktuele map sender.addr. Litte wy it bestân ferpleatse nei de oanmakke map test/addresses/.

Litte wy in ienfâldige test skriuwe dy't gram sil stjoere nei in tûk kontrakt. Hjir is de ynset.

Litte wy no sjen nei de logika fan 'e lotterij.

It earste wat wy dogge is it berjocht kontrolearje bounced of net as bounced, dan negearje wy it. bounced betsjut dat it kontrakt sil weromjaan gram as guon flater optreedt. Wy sille gjin gram werom as der ynienen in flater optreedt.

Wy kontrolearje, as it saldo minder is as in heale gram, dan akseptearje wy gewoan it berjocht en negearje it.

Dêrnei parse wy it adres fan it tûke kontrakt wêrfan it berjocht kaam.

Wy lêze de gegevens fan 'e opslach en wiskje dan âlde bets út' e skiednis as d'r mear as tweintich binne. Foar it gemak skreau ik trije ekstra funksjes pack_order(), unpack_order(), remove_old_orders().

Dêrnei sjogge wy as it lykwicht net genôch is foar de betelling, dan beskôgje wy dat dit gjin weddenskip is, mar in oanfolling en bewarje de oanfolling yn orders.

Dan úteinlik de essinsje fan it tûke kontrakt.

As earste, as de spiler ferliest, bewarje wy it yn 'e weddenskipskiednis en as it bedrach mear is as 3 gram, stjoere wy 1/3 nei de eigner fan it tûke kontrakt.

As de spiler wint, dan stjoere wy dûbel it bedrach nei it adres fan de spiler en bewarje dan de ynformaasje oer de weddenskip yn 'e skiednis.

() 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 is alles. Korrespondearjende commit.

No is alles wat oerbliuwt ienfâldich, litte wy get-metoaden meitsje sadat wy ynformaasje kinne krije oer de steat fan it kontrakt fan 'e bûtenwrâld (yn feite, lês de gegevens fan har tûke kontraktopslach).

Litte wy krije metoaden tafoegje. Wy sille hjirûnder skriuwe oer hoe't jo ynformaasje krije oer in tûk kontrakt.

Ik fergeat ek de koade ta te foegjen dy't it earste fersyk sil ferwurkje dat opkomt by it publisearjen fan in tûk kontrakt. Korrespondearjende commit. En fierder korrizjearre bug mei it ferstjoeren fan 1/3 fan it bedrach nei it akkount fan 'e eigner.

De folgjende stap is om it tûke kontrakt te publisearjen. Litte wy in map meitsje requests.

Ik naam de publikaasjekoade as basis simple-wallet-code.fc wat kin fine yn 'e offisjele repository.

Iets dat it wurdich is om omtinken te jaan. Wy generearje in tûke kontrakt opslach en in ynfier berjocht. Hjirnei wurdt it adres fan 'e tûke kontrakt generearre, dat is, it adres is bekend noch foar publikaasje yn TON. Folgjende moatte jo ferskate grammen nei dit adres stjoere, en pas dêrnei moatte jo in bestân stjoere mei it tûke kontrakt sels, om't it netwurk in kommisje nimt foar it opslaan fan it tûke kontrakt en operaasjes dêryn (validators dy't smart opslaan en útfiere kontrakten). De koade is hjir te besjen.

Folgjende útfiere wy de publikaasjekoade en krije lottery-query.boc smart kontrakt triem en adres.

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

Ferjit net de oanmakke bestannen op te slaan: lottery-query.boc, lottery.addr, lottery.pk.

Wy sille ûnder oaren it adres fan it tûke kontrakt sjen yn 'e útfieringslogs.

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

Krekt foar de wille, lit ús in fersyk meitsje oan TON

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

En wy sille sjen dat it akkount mei dit adres leech is.

account state is empty

Wy stjoere nei it adres 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd 2 Gram en nei in pear sekonden fiere wy itselde kommando út. Om gram te stjoeren brûke ik offisjele beurs, en jo kinne freegje immen út it petear foar test gram, dêr't ik sil prate oer oan 'e ein fan it artikel.

> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

It liket op in net inisjalisearre (state:account_uninit) in tûk kontrakt mei itselde adres en in saldo fan 1 nanograms.

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

Litte wy no it tûke kontrakt publisearje. Litte wy lite-kliïnt starte en útfiere.

> 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 

Lit ús kontrolearje dat it kontrakt is publisearre.

> last
> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Wy krije ûnder oare.

  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

Dat sjogge wy account_active.

Korrespondearjende commit mei feroarings krekt hjir.

Litte wy no oanfragen oanmeitsje om te ynteraksje mei it tûke kontrakt.

Mear krekter, wy sille ferlitte de earste foar it feroarjen fan it adres as in ûnôfhinklik wurk, en wy sille dwaan de twadde foar it ferstjoeren fan grammen nei it adres fan de eigner. Yn feite sille wy itselde ding moatte dwaan as yn 'e test foar it ferstjoeren fan grammen.

Dit is it berjocht dat wy sille stjoere nei de smart kontrakt, wêr msg_seqno 165, action 2 en 9.5 gram foar ferstjoeren.

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

Ferjit net it berjocht te ûndertekenjen mei jo priveekaai lottery.pk, dy't earder generearre waard by it meitsjen fan it tûke kontrakt. Hjir is de oerienkommende commit.

Untfange ynformaasje fan in tûk kontrakt mei get-metoaden

Litte wy no sjen nei hoe't jo metoaden foar tûke kontrakt krije kinne útfiere.

Launch lite-client en rinne de get-metoaden út dy't wy skreaun hawwe.

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

В result befettet de wearde dy't de funksje jout balance() út ús smart kontrakt.
Wy sille itselde dwaan foar ferskate mear metoaden.

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

Lit ús freegje om jo bet skiednis.

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

Wy sille lite-kliïnt brûke en metoaden krije om ynformaasje oer it tûke kontrakt op 'e side te werjaan.

It werjaan fan smart kontraktgegevens op 'e webside

Ik skreau in ienfâldige webside yn Python om de gegevens fan it tûke kontrakt op in handige manier wer te jaan. Hjir sil ik net yn detail op dwaen en sil de side publisearje yn ien commit.

Fersiken oan TON wurde makke fan Python troch lite-client. Foar gemak is de side yn Docker ferpakt en publisearre op Google Cloud. Link.

Litte we it besykje

No litte wy besykje te stjoeren grammen dêr foar oanfolling fan portemonnee. Wy stjoere 40 gram. En lit ús meitsje in pear bets foar dúdlikens. Wy sjogge dat de side de skiednis fan bets toant, it hjoeddeistige winnende persintaazje en oare nuttige ynformaasje.

Wy sjoggedat wy wûn de earste, ferlearen de twadde.

Nei wurd

It artikel blykte folle langer te wêzen as ik hie ferwachte, miskien hie it koarter wêze kinnen, of miskien gewoan foar in persoan dy't neat fan TON wit en in net sa ienfâldich tûk kontrakt skriuwe en publisearje wol mei de mooglikheid om te ynteraksje mei it. Miskien koe guon dingen makliker ferklearre wurde.

Miskien hiene guon aspekten fan de ymplemintaasje effisjinter en eleganter dien kinnen, mar dan hie it noch mear tiid nedich om it artikel te meitsjen. It is ek mooglik dat ik earne in flater makke of wat net begrepen, dus as jo wat serieus dogge, moatte jo fertrouwe op 'e offisjele dokumintaasje of it offisjele repository mei de TON-koade.

It moat opmurken wurde dat, om't TON sels noch yn 'e aktive faze fan ûntwikkeling is, feroaringen kinne foarkomme dy't ien fan' e stappen yn dit artikel sille brekke (wat barde wylst ik skreau, it is al korrizjearre), mar de algemiene oanpak is ûnwierskynlik te feroarjen.

Ik sil net prate oer de takomst fan TON. Miskien sil it platfoarm wat grut wurde en wy moatte tiid besteegje oan it bestudearjen en no in niche folje mei ús produkten.

D'r is ek Libra fan Facebook, dy't in potinsjele publyk hat fan brûkers grutter dan TON. Ik wit hast neat oer Libra, neffens it foarum is d'r folle mear aktiviteit dan yn 'e TON-mienskip. Hoewol de ûntwikkelders en mienskip fan TON mear as ûndergrûn binne, wat ek cool is.

referinsjes

  1. Offisjele TON dokumintaasje: https://test.ton.org
  2. Offisjele TON-repository: https://github.com/ton-blockchain/ton
  3. Offisjele wallet foar ferskate platfoarms: https://wallet.ton.org
  4. Smart kontrakt repository út dit artikel: https://github.com/raiym/astonished
  5. Link nei de webside fan smart contract: https://ton-lottery.appspot.com
  6. Repository foar de útwreiding foar Visual Studio Code foar FunC: https://github.com/raiym/func-visual-studio-plugin
  7. Petear oer TON yn Telegram, wat echt holp om it út te finen yn 'e earste faze. Ik tink dat it gjin fersin wêze sil as ik sis dat elkenien dy't wat foar TON skreaun hat der is. Jo kinne dêr ek om testgrammen freegje. https://t.me/tondev_ru
  8. In oar petear oer TON wêryn ik nuttige ynformaasje fûn: https://t.me/TONgramDev
  9. Earste etappe fan de kompetysje: https://contest.com/blockchain
  10. Twadde etappe fan de kompetysje: https://contest.com/blockchain-2

Boarne: www.habr.com

Add a comment