ProHoster > blog > Utawala > Kuhusu jinsi ya kuandika na kuchapisha mkataba mzuri katika Mtandao wa Open Telegram (TON)
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).
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.
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
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.
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.
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.
Π 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.
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.
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.
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.
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.
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.
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.
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.
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.
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));
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.
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.
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.
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));
}
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).
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.
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.
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.
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.
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.
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