Ynglŷn â sut i ysgrifennu a chyhoeddi contract smart yn Rhwydwaith Agored Telegram (TON)

Ynglŷn â sut i ysgrifennu a chyhoeddi contract smart yn TON

Am beth mae'r erthygl hon?

Yn yr erthygl byddaf yn siarad am sut y cymerais ran yn y gystadleuaeth blockchain Telegram cyntaf (o ddau), ni chymerais wobr, a phenderfynais gofnodi fy mhrofiad mewn erthygl fel na fyddai'n suddo i ebargofiant ac, efallai, yn helpu rhywun.

Gan nad oeddwn i eisiau ysgrifennu cod haniaethol, ond i wneud rhywbeth yn gweithio, ar gyfer yr erthygl ysgrifennais gontract smart ar gyfer loteri ar unwaith a gwefan sy'n dangos data contract smart yn uniongyrchol o TON heb ddefnyddio storfa ganolraddol.

Bydd yr erthygl yn ddefnyddiol i'r rhai sydd am wneud eu contract smart cyntaf yn TON, ond nad ydynt yn gwybod ble i ddechrau.

Gan ddefnyddio'r loteri fel enghraifft, af o osod yr amgylchedd i gyhoeddi contract smart, rhyngweithio ag ef, ac ysgrifennu gwefan ar gyfer derbyn a chyhoeddi data.

Am gymryd rhan yn y gystadleuaeth

Fis Hydref diwethaf, cyhoeddodd Telegram gystadleuaeth blockchain gydag ieithoedd newydd Fift и FunC. Roedd angen dewis o ysgrifennu unrhyw un o'r pum contract smart arfaethedig. Roeddwn i'n meddwl y byddai'n braf gwneud rhywbeth gwahanol, dysgu iaith a gwneud rhywbeth, hyd yn oed os nad oes rhaid i mi ysgrifennu unrhyw beth arall yn y dyfodol. Hefyd, mae'r pwnc yn gyson ar y gwefusau.

Mae'n werth dweud nad oedd gennyf unrhyw brofiad o ddatblygu contractau smart.

Roeddwn i'n bwriadu cymryd rhan tan y diwedd tan y gallwn ac yna ysgrifennu erthygl adolygu, ond methais ar unwaith yn yr un cyntaf. i ysgrifennodd waled gydag aml-lofnod ar FunC a gweithiodd yn gyffredinol. Cymerais fel sail contract smart ar Solidity.

Bryd hynny, roeddwn yn meddwl bod hyn yn bendant yn ddigon i gymryd o leiaf rhywfaint o wobr. O ganlyniad, daeth tua 40 o bob 60 o gyfranogwyr yn enillwyr gwobrau ac nid oeddwn yn eu plith. Yn gyffredinol, nid oes dim o'i le ar hyn, ond roedd un peth yn fy mhoeni. Ar adeg cyhoeddi'r canlyniadau, nid oedd yr adolygiad o'r prawf ar gyfer fy nghontract wedi'i wneud, gofynnais i'r cyfranogwyr yn y sgwrs a oedd unrhyw un arall nad oedd ganddo, nid oedd unrhyw un.

Yn ôl pob tebyg wedi talu sylw i fy negeseuon, ddeuddydd yn ddiweddarach cyhoeddodd y beirniaid sylw ac nid wyf yn deall o hyd a wnaethant fethu fy nghontract craff yn ddamweiniol yn ystod y beirniadu neu ddim ond meddwl ei fod mor ddrwg fel nad oedd angen sylw arno. Gofynnais gwestiwn ar y dudalen, ond ni chefais ateb. Er nad yw'n gyfrinach pwy farnodd, roeddwn i'n ei ystyried yn ddiangen i ysgrifennu negeseuon personol.

Treuliwyd llawer o amser ar ddeall, felly penderfynwyd ysgrifennu erthygl. Gan nad oes llawer o wybodaeth eto, bydd yr erthygl hon yn helpu i arbed amser i bawb sydd â diddordeb.

Y cysyniad o gontractau smart yn TON

Cyn i chi ysgrifennu unrhyw beth, mae angen i chi ddarganfod o ba ochr i fynd at y peth hwn. Felly, yn awr dywedaf wrthych pa rannau y mae'r system yn eu cynnwys. Yn fwy manwl gywir, pa rannau y mae angen i chi eu gwybod er mwyn ysgrifennu o leiaf rhyw fath o gontract gwaith.

Byddwn yn canolbwyntio ar ysgrifennu contract smart a gweithio gyda TON Virtual Machine (TVM), Fift и FunC, felly mae'r erthygl yn debycach i ddisgrifiad o ddatblygiad rhaglen reolaidd. Ni fyddwn yn dibynnu ar sut mae'r platfform ei hun yn gweithio yma.

Yn gyffredinol am sut mae'n gweithio TVM ac iaith Fift mae dogfennaeth swyddogol dda. Wrth gymryd rhan yn y gystadleuaeth a nawr wrth ysgrifennu'r cytundeb presennol, roeddwn i'n aml yn troi ati.

Y brif iaith ar gyfer ysgrifennu contractau smart yw FunC. Nid oes unrhyw ddogfennaeth arno ar hyn o bryd, felly er mwyn ysgrifennu rhywbeth mae angen i chi astudio enghreifftiau o gontractau smart o'r ystorfa swyddogol a gweithrediad yr iaith ei hun yno, a gallwch hefyd edrych ar enghreifftiau o gontractau smart o'r ddau ddiwethaf cystadlaethau. Dolenni ar ddiwedd yr erthygl.

Gadewch i ni ddweud ein bod eisoes wedi ysgrifennu contract smart ar gyfer FunC, ar ôl hynny rydym yn llunio'r cod yn Fift assembler.

