ProHoster > Blog > Rêveberî > Di derbarê meriv çawa di Tora Vekirî ya Telegram (TON) de peymanek jîr binivîsîne û biweşîne
Di derbarê meriv çawa di Tora Vekirî ya Telegram (TON) de peymanek jîr binivîsîne û biweşîne
Di derbarê meriv çawa di TON de peymanek biaqil dinivîse û diweşîne
Ev gotar li ser çi ye?
Di gotarê de ez ê biaxivim ka çawa min beşdarî pêşbirka yekem (ji du) bloka Telegram-ê bû, xelatek negirt, û biryar da ku ezmûna xwe di gotarekê de tomar bikim da ku ew nekeve nav jibîrbûnê û, dibe ku, bibe alîkar. kesek.
Ji ber ku min nexwest koda razber binivîsim, lê ji bo ku ez tiştek bixebitim, ji bo gotarê min ji bo lotoyek tavilê û malperek ku daneyên peymana hişmend rasterast ji TON-ê bêyî karanîna hilanîna navberê nîşan dide peymanek jîr nivîsî.
Gotar dê ji wan kesên ku dixwazin yekem peymana xweya jîr li TON-ê çêbikin re bikêr be, lê nizanin ji ku dest pê bikin.
Bi karanîna lotoyê wekî mînak, ez ê ji sazkirina hawîrdorê berbi weşandina peymanek biaqil, pê re têkilî daynin û ji bo wergirtin û weşandina daneyan malperek binivîsim.
Derbarê beşdarbûna pêşbirkê de
Cotmeha borî, Telegram bi zimanên nû re pêşbaziyek blokê ragihand Fift и FunC. Pêwîst bû ku ji nivîsandina yek ji pênc peymanên hişmend ên pêşniyarkirî hilbijêrin. Min difikirî ku ez tiştekî cuda bikim, zimanekî hîn bibim û tiştekî çêbikim, heta ku di pêşerojê de ne hewce be jî tiştekî din binivîsim dê xweş be. Wekî din, mijar bi berdewamî li ser lêvan e.
Hêjayî gotinê ye ku ezmûna min a pêşxistina peymanên jîr nebû.
Min plan kir ku ez heya dawiyê beşdar bibim heya ku ez bikaribim û dûv re gotarek nirxandinê binivîsim, lê ez tavilê di yekem de têk çûm. ez walletek nivîsand bi pir-îmza li ser FunC û bi gelemperî xebitî. Min ji xwe re esas girt peymana jîr li ser Solidity.
Wê demê, min fikirîn ku ev bê guman bes e ku bi kêmanî cîhek xelat bigire. Di encamê de ji 40 beşdaran nêzî 60 kes bûn xelatgir û ez ne di nav wan de bûm. Bi gelemperî, di vê yekê de tiştek xelet tune, lê tiştek min xemgîn kir. Di dema ragihandina encaman de, vekolîna testa peymana min nehatibû kirin, min ji beşdarên sohbetê pirsî ku kesek din tune ye, tune ye.
Xuyaye ku bala xwe daye peyamên min, du roj şûnda dadger şîroveyek weşandin û ez hîn jî fam nakim ka wan bi xeletî peymana min a jîr di dema dadkirinê de ji dest da an bi tenê fikirîn ku ew ew qas xirab bû ku hewcedarê şîroveyê nebû. Min li ser rûpelê pirsek kir, lê bersiv negirt. Her çend ne veşartî ye ku kê dadbar dike, min nepêwîst dît ku peyamên kesane binivîsim.
Gelek dem li ser têgihiştinê derbas bû, ji ber vê yekê biryar hat dayîn ku gotarek were nivîsandin. Ji ber ku hîna pir agahdarî tune ye, ev gotar dê ji bo her kesê eleqedar dem xilas bike.
Têgeha peymanên jîr li TON
Berî ku hûn tiştek binivîsin, hûn hewce ne ku fêm bikin ka hûn ji kîjan alî ve nêzîkê vê tiştê bibin. Ji ber vê yekê, niha ez ê ji we re bibêjim ku pergal ji kîjan beşan pêk tê. Zêdetir, kîjan beşan divê hûn zanibin da ku hûn bi kêmanî cûreyek peymanek xebatê binivîsin.
Em ê bala xwe bidin ser nivîsandina peymanek biaqil û bi hev re bixebitin TON Virtual Machine (TVM), Fift и FunC, ji ber vê yekê gotar bêtir wekî ravekirina pêşveçûna bernameyek birêkûpêk e. Em ê li ser vê yekê nesekinin ka platform bixwe li vir çawa dixebite.
Bi gelemperî li ser ka ew çawa dixebite TVM û ziman Fift belgeyên fermî yên baş hene. Dema ku beşdarî pêşbirkê bûm û niha dema ku peymana heyî dinivîsim, min gelek caran berê xwe da wê.
Zimanê sereke yê ku peymanên zîrek tê nivîsandin ev e FunC. Heya nuha tu belgeyek li ser wê tune, ji ber vê yekê ji bo ku hûn tiştek binivîsin hûn hewce ne ku nimûneyên peymanên jîr ji depoya fermî û bicîhkirina zimanê xwe li wir bixwînin, plus hûn dikarin li mînakên peymanên jîr ên ji du paşîn binêrin. pêşbirkên. Girêdanên di dawiya gotarê de.
Em bibêjin ku me berê ji bo peymanek jîr nivîsandiye FunC, piştî wê em kodê di komkera Fift de berhev dikin.
Peymana hişmend a berhevkirî dimîne ku were weşandin. Ji bo vê yekê hûn hewce ne ku fonksiyonek tê de binivîsin Fift, ku dê koda peymana jîr û hin pîvanên din wekî têketinê bigire, û encam dê pelek bi dirêjkirinê be. .boc (ku tê wateya "çenta hucreyan"), û, li gorî ka em wê çawa dinivîsin, mifteyek taybet û navnîşanek, ku li ser bingeha koda peymana jîr tê çêkirin. Hûn dikarin berê gram bişînin navnîşana peymanek jîr a ku hîn nehatiye weşandin.
Ji bo weşandina peymanek biaqil di TON de hatî wergirtin .boc pêdivî ye ku pel bi karanîna xerîdarek sivik ji blokê re were şandin (li ser wê yekê li jêr). Lê berî weşankirinê, hûn hewce ne ku gram bi navnîşana hatî hilberandin veguhezînin, wekî din dê peymana hişmend neyê weşandin. Piştî weşandinê, hûn dikarin bi peymana biaqil re bi şandina wê peyamên ji derve (mînakî, bi karanîna xerîdarek sivik) an jî ji hundur ve bişînin (mînakek, peymanek jîr ji yekî din re peyamek di hundurê TON de dişîne).
Dema ku em fêm bikin ka kod çawa tê weşandin, ew hêsantir dibe. Em bi qasî dizanin ku em dixwazin çi binivîsin û bernameya me dê çawa bixebite. Dema ku dinivîsin, em lê digerin ka ev çawa jixwe di peymanên jîr ên heyî de tête bicîh kirin, an jî em li koda bicîhkirinê dinêrin Fift и FunC di depoya fermî de, an li belgeya fermî binihêrin.
Pir caran ez di chat Telegram de ku hemî beşdarên pêşbaziyê û xebatkarên Telegram li hev civiyan li peyvên sereke geriyam, û wusa bû ku di dema pêşbaziyê de her kes li wir kom bû û dest bi nîqaşkirina Fift û FunC kir. Girêdana di dawiya gotarê de.
Dem hatiye ku ji teoriyê derbasî pratîkê bibin.
Amadekirina jîngehê ji bo xebata bi TON re
Min her tiştê ku dê di gotarê de li ser MacOS-ê were vegotin kir û ew di Ubuntu 18.04 LTS-ya paqij a li ser Docker-ê de du caran kontrol kir.
Yekem tiştê ku divê hûn bikin ev e ku dakêşin û saz bikin lite-client bi ku hûn dikarin daxwazan ji TON re bişînin.
Rêbernameyên li ser malpera fermî pêvajoya sazkirinê bi hûrgulî û zelal vedibêjin û hin hûrguliyan ji holê radikin. Li vir em rêwerzanan dişopînin, girêdanên winda di rê de saz dikin. Min her proje bi xwe berhev nekir û ji depoya fermî ya Ubuntu saz kir (li MacOS-ê ku min bikar anî brew).
Dema ku hemî girêdan têne saz kirin hûn dikarin saz bikin lite-client, Fift, FunC.
Pêşîn, em depoya TON û pêgirên wê klon dikin. Ji bo rehetiyê, em ê her tiştî di peldankê de bikin ~/TON.
cd ~/TON
git clone https://github.com/ton-blockchain/ton.git
cd ./ton
git submodule update --init --recursive
Depo jî pêkanînan hilîne Fift и FunC.
Niha em amade ne ku projeyê bicivînin. Koda depoyê di peldankekê de tê klon kirin ~/TON/ton. ew ~/TON peldankek çêbikin build û proje tê de kom bike.
mkdir ~/TON/build
cd ~/TON/build
cmake ../ton
Ji ber ku em ê peymanek biaqil binivîsin, em ne tenê hewce ne lite-clientlê belê, Fift с FunC, da ku em her tiştî berhev bikin. Ew ne pêvajoyek bilez e, ji ber vê yekê em li bendê ne.
cd ~/TON/build
./lite-client/lite-client -C ton-lite-client-test1.config.json
Ger avakirin serketî bû, wê hingê piştî destpêkirinê hûn ê têketinek pêwendiya xerîdar ronahiyê bi nodê re bibînin.
[ 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)
...
Hûn dikarin fermanê bimeşînin help û bibînin ka çi ferman hene.
help
Ka em emrên ku em ê di vê gotarê de bikar bînin navnîş bikin.
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-методы смартконтракта.
Niha em amade ne ku peymanê bi xwe binivîsin.
Реализация
Idea
Wekî ku min li jor jî nivîsî, peymana biaqil a ku em dinivîsin lotikek e.
Digel vê yekê, ev ne lotoyek e ku tê de hewce ye ku hûn bilêtek bikirin û demjimêrek, roj an mehekê li bendê bimînin, lê yek tavilê ye ku tê de bikarhêner vediguhezîne navnîşana peymanê. N gram, û di cih de wê vedigere 2 * N gram an winda dike. Em ê îhtîmala serketinê bi qasî 40% çêbikin. Ger ji bo dravdanê têra gram nebin, wê hingê em ê danûstendinê wekî top-up bihesibînin.
Digel vê yekê, girîng e ku behîs di demek rast û bi rengek hêsan were dîtin, da ku bikarhêner tavilê fêm bike ka wî bi ser ket an winda kir. Ji ber vê yekê, hûn hewce ne ku malperek çêbikin ku rasterast ji TON-ê behîs û encaman nîşan bide.
Nivîsandina peymanek jîr
Ji bo rehetiyê, min koda ji bo FunC ronî kiriye; pêvek dikare di lêgerîna Visual Studio Code de were dîtin û saz kirin; heke hûn ji nişkê ve bixwazin tiştek zêde bikin, min pêvek ji raya giştî re peyda kiriye. Di heman demê de, kesek berê pêvekek çêkir ku bi Fift re bixebite, hûn jî dikarin wê saz bikin û li VSC-ê bibînin.
Werin em tavilê depoyek ku em ê encamên navîn pêk bînin ava bikin.
Ji bo ku jiyana me hêsantir bibe, em ê peymanek biaqil binivîsin û heya ku amade be wê li herêmî ceribandin. Tenê piştî wê em ê di TON de biweşînin.
Peymana zîrek du rêbazên derveyî hene ku dikarin werin gihîştin. Yekem, recv_external() ev fonksiyon dema ku daxwazek peymanê ji cîhana derve tê, ango ne ji TON-ê tê, mînakî, dema ku em bixwe peyamek çêdikin û bi navgîniya lite-mişterî dişînin. Duyem, recv_internal() ev gava ku, di hundurê TON bixwe de, her peymanek ji ya me re vedibêje. Di her du rewşan de, hûn dikarin parameteran ji fonksiyonê re derbas bikin.
Ka em bi mînakek hêsan dest pê bikin ku heke were weşandin dê bixebite, lê di wê de barek fonksiyonel tune.
Li vir divê em rave bikin ka ew çi ye slice. Hemî daneyên ku di TON Blockchain de têne hilanîn berhevokek e TVM cell an tenê cell, di şaneyek weha de hûn dikarin heta 1023 bit daneyan û heta 4 lînkên şaneyên din hilînin.
TVM cell slice an slice ev beşek ji ya heyî ye cell ji bo parskirina wê tê bikaranîn, wê paşê zelal bibe. Ya sereke ji bo me ew e ku em dikarin veguherînin slice û li gorî celebê peyamê, daneyên tê de pêvajoyê bikin recv_external() an recv_internal().
impure - peyvek sereke ya ku destnîşan dike ku fonksiyon daneyên peymana hişmend diguhezîne.
Ka em koda peymanê tê de hilînin lottery-code.fc û berhev dikin.
Wateya alayan bi karanîna fermanê dikare were dîtin
~/TON/build/crypto/func -help
Me koda assembler ya Pêncê di nav de berhev kiriye 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
Li herêmê dikare were destpêkirin, ji bo vê jî em ê hawirdorê amade bikin.
Têbînî ku rêza yekem ve girêdayî ye Asm.fif, ev koda ku di Fift de ji bo komkera Fift hatî nivîsandin e.
Ji ber ku em dixwazin peymana jîr bi herêmî bimeşînin û ceribandin, em ê pelek biafirînin lottery-test-suite.fif û koda berhevkirî li wir kopî bikin, rêza paşîn a tê de biguhezînin, ku koda peymana biaqil bi domdar dinivîse codeDûv re wê veguhezînin makîneya virtual:
"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
Heya nuha zelal xuya dike, naha em ê koda ku em ê ji bo destpêkirina TVM bikar bînin li heman pelê zêde bikin.
В c7 em çerçoveyê tomar dikin, ango daneyên ku TVM (an dewleta torê) pê dê were destpêkirin. Tewra di dema pêşbaziyê de, yek ji pêşdebiran nîşan da ku meriv çawa diafirîne c7 û min kopî kir. Di vê gotarê de dibe ku em hewce ne ku biguherînin rand_seed ji ber ku çêkirina jimareke tesadufî bi wê ve girêdayî ye û ger neyê guhertin, dê her car heman hejmar were vegerandin.
recv_internal и recv_external sabitên bi nirxên 0 û -1 dê ji bo bangkirina fonksiyonên têkildar di peymana hişmend de berpirsiyar bin.
Naha em amade ne ku ceribandina yekem ji bo peymana xweya hişmend a vala biafirînin. Ji bo zelaliyê, heya niha em ê hemî ceribandinan li heman pelê zêde bikin lottery-test-suite.fif.
Werin em guhêrbarek çêbikin storage û yekî vala tê de binivîse cell, ev dê bibe hilanîna peymana jîr.
message Ev peyama ku em ê ji derve ve ji têkiliya biaqil re ragihînin ev e. Em ê jî ji bo niha vala bikin.
Mezin, me yekem guhertoya xebatê ya peymana hişmend nivîsandiye.
Niha em hewce ne ku fonksiyonê zêde bikin. Pêşî bila em bi peyamên ku ji cîhana derve tên re mijûl bibin recv_external()
Pêşdebir bixwe forma peyamê ya ku peyman dikare qebûl bike hildibijêre.
Lê bi gelemperî
yekem, em dixwazin peymana xwe ji cîhana derve biparêzin û wisa bikin ku tenê xwediyê peymanê karibe peyamên derve jê re bişîne.
ya duyemîn, dema ku em peyamek derbasdar ji TON re dişînin, em dixwazin ku ev yek tam carekê çêbibe û dema ku em dîsa heman peyamê bişînin, peymana jîr wê red dike.
Ji ber vê yekê hema hema her peyman van her du pirsgirêkan çareser dike, ji ber ku peymana me peyamên derveyî qebûl dike, pêdivî ye ku em li ser wê jî bisekinin.
Em ê bi rêza berevajî bikin. Pêşî, em pirsgirêkê bi dubarekirinê çareser bikin, heke peymanek jixwe peyamek weha wergirtibe û pêvajo kiribe, ew ê carek din pêk neyê. Dûv re em ê pirsgirêkê çareser bikin da ku tenê xeleka diyarkirî ya mirovan bikaribe ji peymana hişmend re peyaman bişîne.
Ji bo çareserkirina pirsgirêkê bi peyamên dubare re awayên cûda hene. Li vir em ê çawa bikin. Di peymana jîr de, em jimareya peyamên hatine wergirtin bi nirxa destpêkê 0 dest pê dikin. Di her peyamê de ji peymana biaqil re, em ê nirxa hejmarê ya heyî lê zêde bikin. Ger di peyamê de nirxa dijber bi nirxa peymana biaqil re nebe, wê hingê em wê pêvajo nakin; heke wusa be, wê hingê em wê pêvajoyê dikin û di girêbesta jîr de jimare 1 zêde dikin.
Ka em vegerin lottery-test-suite.fif û ceribandinek duyemîn lê zêde bike. Ger em jimareyek xelet bişînin, divê kod îstisnayek bavêje. Mînakî, bila daneyên peymanê 166 hilîne, û em ê 165 bişînin.
<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"
Ka em dest pê bikin.
~/TON/build/crypto/fift -s lottery-test-suite.fif
Û em ê bibînin ku ceribandin bi xeletiyek dimeşîne.
[ 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
Di vê qonaxê de lottery-test-suite.fif divê mîna link.
Naha werin em mantiqa dijber li peymana biaqil zêde bikin 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 peyama ku em dişînin derew e.
Yekem tiştê ku em dikin ev e ku kontrol bikin ka peyam di nav xwe de dane heye, heke na, wê hingê em bi tenê derdikevin.
Piştre em peyamê pars dikin. in_msg~load_uint(32) hejmara 165, 32-bit bar dike unsigned int ji peyama hatî şandin.
Dûv re em 32 bit ji hilanîna peymana jîr bar dikin. Em kontrol dikin ku hejmara barkirî bi ya derbasbûyî re têkildar e; heke na, em îstisnayek bavêjin. Di rewşa me de, ji ber ku em ji maçekê neqewimî derbas dibin, divê îstîsnayek were avêtin.
Koda encam li ser kopî bikin lottery-test-suite.fif, ji bîr nekin ku rêza paşîn veguherînin.
Em kontrol dikin ku test derbas dibe:
~/TON/build/crypto/fift -s lottery-test-suite.fif
Li vir Hûn dikarin bi encamên heyî re peymana têkildar bibînin.
Bala xwe bidinê ku nerehet e ku meriv bi domdarî koda berhevkirî ya peymanek biaqil di pelek bi ceribandinan de kopî bike, ji ber vê yekê em ê skrîptek binivîsin ku dê kodê ji me re domdar binivîse, û em ê bi tenê koda berhevkirî bi ceribandinên xwe ve girêdin. "include".
Di peldanka projeyê de pelek çêbikin build.sh bi naveroka jêrîn.
Naha, tenê skrîpta me bimeşînin da ku peymanê berhev bikin. Lê ji xeynî vê, divê em wê di nav domdar de binivîsin code. Ji ber vê yekê em ê pelek nû çêbikin lotter-compiled-for-test.fif, ku em ê di dosyayê de bihewînin lottery-test-suite.fif.
Ka em koda skirptê li sh lê zêde bikin, ku dê bi tenê pelê berhevkirî tê de dubare bike lotter-compiled-for-test.fif û rêza dawî ya tê de biguherîne.
# 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
Naha, ji bo kontrolkirinê, em skrîpta encam bidin meşandin û pelek dê were çêkirin lottery-compiled-for-test.fif, ku em ê têxin nav xwe lottery-test-suite.fif
В lottery-test-suite.fif koda peymanê jêbirin û rêzê lê zêde bike "lottery-compiled-for-test.fif" include.
Em îmtîhanan dimeşînin da ku kontrol bikin ku ew derbas dibin.
~/TON/build/crypto/fift -s lottery-test-suite.fif
Mezin, naha ji bo destpêkirina ceribandinan otomatîk bikin, em pelê biafirînin test.sh, ya ku dê pêşî were darve kirin build.sh, û paşê ceribandinan bimeşînin.
Werin em bikin test.sh û wê bimeşînin da ku piştrast bikin ku ceribandinan dixebitin.
chmod +x ./test.sh
./test.sh
Em kontrol dikin ku peyman berhev dibe û ceribandin têne kirin.
Mezin, niha li ser destpêkirinê test.sh Îmtîhan dê tavilê bên berhevkirin û bi rê ve bibin. Li vir lînkek heye bikaranîn.
Baş e, berî ku em bidomînin, bila ji bo rehetiyê tiştek din bikin.
Ka em peldankek çêbikin build ku em ê peymana kopîkirî û klona wê ya ku di nav domdar de hatî nivîsandin de hilînin lottery-compiled.fif, lottery-compiled-for-test.fif. Ka em peldankek jî çêbikin test pelê testê dê li ku were hilanîn? lottery-test-suite.fif û potansiyel pelên piştgirî yên din. Girêdana guhertinên têkildar.
Werin em pêşvebirina peymana hişmend bidomînin.
Dûv re pêdivî ye ku ceribandinek hebe ku dema ku em jimareya rast bişînin kontrol dike ka peyam hatî wergirtin û jimarvan li firotgehê nûve dibe. Lê em ê paşê bikin.
Naha em bifikirin ka çi strukturên daneyê û çi dane hewce dike ku di peymana hişmend de were hilanîn.
Ez ê her tiştê ku em hildigirin vebêjim.
`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` переменная типа словарь, хранит последние двадцать ставок.
Piştre hûn hewce ne ku du fonksiyonan binivîsin. Ka em gazî yê yekem bikin pack_state(), ku dê daneyan ji bo hilanîna paşîn di hilanîna peymana hişmend de pak bike. Ka em gazî ya duyemîn bikin unpack_state() dê daneyan ji hilanînê bixwîne û vegerîne.
_ 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;
}
Em van her du fonksiyonan li destpêka peymana jîr zêde dikin. Wê bi ser bikeve welî evê encama navîn.
Ji bo hilanîna daneyan hûn ê hewce bikin ku hûn fonksiyona çêkirî bang bikin set_data() û ew ê daneyan ji binivîse pack_state() di hilanîna peymana jîr de.
Naha ku ji bo nivîsandin û xwendina daneyan fonksiyonên me yên rehet hene, em dikarin pêş de biçin.
Pêdivî ye ku em kontrol bikin ka peyama ku ji derve tê ji hêla xwediyê peymanê ve (an bikarhênerek din a ku xwedan mifteya taybet e) ve hatî îmze kirin.
Dema ku em peymanek biaqil diweşînin, em dikarin wê bi daneya ku em di hilanînê de hewce dikin dest pê bikin, ku dê ji bo karanîna pêşerojê werin hilanîn. Em ê mifteya giştî li wir tomar bikin da ku em karibin verast bikin ku peyama hatî bi mifteya taybet a têkildar ve hatî îmze kirin.
Berî ku em berdewam bikin, werin em mifteyek taybet biafirînin û wê binivîsin test/keys/owner.pk. Ji bo kirina vê yekê, werin em Fift di moda înteraktîf de bidin destpêkirin û çar fermanan bicîh bînin.
`newkeypair` генерация публичного и приватного ключа и запись их в стек.
`drop` удаления из стека верхнего элемента (в данном случае публичный ключ)
`.s` просто посмотреть что лежит в стеке в данный момент
`"owner.pk" B>file` запись приватного ключа в файл с именем `owner.pk`.
`bye` завершает работу с Fift.
Ka em peldankek çêbikin keys di hundurê peldankê de test û mifteya taybet li wir binivîse.
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
Em peldankek di peldanka heyî de dibînin owner.pk.
Em mifteya giştî ji stikê derdixin û gava hewce bike em dikarin ji ya taybet bistînin.
Naha divê em verastkirinek îmzeyê binivîsin. Ka em bi testê dest pê bikin. Pêşî em mifteya taybet ji pelê bi karanîna fonksiyonê dixwînin file>B û li guherbarekê binivîsin owner_private_key, paşê fonksiyonê bikar bînin priv>pub mifteya taybet veguherîne mifteya gelemperî û encamê tê de binivîse owner_public_key.
Wekî encamek, peyama ku em ê ji peymana biaqil re bişînin di guhêrbarek de tê tomar kirin message_to_send, li ser fonksiyonên hashu, ed25519_sign_uint hûn dikarin bixwînin di belgeya pêncan de.
Va ye Di vê qonaxê de divê pelê bi testan bi vî rengî xuya bike.
Ka em ceribandinê bimeşînin û ew ê têk biçe, ji ber vê yekê em ê peymana hişmend biguhezînin da ku ew bikaribe peyamên bi vî rengî werbigire û îmzeyê verast bike.
Pêşî, em 512 bit îmzayê ji peyamê dihejmêrin û li guhêrbarekê dinivîsin, paşê em 32 bit ji guhêrbara hejmartinê dihejmêrin.
Ji ber ku me fonksiyonek ji bo xwendina daneyên ji hilanîna peymana hişmend heye, em ê wê bikar bînin.
Dûv re jimareya ku bi hilanînê ve hatî veguheztin û kontrolkirina îmzeyê ye. Ger tiştek li hev nayê, wê hingê em bi koda guncan re îstîsnayek bavêjin.
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));
Ka em ceribandinan bimeşînin û bibînin ku ceribandina duyemîn têk diçe. Ji ber du sedeman, di peyamê de bit têr nînin û di hilanînê de jî bit têr nîn in, ji ber vê yekê kod dema parskirinê têk diçe. Pêdivî ye ku em îmzeyek li peyama ku em dişînin zêde bikin û hilanînê ji ceribandina paşîn kopî bikin.
Di ceribandina duyemîn de, em ê îmzeyek peyamê zêde bikin û hilanîna peymana hişmend biguhezînin. Va ye dosyaya bi îmtîhanan di vê gavê de xuya dike.
Werin em ceribandinek çaremîn binivîsin, ku tê de em ê peyamek bi mifteya taybetî ya kesek din ve hatî îmzekirin bişînin. Werin em mifteyek taybet a din biafirînin û wê li pelek tomar bikin not-owner.pk. Em ê bi vê mifteya taybet peyamê îmze bikin. Ka em ceribandinan bimeşînin û pê ewle bin ku hemî ceribandin derbas dibin. Bikaranîn di vê gavê de.
Naha em dikarin di dawiyê de derbasî pêkanîna mantiqa peymana biaqil bibin.
В recv_external() em ê du celeb peyaman qebûl bikin.
Ji ber ku peymana me dê windahiyên lîstikvanan berhev bike, divê ev pere ji afirînerê lotoyê re were veguheztin. Dema ku peyman tê çêkirin navnîşana berîka afirînerê lotoyê di hilanînê de tê tomar kirin.
Tenê di rewşê de, em hewceyê kapasîteya ku em navnîşana ku em gramên windayan jê re dişînin biguhezînin. Her weha divê em bikaribin gramên ji lotoyê bişînin navnîşana xwediyê xwe.
Ka em bi ya yekem dest pê bikin. Ka em pêşî ceribandinek binivîsin ku dê kontrol bike ku piştî şandina peyamê, peymana hişmend navnîşana nû di hilanînê de tomar kiriye. Ji kerema xwe bala xwe bidin ku di peyamê de, ji bilî jimare û navnîşana nû, em jî radigihînin action Jimarek ne-neyînî ya 7-bit, li gorî wê, em ê hilbijêrin ka meriv çawa peyamê di peymana jîr de hildibijêre.
<b 0 32 u, 1 @ 7 u, new_owner_wc @ 32 i, new_owner_account_id @ 256 u, b> message_to_sign !
Di îmtîhanê de hûn dikarin bibînin ka hilanîna peymana smart çawa deserialîze kirin storage li Fift. Deserialization of variables di belgeya Pêncşemê de tête diyar kirin.
Werin em ceribandinê bimeşînin û pê ewle bin ku ew têk diçe. Naha em mentiqê zêde bikin da ku navnîşana xwediyê lotoyê biguhezînin.
Di peymana biaqil de em parsekirinê didomînin message, bixwînin action. Werin em bînin bîra we ku em ê du hebin action: navnîşan biguherîne û gram bişîne.
Dûv re em navnîşana nû ya xwediyê peymanê dixwînin û wê di hilanînê de hilînin.
Em testan dimeşînin û dibînin ku ceribandina sêyemîn têk diçe. Ew têk diçe ji ber vê yekê ku peyman naha 7 bit ji peyamê, ku di ceribandinê de winda ne, zêde par dike. Yê ku tune ye li peyamê zêde bike action. Ka em ceribandinan bimeşînin û bibînin ku her tişt derbas dibe. vir guheztinan bikin. Ecêb.
Naha werin em mantiqa şandina jimareya diyarkirî ya gram ji navnîşana ku berê hatî hilanîn re binivîsin.
Pêşîn, em ceribandinek binivîsin. Em ê du ceribandinan binivîsin, yek gava ku hevsengiyek têr nebe, ya duyemîn gava ku divê her tişt bi serfirazî derbas bibe. Test dikare were dîtin di vê kombûnê de.
Naha em kodê lê zêde bikin. Pêşîn, bila em du rêbazên alîkar binivîsin. Rêbaza wergirtina yekem ev e ku meriv balansa heyî ya peymanek jîr bibîne.
int balance() inline_ref method_id {
return get_balance().pair_first();
}
Û ya duyemîn jî ji bo şandina graman ji peymanek din a jîr re ye. Min ev rêbaz bi tevahî ji peymanek din a jîr kopî kir.
() 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
}
Werin em van her du rêbazan li peymana jîr zêde bikin û mantiqê binivîsin. Pêşîn, em hejmara gramên ji peyamê parsek dikin. Dûv re em hevsengiyê kontrol dikin, heke têrê neke em îstisnayek davêjin. Ger her tişt baş e, wê hingê em gramên navnîşana tomarkirî dişînin û jimarvan nûve dikin.
Va ye di vê gavê de mîna peymana jîr xuya dike. Werin em ceribandinan bimeşînin û pê ewle bibin ku ew derbas dibin.
Bi awayê, her carê ji bo peyamek pêvajoyî komîsyonek ji peymana hişmend tê derxistin. Ji bo ku peyamên peymana hişmend daxwazê bicîh bînin, piştî kontrolên bingehîn hûn hewce ne ku bang bikin accept_message().
Naha em biçin ser peyamên navxweyî. Di rastiyê de, em ê tenê gramanan qebûl bikin û ger ku lîstikvan bi ser bikeve du qat û ger ku winda bike yek sêyem jî ji xwediyê xwe re bişînin.
Pêşîn, em ceribandinek hêsan binivîsin. Ji bo kirina vê yekê, em hewceyê navnîşek ceribandinê ya peymana jîr e ku em tê texmîn kirin ku gram ji peymana hişmend re bişînin.
Navnîşana peymana biaqil ji du hejmaran pêk tê, jimareyek 32-bit ku berpirsiyarê zincîra xebatê ye û jimareyek yekta ne-neyînî ya 256-bit di vê zincîra xebatê de. Mînakî, -1 û 12345, ev navnîşana ku em ê li pelek tomar bikin ev e.
Min fonksiyona ji bo tomarkirina navnîşan ji kopî kir 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
Ka em binihêrin ka fonksiyon çawa dixebite, ev ê têgihiştinek bide ka Fift çawa dixebite. Fift di moda înteraktîf de dest pê bikin.
~/TON/build/crypto/fift -i
Pêşî em -1, 12345 û navê pelê paşerojê "sender.addr" davêjin ser stikê:
-1 12345 "sender.addr"
Pêngava din pêkanîna fonksiyonê ye -rot, ku stikê bi vî rengî diguhezîne ku li serê stikê jimareyek peymanek jîr a bêhempa heye:
"sender.addr" -1 12345
256 u>B jimareyek ne-neyînî ya 256-bit diguherîne bayt.
Û di dawiyê de byte li pelê têne nivîsandin B>file. Piştî vê stûyê me vala ye. Em disekinin Fift. Di peldanka heyî de pelek hate çêkirin sender.addr. Ka em pelê veguherînin peldanka çêkirî test/addresses/.
Ka em ceribandinek hêsan binivîsin ku dê gram ji peymanek jîr re bişîne. Li vir peywirdar e.
Niha em li mantiqa lotikan binêrin.
Yekem tiştê ku em dikin ev e ku peyamê kontrol bikin bounced an na heke bounced, paşê em wê paşguh dikin. bounced tê vê wateyê ku heke hin xeletiyek çêbibe dê peyman gram vegerîne. Ger xeletiyek ji nişka ve çêbibe em ê gram venegerînin.
Em kontrol dikin, heke hevseng ji nîv gram kêmtir be, wê hingê em bi tenê peyamê qebûl dikin û jê guh nadin.
Dûv re, em navnîşana peymana jîr a ku jê peyam hat pars dikin.
Em daneyên ji hilanînê dixwînin û dûv re heke ji bîst ji wan zêdetir be behîsên kevn ji dîrokê jêbirin. Ji bo rehetiyê, min sê fonksiyonên din nivîsî pack_order(), unpack_order(), remove_old_orders().
Dûv re, em lê dinêrin ka hevseng ji bo dravdanê têrê nake, wê hingê em dihesibînin ku ev ne behîs e, lê nûvekirinek e û nûvekirinê di nav de hilînin. orders.
Dûv re di dawiyê de cewhera peymana hişmend.
Pêşî, ger lîstikvan winda bike, em wê di dîroka behîsê de tomar dikin û heke mîqdar ji 3 gram zêdetir be, em 1/3 ji xwediyê peymana jîr re dişînin.
Ger lîstikvan bi ser bikeve, wê hingê em du qat mîqdarê dişînin navnîşana lîstikvan û dûv re agahdariya li ser behîsê di dîrokê de tomar dikin.
() 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));
}
Naha her tiştê ku dimîne hêsan e, ka em rêgezên wergirtinê biafirînin da ku em karibin di derheqê rewşa peymanê de ji cîhana derve agahdarî bistînin (bi rastî, daneyên ji hilanîna peymana wan a jîr bixwînin).
Di heman demê de min ji bîr kir ku kodê lê zêde bikim ku dê daxwaza yekem a ku di dema weşandina peymanek jîr de çêdibe pêk bîne. Peywira peywendîdar. Û bêtir serrast kirin xeletiyek bi şandina 1/3 ji mîqdarê ji hesabê xwedan re.
Pêngava paşîn weşandina peymana biaqil e. Ka em peldankek çêbikin requests.
Tiştek hêjayî balê ye. Em hilanînek peymanek jîr û peyamek têketinê diafirînin. Piştî vê yekê, navnîşana peymana biaqil tê çêkirin, ango navnîş berî weşandina di TON de jî tê zanîn. Dûv re, hûn hewce ne ku çend gram ji vê navnîşanê re bişînin, û tenê piştî wê hûn hewce ne ku pelek bi peymana jîr bi xwe re bişînin, ji ber ku torê ji bo hilanîna peymana biaqil û operasyonên tê de komîsyonek digire (verastkerên ku biaqil hildigirin û bicîh dikin peymanan). Kod dikare li vir were dîtin.
Dûv re em koda weşangeriyê pêk tînin û digirin lottery-query.boc pelê peymana jîr û navnîşan.
Em ji navnîşanê re dişînin 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd 2 Gram û piştî çend saniyan em heman fermanê pêk tînin. Ji bo şandina graman ez bikar tînim berîka fermî, û hûn dikarin ji yekî ji sohbetê gramên ceribandinê bipirsin, ku ez ê di dawiya gotarê de li ser biaxivim.
Naha werin em daxwaznameyên biafirînin ku bi peymana hişmend re têkilî daynin.
Bi rastî em ê ya yekem ji bo guhertina navnîşanê wekî xebatek serbixwe bihêlin, ya duyemîn jî ji bo şandina graman ji navnîşana xwediyê xwe re em ê bikin. Bi rastî, em ê hewce bikin ku heman tiştê ku di ceribandina şandina gram de bikin.
Ev peyama ku em ê ji peymana biaqil re bişînin, li ku derê ye msg_seqno 165, action 2 û 9.5 gram ji bo şandinê.
<b 165 32 u, 2 7 u, 9500000000 Gram, b>
Ji bîr nekin ku peyamê bi mifteya xweya taybet îmze bikin lottery.pk, ya ku berê di dema afirandina peymana jîr de hate çêkirin. Li vir peywira têkildar heye.
Agahdariya ji peymanek biaqil bi karanîna rêbazên wergirtinê digirin
Naha em binihêrin ka meriv çawa rêbazên bidestxistina peymana hişmend dimeşîne.
Destpêkirin lite-client û rêbazên wergirtinê yên ku me nivîsandine bimeşînin.
Em ê lite-client bikar bînin û rêbazan bistînin da ku agahdariya li ser peymana hişmend li ser malperê nîşan bidin.
Daneyên peymana hişmend li ser malperê nîşan dide
Min di Python de malperek hêsan nivîsî da ku daneyên ji peymana jîr bi rengek hêsan nîşan bide. Li vir ez ê bi berfirehî li ser nesekinim û malperê biweşînim li yek commit.
Daxwazên ji TON re têne kirin Python bi alîkariya lite-client. Ji bo rehetiyê, malper di Docker de tê pakkirin û li Google Cloud tê weşandin. Pêvek.
Werin em biceribînin
Naha em hewl bidin ku gram ji bo dagirtinê bişînin wir tûrikê diravan. Em ê 40 gram bişînin. Û em ji bo zelaliyê çend behîsan bikin. Em dibînin ku malper dîroka behîsan, rêjeya serkeftina heyî û agahiyên din ên bikêr nîşan dide.
Em dibîninku me ya yekem qezenc kir, ya duyemîn winda kir.
Paşê
Gotar ji ya ku min hêvî dikir pir dirêjtir bû, belkî ew dikaribû kurttir bûya, an jî dibe ku tenê ji bo kesek ku di derbarê TON-ê de tiştek nizane û dixwaze peymanek ne-sade ya jîr binivîsîne û biweşîne. ew. Dibe ku hin tişt bi hêsanî bihatana ravekirin.
Belkî hin aliyên tetbîqatê bi karîgerîtir û xweştir bihatana kirin, lê wê demê ji bo amadekirina gotarê hîn zêdetir wext digirt. Di heman demê de mimkun e ku min li cîhek xeletiyek kir an tiştek fam nekir, ji ber vê yekê heke hûn tiştek cidî dikin, hûn hewce ne ku xwe bispêrin belgeya fermî an depoya fermî ya bi koda TON.
Divê were zanîn ku ji ber ku TON bi xwe hîn di qonaxa çalak a pêşkeftinê de ye, dibe ku guhertin çêbibin ku dê yek ji gavên vê gotarê bişkînin (ku dema ku min dinivîsand qewimî, ew jixwe hatî rast kirin), lê nêzîkatiya gelemperî ev e. ne mimkûne ku biguhere.
Ez ê li ser pêşeroja TON nebêjim. Dibe ku platform bibe tiştek mezin û pêdivî ye ku em wextê xwe bi xwendina wê derbas bikin û naha bi hilberên xwe cîhek tije bikin.
Di heman demê de Libra ji Facebookê jî heye, ku xwedan temaşevanek potansiyel a bikarhênerên ji TON-ê mezintir e. Ez di derbarê Libra de hema hema tiştek nizanim, li gorî forumê dadbar kirin ku li wir ji civata TON-ê pir bêtir çalakî heye. Her çend pêşdebir û civata TON-ê bêtir mîna binê erdê ne, ku ew jî xweş e.
Li ser TON-ê di Telegram-ê de sohbet bikin, ku bi rastî di qonaxa destpêkê de alîkariya wê kir. Ez difikirim ku ew ê ne xelet be heke ez bibêjim ku her kesê ku ji bo TON tiştek nivîsandiye li wir e. Her weha hûn dikarin li wir gramên ceribandinê bixwazin. https://t.me/tondev_ru