Kuhusu jinsi ya kuandika na kuchapisha mkataba mzuri katika Mtandao wa Open Telegram (TON)

Kuhusu jinsi ya kuandika na kuchapisha mkataba mzuri katika TON

Makala hii inahusu nini?

Katika nakala hiyo nitazungumza juu ya jinsi nilivyoshiriki katika shindano la kwanza (kati la mbili) la blockchain ya Telegraph, sikuchukua tuzo, na niliamua kurekodi uzoefu wangu katika nakala ili isiingie kwenye usahaulifu na, labda, kusaidia. mtu.

Kwa kuwa sikutaka kuandika msimbo wa kufikirika, lakini kufanya kitu kinachofanya kazi, kwa makala niliandika mkataba wa smart kwa bahati nasibu ya papo hapo na tovuti inayoonyesha data ya mkataba wa smart moja kwa moja kutoka kwa TON bila kutumia hifadhi ya kati.

Nakala hiyo itakuwa muhimu kwa wale ambao wanataka kufanya mkataba wao wa kwanza wa smart katika TON, lakini hawajui wapi kuanza.

Kwa kutumia bahati nasibu kama mfano, nitatoka kusakinisha mazingira hadi kuchapisha mkataba mzuri, kuingiliana nao, na kuandika tovuti ya kupokea na kuchapisha data.

Kuhusu kushiriki katika mashindano

Oktoba iliyopita, Telegram ilitangaza shindano la blockchain na lugha mpya Fift ΠΈ FunC. Ilikuwa ni lazima kuchagua kuandika yoyote kati ya mikataba mitano iliyopendekezwa. Nilidhani itakuwa nzuri kufanya kitu tofauti, kujifunza lugha na kutengeneza kitu, hata ikiwa sitalazimika kuandika kitu kingine chochote katika siku zijazo. Zaidi ya hayo, mada ni mara kwa mara kwenye midomo.

Inafaa kusema kuwa sikuwa na uzoefu wa kuunda kandarasi nzuri.

Nilipanga kushiriki hadi mwisho kabisa hadi ningeweza na kisha kuandika nakala ya mapitio, lakini nilishindwa mara moja kwenye ile ya kwanza. I aliandika pochi ikiwa na saini nyingi FunC na ilifanya kazi kwa ujumla. Niliichukua kama msingi mkataba wa smart juu ya Solidity.

Wakati huo, nilifikiri kwamba hii ilikuwa ya kutosha kuchukua angalau nafasi fulani ya tuzo. Kwa hiyo, washiriki wapatao 40 kati ya 60 wakawa washindi wa zawadi na mimi sikuwa miongoni mwao. Kwa ujumla, hakuna kitu kibaya na hili, lakini jambo moja lilinisumbua. Wakati wa kutangazwa kwa matokeo, uhakiki wa mtihani wa mkataba wangu ulikuwa haujafanyika, niliwauliza washiriki kwenye gumzo ikiwa kuna mtu mwingine ambaye hakuwa nayo, hakuna.

Inavyoonekana kwa kuzingatia ujumbe wangu, siku mbili baadaye majaji walichapisha maoni na bado sielewi ikiwa walikosa kwa bahati mbaya mkataba wangu mzuri wakati wa kuhukumu au walidhani tu kuwa ilikuwa mbaya sana kwamba haikuhitaji maoni. Niliuliza swali kwenye ukurasa, lakini sikupata jibu. Ingawa sio siri ni nani alihukumu, niliona kuwa sio lazima kuandika ujumbe wa kibinafsi.

Muda mwingi ulitumika kuelewa, kwa hivyo iliamuliwa kuandika nakala. Kwa kuwa hakuna habari nyingi bado, makala hii itasaidia kuokoa muda kwa kila mtu anayependa.

Dhana ya mikataba mahiri katika TON

Kabla ya kuandika chochote, unahitaji kujua ni upande gani wa kukaribia jambo hili. Kwa hivyo, sasa nitakuambia ni sehemu gani mfumo unajumuisha. Kwa usahihi, ni sehemu gani unahitaji kujua ili kuandika angalau aina fulani ya mkataba wa kufanya kazi.

Tutazingatia kuandika mkataba mzuri na kufanya kazi nao TON Virtual Machine (TVM), Fift ΠΈ FunC, kwa hivyo kifungu hicho kinafanana zaidi na maelezo ya ukuzaji wa programu ya kawaida. Hatutazingatia jinsi jukwaa lenyewe linavyofanya kazi hapa.

Kwa ujumla kuhusu jinsi inavyofanya kazi TVM na lugha Fift kuna nyaraka nzuri rasmi. Wakati nikishiriki katika shindano na sasa nikiandika mkataba wa sasa, mara nyingi nilimgeukia.

Lugha kuu ambayo mikataba mahiri huandikwa ni FunC. Hakuna nyaraka juu yake kwa sasa, kwa hivyo ili kuandika kitu unahitaji kusoma mifano ya mikataba smart kutoka hazina rasmi na utekelezaji wa lugha yenyewe huko, pamoja na unaweza kuangalia mifano ya mikataba smart kutoka mbili zilizopita. mashindano. Viungo mwishoni mwa makala.

Wacha tuseme tayari tumeandika mkataba mzuri FunC, baada ya hapo tunakusanya nambari kwenye mkusanyiko wa Fift.

Mkataba mzuri uliokusanywa unasalia kuchapishwa. Kwa kufanya hivyo unahitaji kuandika kazi katika Fift, ambayo itachukua msimbo mzuri wa mkataba na vigezo vingine kama ingizo, na matokeo yatakuwa faili iliyo na kiendelezi. .boc (ambayo ina maana ya "mfuko wa seli"), na, kulingana na jinsi tunavyoiandika, ufunguo wa faragha na anwani, ambayo hutolewa kulingana na msimbo mzuri wa mkataba. Tayari unaweza kutuma gramu kwa anwani ya mkataba mahiri ambao bado haujachapishwa.

