ProHoster > Blog > Administrazioa > Telegram Open Network (TON) kontratu adimendun bat nola idatzi eta argitaratzeari buruz
Telegram Open Network (TON) kontratu adimendun bat nola idatzi eta argitaratzeari buruz
TON-en kontratu adimendun bat nola idatzi eta argitaratzeari buruz
Zeri buruz da artikulu hau?
Artikuluan Telegram blockchain lehiaketan lehenengo (bietatik) parte hartu nuen, saririk hartu ez nuen eta nire esperientzia artikulu batean grabatzea erabaki nuen, ahanzturan murgil ez zedin eta, beharbada, laguntzeari buruz hitz egingo dut. norbait.
Kode abstraktua idatzi nahi ez nuenez, funtzionatzen duen zerbait egin nahi nuenez, artikulurako kontratu adimenduna idatzi nuen berehalako loteria baterako eta TONetik zuzenean kontratu adimendunen datuak erakusten dituen webgune bat, tarteko biltegiratzea erabili gabe.
Artikulua erabilgarria izango da TON-en lehen kontratu adimenduna egin nahi dutenentzat, baina nondik hasi ez dakitenentzat.
Loteria adibide gisa hartuta, ingurunea instalatzetik kontratu adimendun bat argitaratzera pasako naiz, harekin elkarreragin eta datuak jaso eta argitaratzeko webgune bat idaztera.
Lehiaketan parte hartzeari buruz
Joan den urrian, Telegramek hizkuntza berriekin blockchain lehiaketa bat iragarri zuen Fift ΠΈ FunC. Beharrezkoa zen proposatutako bost kontratu adimendunetatik edozein idazteko aukeratzea. Pentsatu nuen polita izango zela zerbait ezberdina egitea, hizkuntza bat ikastea eta zerbait egitea, nahiz eta etorkizunean beste ezer idatzi behar ez izan. Gainera, gaia etengabe ezpainetan dago.
Esan beharra dago ez nuela esperientziarik kontratu adimentsuak garatzen.
Ahal nuen arte amaierara arte parte hartzeko asmoa nuen eta gero berrikuspen-artikulu bat idazteko, baina lehenengoan huts egin nuen berehala. I zorro bat idatzi zuen sinadura anitzeko aktibatuta FunC eta orokorrean funtzionatu zuen. Oinarritzat hartu nuen Solidity-ri buruzko kontratu adimenduna.
Garai hartan, uste nuen hori nahikoa zela, behintzat, sari-posturen bat hartzeko. Ondorioz, 40 parte-hartzaileetatik 60 inguru izan ziren saridun eta ni ez nintzen haien artean. Orokorrean, ez dago ezer gaizki, baina gauza batek molestatzen ninduen. Emaitzak iragartzeko momentuan, nire kontratuaren azterketaren berrikuspena egin gabe zegoen, txatean parte hartzaileei galdetu nien ea ez zegoen beste inor, ez zegoen.
Itxuraz nire mezuei erreparatuz, bi egun geroago epaileek iruzkin bat argitaratu zuten eta oraindik ez dut ulertzen ustekabean nire kontratu adimenduna galdu ote zuten epaiketa garaian edo, besterik gabe, uste zuten hain txarra zela, ez zuela komentariorik behar. Galdera bat egin nuen orrialdean, baina ez nuen erantzunik jaso. Nork epaitu zuen sekretua ez den arren, mezu pertsonalak idaztea alferrikakotzat jo nuen.
Ulermenean denbora asko eman zen, beraz, artikulu bat idaztea erabaki zen. Oraindik informazio asko ez dagoenez, artikulu honek denbora aurrezten lagunduko die interesa duten guztiei.
Kontratu adimendunen kontzeptua TONen
Ezer idatzi aurretik, gauza honi zein aldetatik heldu behar zaion asmatu behar duzu. Hori dela eta, orain esango dizut zer atalez osatuta dagoen sistema. Zehatzago esanda, zein zati jakin behar dituzun gutxienez lan-kontraturen bat idazteko.
Kontratu adimendun bat idaztera eta harekin lan egitean zentratuko gara TON Virtual Machine (TVM), Fift ΠΈ FunC, beraz, artikulua ohiko programa baten garapenaren deskribapena bezalakoa da. Ez gara hemen plataformak berak nola funtzionatzen duen azalduko.
Oro har, nola funtzionatzen duen TVM eta hizkuntza Fift dokumentazio ofizial ona dago. Lehiaketan parte hartzen nuen bitartean eta orain egungo kontratua idazten ari nintzenean, askotan jotzen nuen harengana.
Kontratu adimendunak idazten diren hizkuntza nagusia da FunC. Momentuz ez dago horri buruzko dokumentaziorik, beraz, zerbait idazteko, biltegi ofizialeko kontratu adimendunen adibideak aztertu behar dituzu eta hizkuntzaren beraren ezarpena bertan, gainera, azken bietako kontratu adimendunen adibideak ere ikus ditzakezu. lehiaketak. Artikuluaren amaieran dauden estekak.
Demagun dagoeneko kontratu adimendun bat idatzi dugula FunC, horren ondoren kodea Fift muntatzailean konpilatzen dugu.
Konpilatutako kontratu adimenduna argitaratzeko dago. Horretarako, funtzio bat idatzi behar duzu Fift, kontratu adimendunaren kodea eta beste parametro batzuk sarrera gisa hartuko dituena, eta irteera luzapena duen fitxategi bat izango da .boc (Β«zelula poltsaΒ» esan nahi du), eta, nola idazten dugunaren arabera, gako eta helbide pribatu bat, smart contract kodean oinarrituta sortzen dena. Gramoak bidal ditzakezu oraindik argitaratu ez den kontratu adimendun baten helbidera.
Jasotako TON-en kontratu adimenduna argitaratzeko .boc fitxategia blockchain-era bidali beharko da bezero arin bat erabiliz (behean gehiago). Baina argitaratu aurretik, gramoak transferitu behar dituzu sortutako helbidera, bestela kontratu adimenduna ez da argitaratuko. Argitaratu ondoren, kontratu adimendunarekin elkarreragin dezakezu kanpotik mezuak bidaliz (adibidez, bezero argi bat erabiliz) edo barrutik (adibidez, kontratu adimendun batek beste bati mezu bat bidaltzen dio TON barruan).
Kodea nola argitaratzen den ulertzen dugunean, errazagoa da. Gutxi gorabehera badakigu zer idatzi nahi dugun eta gure programa nola funtzionatuko duen. Eta idazten ari zaren bitartean, hori lehendik dauden kontratu adimendunetan nola inplementatzen den bilatzen dugu edo inplementazio kodea aztertzen dugu Fift ΠΈ FunC biltegi ofizialean, edo begiratu dokumentazio ofizialean.
Askotan, lehiaketako parte-hartzaile guztiak eta Telegrameko langileak biltzen ziren Telegrameko txatean gako-hitzak bilatzen nituen, eta gertatu zen lehiaketan denak bertan bildu zirela eta Fift eta FunC eztabaidatzen hasi zirela. Artikuluaren amaieran dagoen esteka.
Teoriatik praktikara pasatzeko garaia da.
TONekin lan egiteko ingurunea prestatzea
MacOS-en artikuluan deskribatuko den guztia egin nuen eta Docker-en Ubuntu 18.04 LTS garbian egiaztatu nuen.
Egin behar duzun lehenengo gauza deskargatu eta instalatu da lite-client horrekin eskaerak bidal ditzakezu TONera.
Webgune ofizialeko argibideek instalazio-prozesua oso zehatz eta argi deskribatzen dute eta xehetasun batzuk baztertzen dituzte. Hemen argibideak jarraitzen ditugu, bidean falta diren mendekotasunak instalatuz. Nik ez nuen proiektu bakoitza konpilatu eta Ubunturen biltegi ofizialetik instalatu (erabili nuen MacOS-en brew).
Mendekotasun guztiak instalatu ondoren instalatu dezakezu lite-client, Fift, FunC.
Lehenik eta behin, TON biltegia klonatuko dugu bere menpekotasunekin batera. Erosotasunerako, dena karpeta batean egingo dugu ~/TON.
cd ~/TON
git clone https://github.com/ton-blockchain/ton.git
cd ./ton
git submodule update --init --recursive
Biltegiak inplementazioak ere gordetzen ditu Fift ΠΈ FunC.
Orain prest gaude proiektua muntatzeko. Biltegiko kodea karpeta batean klonatzen da ~/TON/ton. Urtean ~/TON karpeta bat sortu build eta proiektua bertan jaso.
mkdir ~/TON/build
cd ~/TON/build
cmake ../ton
Kontratu adimendun bat idatziko dugunez, ez dugu bakarrik behar lite-clientBaina Fift Ρ FunC, beraz, konpila dezagun dena. Ez da prozesu azkarra, beraz, zain gaude.
cd ~/TON/build
./lite-client/lite-client -C ton-lite-client-test1.config.json
Eraikuntza arrakastatsua izan bada, abiarazi ondoren argi bezeroak nodoarekin duen konexioaren erregistroa ikusiko duzu.
[ 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)
...
Komandoa exekutatu dezakezu help eta ikusi zer komando dauden eskuragarri.
help
Zerrenda ditzagun artikulu honetan erabiliko ditugun komandoak.
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
Goian idatzi dudan bezala, idazten ari garen kontratu adimenduna loteria bat da.
Gainera, hau ez da txartela erosi eta ordubete, egun edo hilabete itxaron behar duzun loteria bat, erabiltzaileak kontratuaren helbidera transferitzen duen berehalakoa baizik. N gramo, eta berehala berreskuratzen du 2 * N gramo edo galtzen. Irabazteko probabilitatea %40 inguru egingo dugu. Ordaintzeko gramo nahikorik ez badago, transakzioa karga gisa hartuko dugu.
Gainera, garrantzitsua da apustuak denbora errealean eta modu erosoan ikustea, erabiltzaileak irabazi duen ala galdu duen berehala uler dezan. Hori dela eta, TONetik zuzenean apustuak eta emaitzak erakutsiko dituen webgune bat egin behar duzu.
Kontratu adimenduna idaztea
Erosotasunerako, FunC-ren kodea nabarmendu dut; plugina Visual Studio Code bilaketan aurkitu eta instalatu daiteke; bat-batean zerbait gehitu nahi baduzu, plugina publikoki eskuragarri jarri dut. Gainera, norbaitek Fift-ekin lan egiteko plugin bat egin zuen, instalatu eta VSC-en aurki dezakezu.
Sor dezagun berehala biltegi bat non tarteko emaitzak konprometituko ditugun.
Gure bizitza errazteko, smart contract bat idatziko dugu eta lokalean probatuko dugu prest egon arte. Horren ostean bakarrik argitaratuko dugu TONen.
Kontratu adimendunak kanpoko bi metodo ditu atzitu daitezkeen. Lehenik eta behin, recv_external() funtzio hori kontratuaren eskaera kanpotik datorrenean exekutatzen da, hau da, ez TONetik, adibidez, guk geuk mezu bat sortu eta lite-client bidez bidaltzen dugunean. Bigarrena, recv_internal() hau da, TON beraren baitan, edozein kontratu gureari egiten dio erreferentzia. Bi kasuetan, parametroak pasa ditzakezu funtzioari.
Has gaitezen argitaratzen bada funtzionatuko duen adibide sinple batekin, baina ez dago karga funtzionalik.
Hemen azaldu behar dugu zer den slice. TON Blockchain-en gordetako datu guztiak bilduma bat dira TVM cell edo, besterik gabe, cell, halako gelaxka batean 1023 bit datu eta gehienez 4 esteka beste gelaxketarako gorde ditzakezu.
TVM cell slice edo slice hau lehendik dagoenaren parte da cell analizatzeko erabiltzen da, gero argi geratuko da. Guretzat gauza nagusia transferitzea da slice eta mezu motaren arabera, datuak prozesatu recv_external() edo recv_internal().
impure β Funtzioak kontratu adimendunen datuak aldatzen dituela adierazten duen gako-hitz bat.
Gorde dezagun kontratuaren kodea lottery-code.fc eta konpilatu.
Fift muntatzaileen kodea bildu dugu 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
Lokalean jarri daiteke martxan, horretarako ingurumena prestatuko dugu.
Kontuan izan lehen lerroa lotzen dela Asm.fif, Fift-en idatzitako kodea da Fift-en muntatzailearentzat.
Kontratu adimenduna lokalean exekutatu eta probatu nahi dugunez, fitxategi bat sortuko dugu lottery-test-suite.fif eta kopiatu konpilatutako kodea bertan, azken lerroa ordezkatuz, kontratu adimendunaren kodea konstante batean idazten duena codegero makina birtualera transferitzeko:
"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
Orain arte argia dirudi, orain gehi diezaiogun fitxategi berean TVM abiarazteko erabiliko dugun kodea.
Π c7 testuingurua erregistratzen dugu, hau da, TVM (edo sarearen egoera) abiaraziko den datuekin. Lehiaketan ere, garatzaileetako batek nola sortu erakutsi zuen c7 eta kopiatu nuen. Artikulu honetan agian aldatu beharko dugu rand_seed ausazko zenbaki baten sorrera horren araberakoa baita eta aldatzen ez bada, zenbaki bera itzuliko da bakoitzean.
recv_internal ΠΈ recv_external 0 eta -1 balioak dituzten konstanteak kontratu adimendunean dagozkien funtzioak deitzeaz arduratuko dira.
Orain prest gaude gure kontratu adimendun hutsaren lehen proba sortzeko. Argitasuna lortzeko, oraingoz proba guztiak fitxategi berean gehituko ditugu lottery-test-suite.fif.
Sor dezagun aldagai bat storage eta idatzi bertan huts bat cell, hau izango da kontratu adimendunaren biltegia.
message Hau da kanpotik kontaktu adimendunari transmitituko diogun mezua. Oraingoz ere hutsik egingo dugu.
Bikaina, kontratu adimendunaren lehen lan-bertsioa idatzi dugu.
Orain funtzionaltasuna gehitu behar dugu. Lehenik eta behin kanpotik datozen mezuak jorratu ditzagun recv_external()
Garatzaileak berak aukeratzen du kontratuak onar dezakeen mezu formatua.
Baina normalean
lehenik eta behin, gure kontratua kanpotik babestu nahi dugu eta kontratuaren jabeak bakarrik bidali diezazkion kanpoko mezuak.
bigarrenik, baliozko mezu bat TON-i bidaltzen diogunean, hau zehatz-mehatz behin gertatzea nahi dugu eta mezu bera berriro bidaltzen dugunean, kontratu adimendunak baztertzen du.
Beraz, ia kontratu guztiek konpontzen dituzte bi arazo hauek, gure kontratuak kanpoko mezuak onartzen dituenez, hori ere zaindu behar dugu.
Alderantzizko ordenan egingo dugu. Lehenik eta behin, konpon dezagun arazoa errepikapenarekin; kontratuak dagoeneko halako mezu bat jaso eta prozesatu badu, ez du bigarren aldiz exekutatuko. Eta orduan arazoa konponduko dugu, pertsona zirkulu jakin batek soilik bidal ditzan kontratu adimendunari mezuak.
Mezu bikoiztuekin arazoa konpontzeko modu desberdinak daude. Hona hemen nola egingo dugun. Kontratu adimendunean, jasotako mezuen kontagailua hasierako 0 balioarekin hasieratzen dugu. Kontratu adimendunaren mezu bakoitzean, uneko kontagailuaren balioa gehituko dugu. Mezuko kontagailuaren balioa ez badator bat kontratu adimendunaren balioarekin, orduan ez dugu prozesatzen; hala bada, prozesatu eta kontratu adimendunean kontagailua 1 handituko dugu.
Itzuli gaitezen lottery-test-suite.fif eta gehitu bigarren proba bat. Zenbaki oker bat bidaltzen badugu, kodeak salbuespen bat bota beharko luke. Adibidez, utzi kontratuaren datuek 166 gorde, eta 165 bidaliko dugu.
<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"
Abiarazi gaitezen.
~/TON/build/crypto/fift -s lottery-test-suite.fif
Eta proba errore batekin exekutatzen dela ikusiko dugu.
[ 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
Etapa honetan lottery-test-suite.fif itxura izan beharko luke ΠΏΠΎ ΡΡΡΠ»ΠΊΠ΅.
Orain gehi diezaiogun kontagailuaren logika kontratu adimendunari 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 bidaltzen dugun mezua datza.
Egiten dugun lehenengo gauza mezuak datuak dituen egiaztatzea da, ez bada, irteten gara besterik gabe.
Ondoren, mezua analizatzen dugu. in_msg~load_uint(32) 165 zenbakia kargatzen du, 32 biteko unsigned int igorritako mezutik.
Ondoren, 32 bit kargatzen ditugu kontratu adimendunaren biltegitik. Kargatutako zenbakia gainditutakoarekin bat datorrela egiaztatzen dugu; hala ez bada, salbuespen bat botako dugu. Gure kasuan, partida ez den bat pasatzen ari garenez, salbuespen bat bota behar da.
Kopiatu ondoriozko kodea hemen lottery-test-suite.fif, azken lerroa ordezkatzeaz ahaztu gabe.
Proba gainditzen dela egiaztatzen dugu:
~/TON/build/crypto/fift -s lottery-test-suite.fif
Hementxe Dagokion konpromisoa ikus dezakezu uneko emaitzekin.
Kontuan izan deserosoa dela kontratu adimendun baten kodea konpilatua etengabe probak dituen fitxategi batean kopiatzea, beraz, kodea konstante batean idatziko duen script bat idatziko dugu, eta konpilatutako kodea gure probetara konektatuko dugu. "include".
Sortu fitxategi bat proiektuaren karpetan build.sh ondoko edukiarekin.
Orain, exekutatu gure script-a kontratua osatzeko. Baina honetaz gain, konstante batean idatzi behar dugu code. Beraz, fitxategi berri bat sortuko dugu lotter-compiled-for-test.fif, fitxategian sartuko duguna lottery-test-suite.fif.
Gehi dezagun skirpt kodea sh-ra, eta horrek konpilatutako fitxategia bikoiztuko du lotter-compiled-for-test.fif eta aldatu azken lerroa.
# 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
Orain, egiaztatzeko, exekutatu dezagun ondoriozko scripta eta fitxategi bat sortuko da lottery-compiled-for-test.fif, gurean sartuko duguna lottery-test-suite.fif
Π lottery-test-suite.fif ezabatu kontratuaren kodea eta gehitu lerroa "lottery-compiled-for-test.fif" include.
Probak egiten ditugu gainditzen direla egiaztatzeko.
~/TON/build/crypto/fift -s lottery-test-suite.fif
Bikaina, orain probak abiarazteko automatizatzeko, sor dezagun fitxategi bat test.sh, lehenengo exekutatu egingo dena build.sh, eta ondoren exekutatu probak.
Egin dezagun test.sh eta exekutatu probak funtzionatzen duela ziurtatzeko.
chmod +x ./test.sh
./test.sh
Kontratua osatzen dela eta probak egiten direla egiaztatzen dugu.
Bikaina, orain martxan jartzen test.sh Probak bildu eta berehala egingo dira martxan. Hona hemen esteka konprometitu.
Ados, jarraitu baino lehen, egin dezagun gauza bat erosotasunerako.
Sor dezagun karpeta bat build bertan kopiatutako kontratua eta bere klona konstante batean idatzita gordeko ditugu lottery-compiled.fif, lottery-compiled-for-test.fif. Sor dezagun karpeta bat ere test non gordeko da proba fitxategia? lottery-test-suite.fif eta balizko beste fitxategi osagarri batzuk. Lotura dagozkion aldaketetarako.
Jarrai dezagun kontratu adimenduna garatzen.
Ondoren, mezua jaso dela egiaztatzen duen proba bat egin behar da eta kontagailua dendan eguneratzen dela zenbaki zuzena bidaltzen dugunean. Baina hori geroago egingo dugu.
Orain pentsa dezagun zer datu-egitura eta zer datu gorde behar diren kontratu adimendunean.
Ondoren, bi funtzio idatzi behar dituzu. Dei diezaiogun lehenengoari pack_state(), datuak kontratu adimendunen biltegian gero gordetzeko bilduko dituena. Dei diezaiogun bigarrenari unpack_state() biltegitik datuak irakurri eta itzuliko ditu.
_ 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;
}
Bi funtzio hauek kontratu adimendunaren hasieran gehitzen ditugu. Landuko da horrela tarteko emaitza.
Datuak gordetzeko integratutako funtziora deitu beharko duzu set_data() eta datuak idatziko ditu pack_state() smart contract biltegian.
Orain datuak idazteko eta irakurtzeko funtzio erosoak ditugula, aurrera egin dezakegu.
Kanpotik jasotzen den mezua kontratuaren jabeak (edo gako pribaturako sarbidea duen beste erabiltzaile batek) sinatzen duela egiaztatu behar dugu.
Kontratu adimendun bat argitaratzen dugunean, biltegian behar ditugun datuekin abiarazi dezakegu, etorkizunean erabiltzeko gordeko direnak. Bertan gako publikoa grabatuko dugu, sarrerako mezua dagokion gako pribatuarekin sinatu dela egiaztatu ahal izateko.
Jarraitu aurretik, sor dezagun gako pribatu bat eta idatz dezagun test/keys/owner.pk. Horretarako, abiarazi dezagun Fift modu interaktiboan eta exekuta ditzagun lau komando.
Sor dezagun karpeta bat keys karpeta barruan test eta idatzi bertan gako pribatua.
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
Uneko karpetan fitxategi bat ikusten dugu owner.pk.
Gako publikoa pilatik kentzen dugu eta behar denean pribatutik lor dezakegu.
Orain sinadura egiaztapena idatzi behar dugu. Has gaitezen probarekin. Lehenik eta behin, fitxategiko gako pribatua irakurriko dugu funtzioa erabiliz file>B eta idatzi aldagai batean owner_private_key, gero funtzioa erabiliz priv>pub bihurtu gako pribatua gako publiko batean eta idatzi emaitza owner_public_key.
Jarraian, sinatutako mezu bat idatziko dugu, sinadura eta kontagailuaren balioa soilik izango ditu.
Lehenik eta behin, transmititu nahi ditugun datuak sortzen ditugu, ondoren gako pribatu batekin sinatzen ditugu eta azkenik sinatutako mezu bat sortzen dugu.
Ondorioz, smart contract-era bidaliko dugun mezua aldagai batean erregistratzen da message_to_send, funtzioei buruz hashu, ed25519_sign_uint irakur dezakezu Bosteko dokumentazioan.
Horrela Probak dituen fitxategiak honelakoa izan beharko luke fase honetan.
Egin dezagun proba eta huts egingo du, beraz, kontratu adimenduna aldatuko dugu, formatu honetako mezuak jaso eta sinadura egiazta ditzan.
Lehenik eta behin, mezutik sinaduraren 512 bit zenbatu eta aldagai batean idazten dugu, gero kontagailuaren aldagaiaren 32 bit zenbatuko ditugu.
Smart Contract biltegitik datuak irakurtzeko funtzio bat dugunez, erabiliko dugu.
Hurrengoa biltegiratzearekin transferitutako kontagailua egiaztatzea eta sinadura egiaztatzea da. Zerbait bat ez badator, orduan salbuespen bat botako dugu dagokion kodearekin.
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));
Egin ditzagun probak eta ikus ditzagun bigarren probak huts egiten duela. Bi arrazoirengatik, mezuan ez dago bit nahikorik eta biltegian ez dago nahikoa bit, beraz, kodea huts egiten du analizatzean. Bidaltzen ari garen mezuari sinadura bat gehitu eta azken probako biltegiratzea kopiatu behar dugu.
Bigarren proban, mezu sinadura bat gehituko dugu eta kontratu adimendunen biltegiratzea aldatuko dugu. Horrela probak dituen fitxategia une honetan itxura du.
Idatz dezagun laugarren proba, eta bertan beste norbaiten gako pribatuarekin sinatutako mezu bat bidaliko dugu. Sor dezagun beste gako pribatu bat eta gorde dezagun fitxategi batean not-owner.pk. Gako pribatu honekin sinatuko dugu mezua. Egin ditzagun probak eta ziurtatu proba guztiak gainditzen direla. Konprometitu une honetan.
Orain, azkenean, kontratu adimendunaren logika ezartzera pasa gaitezke.
Π recv_external() bi mezu mota onartuko ditugu.
Gure kontratuak jokalarien galerak pilatuko dituenez, diru hori loteriaren sortzaileari transferitu behar zaio. Loteriaren sortzailearen zorroaren helbidea biltegian erregistratzen da kontratua sortzen denean.
Badaezpada, galtzaileen gramoak bidaltzen ditugun helbidea aldatzeko gaitasuna behar dugu. Loteriatik gramoak jabearen helbidera bidaltzeko aukera ere izan beharko genuke.
Has gaitezen lehenengotik. Idatz dezagun lehenik mezua bidali ondoren, kontratu adimendunak helbide berria biltegian gorde duela egiaztatuko duen proba. Kontuan izan mezuan, kontagailuaz eta helbide berriaz gain, transmititzen dugula ere action 7 biteko zenbaki oso ez negatiboa, horren arabera, mezua nola prozesatu aukeratuko dugu kontratu adimendunean.
<b 0 32 u, 1 @ 7 u, new_owner_wc @ 32 i, new_owner_account_id @ 256 u, b> message_to_sign !
Probak smartcontract biltegiratzea nola deserializatuta dagoen ikus dezakezu storage Bostean. Aldagaien deserializazioa Fift-en dokumentazioan deskribatzen da.
Egin dezagun proba eta ziurtatu huts egiten duela. Orain gehi dezagun logika loteriaren jabearen helbidea aldatzeko.
Kontratu adimendunean analizatzen jarraitzen dugu message, irakurri action. Gogora dezagun bi izango ditugula action: helbidea aldatu eta gramoak bidali.
Ondoren, kontratuaren jabearen helbide berria irakurri eta biltegian gordetzen dugu.
Probak egiten ditugu eta hirugarren probak huts egiten duela ikusten dugu. Huts egiten du kontratuak orain mezutik 7 bit analizatzen dituelako, proban falta direnak. Gehitu existitzen ez den bat mezuari action. Egin ditzagun probak eta ea dena pasatzen dela. Hemen aldaketak egiteko konpromisoa. Bikaina.
Orain idatz dezagun zehaztutako gramo kopurua aurrez gordetako helbidera bidaltzeko logika.
Lehenik eta behin, idatzi dezagun proba. Bi proba idatziko ditugu, bata oreka nahikorik ez dagoenean, bigarrena dena ongi gainditu behar denean. Probak ikus daitezke konpromiso honetan.
Orain gehi dezagun kodea. Lehenik eta behin, idatzi ditzagun bi metodo laguntzaile. Lehenengo lortzeko metodoa kontratu adimendun baten egungo saldoa jakitea da.
int balance() inline_ref method_id {
return get_balance().pair_first();
}
Eta bigarrena gramoak beste kontratu adimendun batera bidaltzeko da. Metodo hau guztiz kopiatu nuen beste kontratu adimendun batetik.
() 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
}
Gehi ditzagun bi metodo hauek kontratu adimendunari eta idatzi logika. Lehenik eta behin, mezuaren gramo kopurua analizatzen dugu. Jarraian balantzea egiaztatzen dugu, nahikoa ez bada salbuespen bat botatzen dugu. Dena ondo badago, gramoak gordetako helbidera bidaliko ditugu eta kontagailua eguneratzen dugu.
Horrela kontratu adimenduna dirudi momentu honetan. Egin ditzagun probak eta ziurtatu gainditzen direla.
Bide batez, komisio bat kentzen zaio kontratu adimendunetik prozesatutako mezu baterako. Kontratu adimendunaren mezuek eskaera gauzatu ahal izateko, oinarrizko egiaztapenen ondoren deitu behar duzu accept_message().
Orain barruko mezuetara pasa gaitezen. Izan ere, gramoak bakarrik onartuko ditugu eta irabazten badu jokalariari kopuru bikoitza itzuliko diogu eta jabeari hirugarren bat galtzen badu.
Lehenik eta behin, idatz dezagun proba sinple bat. Horretarako, kontratu adimendunaren proba-helbide bat behar dugu, zeinetatik ustez gramoak bidaltzen ditugun kontratu adimendunera.
Kontratu adimendunaren helbidea bi zenbakiz osatuta dago, lan-katearen ardura duen 32 biteko zenbaki oso bat eta lan-kate honetako 256 biteko zenbaki oso negatibo ez den kontu bakarra. Adibidez, -1 eta 12345, hau da fitxategi batean gordeko dugun helbidea.
Eta azkenik, byteak fitxategian idazten dira B>file. Honen ondoren gure pila hutsik dago. Gelditzen gara Fift. Fitxategi bat sortu da uneko karpetan sender.addr. Muga dezagun fitxategia sortutako karpetara test/addresses/.
Idatz dezagun gramoak kontratu adimendun batera bidaliko dituen proba sinple bat. Hona hemen konpromisoa.
Ikus dezagun orain loteriaren logika.
Egiten dugun lehenengo gauza mezua egiaztatzea da bounced edo ez bada bounced, orduan alde batera uzten dugu. bounced esan nahi du kontratuak gramoak itzuliko dituela erroreren bat gertatzen bada. Ez dugu gramorik itzuliko bat-batean erroreren bat gertatzen bada.
Egiaztatzen dugu, saldoa gramo erdia baino txikiagoa bada, orduan mezua onartu eta ez ikusiarena egiten dugu.
Ondoren, mezua atera den kontratu adimendunaren helbidea aztertuko dugu.
Biltegiko datuak irakurtzen ditugu eta, gero, apustu zaharrak historiatik ezabatzen ditugu, hogei baino gehiago badira. Erosotasunerako, hiru funtzio gehigarri idatzi ditut pack_order(), unpack_order(), remove_old_orders().
Jarraian, saldoa ordainketarako nahikoa ez den aztertzen dugu, orduan hau ez dela apustu bat, birjartzea baizik eta gordeko dugu. orders.
Ondoren, azkenik, kontratu adimendunaren funtsa.
Lehenik eta behin, jokalariak galtzen badu, apustuen historian gordetzen dugu eta zenbatekoa 3 gramotik gorakoa bada, 1/3 bidaltzen diogu smart contractaren jabeari.
Jokalariak irabazten badu, bikoitza bidaltzen dugu jokalariaren helbidera eta gero apustuari buruzko informazioa historian gordetzen dugu.
() 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));
}
Orain geratzen dena sinplea da, sor ditzagun get-metodoak, kontratuaren egoerari buruzko informazioa kanpotik lortu ahal izateko (hain zuzen ere, irakurri haien kontratu adimendunen biltegiko datuak).
Gehi ditzagun get metodoak. Jarraian idatziko dugu kontratu adimendun bati buruzko informazioa nola jaso.
Kontratu adimendun bat argitaratzean gertatzen den lehenengo eskaera prozesatuko duen kodea gehitzea ere ahaztu zait. Dagokion konpromisoa. Eta harago zuzenduta akatsa jabearen kontura zenbatekoaren 1/3 bidaltzearekin.
Hurrengo urratsa kontratu adimenduna argitaratzea da. Sor dezagun karpeta bat requests.
Arreta ematea merezi duen zerbait. Kontratu adimendunen biltegiratze bat eta sarrera-mezu bat sortzen ditugu. Horren ostean, kontratu adimendunaren helbidea sortzen da, hau da, helbidea TON-en argitaratu aurretik ere ezagutzen da. Ondoren, hainbat gramo bidali behar dituzu helbide honetara, eta horren ondoren bakarrik fitxategi bat bidali behar duzu kontratu adimendunarekin berarekin, sareak kontratu adimenduna eta eragiketak bertan gordetzeko komisioa hartzen baitu (kontratu adimendunak gordetzen eta exekutatzen dituzten balioztatzaileak). ). Kodea hemen ikus daiteke.
Ondoren, argitalpen-kodea exekutatu eta lortuko dugu lottery-query.boc smart contract fitxategia eta helbidea.
Eta helbide hau duen kontua hutsik dagoela ikusiko dugu.
account state is empty
Helbidera bidaltzen dugu 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd 2 Gram eta segundo batzuk igaro ondoren komando bera exekutatzen dugu. Erabiltzen ditudan gramoak bidaltzeko zorro ofiziala, eta txatetik norbaiti eskatu diezaiokezu probako gramoak, artikuluaren amaieran hitz egingo dudanez.
Sor ditzagun orain kontratu adimendunarekin elkarreragiteko eskaerak.
Zehatzago esanda, lehenengoa helbidea aldatzeko lan independente gisa utziko dugu, eta bigarrena jabearen helbidera gramoak bidaltzeko egingo dugu. Izan ere, gramoak bidaltzeko proban egiten den gauza bera egin beharko dugu.
Hau da kontratu adimendunari bidaliko diogun mezua, non msg_seqno 165, action 2 eta 9.5 gramo bidaltzeko.
<b 165 32 u, 2 7 u, 9500000000 Gram, b>
Ez ahaztu mezua zure gako pribatuarekin sinatzea lottery.pk, kontratu adimenduna sortzean lehenago sortu zena. Hona hemen dagokion konpromisoa.
Kontratu adimendun batetik informazioa jasotzea get metodoak erabiliz
Orain ikus dezagun nola exekutatu smart contract get metodoak.
korrika lite-client eta exekutatu idatzi ditugun get metodoak.
Lite-client erabiliko dugu eta kontratu adimendunari buruzko informazioa webgunean bistaratzeko metodoak lortuko ditugu.
Kontratu adimendunen datuak webgunean bistaratzea
Webgune sinple bat idatzi nuen Python-en kontratu adimendunaren datuak modu erosoan bistaratzeko. Hemen ez naiz zehatz-mehatz luzatuko eta gunea argitaratuko dut konpromiso batean.
TON-ri egindako eskaerak Python laguntzarekin lite-client. Erosotasunerako, gunea Docker-en bilduta dago eta Google Cloud-en argitaratzen da. Esteka.
Saiatzen
Orain saia gaitezen gramoak hortik hornitzeko bidaltzen poltsan. 40 gramo bidaliko ditugu. Eta egin ditzagun apustu pare bat argitasuna lortzeko. Ikusten dugu webguneak apustuen historia, egungo irabazi-ehunekoa eta beste informazio erabilgarria erakusten duela.
Ikusten dugulehenengoa irabazi genuela, bigarrena galdu.
afterword
Artikulua espero nuena baino askoz luzeagoa izan da, agian laburragoa izan zitekeen, edo agian TON-i buruz ezer ez dakien eta kontratu adimendun ez hain sinple bat idatzi eta argitaratu nahi duen pertsona batentzat, elkarrekin harremanetan jartzeko gaitasuna duena. hura. Agian gauza batzuk modu sinpleagoan azaldu zitezkeen.
Agian inplementazioaren alderdi batzuk eraginkorrago eta dotoreago egin zitezkeen, baina orduan are denbora gehiago beharko zen artikulua prestatzeko. Baliteke ere nonbait akats bat egitea edo zerbait ulertu ez izatea, beraz, zerbait serioa egiten ari bazara, dokumentazio ofizialean edo TON kodea duen biltegi ofizialean oinarritu behar duzu.
Kontuan izan behar da TON bera oraindik garapen fase aktiboan dagoenez, artikulu honetako edozein urrats hautsiko duten aldaketak gerta daitezkeela (idazten ari nintzen bitartean gertatu zena, dagoeneko zuzenduta dago), baina ikuspegi orokorra da. nekez aldatuko da.
Ez dut TONen etorkizunaz hitz egingo. Agian plataforma zerbait handia bihurtuko da eta denbora pasa beharko genuke aztertzen eta nitxo bat bete gure produktuekin orain.
Facebook-eko Libra ere badago, TON baino erabiltzaileen audientzia potentziala duena. Librari buruz ia ezer ez dakit, foroaren arabera TON komunitatean baino jarduera gehiago dago bertan. TON-en garatzaileak eta komunitateak lurpeko antzekoak diren arren, hori ere polita da.
Txateatu TON-i buruz Telegram-en, eta horrek benetan lagundu zuen hasierako fasean. Uste dut ez dela akats bat izango TON-entzat zerbait idatzi duten guztiak hor daudela esaten badut. Test gramoak ere eska ditzakezu bertan. https://t.me/tondev_ru
TON-i buruzko beste berriketa bat non informazio baliagarria aurkitu nuen: https://t.me/TONgramDev