Mae'r contract smart a luniwyd yn dal i gael ei gyhoeddi. I wneud hyn mae angen i chi ysgrifennu swyddogaeth yn Fift, a fydd yn cymryd y cod contract smart a rhai paramedrau eraill fel mewnbwn, a bydd yr allbwn yn ffeil gyda'r estyniad .boc (sy’n golygu “bag o gelloedd”), ac, yn dibynnu ar sut rydym yn ei ysgrifennu, allwedd breifat a chyfeiriad, a gynhyrchir yn seiliedig ar y cod contract clyfar. Gallwch chi eisoes anfon gramau i gyfeiriad contract smart nad yw wedi'i gyhoeddi eto.

I gyhoeddi contract smart yn TON a dderbyniwyd .boc bydd angen anfon y ffeil i'r blockchain gan ddefnyddio cleient ysgafn (mwy ar hynny isod). Ond cyn cyhoeddi, mae angen i chi drosglwyddo gramau i'r cyfeiriad a gynhyrchir, fel arall ni fydd y contract smart yn cael ei gyhoeddi. Ar ôl ei gyhoeddi, gallwch chi ryngweithio â'r contract smart trwy anfon negeseuon ato o'r tu allan (er enghraifft, defnyddio cleient ysgafn) neu o'r tu mewn (er enghraifft, mae un contract smart yn anfon neges arall y tu mewn i TON).

Unwaith y byddwn yn deall sut y caiff y cod ei gyhoeddi, daw'n haws. Rydyn ni'n gwybod yn fras beth rydyn ni am ei ysgrifennu a sut bydd ein rhaglen yn gweithio. Ac wrth ysgrifennu, rydym yn edrych am sut mae hyn eisoes yn cael ei weithredu mewn contractau smart presennol, neu rydym yn edrych i mewn i'r cod gweithredu Fift и FunC yn y gadwrfa swyddogol, neu edrychwch yn y ddogfennaeth swyddogol.

Yn aml iawn, fe wnes i chwilio am eiriau allweddol yn sgwrs Telegram lle casglodd holl gyfranogwyr y gystadleuaeth a gweithwyr Telegram, a digwyddodd felly bod pawb yn ymgynnull yno yn ystod y gystadleuaeth a dechrau trafod Fift a FunC. Dolen ar ddiwedd yr erthygl.

Mae'n bryd symud o theori i ymarfer.

Paratoi'r amgylchedd ar gyfer gweithio gyda TON

Gwneuthum bopeth a fydd yn cael ei ddisgrifio yn yr erthygl ar MacOS a'i wirio ddwywaith yn Ubuntu 18.04 LTS glân ar Docker.

Y peth cyntaf y mae angen i chi ei wneud yw lawrlwytho a gosod lite-client ag y gallwch anfon ceisiadau i TON.