Ili kuchapisha mkataba mzuri katika TON ulipokelewa .boc faili itahitaji kutumwa kwa blockchain kwa kutumia mteja mwanga (zaidi juu ya hapo chini). Lakini kabla ya kuchapisha, unahitaji kuhamisha gramu kwa anwani iliyozalishwa, vinginevyo mkataba wa smart hautachapishwa. Baada ya kuchapishwa, unaweza kuingiliana na mkataba mahiri kwa kuutumia ujumbe kutoka nje (kwa mfano, kwa kutumia mteja mwepesi) au kutoka ndani (kwa mfano, mkataba mmoja mahiri hutuma ujumbe mwingine ndani ya TON).

Tukishaelewa jinsi msimbo unavyochapishwa, inakuwa rahisi. Takriban tunajua tunachotaka kuandika na jinsi programu yetu itafanya kazi. Na tunapoandika, tunatafuta jinsi hii tayari inatekelezwa katika mikataba mahiri iliyopo, au tunaangalia msimbo wa utekelezaji Fift ΠΈ FunC katika hazina rasmi, au angalia katika nyaraka rasmi.

Mara nyingi nilitafuta maneno muhimu kwenye mazungumzo ya Telegraph ambapo washiriki wote wa shindano na wafanyikazi wa Telegraph walikusanyika, na ikawa kwamba wakati wa shindano kila mtu alikusanyika hapo na kuanza kujadili Fift na FunC. Kiungo mwishoni mwa makala.

Ni wakati wa kuhama kutoka kwa nadharia hadi mazoezi.

Kuandaa mazingira ya kufanya kazi na TON

Nilifanya kila kitu ambacho kitaelezewa katika nakala ya MacOS na nikaiangalia mara mbili kwenye Ubuntu 18.04 LTS safi kwenye Docker.

Jambo la kwanza unahitaji kufanya ni kupakua na kusakinisha lite-client ambayo unaweza kutuma maombi kwa TON.