Mae'r cyfarwyddiadau ar y wefan swyddogol yn disgrifio'r broses osod yn eithaf manwl ac yn glir ac yn hepgor rhai manylion. Yma rydym yn dilyn y cyfarwyddiadau, gan osod y dibyniaethau coll ar hyd y ffordd. Ni wnes i lunio pob prosiect fy hun a'i osod o'r ystorfa Ubuntu swyddogol (ar MacOS a ddefnyddiais 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 

Unwaith y bydd yr holl ddibyniaethau wedi'u gosod gallwch chi osod lite-client, Fift, FunC.

Yn gyntaf, rydym yn clonio'r ystorfa TON ynghyd â'i dibyniaethau. Er hwylustod, byddwn yn gwneud popeth mewn ffolder ~/TON.

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

Mae'r ystorfa hefyd yn storio gweithrediadau Fift и FunC.

Nawr rydym yn barod i gydosod y prosiect. Mae'r cod ystorfa wedi'i glonio i mewn i ffolder ~/TON/ton. Yn ~/TON creu ffolder build a chasglu y prosiect ynddo.

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

Gan ein bod yn mynd i ysgrifennu contract smart, mae angen nid yn unig lite-clientOnd Fift с FunC, felly gadewch i ni lunio popeth. Nid yw'n broses gyflym, felly rydym yn aros.

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

Nesaf, lawrlwythwch y ffeil ffurfweddu sy'n cynnwys data am y nod i ba un lite-client bydd yn cysylltu.

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

Gwneud y ceisiadau cyntaf i TON

Nawr gadewch i ni lansio lite-client.

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

Pe bai'r adeilad yn llwyddiannus, yna ar ôl ei lansio fe welwch log o gysylltiad y cleient ysgafn â'r nod.

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

Gallwch chi redeg y gorchymyn help a gweld pa orchmynion sydd ar gael.

help

Gadewch i ni restru'r gorchmynion y byddwn yn eu defnyddio yn yr erthygl hon.

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

Nawr rydym yn barod i ysgrifennu'r contract ei hun.

Gweithredu

Syniad

Fel yr ysgrifennais uchod, mae'r contract smart yr ydym yn ei ysgrifennu yn loteri.

Ar ben hynny, nid yw hon yn loteri lle mae angen i chi brynu tocyn ac aros am awr, diwrnod neu fis, ond un ar unwaith lle mae'r defnyddiwr yn trosglwyddo i gyfeiriad y contract. N gram, ac yn syth yn ei gael yn ôl 2 * N gram neu golli. Byddwn yn gwneud y tebygolrwydd o ennill tua 40%. Os nad oes digon o gramau ar gyfer taliad, yna byddwn yn ystyried y trafodiad fel ychwanegiad.

Ar ben hynny, mae'n bwysig bod betiau i'w gweld mewn amser real ac mewn ffurf gyfleus, fel y gall y defnyddiwr ddeall ar unwaith a enillodd neu a gollodd. Felly, mae angen i chi wneud gwefan a fydd yn dangos betiau a chanlyniadau yn uniongyrchol o TON.

Ysgrifennu contract smart

Er hwylustod, rwyf wedi tynnu sylw at y cod ar gyfer FunC; gellir dod o hyd i'r ategyn a'i osod yn y chwiliad Cod Stiwdio Gweledol; os ydych chi am ychwanegu rhywbeth yn sydyn, rydw i wedi sicrhau bod yr ategyn ar gael i'r cyhoedd. Hefyd, mae rhywun wedi gwneud ategyn yn flaenorol ar gyfer gweithio gyda Fift, gallwch hefyd ei osod a dod o hyd iddo yn VSC.

Gadewch i ni greu ystorfa ar unwaith lle byddwn yn ymrwymo'r canlyniadau canolradd.

Er mwyn gwneud ein bywyd yn haws, byddwn yn ysgrifennu contract smart ac yn ei brofi'n lleol nes ei fod yn barod. Dim ond ar ôl hynny y byddwn yn ei gyhoeddi yn TON.

Mae gan y contract smart ddau ddull allanol y gellir eu cyrchu. Yn gyntaf, recv_external() cyflawnir y swyddogaeth hon pan ddaw cais i'r contract o'r byd y tu allan, hynny yw, nid o TON, er enghraifft, pan fyddwn ni ein hunain yn cynhyrchu neges a'i hanfon trwy'r cleient lite. Yn ail, recv_internal() dyma pryd, o fewn TON ei hun, mae unrhyw gontract yn cyfeirio at ein un ni. Yn y ddau achos, gallwch drosglwyddo paramedrau i'r swyddogaeth.

Gadewch i ni ddechrau gydag enghraifft syml a fydd yn gweithio os caiff ei chyhoeddi, ond nid oes llwyth swyddogaethol ynddi.

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

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

Yma mae angen i ni egluro beth ydyw slice. Mae'r holl ddata sy'n cael ei storio yn TON Blockchain yn gasgliad TVM cell neu yn syml cell, mewn cell o'r fath gallwch storio hyd at 1023 o ddarnau o ddata a hyd at 4 dolen i gelloedd eraill.

TVM cell slice neu slice mae hyn yn rhan o'r un presennol cell yn cael ei ddefnyddio i'w ddosrannu, daw'n amlwg yn nes ymlaen. Y prif beth i ni yw y gallwn drosglwyddo slice ac yn dibynnu ar y math o neges, proseswch y data i mewn recv_external() neu recv_internal().

impure - allweddair sy'n nodi bod y swyddogaeth yn addasu data contract smart.

Gadewch i ni arbed cod y contract i mewn lottery-code.fc a llunio.

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

Gellir gweld ystyr y fflagiau gan ddefnyddio'r gorchymyn

~/TON/build/crypto/func -help

Rydym wedi llunio cod cydosodwr Fift 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

Gellir ei lansio'n lleol, ar gyfer hyn byddwn yn paratoi'r amgylchedd.

Sylwch fod y llinell gyntaf yn cysylltu Asm.fif, dyma god a ysgrifennwyd yn Fift for the Fift assembler.

Gan ein bod am redeg a phrofi'r contract smart yn lleol, byddwn yn creu ffeil lottery-test-suite.fif a chopïwch y cod a luniwyd yno, gan ddisodli'r llinell olaf ynddo, sy'n ysgrifennu'r cod contract smart i gysonyn codei'w drosglwyddo wedyn i'r peiriant rhithwir:

"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

Hyd yn hyn mae'n ymddangos yn glir, nawr gadewch i ni ychwanegu at yr un ffeil y cod y byddwn yn ei ddefnyddio i lansio 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 rydym yn cofnodi'r cyd-destun, hynny yw, y data y bydd y TVM (neu gyflwr rhwydwaith) yn cael ei lansio ag ef. Hyd yn oed yn ystod y gystadleuaeth, dangosodd un o'r datblygwyr sut i greu c7 ac yr wyf yn copio. Yn yr erthygl hon efallai y bydd angen i ni newid rand_seed gan fod cynhyrchu rhif ar hap yn dibynnu arno ac os na chaiff ei newid, bydd yr un rhif yn cael ei ddychwelyd bob tro.

recv_internal и recv_external cysonion gyda gwerthoedd 0 a -1 fydd yn gyfrifol am alw'r swyddogaethau cyfatebol yn y contract smart.

Nawr rydym yn barod i greu'r prawf cyntaf ar gyfer ein contract smart gwag. Er eglurder, am y tro byddwn yn ychwanegu pob prawf at yr un ffeil lottery-test-suite.fif.

Gadewch i ni greu newidyn storage ac ysgrifennu un gwag i mewn iddo cell, hwn fydd y storfa gontract smart.

message Dyma'r neges y byddwn yn ei throsglwyddo i'r cyswllt smart o'r tu allan. Byddwn hefyd yn ei wneud yn wag am y tro.

variable storage 
<b b> storage ! 

variable message 
<b b> message ! 

Ar ôl i ni baratoi'r cysonion a'r newidynnau, rydym yn lansio TVM gan ddefnyddio'r gorchymyn runvmctx a throsglwyddo'r paramedrau a grëwyd i'r mewnbwn.

message @ 
recv_external 
code 
storage @ 
c7 
runvmctx 

Yn y diwedd byddwn yn llwyddo fel yna cod canolradd ar gyfer Fift.

Nawr gallwn redeg y cod canlyniadol.

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

Dylai'r rhaglen redeg heb wallau ac yn yr allbwn fe welwn y log gweithredu:

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

Gwych, rydym wedi ysgrifennu'r fersiwn weithredol gyntaf o'r contract smart.

Nawr mae angen i ni ychwanegu ymarferoldeb. Yn gyntaf gadewch i ni ddelio â negeseuon sy'n dod o'r byd y tu allan i recv_external()

Mae'r datblygwr ei hun yn dewis y fformat neges y gall y contract ei dderbyn.

Ond fel arfer

  • yn gyntaf, rydym am amddiffyn ein contract rhag y byd y tu allan a'i wneud fel mai dim ond perchennog y contract all anfon negeseuon allanol ato.
  • yn ail, pan fyddwn yn anfon neges ddilys i TON, rydym am i hyn ddigwydd yn union unwaith a phan fyddwn yn anfon yr un neges eto, mae'r contract smart yn ei wrthod.

Felly mae bron pob contract yn datrys y ddwy broblem hyn, gan fod ein contract yn derbyn negeseuon allanol, mae angen inni ofalu am hynny hefyd.

Byddwn yn ei wneud yn y drefn arall. Yn gyntaf, gadewch i ni ddatrys y broblem gydag ailadrodd; os yw'r contract eisoes wedi derbyn neges o'r fath a'i brosesu, ni fydd yn ei weithredu yr eildro. Ac yna byddwn yn datrys y broblem fel mai dim ond cylch penodol o bobl sy'n gallu anfon negeseuon i'r contract smart.

Mae yna wahanol ffyrdd o ddatrys y broblem gyda negeseuon dyblyg. Dyma sut y byddwn yn ei wneud. Yn y contract smart, rydym yn cychwyn y cownter o negeseuon a dderbyniwyd gyda'r gwerth cychwynnol 0. Ym mhob neges i'r contract smart, byddwn yn ychwanegu'r gwerth cownter cyfredol. Os nad yw'r gwerth cownter yn y neges yn cyfateb i'r gwerth yn y contract smart, yna nid ydym yn ei brosesu; os ydyw, yna rydym yn ei brosesu ac yn cynyddu'r cownter yn y contract smart gan 1.

Gadewch i ni ddychwelyd i lottery-test-suite.fif ac ychwanegu ail brawf ato. Os byddwn yn anfon rhif anghywir, dylai'r cod daflu eithriad. Er enghraifft, gadewch i'r storfa ddata contract 166, a byddwn yn anfon 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"

Gadewch i ni lansio.

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

A byddwn yn gweld bod y prawf yn cael ei weithredu gyda gwall.

[ 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

Ar y cam hwn lottery-test-suite.fif dylai edrych fel по ссылке.

Nawr, gadewch i ni ychwanegu'r rhesymeg cownter i'r contract smart i mewn 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 celwydd y neges a anfonwn.

Y peth cyntaf rydyn ni'n ei wneud yw gwirio a yw'r neges yn cynnwys data, os na, yna rydyn ni'n gadael.

Nesaf rydym yn dosrannu'r neges. in_msg~load_uint(32) yn llwytho'r rhif 165, 32-bit unsigned int o'r neges a drosglwyddir.

Nesaf rydym yn llwytho 32 did o'r storfa gontract smart. Rydym yn gwirio bod y rhif llwythog yn cyfateb i'r un a basiwyd; os na, rydym yn taflu eithriad. Yn ein hachos ni, gan ein bod yn pasio diffyg gêm, dylid taflu eithriad.

Nawr gadewch i ni lunio.

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

Copïwch y cod canlyniadol i lottery-test-suite.fif, heb anghofio disodli'r llinell olaf.

Rydym yn gwirio bod y prawf yn pasio:

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

Dde yma Gallwch weld yr ymrwymiad cyfatebol gyda'r canlyniadau cyfredol.

Sylwch ei bod yn anghyfleus i gopïo cod cryno contract smart yn gyson i ffeil gyda phrofion, felly gadewch i ni ysgrifennu sgript a fydd yn ysgrifennu'r cod yn gysonyn i ni, a byddwn yn syml yn cysylltu'r cod a luniwyd i'n profion gan ddefnyddio "include".

Creu ffeil yn y ffolder prosiect build.sh gyda'r cynnwys canlynol.

#!/bin/bash

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

Gadewch i ni ei wneud yn weithredadwy.

chmod +x ./build.sh

Nawr, rhedwch ein sgript i lunio'r contract. Ond heblaw hyn, mae angen inni ei ysgrifennu'n gysonyn code. Felly byddwn yn creu ffeil newydd lotter-compiled-for-test.fif, y byddwn yn ei gynnwys yn y ffeil lottery-test-suite.fif.

Gadewch i ni ychwanegu cod skirpt at sh, a fydd yn syml yn dyblygu'r ffeil a luniwyd i mewn lotter-compiled-for-test.fif a newid y llinell olaf ynddi.

# 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

Nawr, i wirio, gadewch i ni redeg y sgript canlyniadol a bydd ffeil yn cael ei chynhyrchu lottery-compiled-for-test.fif, y byddwn yn ei gynnwys yn ein lottery-test-suite.fif

В lottery-test-suite.fif dileu cod y contract ac ychwanegu'r llinell "lottery-compiled-for-test.fif" include.

Rydym yn cynnal profion i wirio eu bod yn pasio.

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

Gwych, nawr i awtomeiddio lansiad profion, gadewch i ni greu ffeil test.sh, a fydd yn gweithredu yn gyntaf build.sh, ac yna rhedeg y profion.

touch test.sh
chmod +x test.sh

Rydym yn ysgrifennu y tu mewn

./build.sh 

echo "nCompilation completedn"

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

Gadewch i ni ei wneud test.sh a'i redeg i sicrhau bod y profion yn gweithio.

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

Rydym yn gwirio bod y contract yn cael ei lunio a bod y profion yn cael eu cynnal.

Gwych, nawr ar gychwyn test.sh Bydd y profion yn cael eu llunio a'u rhedeg ar unwaith. Dyma'r ddolen i ymrwymo.

Iawn, cyn inni barhau, gadewch i ni wneud un peth arall er hwylustod.

Gadewch i ni greu ffolder build lle byddwn yn storio'r contract wedi'i gopïo a'i glon wedi'i ysgrifennu'n gysonyn lottery-compiled.fif, lottery-compiled-for-test.fif. Gadewch i ni hefyd greu ffolder test ble bydd y ffeil prawf yn cael ei storio? lottery-test-suite.fif a ffeiliau ategol eraill o bosibl. Dolen i newidiadau perthnasol.

Gadewch i ni barhau i ddatblygu'r contract smart.

Nesaf dylai fod prawf sy'n gwirio bod y neges yn cael ei derbyn a bod y cownter yn cael ei ddiweddaru yn y siop pan fyddwn yn anfon y rhif cywir. Ond byddwn yn gwneud hynny yn nes ymlaen.

Nawr, gadewch i ni feddwl pa strwythur data a pha ddata sydd angen ei storio yn y contract smart.

Byddaf yn disgrifio popeth yr ydym yn ei storio.

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

Nesaf mae angen i chi ysgrifennu dwy swyddogaeth. Gadewch i ni alw'r cyntaf pack_state(), a fydd yn pecyn y data ar gyfer arbed dilynol yn y storio contract smart. Gadewch i ni alw'r ail unpack_state() yn darllen ac yn dychwelyd data o'r storfa.

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

Rydym yn ychwanegu'r ddwy swyddogaeth hyn at ddechrau'r contract smart. Bydd yn gweithio allan fel yna canlyniad canolradd.

I arbed data bydd angen i chi ffonio'r swyddogaeth adeiledig set_data() a bydd yn ysgrifennu data o pack_state() yn y storfa gontract smart.

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

Nawr bod gennym swyddogaethau cyfleus ar gyfer ysgrifennu a darllen data, gallwn symud ymlaen.

Mae angen i ni wirio bod y neges sy'n dod i mewn o'r tu allan wedi'i llofnodi gan berchennog y contract (neu ddefnyddiwr arall sydd â mynediad at yr allwedd breifat).

Pan fyddwn yn cyhoeddi contract smart, gallwn ei gychwyn gyda'r data sydd ei angen arnom wrth storio, a fydd yn cael ei arbed i'w ddefnyddio yn y dyfodol. Byddwn yn cofnodi'r allwedd gyhoeddus yno fel y gallwn wirio bod y neges sy'n dod i mewn wedi'i llofnodi gyda'r allwedd breifat gyfatebol.

Cyn parhau, gadewch i ni greu allwedd breifat ac ysgrifennu ati test/keys/owner.pk. I wneud hyn, gadewch i ni lansio Fift yn y modd rhyngweithiol a gweithredu pedwar gorchymyn.

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

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

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

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

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

Gadewch i ni greu ffolder keys tu mewn i'r ffolder test ac ysgrifennwch yr allwedd breifat yno.

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

Rydym yn gweld ffeil yn y ffolder gyfredol owner.pk.

Rydym yn tynnu'r allwedd gyhoeddus o'r pentwr a phan fo angen gallwn ei chael o'r un preifat.

Nawr mae angen i ni ysgrifennu dilysiad llofnod. Gadewch i ni ddechrau gyda'r prawf. Yn gyntaf rydym yn darllen yr allwedd breifat o'r ffeil gan ddefnyddio'r swyddogaeth file>B a'i ysgrifennu i newidyn owner_private_key, yna defnyddio'r swyddogaeth priv>pub trosi'r allwedd breifat yn allwedd gyhoeddus ac ysgrifennu'r canlyniad i mewn 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 !

Bydd angen y ddwy allwedd arnom.

Rydym yn cychwyn y storfa gontract smart gyda data mympwyol yn yr un dilyniant ag yn y swyddogaeth pack_state()a'i ysgrifennu i mewn i newidyn 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 !

Nesaf, byddwn yn cyfansoddi neges wedi'i llofnodi, bydd yn cynnwys y llofnod a'r gwerth cownter yn unig.

Yn gyntaf, rydyn ni'n creu'r data rydyn ni am ei drosglwyddo, yna rydyn ni'n ei lofnodi gydag allwedd breifat ac yn olaf rydyn ni'n cynhyrchu neges wedi'i llofnodi.

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 !  

O ganlyniad, mae'r neges y byddwn yn ei hanfon at y contract smart yn cael ei chofnodi mewn newidyn message_to_send, am swyddogaethau hashu, ed25519_sign_uint gallwch ddarllen yn nogfennaeth Fift.

Ac i redeg y prawf rydym yn galw eto.

message_to_send @ 
recv_external 
code 
storage @
c7
runvmctx

Yma felly Dylai'r ffeil gyda phrofion edrych fel hyn ar hyn o bryd.

Gadewch i ni redeg y prawf a bydd yn methu, felly byddwn yn newid y contract smart fel y gall dderbyn negeseuon o'r fformat hwn a gwirio'r llofnod.

Yn gyntaf, rydyn ni'n cyfrif 512 did o'r llofnod o'r neges ac yn ei ysgrifennu i newidyn, yna rydyn ni'n cyfrif 32 did o'r newidyn rhifydd.

Gan fod gennym swyddogaeth ar gyfer darllen data o'r storfa gontract smart, byddwn yn ei ddefnyddio.

Nesaf yw gwirio'r cownter a drosglwyddwyd gyda'r storfa a gwirio'r llofnod. Os nad yw rhywbeth yn cyfateb, yna rydym yn taflu eithriad gyda'r cod priodol.

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

Ymrwymiad perthnasol yma.

Gadewch i ni redeg y profion a gweld bod yr ail brawf yn methu. Am ddau reswm, nid oes digon o ddarnau yn y neges ac nid oes digon o ddarnau yn y storfa, felly mae'r cod yn chwalu wrth ddosrannu. Mae angen i ni ychwanegu llofnod at y neges rydyn ni'n ei hanfon a chopïo'r storfa o'r prawf diwethaf.

Yn yr ail brawf, byddwn yn ychwanegu llofnod neges ac yn newid y storfa contract smart. Yma felly mae'r ffeil gyda phrofion yn edrych fel ar hyn o bryd.

Gadewch i ni ysgrifennu pedwerydd prawf, lle byddwn yn anfon neges wedi'i llofnodi ag allwedd breifat rhywun arall. Gadewch i ni greu allwedd breifat arall a'i chadw mewn ffeil not-owner.pk. Byddwn yn llofnodi'r neges gyda'r allwedd breifat hon. Gadewch i ni redeg y profion a gwneud yn siŵr bod pob prawf yn pasio. Ymrwymo ar hyn o bryd.

Nawr gallwn symud ymlaen o'r diwedd i weithredu'r rhesymeg contract smart.
В recv_external() byddwn yn derbyn dau fath o neges.

Gan y bydd ein contract yn cronni colledion y chwaraewyr, rhaid trosglwyddo'r arian hwn i greawdwr y loteri. Mae cyfeiriad waled crëwr y loteri yn cael ei gofnodi yn y storfa pan fydd y contract yn cael ei greu.

Rhag ofn, mae angen y gallu i newid y cyfeiriad yr ydym yn anfon gramau o'r collwyr iddo. Dylem hefyd allu anfon gramau o'r loteri i gyfeiriad y perchennog.

Gadewch i ni ddechrau gyda'r un cyntaf. Yn gyntaf, gadewch i ni ysgrifennu prawf a fydd yn gwirio bod y contract smart wedi arbed y cyfeiriad newydd yn y storfa ar ôl anfon y neges. Sylwch, yn y neges, yn ogystal â'r cownter a'r cyfeiriad newydd, rydym hefyd yn trosglwyddo action Rhif cyfanrif 7-did nad yw'n negyddol, yn dibynnu arno, byddwn yn dewis sut i brosesu'r neges yn y contract smart.

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

Yn y prawf gallwch weld sut mae storio contract smart yn cael ei ddadgyfodi storage yn Fift. Disgrifir dad-gyfrifo newidynnau yn nogfennaeth Fift.

Ymrwymo dolen gyda thoes ychwanegol.

Gadewch i ni redeg y prawf a gwneud yn siŵr ei fod yn methu. Nawr, gadewch i ni ychwanegu rhesymeg i newid cyfeiriad perchennog y loteri.

Yn y contract smart rydym yn parhau i ddosrannu message, darllenwch i mewn action. Gadewch inni eich atgoffa y bydd gennym ddau action: newid cyfeiriad ac anfon gram.

Yna rydym yn darllen cyfeiriad newydd perchennog y contract a'i gadw yn y storfa.
Rydyn ni'n cynnal y profion ac yn gweld bod y trydydd prawf yn methu. Mae'n damwain oherwydd bod y contract bellach hefyd yn dosrannu 7 did o'r neges, sydd ar goll yn y prawf. Ychwanegu un nad yw'n bodoli i'r neges action. Gadewch i ni redeg y profion a gweld bod popeth yn mynd heibio. Yma ymrwymo i newidiadau. Gwych.

Nawr, gadewch i ni ysgrifennu'r rhesymeg ar gyfer anfon y nifer penodedig o gramau i'r cyfeiriad a gadwyd yn flaenorol.

Yn gyntaf, gadewch i ni ysgrifennu prawf. Byddwn yn ysgrifennu dau brawf, un pan nad oes digon o gydbwysedd, yr ail pan ddylai popeth basio'n llwyddiannus. Gellir gweld profion yn yr ymrwymiad hwn.

Nawr, gadewch i ni ychwanegu'r cod. Yn gyntaf, gadewch i ni ysgrifennu dau ddull cynorthwyydd. Y dull cael cyntaf yw darganfod cydbwysedd cyfredol contract smart.

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

Ac mae'r ail un ar gyfer anfon gramau i gontract smart arall. Copïais y dull hwn yn llwyr o gontract smart arall.

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

Gadewch i ni ychwanegu'r ddau ddull hyn at y contract smart ac ysgrifennu'r rhesymeg. Yn gyntaf, rydym yn dosrannu nifer y gramau o'r neges. Nesaf rydym yn gwirio'r balans, os nad yw'n ddigon rydyn ni'n taflu eithriad. Os yw popeth yn iawn, yna rydyn ni'n anfon y gramau i'r cyfeiriad sydd wedi'i gadw ac yn diweddaru'r cownter.

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

Yma felly edrych fel y contract smart ar hyn o bryd. Gadewch i ni redeg y profion a gwneud yn siŵr eu bod yn pasio.

Gyda llaw, mae comisiwn yn cael ei dynnu o'r contract smart bob tro ar gyfer neges wedi'i phrosesu. Er mwyn i'r negeseuon contract smart gyflawni'r cais, ar ôl gwiriadau sylfaenol mae angen i chi ffonio accept_message().

Nawr, gadewch i ni symud ymlaen i negeseuon mewnol. Mewn gwirionedd, dim ond gramau y byddwn yn eu derbyn ac yn anfon dwbl y swm yn ôl i'r chwaraewr os yw'n ennill a thraean i'r perchennog os bydd yn colli.

Yn gyntaf, gadewch i ni ysgrifennu prawf syml. I wneud hyn, mae angen cyfeiriad prawf y contract smart yr ydym i fod i anfon gramau ohono i'r contract smart.

Mae cyfeiriad y contract smart yn cynnwys dau rif, cyfanrif 32-did sy'n gyfrifol am y gadwyn waith a rhif cyfrif cyfanrif unigryw annegyddol 256-did yn y gadwyn waith hon. Er enghraifft, -1 a 12345, dyma'r cyfeiriad y byddwn yn ei gadw i ffeil.

Fe wnes i gopïo'r swyddogaeth ar gyfer cadw'r cyfeiriad ohono 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

Gadewch i ni edrych ar sut mae'r swyddogaeth yn gweithio, bydd hyn yn rhoi dealltwriaeth o sut mae Fift yn gweithio. Lansio Fift yn y modd rhyngweithiol.

~/TON/build/crypto/fift -i 

Yn gyntaf rydym yn gwthio -1, 12345 ac enw'r ffeil dyfodol "sender.addr" ar y pentwr:

-1 12345 "sender.addr" 

Y cam nesaf yw gweithredu'r swyddogaeth -rot, sy'n symud y pentwr yn y fath fodd fel bod rhif contract smart unigryw ar frig y pentwr:

"sender.addr" -1 12345

256 u>B yn trosi cyfanrif annegatif 256-did yn beit.

"sender.addr" -1 BYTES:0000000000000000000000000000000000000000000000000000000000003039

swap yn cyfnewid dwy elfen uchaf y pentwr.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 -1

32 i>B yn trosi cyfanrif 32-did yn beit.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 BYTES:FFFFFFFF

B+ yn cysylltu dau ddilyniant o beit.

 "sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF

Unwaith eto swap.

BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF "sender.addr" 

Ac yn olaf mae'r bytes yn cael eu hysgrifennu i'r ffeil B>file. Ar ôl hyn mae ein pentwr yn wag. Rydyn ni'n stopio Fift. Mae ffeil wedi'i chreu yn y ffolder gyfredol sender.addr. Gadewch i ni symud y ffeil i'r ffolder a grëwyd test/addresses/.

Gadewch i ni ysgrifennu prawf syml a fydd yn anfon gramau i gontract smart. Dyma'r ymrwymiad.

Nawr gadewch i ni edrych ar resymeg y loteri.

Y peth cyntaf rydyn ni'n ei wneud yw gwirio'r neges bounced neu ddim os bounced, yna rydym yn ei anwybyddu. bounced yn golygu y bydd y contract yn dychwelyd gramau os bydd rhyw gamgymeriad yn digwydd. Ni fyddwn yn dychwelyd gramau os bydd gwall yn digwydd yn sydyn.

Rydyn ni'n gwirio, os yw'r balans yn llai na hanner gram, yna rydyn ni'n derbyn y neges a'i hanwybyddu.

Nesaf, rydym yn dosrannu cyfeiriad y contract smart y daeth y neges ohono.

Rydyn ni'n darllen y data o'r storfa ac yna'n dileu hen betiau o'r hanes os oes mwy nag ugain ohonyn nhw. Er hwylustod, ysgrifennais dair swyddogaeth ychwanegol pack_order(), unpack_order(), remove_old_orders().

Nesaf, rydym yn edrych os nad yw'r balans yn ddigon ar gyfer y taliad, yna rydym yn ystyried nad bet yw hwn, ond ailgyflenwi ac arbed yr ailgyflenwi yn orders.

Yna yn olaf hanfod y contract smart.

Yn gyntaf, os bydd y chwaraewr yn colli, rydym yn ei arbed yn yr hanes betio ac os yw'r swm yn fwy na 3 gram, rydym yn anfon 1/3 at berchennog y contract smart.

Os yw'r chwaraewr yn ennill, yna byddwn yn anfon dwbl y swm i gyfeiriad y chwaraewr ac yna'n arbed y wybodaeth am y bet mewn hanes.

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

Dyna'r cyfan. Ymrwymiad cyfatebol.

Nawr bod y cyfan sydd ar ôl yn syml, gadewch i ni greu dulliau cychwyn fel y gallwn gael gwybodaeth am gyflwr y contract o'r byd y tu allan (mewn gwirionedd, darllenwch y data o'u storfa gontract smart).

Gadewch i ni ychwanegu dulliau cael. Byddwn yn ysgrifennu isod am sut i dderbyn gwybodaeth am gontract smart.

Anghofiais hefyd ychwanegu'r cod a fydd yn prosesu'r cais cyntaf un sy'n digwydd wrth gyhoeddi contract smart. Ymrwymiad cyfatebol. Ac ymhellach cywiro byg ag anfon 1/3 o'r swm i gyfrif y perchenog.

Y cam nesaf yw cyhoeddi'r contract smart. Gadewch i ni greu ffolder requests.

Cymerais y cod cyhoeddi fel sail simple-wallet-code.fc sydd yn gallu dod o hyd yn y gadwrfa swyddogol.

Rhywbeth gwerth rhoi sylw iddo. Rydym yn cynhyrchu storfa gontract smart a neges fewnbwn. Ar ôl hyn, cynhyrchir cyfeiriad y contract smart, hynny yw, mae'r cyfeiriad yn hysbys hyd yn oed cyn ei gyhoeddi yn TON. Yna mae angen i chi anfon sawl gram i'r cyfeiriad hwn, a dim ond ar ôl hynny mae angen i chi anfon ffeil gyda'r contract smart ei hun, gan fod y rhwydwaith yn cymryd comisiwn ar gyfer storio'r contract smart a'r gweithrediadau ynddo (dilyswyr sy'n storio ac yn gweithredu contractau smart ). Gellir gweld y cod yma.

Nesaf rydym yn gweithredu'r cod cyhoeddi a chael lottery-query.boc ffeil contract smart a chyfeiriad.

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

Peidiwch ag anghofio arbed y ffeiliau a gynhyrchir: lottery-query.boc, lottery.addr, lottery.pk.

Ymhlith pethau eraill, byddwn yn gweld cyfeiriad y contract smart yn y logiau gweithredu.

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

Dim ond am hwyl, gadewch i ni wneud cais i TON

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

A byddwn yn gweld bod y cyfrif gyda'r cyfeiriad hwn yn wag.

account state is empty

Anfonwn i'r cyfeiriad 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd 2 Gram ac ar ôl ychydig eiliadau rydym yn gweithredu'r un gorchymyn. I anfon gramau dwi'n defnyddio waled swyddogol, a gallwch ofyn i rywun o'r sgwrs am gramau prawf, y byddaf yn siarad amdanynt ar ddiwedd yr erthygl.

> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Mae'n edrych fel un anflaengar (state:account_uninit) contract smart gyda'r un cyfeiriad a chydbwysedd o 1 nanogram.

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

Nawr, gadewch i ni gyhoeddi'r contract smart. Gadewch i ni lansio lite-cleient a gweithredu.

> 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 

Gadewch i ni wirio bod y contract wedi'i gyhoeddi.