Maagizo kwenye tovuti rasmi yanaelezea mchakato wa ufungaji kwa undani kabisa na kwa uwazi na huacha maelezo fulani. Hapa tunafuata maagizo, kusanikisha utegemezi uliokosekana njiani. Sikukusanya kila mradi mwenyewe na kusanikisha kutoka kwa hazina rasmi ya Ubuntu (kwenye MacOS nilitumia 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 

Mara tu utegemezi wote umewekwa unaweza kusanikisha lite-client, Fift, FunC.

Kwanza, tunaunganisha hazina ya TON pamoja na tegemezi zake. Kwa urahisi, tutafanya kila kitu kwenye folda ~/TON.

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

Hifadhi pia huhifadhi utekelezaji Fift ΠΈ FunC.

Sasa tuko tayari kukusanyika mradi. Nambari ya kumbukumbu imeundwa kwenye folda ~/TON/ton. Katika ~/TON tengeneza folda build na kukusanya mradi ndani yake.

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

Kwa kuwa tutaandika mkataba mzuri, hatuhitaji tu lite-clientLakini Fift с FunC, kwa hivyo wacha tukusanye kila kitu. Si mchakato wa haraka, kwa hivyo tunasubiri.

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

Ifuatayo, pakua faili ya usanidi ambayo ina data kuhusu nodi ambayo lite-client itaunganishwa.

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

Kutuma maombi ya kwanza kwa TON

Sasa tuzindue lite-client.

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

Ikiwa ujenzi ulifanikiwa, basi baada ya uzinduzi utaona logi ya uunganisho wa mteja wa mwanga kwenye node.

[ 1][t 2][1582054822.963129282][lite-client.h:201][!testnode]   conn ready
[ 2][t 2][1582054823.085654020][lite-client.cpp:277][!testnode] server version is 1.1, capabilities 7
[ 3][t 2][1582054823.085725069][lite-client.cpp:286][!testnode] server time is 1582054823 (delta 0)
...

Unaweza kuendesha amri help na uone ni amri gani zinapatikana.

help

Hebu tuorodhe amri ambazo tutatumia katika makala hii.

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-ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ смартконтракта. 

Sasa tuko tayari kuandika mkataba wenyewe.

Utekelezaji

Wazo

Kama nilivyoandika hapo juu, mkataba mzuri tunaoandika ni bahati nasibu.

Kwa kuongezea, hii sio bahati nasibu ambayo unahitaji kununua tikiti na kungojea saa, siku au mwezi, lakini moja ya papo hapo ambayo mtumiaji huhamisha kwa anwani ya mkataba. N gramu, na huirudisha mara moja 2 * N gramu au kupoteza. Tutafanya uwezekano wa kushinda kama 40%. Ikiwa hakuna gramu za kutosha za malipo, basi tutazingatia muamala kama nyongeza.

Zaidi ya hayo, ni muhimu kwamba dau zionekane kwa wakati halisi na kwa njia inayofaa, ili mtumiaji aweze kuelewa mara moja ikiwa alishinda au alipoteza. Kwa hivyo, unahitaji kutengeneza tovuti ambayo itaonyesha dau na matokeo moja kwa moja kutoka kwa TON.

Kuandika mkataba wa busara

Kwa urahisi, nimeangazia nambari ya FunC; programu-jalizi inaweza kupatikana na kusanikishwa katika Utaftaji wa Msimbo wa Visual Studio; ikiwa ghafla unataka kuongeza kitu, nimefanya programu-jalizi ipatikane hadharani. Pia, mtu hapo awali alifanya programu-jalizi ya kufanya kazi na Fift, unaweza pia kuiweka na kuipata kwenye VSC.

Wacha tuunde hazina mara moja ambapo tutafanya matokeo ya kati.

Ili kurahisisha maisha yetu, tutaandika mkataba mzuri na kuufanyia majaribio ndani ya nchi hadi utakapokuwa tayari. Ni baada ya hapo tu tutaichapisha katika TON.

Mkataba mzuri una njia mbili za nje zinazoweza kufikiwa. Kwanza, recv_external() kazi hii inatekelezwa wakati ombi la mkataba linatoka kwa ulimwengu wa nje, yaani, sio kutoka kwa TON, kwa mfano, wakati sisi wenyewe tunazalisha ujumbe na kuutuma kupitia lite-mteja. Pili, recv_internal() huu ndio wakati, ndani ya TON yenyewe, mkataba wowote unahusu yetu. Katika hali zote mbili, unaweza kupitisha vigezo kwa kazi.

Hebu tuanze na mfano rahisi ambao utafanya kazi ikiwa utachapishwa, lakini hakuna mzigo wa kazi ndani yake.

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

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

Hapa tunahitaji kueleza ni nini slice. Data zote zilizohifadhiwa katika TON Blockchain ni mkusanyiko TVM cell au tu cell, katika seli kama hiyo unaweza kuhifadhi hadi bits 1023 za data na hadi viungo 4 kwa seli zingine.

TVM cell slice au slice hii ni sehemu ya iliyopo cell inatumika kuichanganua, itadhihirika baadaye. Jambo kuu kwetu ni kwamba tunaweza kuhamisha slice na kulingana na aina ya ujumbe, kuchakata data ndani recv_external() au recv_internal().

impure - neno kuu ambalo linaonyesha kuwa chaguo za kukokotoa hurekebisha data ya mkataba mahiri.

Wacha tuhifadhi nambari ya mkataba ndani lottery-code.fc na kukusanya.

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

Maana ya bendera inaweza kutazamwa kwa kutumia amri

~/TON/build/crypto/func -help

Tumekusanya nambari ya mkusanyiko wa Fift ndani 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

Inaweza kuzinduliwa ndani ya nchi, kwa hili tutatayarisha mazingira.

Kumbuka kwamba mstari wa kwanza unaunganisha Asm.fif, hii ni nambari iliyoandikwa katika Fift kwa mkusanyiko wa Fift.

Kwa kuwa tunataka kuendesha na kujaribu mkataba mahiri ndani ya nchi, tutaunda faili lottery-test-suite.fif na unakili msimbo uliokusanywa hapo, ukibadilisha mstari wa mwisho ndani yake, ambao huandika msimbo mahiri wa mkataba kuwa wa kudumu codekisha kuihamisha kwa mashine ya kawaida:

"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

Kufikia sasa inaonekana wazi, sasa hebu tuongeze kwenye faili sawa msimbo ambao tutatumia kuzindua TVM.

0 tuple 0x076ef1ea , // magic
0 , 0 , // actions msg_sents
1570998536 , // unix_time
1 , 1 , 3 , // block_lt, trans_lt, rand_seed
0 tuple 100000000000000 , dictnew , , // remaining balance
0 , dictnew , // contract_address, global_config
1 tuple // wrap to another tuple
constant c7

0 constant recv_internal // to run recv_internal() 
-1 constant recv_external // to invoke recv_external()

Π’ c7 tunarekodi muktadha, yaani, data ambayo TVM (au hali ya mtandao) itazinduliwa. Hata wakati wa mashindano, mmoja wa watengenezaji alionyesha jinsi ya kuunda c7 na nilinakili. Katika makala hii tunaweza kuhitaji kubadilika rand_seed kwa kuwa kizazi cha nambari nasibu kinategemea na isipobadilishwa, nambari hiyo hiyo itarejeshwa kila wakati.

recv_internal ΠΈ recv_external vidhibiti vilivyo na maadili 0 na -1 vitawajibika kwa kupiga kazi zinazolingana katika mkataba mzuri.

Sasa tuko tayari kuunda jaribio la kwanza la mkataba wetu mahiri tupu. Kwa uwazi, kwa sasa tutaongeza vipimo vyote kwenye faili moja lottery-test-suite.fif.

Hebu tutengeneze tofauti storage na uandike tupu ndani yake cell, hii itakuwa hifadhi mahiri ya mkataba.

message Huu ndio ujumbe ambao tutasambaza kwa mtu mahiri kutoka nje. Pia tutaifanya iwe tupu kwa sasa.

variable storage 
<b b> storage ! 

variable message 
<b b> message ! 

Baada ya kuandaa mara kwa mara na vigezo, tunazindua TVM kwa kutumia amri runvmctx na kupitisha vigezo vilivyoundwa kwa pembejeo.

message @ 
recv_external 
code 
storage @ 
c7 
runvmctx 

Mwishoni tutafanikiwa kama hivyo msimbo wa kati kwa Fift.

Sasa tunaweza kuendesha msimbo unaosababisha.

export FIFTPATH=~/TON/ton/crypto/fift/lib // выполняСм ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π· для удобства 
~/TON/build/crypto/fift -s lottery-test-suite.fif 

Programu inapaswa kukimbia bila makosa na katika matokeo tutaona logi ya utekelezaji:

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

Sawa, tumeandika toleo la kwanza la kazi la mkataba mahiri.

Sasa tunahitaji kuongeza utendaji. Kwanza tushughulike na jumbe zinazotoka kwa ulimwengu wa nje kwenda recv_external()

Msanidi mwenyewe anachagua umbizo la ujumbe ambalo mkataba unaweza kukubali.

Lakini kwa kawaida

  • kwanza, tunataka kulinda mkataba wetu kutoka kwa ulimwengu wa nje na kuifanya ili tu mmiliki wa mkataba anaweza kutuma ujumbe wa nje kwake.
  • pili, tunapotuma ujumbe halali kwa TON, tunataka hii ifanyike mara moja na tunapotuma ujumbe sawa tena, mkataba wa busara unakataa.

Kwa hivyo karibu kila mkataba hutatua matatizo haya mawili, kwa kuwa mkataba wetu unakubali ujumbe wa nje, tunahitaji kutunza hilo pia.

Tutafanya kwa mpangilio wa nyuma. Kwanza, wacha tusuluhishe shida kwa kurudia; ikiwa mkataba tayari umepokea ujumbe kama huo na kuushughulikia, hautautekeleza kwa mara ya pili. Na kisha tutatatua tatizo ili tu mzunguko fulani wa watu wanaweza kutuma ujumbe kwa mkataba wa smart.

Kuna njia tofauti za kutatua tatizo na nakala za ujumbe. Hivi ndivyo tutakavyofanya. Katika mkataba wa mahiri, tunaanzisha kihesabu cha ujumbe uliopokewa kwa thamani ya awali 0. Katika kila ujumbe kwa mkataba mahiri, tutaongeza thamani ya sasa ya kaunta. Iwapo thamani ya kanusho katika ujumbe hailingani na thamani iliyo katika mkataba mahiri, basi hatuichakati; ikiwa inafanya hivyo, basi tunaichakata na kuongeza kaunta katika mkataba mahiri kwa 1.

Hebu kurudi lottery-test-suite.fif na ongeza mtihani wa pili kwake. Ikiwa tutatuma nambari isiyo sahihi, msimbo unapaswa kutupa ubaguzi. Kwa mfano, acha data ya mkataba ihifadhi 166, na tutatuma 165.

<b 166 32 u, b> storage !
<b 165 32 u, b> message !

message @ 
recv_external 
code 
storage @ 
c7 
runvmctx

drop 
exit_code ! 
."Exit code " exit_code @ . cr 
exit_code @ 33 - abort"Test #2 Not passed"

Hebu tuzindue.

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

Na tutaona kwamba mtihani unafanywa na kosa.

[ 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

Katika hatua hii lottery-test-suite.fif inapaswa kuonekana kama ΠΏΠΎ ссылкС.

Sasa hebu tuongeze mantiki ya kukabiliana na mkataba mzuri ndani 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 uongo ujumbe tunatuma.

Jambo la kwanza tunalofanya ni kuangalia ikiwa ujumbe una data, ikiwa sivyo, basi tunatoka tu.

Ifuatayo, tunachanganua ujumbe. in_msg~load_uint(32) hupakia nambari 165, 32-bit unsigned int kutoka kwa ujumbe uliotumwa.

Kisha tunapakia biti 32 kutoka kwa hifadhi mahiri ya mkataba. Tunaangalia kuwa nambari iliyopakiwa inalingana na ile iliyopitishwa; ikiwa sivyo, tunatupa ubaguzi. Kwa upande wetu, kwa kuwa tunapita bila mechi, ubaguzi unapaswa kutupwa.

Sasa hebu tukusanye.

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

Nakili msimbo unaotokana na lottery-test-suite.fif, bila kusahau kuchukua nafasi ya mstari wa mwisho.

Tunaangalia kama mtihani unapita:

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

Hapa Unaweza kuona ahadi inayolingana na matokeo ya sasa.

Kumbuka kuwa haifai kunakili kila mara nambari iliyokusanywa ya mkataba mzuri kwenye faili iliyo na vipimo, kwa hivyo tutaandika hati ambayo itatuandikia nambari hiyo kuwa ya kudumu, na tutaunganisha nambari iliyokusanywa kwa majaribio yetu kwa kutumia. "include".

Unda faili kwenye folda ya mradi build.sh na maudhui yafuatayo.

#!/bin/bash

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

Wacha tuifanye iweze kutekelezwa.

chmod +x ./build.sh

Sasa, endesha tu hati yetu ili kuunda mkataba. Lakini zaidi ya hii, tunahitaji kuiandika kwa mara kwa mara code. Kwa hivyo tutaunda faili mpya lotter-compiled-for-test.fif, ambayo tutajumuisha kwenye faili lottery-test-suite.fif.

Wacha tuongeze nambari ya skirpt kwa sh, ambayo itafanya nakala ya faili iliyokusanywa lotter-compiled-for-test.fif na ubadilishe mstari wa mwisho ndani yake.

# 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

Sasa, ili kuangalia, hebu tuendeshe hati inayosababisha na faili itatolewa lottery-compiled-for-test.fif, ambayo tutajumuisha katika yetu lottery-test-suite.fif

Π’ lottery-test-suite.fif futa msimbo wa mkataba na uongeze mstari "lottery-compiled-for-test.fif" include.

Tunafanya vipimo ili kuangalia kama wamefaulu.

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

Nzuri, sasa ili kuamilisha uzinduzi wa majaribio, wacha tuunde faili test.sh, ambayo itatekelezwa kwanza build.sh, na kisha endesha vipimo.

touch test.sh
chmod +x test.sh

Tunaandika ndani

./build.sh 

echo "nCompilation completedn"

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

Hebu tufanye test.sh na uiendeshe ili kuhakikisha kuwa vipimo vinafanya kazi.

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

Tunaangalia kwamba mkataba unajumuisha na vipimo vinatekelezwa.

Kubwa, sasa juu ya kuanza test.sh Majaribio yatakusanywa na kuendeshwa mara moja. Hapa kuna kiungo cha kujitolea.

Sawa, kabla hatujaendelea, tufanye jambo moja zaidi kwa urahisi.

Wacha tuunde folda build ambapo tutahifadhi mkataba ulionakiliwa na mshirika wake ulioandikwa kwa kudumu lottery-compiled.fif, lottery-compiled-for-test.fif. Hebu pia tutengeneze folda test faili ya majaribio itahifadhiwa wapi? lottery-test-suite.fif na faili zingine zinazoweza kusaidia. Unganisha kwa mabadiliko husika.

Wacha tuendelee kutengeneza mkataba mzuri.

Ifuatayo kunapaswa kuwa na jaribio ambalo hukagua ikiwa ujumbe umepokelewa na kaunta inasasishwa dukani tunapotuma nambari sahihi. Lakini tutafanya hivyo baadaye.

Sasa hebu tufikirie ni muundo gani wa data na data gani inahitaji kuhifadhiwa katika mkataba wa smart.

Nitaelezea kila kitu tunachohifadhi.

`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` пСрСмСнная Ρ‚ΠΈΠΏΠ° ΡΠ»ΠΎΠ²Π°Ρ€ΡŒ, Ρ…Ρ€Π°Π½ΠΈΡ‚ послСдниС Π΄Π²Π°Π΄Ρ†Π°Ρ‚ΡŒ ставок. 

Ifuatayo unahitaji kuandika kazi mbili. Wacha tuite wa kwanza pack_state(), ambayo itapakia data kwa ajili ya kuhifadhi baadaye katika hifadhi mahiri ya mkataba. Hebu piga simu ya pili unpack_state() itasoma na kurudisha data kutoka kwa hifadhi.

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

Tunaongeza kazi hizi mbili mwanzoni mwa mkataba mzuri. Itafanya kazi nje kama hivyo matokeo ya kati.

Ili kuhifadhi data utahitaji kupiga kazi iliyojengwa set_data() na itaandika data kutoka pack_state() katika hifadhi ya mkataba mahiri.

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

Kwa kuwa sasa tuna vitendaji vinavyofaa vya kuandika na kusoma data, tunaweza kuendelea.

Tunahitaji kuangalia kwamba ujumbe unaoingia kutoka nje umetiwa saini na mmiliki wa mkataba (au mtumiaji mwingine ambaye anaweza kufikia ufunguo wa faragha).

Tunapochapisha mkataba mahiri, tunaweza kuuanzisha kwa kutumia data tunayohitaji katika hifadhi, ambayo itahifadhiwa kwa matumizi ya baadaye. Tutarekodi ufunguo wa umma hapo ili tuweze kuthibitisha kuwa ujumbe unaoingia ulitiwa saini kwa ufunguo wa faragha unaolingana.

Kabla ya kuendelea, hebu tuunde ufunguo wa faragha na kuuandikia test/keys/owner.pk. Ili kufanya hivyo, hebu tuzindue Fift katika hali ya maingiliano na kutekeleza amri nne.

`newkeypair` гСнСрация ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΎΠ³ΠΎ ΠΈ ΠΏΡ€ΠΈΠ²Π°Ρ‚Π½ΠΎΠ³ΠΎ ΠΊΠ»ΡŽΡ‡Π° ΠΈ запись ΠΈΡ… Π² стСк. 

`drop` удалСния ΠΈΠ· стСка Π²Π΅Ρ€Ρ…Π½Π΅Π³ΠΎ элСмСнта (Π² Π΄Π°Π½Π½ΠΎΠΌ случаС ΠΏΡƒΠ±Π»ΠΈΡ‡Π½Ρ‹ΠΉ ΠΊΠ»ΡŽΡ‡)  

`.s` просто ΠΏΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ‡Ρ‚ΠΎ Π»Π΅ΠΆΠΈΡ‚ Π² стСкС Π² Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ 

`"owner.pk" B>file` запись ΠΏΡ€ΠΈΠ²Π°Ρ‚Π½ΠΎΠ³ΠΎ ΠΊΠ»ΡŽΡ‡Π° Π² Ρ„Π°ΠΉΠ» с ΠΈΠΌΠ΅Π½Π΅ΠΌ `owner.pk`. 

`bye` Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Ρƒ с Fift. 

Wacha tuunde folda keys ndani ya folda test na uandike ufunguo wa kibinafsi hapo.

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

Tunaona faili kwenye folda ya sasa owner.pk.

Tunaondoa ufunguo wa umma kwenye rafu na inapohitajika tunaweza kuupata kutoka kwa ule wa faragha.

Sasa tunahitaji kuandika uthibitishaji wa saini. Wacha tuanze na mtihani. Kwanza tunasoma ufunguo wa kibinafsi kutoka kwa faili kwa kutumia kazi file>B na uandike kwa kutofautisha owner_private_key, kisha kutumia kitendakazi priv>pub badilisha ufunguo wa faragha kuwa ufunguo wa umma na uandike matokeo 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 !

Tutahitaji funguo zote mbili.

Tunaanzisha hifadhi mahiri ya mkataba kwa kutumia data kiholela katika mlolongo sawa na utendakazi pack_state()na uandike kuwa kigezo 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 !

Ifuatayo, tutatunga ujumbe uliotiwa saini, utakuwa na saini tu na thamani ya kaunta.

Kwanza, tunaunda data ambayo tunataka kusambaza, kisha tunatia saini kwa ufunguo wa faragha na hatimaye tunatoa ujumbe uliotiwa saini.

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 !  

Kwa hivyo, ujumbe ambao tutatuma kwa kandarasi mahiri hurekodiwa katika hali tofauti message_to_send, kuhusu utendaji hashu, ed25519_sign_uint unaweza kusoma katika Nyaraka za Tano.

Na kukimbia mtihani tunaita tena.

message_to_send @ 
recv_external 
code 
storage @
c7
runvmctx

Kama hii Faili iliyo na vipimo inapaswa kuonekana kama hii katika hatua hii.

Hebu tufanye jaribio na halitafaulu, kwa hivyo tutabadilisha mkataba mahiri ili iweze kupokea ujumbe wa muundo huu na kuthibitisha sahihi.

Kwanza, tunahesabu bits 512 za saini kutoka kwa ujumbe na kuiandika kwa kutofautiana, kisha tunahesabu bits 32 za kutofautiana kwa counter.

Kwa kuwa tuna kipengele cha kusoma data kutoka kwa hifadhi mahiri ya mkataba, tutaitumia.

Inayofuata ni kuangalia kaunta iliyohamishwa na hifadhi na kuangalia saini. Ikiwa kitu hailingani, basi tunatupa ubaguzi na nambari inayofaa.

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

Ahadi husika hapa.

Wacha tuendeshe vipimo na tuone kuwa jaribio la pili halifaulu. Kwa sababu mbili, hakuna biti za kutosha katika ujumbe na hakuna biti za kutosha kwenye hifadhi, kwa hivyo msimbo huanguka wakati wa kuchanganua. Tunahitaji kuongeza saini kwa ujumbe tunaotuma na kunakili hifadhi kutoka kwa jaribio la mwisho.

Katika jaribio la pili, tutaongeza saini ya ujumbe na kubadilisha hifadhi mahiri ya mkataba. Kama hii faili iliyo na vipimo inaonekana kama kwa sasa.

Wacha tuandike jaribio la nne, ambalo tutatuma ujumbe uliosainiwa na ufunguo wa kibinafsi wa mtu mwingine. Wacha tuunde ufunguo mwingine wa kibinafsi na uihifadhi kwenye faili not-owner.pk. Tutatia sahihi ujumbe kwa ufunguo huu wa faragha. Wacha tufanye majaribio na tuhakikishe kuwa majaribio yote yanapita. Jitolea kwa wakati huu.

Sasa tunaweza kuendelea na utekelezaji wa mantiki ya mkataba mzuri.
Π’ recv_external() tutakubali aina mbili za jumbe.

Kwa kuwa mkataba wetu utakusanya hasara za wachezaji, pesa hizi lazima zipelekwe kwa muundaji wa bahati nasibu. Anwani ya mkoba ya muundaji wa bahati nasibu imeandikwa kwenye hifadhi wakati mkataba unaundwa.

Ikiwezekana, tunahitaji uwezo wa kubadilisha anwani ambayo tunatuma gramu za waliopotea. Tunapaswa pia kutuma gramu kutoka kwa bahati nasibu hadi kwa anwani ya mmiliki.

Hebu tuanze na ya kwanza. Hebu kwanza tuandike jaribio ambalo litaangalia kwamba baada ya kutuma ujumbe, mkataba wa smart ulihifadhi anwani mpya kwenye hifadhi. Tafadhali kumbuka kuwa katika ujumbe, pamoja na kaunta na anwani mpya, pia tunasambaza action Nambari kamili ya biti 7 isiyo hasi, kulingana nayo, tutachagua jinsi ya kuchakata ujumbe katika mkataba mzuri.

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

Katika jaribio unaweza kuona jinsi hifadhi ya smartcontract inavyoondolewa storage katika Tano. Deserialization ya vigezo ni ilivyoelezwa katika Fift nyaraka.

Kiungo cha kujitolea na unga ulioongezwa.

Wacha tufanye mtihani na tuhakikishe kuwa haijafaulu. Sasa hebu tuongeze mantiki ili kubadilisha anwani ya mmiliki wa bahati nasibu.

Katika mkataba wa busara tunaendelea kuchanganua message, soma ndani action. Hebu tukumbushe kwamba tutakuwa na mbili action: kubadilisha anwani na kutuma gramu.

Kisha tunasoma anwani mpya ya mmiliki wa mkataba na kuihifadhi kwenye hifadhi.
Tunaendesha vipimo na kuona kwamba mtihani wa tatu unashindwa. Inaanguka kwa sababu ya ukweli kwamba mkataba sasa unaongeza bits 7 kutoka kwa ujumbe, ambazo hazipo kwenye jaribio. Ongeza moja ambayo haipo kwenye ujumbe action. Hebu tuendeshe vipimo na tuone kwamba kila kitu kinapita. Hapa kujitolea kwa mabadiliko. Kubwa.

Sasa hebu tuandike mantiki ya kutuma nambari maalum ya gramu kwa anwani iliyohifadhiwa hapo awali.

Kwanza, hebu tuandike mtihani. Tutaandika vipimo viwili, moja wakati hakuna usawa wa kutosha, pili wakati kila kitu kinapaswa kupita kwa mafanikio. Vipimo vinaweza kutazamwa katika ahadi hii.

Sasa hebu tuongeze msimbo. Kwanza, hebu tuandike njia mbili za msaidizi. Njia ya kwanza ya kupata ni kujua usawa wa sasa wa mkataba mzuri.

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

Na ya pili ni ya kutuma gramu kwa mkataba mwingine wa smart. Nilinakili kabisa njia hii kutoka kwa mkataba mwingine mzuri.

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

Wacha tuongeze njia hizi mbili kwenye mkataba mzuri na tuandike mantiki. Kwanza, tunachanganua idadi ya gramu kutoka kwa ujumbe. Ifuatayo tunaangalia usawa, ikiwa haitoshi tunatupa ubaguzi. Ikiwa kila kitu ni sawa, basi tunatuma gramu kwa anwani iliyohifadhiwa na kusasisha counter.

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

Kama hii inaonekana kama mkataba wa busara kwa sasa. Wacha tuendeshe majaribio na tuhakikishe wamefaulu.

Kwa njia, tume inakatwa kutoka kwa mkataba mzuri kila wakati kwa ujumbe uliochakatwa. Ili ujumbe wa mikataba mahiri utekeleze ombi, baada ya ukaguzi wa kimsingi unahitaji kupiga simu accept_message().

Sasa hebu tuendelee kwenye ujumbe wa ndani. Kwa kweli, tutakubali gramu tu na kumrejeshea mchezaji mara mbili ya kiasi akishinda na theluthi moja kwa mmiliki akishindwa.

Kwanza, hebu tuandike mtihani rahisi. Ili kufanya hivyo, tunahitaji anwani ya majaribio ya kandarasi mahiri ambayo inadaiwa tunatuma gramu kwa mkataba mahiri.

Anwani mahiri ya mkataba ina nambari mbili, nambari kamili ya biti 32 inayowajibika kwa msururu wa kazi na nambari ya kipekee ya akaunti isiyo hasi ya biti 256 katika msururu huu wa kazi. Kwa mfano, -1 na 12345, hii ndiyo anwani tutakayohifadhi kwenye faili.

Nilinakili chaguo za kukokotoa za kuhifadhi anwani kutoka 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

Wacha tuangalie jinsi kazi inavyofanya kazi, hii itatoa ufahamu wa jinsi Fift inavyofanya kazi. Zindua Fift katika hali ya mwingiliano.

~/TON/build/crypto/fift -i 

Kwanza tunasukuma -1, 12345 na jina la faili ya baadaye "sender.addr" kwenye rafu:

-1 12345 "sender.addr" 

Hatua inayofuata ni kutekeleza kazi -rot, ambayo huhamisha rafu kwa njia ambayo juu ya rafu kuna nambari ya kipekee ya mkataba mahiri:

"sender.addr" -1 12345

256 u>B hubadilisha nambari kamili isiyo hasi ya biti 256 hadi baiti.

"sender.addr" -1 BYTES:0000000000000000000000000000000000000000000000000000000000003039

swap hubadilisha vipengele viwili vya juu vya rafu.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 -1

32 i>B hubadilisha nambari kamili ya biti-32 hadi baiti.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 BYTES:FFFFFFFF

B+ huunganisha mlolongo mbili za ka.

 "sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF

Tena swap.

BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF "sender.addr" 

Na hatimaye ka zimeandikwa kwa faili B>file. Baada ya hii stack yetu ni tupu. Hebu tuache Fift. Faili imeundwa kwenye folda ya sasa sender.addr. Wacha tuhamishe faili kwenye folda iliyoundwa test/addresses/.

Wacha tuandike mtihani rahisi ambao utatuma gramu kwa mkataba mzuri. Hapa kuna ahadi.

Sasa hebu tuangalie mantiki ya bahati nasibu.

Jambo la kwanza tunalofanya ni kuangalia ujumbe bounced au sio kama bounced, basi tunapuuza. bounced inamaanisha kuwa mkataba utarudisha gramu ikiwa hitilafu fulani itatokea. Hatutarudisha gramu ikiwa kosa litatokea ghafla.

Tunaangalia, ikiwa usawa ni chini ya nusu ya gramu, basi tunakubali tu ujumbe na kupuuza.

Ifuatayo, tunachanganua anwani ya mkataba mzuri ambao ujumbe ulitoka.

Tunasoma data kutoka kwa hifadhi na kisha kufuta dau za zamani kutoka kwa historia ikiwa kuna zaidi ya ishirini kati yao. Kwa urahisi, niliandika kazi tatu za ziada pack_order(), unpack_order(), remove_old_orders().

Ifuatayo, tunaangalia ikiwa salio haitoshi kwa malipo, basi tunazingatia kuwa hii sio dau, lakini ni kujaza tena na kuhifadhi kujaza tena. orders.

Kisha hatimaye kiini cha mkataba wa smart.

Kwanza, ikiwa mchezaji atapoteza, tunaihifadhi kwenye historia ya kamari na ikiwa kiasi ni zaidi ya gramu 3, tunatuma 1/3 kwa mmiliki wa mkataba mzuri.

Ikiwa mchezaji atashinda, basi tunatuma kiasi mara mbili kwa anwani ya mchezaji na kisha kuhifadhi taarifa kuhusu dau katika historia.

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

Hiyo ni. Ahadi inayolingana.

Sasa kilichobaki ni rahisi, hebu tuunde mbinu za kupata ili tuweze kupata taarifa kuhusu hali ya mkataba kutoka kwa ulimwengu wa nje (kwa kweli, soma data kutoka kwa hifadhi yao ya mkataba mzuri).

Wacha tuongeze kupata mbinu. Tutaandika hapa chini kuhusu jinsi ya kupokea habari kuhusu mkataba wa smart.

Pia nilisahau kuongeza msimbo ambao utashughulikia ombi la kwanza kabisa linalotokea wakati wa kuchapisha mkataba mahiri. Ahadi inayolingana. Na zaidi iliyosahihishwa hitilafu kwa kutuma 1/3 ya kiasi kwa akaunti ya mmiliki.

Hatua inayofuata ni kuchapisha mkataba mahiri. Wacha tuunde folda requests.

Nilichukua msimbo wa uchapishaji kama msingi simple-wallet-code.fc ambayo wanaweza kupata katika hazina rasmi.

Kitu cha kuzingatia. Tunatengeneza hifadhi mahiri ya mkataba na ujumbe wa ingizo. Baada ya hayo, anwani ya mkataba wa smart inazalishwa, yaani, anwani inajulikana hata kabla ya kuchapishwa katika TON. Ifuatayo, unahitaji kutuma gramu kadhaa kwa anwani hii, na tu baada ya hapo unahitaji kutuma faili na mkataba wa smart yenyewe, kwani mtandao unachukua tume ya kuhifadhi mkataba wa smart na uendeshaji ndani yake (wathibitishaji ambao huhifadhi na kutekeleza smart. mikataba). Kanuni inaweza kutazamwa hapa.

Ifuatayo, tunatumia nambari ya uchapishaji na kupata lottery-query.boc faili ya mkataba mzuri na anwani.

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

Usisahau kuhifadhi faili zinazozalishwa: lottery-query.boc, lottery.addr, lottery.pk.

Miongoni mwa mambo mengine, tutaona anwani ya mkataba wa smart katika kumbukumbu za utekelezaji.

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

Kwa kujifurahisha tu, hebu tutume ombi kwa TON

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

Na tutaona kwamba akaunti iliyo na anwani hii ni tupu.

account state is empty

Tunatuma kwa anwani 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd 2 Gram na baada ya sekunde chache tunafanya amri sawa. Kutuma gramu mimi kutumia mkoba rasmi, na unaweza kuuliza mtu kutoka kwa mazungumzo kwa gramu za mtihani, ambazo nitazungumzia mwishoni mwa makala hiyo.

> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Inaonekana kama mtu asiyejulikana (state:account_uninit) mkataba mzuri wenye anwani sawa na salio la nanogram 1.

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

Sasa hebu tuchapishe mkataba wa busara. Wacha tuzindue mteja mdogo na tutekeleze.

> 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 

Wacha tuangalie ikiwa mkataba umechapishwa.

> last
> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Miongoni mwa mambo mengine tunapata.

  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

Tunaona hilo account_active.

Ahadi inayolingana na mabadiliko hapa.

Sasa hebu tuunde maombi ya kuingiliana na mkataba mahiri.

Kwa usahihi, tutaacha ya kwanza kwa kubadilisha anwani kama kazi ya kujitegemea, na tutafanya ya pili kwa kutuma gramu kwa anwani ya mmiliki. Kwa kweli, tutahitaji kufanya kitu sawa na katika mtihani wa kutuma gramu.

Huu ndio ujumbe ambao tutatuma kwa mkataba mzuri, wapi msg_seqno 165, action 2 na 9.5 gramu kwa kutuma.

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

Usisahau kusaini ujumbe kwa ufunguo wako wa faragha lottery.pk, ambayo ilitolewa mapema wakati wa kuunda mkataba wa smart. Hapa kuna ahadi inayolingana.

Kupokea taarifa kutoka kwa mkataba mahiri kwa kutumia mbinu za kupata

Sasa hebu tuangalie jinsi ya kuendesha mkataba mzuri kupata mbinu.

Uzinduzi lite-client na endesha kupata njia ambazo tuliandika.

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

Π’ result ina thamani ambayo chaguo za kukokotoa hurejesha balance() kutoka kwa mkataba wetu mzuri.
Tutafanya vivyo hivyo kwa njia kadhaa zaidi.

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

Hebu tuulize historia yako ya kamari.

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

Tutatumia lite-client na kupata mbinu za kuonyesha maelezo kuhusu mkataba mahiri kwenye tovuti.

Inaonyesha data ya mkataba mahiri kwenye tovuti

Niliandika wavuti rahisi huko Python kuonyesha data kutoka kwa mkataba mzuri kwa njia rahisi. Hapa sitakaa juu yake kwa undani na nitachapisha tovuti katika ahadi moja.

Maombi kwa TON yanafanywa kutoka Python na msaada lite-client. Kwa urahisi, tovuti imewekwa kwenye Docker na kuchapishwa kwenye Wingu la Google. Kiungo.

Kujaribu

Sasa hebu tujaribu kutuma gramu huko kwa kujaza tena kutoka mkoba. Tunatuma gramu 40. Na wacha tufanye dau kadhaa kwa uwazi. Tunaona kwamba tovuti inaonyesha historia ya dau, asilimia ya sasa ya ushindi na taarifa nyingine muhimu.

Tunaonakwamba tulishinda ya kwanza, tukapoteza ya pili.

Baada ya

Nakala hiyo iligeuka kuwa ndefu zaidi kuliko nilivyotarajia, labda inaweza kuwa fupi, au labda tu kwa mtu ambaye hajui chochote kuhusu TON na anataka kuandika na kuchapisha mkataba wa smart ambao sio rahisi sana na uwezo wa kuingiliana nao. ni. Labda baadhi ya mambo yangeweza kufafanuliwa kwa urahisi zaidi.

Labda baadhi ya vipengele vya utekelezaji vingeweza kufanywa kwa ufanisi zaidi na kifahari, lakini basi ingechukua muda zaidi kuandaa makala. Inawezekana pia kwamba nilifanya makosa mahali fulani au sikuelewa kitu, hivyo ikiwa unafanya jambo kubwa, unahitaji kutegemea nyaraka rasmi au hifadhi rasmi na msimbo wa TON.

Ikumbukwe kwamba kwa kuwa TON yenyewe bado iko katika hatua ya kazi ya maendeleo, mabadiliko yanaweza kutokea ambayo yatavunja hatua yoyote katika makala hii (ambayo ilitokea wakati nikiandika, tayari imesahihishwa), lakini mbinu ya jumla ni. uwezekano wa kubadilika.

Sitazungumza juu ya mustakabali wa TON. Labda jukwaa litakuwa jambo kubwa na tunapaswa kutumia muda kuisoma na kujaza niche na bidhaa zetu sasa.

Pia kuna Mizani kutoka Facebook, ambayo ina uwezekano wa hadhira ya watumiaji kubwa kuliko TON. Sijui karibu chochote kuhusu Libra, kwa kuzingatia kongamano kuna shughuli nyingi zaidi huko kuliko katika jamii ya TON. Ingawa watengenezaji na jumuiya ya TON ni kama chini ya ardhi, ambayo pia ni nzuri.

marejeo

  1. Nyaraka rasmi za TON: https://test.ton.org
  2. Hazina rasmi ya TON: https://github.com/ton-blockchain/ton
  3. Mkoba rasmi kwa majukwaa tofauti: https://wallet.ton.org
  4. Hazina ya mkataba mzuri kutoka kwa nakala hii: https://github.com/raiym/astonished
  5. Unganisha kwa tovuti ya mkataba mahiri: https://ton-lottery.appspot.com
  6. Hazina ya kiendelezi cha Msimbo wa Visual Studio wa FunC: https://github.com/raiym/func-visual-studio-plugin
  7. Ongea kuhusu TON kwenye Telegramu, ambayo ilisaidia sana kuijua katika hatua ya awali. Nadhani haitakuwa kosa ikiwa nasema kwamba kila mtu aliyeandika kitu kwa TON yupo. Unaweza pia kuomba gramu za mtihani huko. https://t.me/tondev_ru
  8. Gumzo lingine kuhusu TON ambalo nilipata habari muhimu: https://t.me/TONgramDev
  9. Hatua ya kwanza ya mashindano: https://contest.com/blockchain
  10. Hatua ya pili ya mashindano: https://contest.com/blockchain-2

Chanzo: mapenzi.com

Kuongeza maoni