> last
> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Ymhlith pethau eraill a gawn.

  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

Gwelwn hynny account_active.

Ymrwymiad cyfatebol gyda newidiadau yma.

Nawr, gadewch i ni greu ceisiadau i ryngweithio â'r contract smart.

Yn fwy manwl gywir, byddwn yn gadael yr un cyntaf ar gyfer newid y cyfeiriad fel gwaith annibynnol, a byddwn yn gwneud yr ail un ar gyfer anfon gramau i gyfeiriad y perchennog. Yn wir, bydd angen i ni wneud yr un peth ag yn y prawf ar gyfer anfon gram.

Dyma'r neges y byddwn yn ei hanfon at y contract smart, lle msg_seqno 165, action 2 a 9.5 gram i'w hanfon.

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

Peidiwch ag anghofio llofnodi'r neges gyda'ch allwedd breifat lottery.pk, a gynhyrchwyd yn gynharach wrth greu'r contract smart. Dyma'r ymrwymiad cyfatebol.

Derbyn gwybodaeth o gontract smart gan ddefnyddio dulliau cael

Nawr, gadewch i ni edrych ar sut i redeg dulliau cael contract smart.

Lansio lite-client a rhedeg y dulliau get a ysgrifenasom.

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

В result yn cynnwys y gwerth y mae'r ffwythiant yn ei ddychwelyd balance() o'n contract smart.
Byddwn yn gwneud yr un peth ar gyfer sawl dull arall.

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

Gadewch i ni ofyn am eich hanes bet.

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

Byddwn yn defnyddio lite-client ac yn cael dulliau i arddangos gwybodaeth am y contract smart ar y wefan.

Arddangos data contract smart ar y wefan

Ysgrifennais wefan syml yn Python i arddangos y data o'r contract smart mewn ffordd gyfleus. Yma ni fyddaf yn aros arno'n fanwl a byddaf yn cyhoeddi'r wefan mewn un ymrwymiad.

Gwneir ceisiadau i TON oddi wrth Python gyda help lite-client. Er hwylustod, mae'r wefan wedi'i phecynnu yn Docker a'i chyhoeddi ar Google Cloud. Dolen.

Yn ceisio

Nawr, gadewch i ni geisio anfon gramau yno i'w hailgyflenwi o waled. Byddwn yn anfon 40 gram. A gadewch i ni wneud cwpl o betiau er eglurder. Gwelwn fod y wefan yn dangos hanes betiau, y ganran fuddugol gyfredol a gwybodaeth ddefnyddiol arall.

Rydyn ni'n gweldein bod wedi ennill y cyntaf, colli'r ail.

Afterword

Trodd yr erthygl allan i fod yn llawer hirach nag yr oeddwn yn ei ddisgwyl, efallai y gallai fod wedi bod yn fyrrach, neu efallai dim ond i berson nad yw'n gwybod dim am TON ac sydd am ysgrifennu a chyhoeddi contract smart nad yw mor syml â'r gallu i ryngweithio ag ef. mae'n. Efallai y gellid bod wedi egluro rhai pethau yn symlach.

Efallai y gallai rhai agweddau ar y gweithredu fod wedi cael eu gwneud yn fwy effeithlon a chain, ond yna byddai wedi cymryd hyd yn oed mwy o amser i baratoi'r erthygl. Mae hefyd yn bosibl imi wneud camgymeriad yn rhywle neu nad oeddwn yn deall rhywbeth, felly os ydych chi'n gwneud rhywbeth difrifol, mae angen i chi ddibynnu ar y ddogfennaeth swyddogol neu'r ystorfa swyddogol gyda'r cod TON.

Dylid nodi, gan fod TON ei hun yn dal i fod yn y cyfnod datblygu gweithredol, gall newidiadau ddigwydd a fydd yn torri unrhyw un o'r camau yn yr erthygl hon (a ddigwyddodd tra roeddwn i'n ysgrifennu, mae eisoes wedi'i gywiro), ond y dull cyffredinol yw annhebygol o newid.

Ni fyddaf yn siarad am ddyfodol TON. Efallai y bydd y platfform yn dod yn rhywbeth mawr a dylem dreulio amser yn ei astudio a llenwi cilfach gyda'n cynnyrch nawr.

Mae Libra hefyd gan Facebook, sydd â chynulleidfa bosibl o ddefnyddwyr yn fwy na TON. Nid wyf yn gwybod bron dim am Libra, a barnu yn ôl y fforwm mae llawer mwy o weithgaredd yno nag yn y gymuned TON. Er bod datblygwyr a chymuned TON yn debycach o dan y ddaear, sydd hefyd yn cŵl.

cyfeiriadau

  1. Dogfennaeth swyddogol TON: https://test.ton.org
  2. Ystorfa TON swyddogol: https://github.com/ton-blockchain/ton
  3. Waled swyddogol ar gyfer gwahanol lwyfannau: https://wallet.ton.org
  4. Ystorfa gontract smart o'r erthygl hon: https://github.com/raiym/astonished
  5. Dolen i wefan contract smart: https://ton-lottery.appspot.com
  6. Ystorfa ar gyfer yr estyniad ar gyfer Visual Studio Code ar gyfer FunC: https://github.com/raiym/func-visual-studio-plugin
  7. Sgwrsiwch am TON yn Telegram, a helpodd yn fawr i'w ddarganfod yn y cam cychwynnol. Rwy'n credu na fydd yn gamgymeriad os dywedaf fod pawb a ysgrifennodd rywbeth i TON yno. Gallwch hefyd ofyn am gramau prawf yno. https://t.me/tondev_ru
  8. Sgwrs arall am TON lle des i o hyd i wybodaeth ddefnyddiol: https://t.me/TONgramDev
  9. Cam cyntaf y gystadleuaeth: https://contest.com/blockchain
  10. Ail gam y gystadleuaeth: https://contest.com/blockchain-2

Ffynhonnell: hab.com

Ychwanegu sylw