د ټیلیګرام خلاصې شبکې (TON) کې د سمارټ قرارداد لیکلو او خپرولو څرنګوالي په اړه

په TON کې د سمارټ قرارداد لیکلو او خپرولو څرنګوالي په اړه

دا مقاله د څه په اړه ده؟

په مقاله کې به زه د دې په اړه وغږیږم چې څنګه ما په لومړي (دوه) ټیلیګرام بلاکچین سیالۍ کې برخه اخیستې ، جایزه یې نه ده اخیستې ، او پریکړه یې کړې چې خپله تجربه په یوه مقاله کې ثبت کړم ترڅو دا په هیرولو کې ډوب نشي او شاید مرسته وکړي. یو څوک

له هغه ځایه چې زه نه غواړم خلاص کوډ ولیکم ، مګر د یو څه کار کولو لپاره ، د مقالې لپاره ما د سمدستي لاټري او ویب پا forې لپاره سمارټ قرارداد لیکلی چې د مینځنۍ ذخیره کارولو پرته د TON څخه مستقیم د سمارټ قرارداد ډیټا ښیې.

مقاله به د هغو کسانو لپاره ګټوره وي څوک چې غواړي په TON کې خپل لومړی سمارټ قرارداد وکړي ، مګر نه پوهیږي چیرې یې پیل کړي.

د مثال په توګه د لاټري په کارولو سره، زه به د چاپیریال له نصبولو څخه د سمارټ قرارداد خپرولو، د هغې سره تعامل، او د معلوماتو ترلاسه کولو او خپرولو لپاره ویب پاڼه لیکلو ته لاړ شم.

په سیالۍ کې د ګډون په اړه

تیر اکتوبر، ټیلیګرام د نویو ژبو سره د بلاکچین سیالي اعلان کړه Fift и FunC. دا اړینه وه چې د پنځو وړاندیز شوي سمارټ قراردادونو څخه د لیکلو څخه غوره کړئ. ما فکر کاوه چې دا به ښه وي چې یو څه توپیر وکړم، ژبه زده کړم او یو څه جوړ کړم، حتی که زه په راتلونکي کې نور څه ولیکم. برسېره پردې، موضوع په دوامداره توګه په شونډو کې ده.

دا د ویلو وړ ده چې ما د سمارټ قراردادونو رامینځته کولو تجربه نه درلوده.

ما پلان درلود چې تر پای پورې برخه واخلم تر هغه چې زه وکولی شم او بیا د بیاکتنې مقاله ولیکم ، مګر زه په لومړي سر کې سمدلاسه ناکام شوم. زه یوه بټوه لیکلې د څو لاسلیکونو سره FunC и он в общем работал. За основу взял په پیوستون کې سمارټ قرارداد.

په هغه وخت کې، ما فکر کاوه چې دا یقینا د لږ تر لږه د انعام ځای نیولو لپاره کافی دی. د پایلې په توګه، د 40 ګډون کوونکو څخه شاوخوا 60 د جایزې ګټونکي شول او زه د دوی په منځ کې نه وم. په عموم کې، پدې کې هیڅ شی نشته، مګر یو شی ما ځوروي. د پایلو د اعلان په وخت کې، زما د قرارداد لپاره د ازموینې بیاکتنه نه وه شوې، ما په خبرو اترو کې د ګډون کوونکو څخه وپوښتل چې ایا بل څوک شتون لري چې دا یې نه درلود، هیڅوک شتون نلري.

ظاهرا زما پیغامونو ته په پام سره ، دوه ورځې وروسته قاضیانو تبصره خپره کړه او زه لاهم نه پوهیږم چې ایا دوی په تصادفي ډول د قضاوت پرمهال زما سمارټ تړون له لاسه ورکړی یا په ساده ډول فکر کاوه چې دا دومره خراب و چې تبصرې ته اړتیا نلري. ما په پاڼه کې پوښتنه وکړه، مګر ځواب یې ترلاسه نه کړ. که څه هم دا پټه نه ده چې څوک قضاوت کوي، ما د شخصي پیغامونو لیکلو لپاره غیر ضروري وګڼله.

په پوهیدو کې ډیر وخت تیر شو، نو پریکړه وشوه چې یوه مقاله ولیکئ. څرنګه چې لا تر اوسه ډیر معلومات شتون نلري، دا مقاله به د هر چا لپاره د وخت خوندي کولو کې مرسته وکړي.

په TON کې د سمارټ قراردادونو مفهوم

مخکې له دې چې تاسو یو څه ولیکئ، تاسو اړتیا لرئ چې معلومه کړئ چې کوم لوري ته دا شی ته ورسیږئ. له همدې امله، اوس زه به تاسو ته ووایم چې سیسټم کومې برخې لري. په دقیقه توګه، کوم برخې چې تاسو اړتیا لرئ د لږ تر لږه یو ډول کاري قرارداد لیکلو لپاره پوه شئ.

موږ به د سمارټ قرارداد لیکلو او کار کولو تمرکز وکړو TON Virtual Machine (TVM), Fift и FunC، نو دا مقاله د منظم برنامې پراختیا توضیحاتو په څیر ده. موږ به پدې اړه فکر ونه کړو چې څنګه پلیټ فارم پخپله دلته کار کوي.

په عمومي توګه دا څنګه کار کوي TVM او ژبه Fift ښه رسمي اسناد شتون لري. په سیالۍ کې د ګډون پرمهال او اوس د اوسني تړون لیکلو پرمهال ، ما ډیری وختونه هغې ته مخه کړه.

اصلي ژبه په کوم کې چې سمارټ قراردادونه لیکل کیږي FunC. دا مهال پدې اړه هیڅ سند شتون نلري ، نو د یو څه لیکلو لپاره تاسو اړتیا لرئ د رسمي ذخیره څخه د سمارټ قراردادونو مثالونه مطالعه کړئ او پخپله د ژبې پلي کول ، او تاسو کولی شئ د تیرو دوه څخه د سمارټ قراردادونو مثالونه وګورئ. سیالۍ د مقالې په پای کې لینکونه.

راځئ چې ووایو موږ دمخه د دې لپاره سمارټ قرارداد لیکلی دی FunC، له هغې وروسته موږ کوډ په فټ اسمبلر کې تالیف کوو.

تالیف شوی سمارټ قرارداد خپریدو ته پاتې دی. د دې کولو لپاره تاسو اړتیا لرئ په کې یو فنکشن ولیکئ Fift، کوم چې به د سمارټ قرارداد کوډ او ځینې نور پیرامیټونه د ان پټ په توګه واخلي ، او محصول به د توسیع سره فایل وي .boc (چې د "حجرو کڅوړه" معنی لري)، او د دې پورې اړه لري چې موږ دا څنګه لیکو، یو شخصي کیلي او پته، کوم چې د سمارټ قرارداد کوډ پراساس رامینځته کیږي. تاسو کولی شئ دمخه د سمارټ قرارداد پتې ته ګرامونه واستوئ چې تراوسه ندي خپاره شوي.

ترلاسه شوي TON کې د سمارټ قرارداد خپرولو لپاره .boc فایل به اړتیا ولري چې د روښانه پیرودونکي په کارولو سره بلاکچین ته واستول شي (لاندې نور). مګر د خپرولو دمخه، تاسو اړتیا لرئ چې تولید شوي پتې ته ګرامونه انتقال کړئ، که نه نو سمارټ قرارداد به خپور نشي. د خپرولو وروسته، تاسو کولی شئ د بهر څخه د پیغامونو په لیږلو سره د سمارټ قرارداد سره اړیکه ونیسئ (د بیلګې په توګه، د رڼا پیرودونکي په کارولو سره) یا د دننه څخه (د مثال په توګه، یو سمارټ قرارداد د TON دننه بل پیغام لیږي).

یوځل چې موږ پوه شو چې کوډ څنګه خپور شوی، دا اسانه کیږي. موږ تقریبا پوهیږو چې موږ څه لیکل غواړو او زموږ برنامه به څنګه کار وکړي. او د لیکلو پرمهال ، موږ ګورو چې دا څنګه دمخه په موجوده سمارټ قراردادونو کې پلي کیږي ، یا موږ د پلي کولو کوډ ګورو Fift и FunC په رسمي ذخیره کې، یا په رسمي اسنادو کې وګورئ.

ډیری وختونه ما د ټیلیګرام چیٹ کې کلیدي کلمې لټولې چیرې چې د سیالۍ ټول ګډون کونکي او د ټیلیګرام کارمندان راټول شوي ، او داسې پیښ شوي چې د سیالۍ په جریان کې هرڅوک هلته راټول شوي او د فټ او فن سی بحث یې پیل کړی. د مقالې په پای کې لینک.

دا وخت دی چې له تیوري څخه عمل ته حرکت وکړئ.

د TON سره کار کولو لپاره چاپیریال چمتو کول

ما هرڅه وکړل چې د MacOS په مقاله کې به تشریح شي او په ډاکر کې یې په پاک اوبنټو 18.04 LTS کې دوه ځله چیک کړي.

لومړی شی چې تاسو یې کولو ته اړتیا لرئ ډاونلوډ او نصب کول دي lite-client د کوم سره تاسو کولی شئ TON ته غوښتنې واستوئ.

په رسمي ویب پاڼه کې لارښوونې د نصب کولو پروسه په تفصیل او واضح ډول بیانوي او ځینې توضیحات پریږدي. دلته موږ لارښوونې تعقیبوو، د لارې په اوږدو کې د ورک شوي انحصارونو نصب کول. ما هره پروژه پخپله نه ده جوړه کړې او د رسمي اوبنټو ذخیره څخه نصب شوې (په MacOS کې ما کارولې 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 

یوځل چې ټول انحصارونه نصب شي تاسو کولی شئ نصب کړئ lite-client, Fift, FunC.

لومړی، موږ د TON ذخیره د هغې د انحصار سره کلون کوو. د اسانتیا لپاره، موږ به هر څه په فولډر کې ترسره کړو ~/TON.

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

ذخیره هم پلي کول ذخیره کوي Fift и FunC.

اوس موږ د پروژې راټولولو ته چمتو یو. د ذخیره کولو کوډ په فولډر کې کلون شوی ~/TON/ton. د ~/TON یو فولډر جوړ کړئ build او په هغې کې پروژه راټول کړئ.

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

څرنګه چې موږ یو سمارټ قرارداد لیکلو ته اړتیا لرو، موږ نه یوازې اړتیا لرو lite-clientخو Fift с FunCنو راځئ چې هرڅه راټول کړو. دا یو چټک بهیر نه دی، نو موږ انتظار کوو.

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

بیا، د ترتیب کولو فایل ډاونلوډ کړئ کوم چې د نوډ په اړه معلومات لري lite-client نښلوي.

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

TON ته لومړنۍ غوښتنې کول

اوس راځئ چې پیل وکړو lite-client.

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

که جوړونه بریالۍ وه ، نو د لانچ وروسته به تاسو نوډ ته د ر lightا پیرودونکي اتصال لاګ وګورئ.

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

تاسو کولی شئ کمانډ چل کړئ help او وګورئ چې کوم حکمونه شتون لري.

help

راځئ هغه کمانډونه لیست کړو چې موږ به پدې مقاله کې وکاروو.

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

اوس موږ چمتو یو چې قرارداد پخپله ولیکو.

پلي کول

ایډا

لکه څنګه چې ما پورته لیکلي، هغه سمارټ قرارداد چې موږ یې لیکو لاټری دی.

سربیره پردې ، دا لاټری نده چې په هغه کې تاسو اړتیا لرئ ټیکټ واخلئ او یو ساعت ، ورځ یا میاشت انتظار وکړئ ، مګر یو سمدستي چې پکې کارونکي د تړون پتې ته لیږدوي. N ګرام، او سمدستي یې بیرته ترلاسه کوي 2 * N ګرام یا له لاسه ورکوي. موږ به د ګټلو احتمال شاوخوا 40٪ جوړ کړو. که چیرې د تادیې لپاره کافي ګرام شتون ونلري، نو موږ به معامله د لوړ پوړ په توګه په پام کې ونیسو.

سربیره پردې ، دا مهمه ده چې شرطونه په ریښتیني وخت او مناسب شکل کې ولیدل شي ، ترڅو کارونکي سمدلاسه پوه شي چې ایا هغه ګټلی یا بایللی. له همدې امله، تاسو اړتیا لرئ یوه ویب پاڼه جوړه کړئ چې شرطونه او پایلې به مستقیم له TON څخه ښکاره کړي.

د سمارټ قرارداد لیکل

د اسانتیا لپاره ، ما د FunC لپاره کوډ روښانه کړی؛ پلگ ان د لید سټوډیو کوډ لټون کې موندل کیدی شي او نصب کیدی شي؛ که تاسو ناڅاپه غواړئ یو څه اضافه کړئ ، ما پلگ ان په عامه توګه چمتو کړی دی. همچنان ، یو چا دمخه د فټ سره کار کولو لپاره پلگ ان جوړ کړی ، تاسو کولی شئ دا هم نصب کړئ او په VSC کې یې ومومئ.

راځئ سمدلاسه یو ذخیره جوړه کړو چیرې چې موږ به منځمهاله پایلې ترسره کړو.

زموږ د ژوند د اسانه کولو لپاره، موږ به یو سمارټ قرارداد ولیکئ او په محلي توګه به یې ازموینه وکړو تر هغه چې دا چمتو وي. یوازې له هغې وروسته به موږ دا په TON کې خپاره کړو.

سمارټ قرارداد دوه بهرنۍ میتودونه لري چې لاسرسی کیدی شي. لومړی، recv_external() دا فعالیت هغه وخت اجرا کیږي کله چې قرارداد ته غوښتنه له بهرنۍ نړۍ څخه راځي، دا د TON څخه نه، د بیلګې په توګه، کله چې موږ پخپله یو پیغام تولیدوو او د لایټ کلائنټ له لارې یې لیږو. دوهم، recv_internal() دا هغه وخت دی چې، پخپله TON کې، کوم قرارداد زموږ ته راجع کیږي. په دواړو حالتونو کې، تاسو کولی شئ فعالیت ته پیرامیټونه انتقال کړئ.

راځئ چې د یو ساده مثال سره پیل وکړو چې د خپریدو په صورت کې به کار وکړي، مګر په دې کې هیڅ فعال بار نشته.

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

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

دلته موږ باید تشریح کړو چې دا څه دي slice. په TON بلاکچین کې ذخیره شوي ټول معلومات ټولګه ده TVM cell یا ساده وي cell، په داسې یوه حجره کې تاسو کولی شئ تر 1023 بټونو پورې ډیټا او نورو حجرو ته تر 4 پورې لینکونه ذخیره کړئ.

TVM cell slice او یا slice دا د موجوده یوه برخه ده cell د تحلیل لپاره کارول کیږي، دا به وروسته روښانه شي. زموږ لپاره اصلي شی دا دی چې موږ کولی شو انتقال کړو slice او د پیغام ډول پورې اړه لري، ډاټا پروسس کړئ recv_external() او یا recv_internal().

impure - یوه کلیدي کلمه چې دا په ګوته کوي چې فعالیت د سمارټ قرارداد ډیټا بدلوي.

راځئ چې د قرارداد کوډ په کې خوندي کړو lottery-code.fc او تالیف.

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

د بیرغونو معنی د کمانډ په کارولو سره لیدل کیدی شي

~/TON/build/crypto/func -help

موږ په کې د فټ اسمبلر کوډ ترتیب کړی دی 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

دا په محلي توګه پیل کیدی شي، د دې لپاره به موږ چاپیریال چمتو کړو.

په یاد ولرئ چې لومړۍ کرښه نښلوي Asm.fif، دا کوډ دی چې په Fift کې د فیفټ راټولونکي لپاره لیکل شوی.

له هغه ځایه چې موږ غواړو په ځایی توګه سمارټ قرارداد چل او ازموینه وکړو، موږ به یو فایل جوړ کړو lottery-test-suite.fif او هلته تالیف شوی کوډ کاپي کړئ ، په هغې کې وروستۍ کرښه ځای په ځای کړئ ، کوم چې د سمارټ قرارداد کوډ په ثابت ډول لیکي codeبیا یې مجازی ماشین ته لیږدولو لپاره:

"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

تر دې دمه دا روښانه بریښي ، اوس راځئ چې ورته فایل کې کوډ اضافه کړو چې موږ به یې د 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 موږ شرایط ثبت کوو، دا هغه معلومات دي چې ورسره TVM (یا د شبکې حالت) به پیل شي. حتی د سیالۍ په جریان کې، یو پرمخ وړونکي وښودل چې څنګه جوړ کړي c7 او ما کاپي کړه. پدې مقاله کې موږ ممکن بدلون ته اړتیا ولرو rand_seed ځکه چې د تصادفي شمیرې نسل په دې پورې اړه لري او که بدل نه شي، ورته شمیره به هر ځل بیرته راستانه شي.

recv_internal и recv_external د 0 او -1 ارزښتونو سره ثبات به په سمارټ قرارداد کې د اړونده دندو غږولو لپاره مسؤل وي.

اوس موږ چمتو یو چې زموږ د خالي سمارټ قرارداد لپاره لومړۍ ازموینه جوړه کړو. د وضاحت لپاره، د اوس لپاره موږ به ټول ازموینې ورته فایل ته اضافه کړو lottery-test-suite.fif.

راځئ چې یو متغیر جوړ کړو storage او په هغې کې یو خالي ولیکئ cell، دا به د سمارټ قرارداد ذخیره وي.

message دا هغه پیغام دی چې موږ به له بهر څخه سمارټ تماس ته انتقال کړو. موږ به دا د اوس لپاره خالي هم کړو.

variable storage 
<b b> storage ! 

variable message 
<b b> message ! 

وروسته له هغه چې موږ ثابت او متغیرونه چمتو کړل، موږ د کمانډ په کارولو سره TVM پیل کوو runvmctx او جوړ شوي پیرامیټونه داخل ته انتقال کړئ.

message @ 
recv_external 
code 
storage @ 
c7 
runvmctx 

په پای کې به موږ بریالي شو لکه لپاره منځنی کوډ Fift.

اوس موږ کولی شو پایله کوډ پرمخ یوسو.

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

برنامه باید پرته له خطا پرمخ ولاړه شي او په محصول کې به موږ د اعدام لاګ وګورو:

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

عالي ، موږ د سمارټ قرارداد لومړۍ کاري نسخه لیکلې ده.

اوس موږ اړتیا لرو چې فعالیت اضافه کړو. لومړی راځئ چې د هغه پیغامونو سره معامله وکړو چې د بهرنۍ نړۍ څخه راځي recv_external()

پراختیا کونکی پخپله د پیغام بڼه غوره کوي چې قرارداد یې ومني.

مګر معمولا

  • لومړی، موږ غواړو خپل تړون له بهرنۍ نړۍ څخه خوندي کړو او داسې یې جوړ کړو چې یوازې د تړون مالک کولی شي بهرني پیغامونه ورته واستوي.
  • دوهم، کله چې موږ TON ته یو باوري پیغام واستوو، موږ غواړو چې دا یو ځل واقع شي او کله چې موږ ورته پیغام بیا واستوو، سمارټ قرارداد یې ردوي.

نو نږدې هر قرارداد دا دوه ستونزې حل کوي، ځکه چې زموږ قرارداد بهرني پیغامونه مني، نو موږ باید ورته پاملرنه وکړو.

موږ به دا په برعکس ترتیب کې ترسره کړو. لومړی، راځئ چې ستونزه په تکرار سره حل کړو؛ که چیرې قرارداد دمخه ورته پیغام ترلاسه کړی وي او پروسس یې کړی وي، دا به دویم ځل اجرا نه کړي. او بیا به موږ ستونزه حل کړو ترڅو یوازې د خلکو یو ټاکلی حلقه سمارټ قرارداد ته پیغامونه واستوي.

د نقل پیغامونو سره د ستونزې حل کولو لپاره مختلف لارې شتون لري. دلته دی چې موږ به یې څنګه وکړو. په سمارټ قرارداد کې، موږ د ترلاسه شوي پیغامونو کاونټر د لومړني ارزښت 0 سره پیل کوو. په سمارټ قرارداد کې په هر پیغام کې، موږ به اوسنی کاونټر ارزښت اضافه کړو. که په پیغام کې د کاونټر ارزښت په سمارټ قرارداد کې د ارزښت سره سمون نه خوري، نو موږ دا پروسس نه کوو؛ که دا وي، نو موږ یې پروسس کوو او په سمارټ قرارداد کې کاونټر د 1 لخوا زیاتوو.

راځئ چې بیرته راشو lottery-test-suite.fif او دې ته دوهم ازموینه اضافه کړئ. که موږ غلط شمیره واستوو، کوډ باید یو استثنا وغورځوي. د مثال په توګه، اجازه راکړئ چې د قرارداد ډاټا 166 ذخیره کړئ، او موږ به 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"

راځئ چې پیل کړو.

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

او موږ به وګورو چې ازموینه د غلطۍ سره اجرا کیږي.

[ 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

پدې مرحله کې lottery-test-suite.fif باید داسې ښکاري مخونه.

اوس راځئ چې د کاونټر منطق په سمارټ قرارداد کې اضافه کړو 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 هغه پیغام دروغ دی چې موږ یې لیږو.

لومړی شی چې موږ یې کوو دا چیک کوو چې ایا پیغام معلومات لري، که نه، نو موږ په ساده ډول وځو.

بیا موږ پیغام تجزیه کوو. in_msg~load_uint(32) د 165 شمیره، 32-bit پورته کوي unsigned int د لیږدول شوي پیغام څخه.

بیا موږ د سمارټ قرارداد ذخیره کولو څخه 32 بټونه پورته کوو. موږ ګورو چې بار شوي شمیره د منظور شوي سره سمون لري؛ که نه، موږ یو استثنا غورځوو. زموږ په قضیه کې، ځکه چې موږ یو غیر میچ تیر کوو، یو استثنا باید وغورځول شي.

اوس راځئ چې تالیف وکړو.

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

پایله کوډ ته کاپي کړئ lottery-test-suite.fif، د وروستۍ کرښې ځای په ځای کول مه هیروئ.

موږ ګورو چې ازموینه تیره شوې:

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

همدلته تاسو کولی شئ د اوسني پایلو سره ورته ژمنې وګورئ.

په یاد ولرئ چې دا ناشونې ده چې د سمارټ قرارداد تالیف شوي کوډ په دوامداره توګه د ازموینو سره په فایل کې کاپي کړئ ، نو راځئ چې یو سکریپټ ولیکو چې کوډ به زموږ لپاره په ثابت ډول ولیکي ، او موږ به په ساده ډول د تالیف شوي کوډ په کارولو سره زموږ ازموینې سره وصل کړو. "include".

د پروژې فولډر کې یو فایل جوړ کړئ build.sh د لاندې منځپانګې سره.

#!/bin/bash

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

راځئ چې دا د اجرا وړ کړو.

chmod +x ./build.sh

اوس، یوازې زموږ سکریپټ چل کړئ ترڅو قرارداد تالیف کړئ. مګر د دې سربیره، موږ باید دا په ثابت ډول ولیکو code. نو موږ به یو نوی فایل جوړ کړو lotter-compiled-for-test.fif، کوم چې موږ به په فایل کې شامل کړو lottery-test-suite.fif.

راځئ چې د سکرپټ کوډ sh ته اضافه کړو، کوم چې به په ساده ډول ترتیب شوي فایل په کې نقل کړي lotter-compiled-for-test.fif او په دې کې وروستۍ کرښه بدله کړئ.

# 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

اوس، د چک کولو لپاره، راځئ چې پایله لرونکی سکریپټ پرمخ بوځو او یو فایل به تولید شي lottery-compiled-for-test.fif، کوم چې موږ به زموږ په کې شامل کړو lottery-test-suite.fif

В lottery-test-suite.fif د تړون کوډ حذف کړئ او کرښه اضافه کړئ "lottery-compiled-for-test.fif" include.

موږ ازموینې ترسره کوو ترڅو وګورو چې دوی بریالي شوي.

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

عالي ، اوس د ازموینو لانچ اتومات کولو لپاره ، راځئ چې فایل جوړ کړو test.sh، کوم چې به لومړی اجرا شي build.sh، او بیا ازموینې پرمخ وړئ.

touch test.sh
chmod +x test.sh

موږ دننه لیکو

./build.sh 

echo "nCompilation completedn"

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

راځئ چې جوړ کړو test.sh او دا چل کړئ ترڅو ډاډ ترلاسه کړئ چې ازموینې کار کوي.

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

موږ ګورو چې قرارداد تالیف شوی او ازموینې اجرا کیږي.

ښه، اوس په پیل کې test.sh ازموینې به سمدلاسه تنظیم او پرمخ وړل کیږي. دلته یې لینک دی ژمن.

ښه، مخکې له دې چې موږ دوام ورکړو، راځئ چې د اسانتیا لپاره یو بل کار وکړو.

راځئ چې یو فولډر جوړ کړو build چیرې چې موږ به کاپي شوي قرارداد او د هغې کلون په ثابت ډول لیکل شوي ذخیره کړو lottery-compiled.fif, lottery-compiled-for-test.fif. راځئ چې یو فولډر هم جوړ کړو test د ټیسټ فایل به چیرته زیرمه شي؟ lottery-test-suite.fif او په احتمالي توګه نور ملاتړ کونکي فایلونه. د اړونده بدلونونو لینک.

راځئ چې د سمارټ قرارداد پراختیا ته دوام ورکړو.

بیا باید یوه ازموینه وي چې وګوري چې پیغام ترلاسه شوی او کاونټر په پلورنځي کې تازه کیږي کله چې موږ سمه شمیره واستوو. مګر موږ به وروسته دا وکړو.

اوس راځئ چې د کوم ډیټا جوړښت په اړه فکر وکړو او کوم ډیټا باید په سمارټ قرارداد کې زیرمه شي.

زه به هر هغه څه تشریح کړم چې موږ یې ذخیره کوو.

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

بیا تاسو اړتیا لرئ دوه افعال ولیکئ. راځئ چې لومړی غږ وکړو pack_state()، کوم چې به د سمارټ قرارداد ذخیره کې د راتلونکي خوندي کولو لپاره ډاټا بسته کړي. راځئ چې دویم غږ وکړو unpack_state() د ذخیره کولو څخه ډاټا به لوستل او بیرته راستانه کړي.

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

موږ دا دوه دندې د سمارټ قرارداد په پیل کې اضافه کوو. دا به کار وکړي لکه منځمهاله پایله.

د معلوماتو خوندي کولو لپاره تاسو اړتیا لرئ جوړ شوي فنکشن ته زنګ ووهئ set_data() او دا به له څخه ډاټا لیکي pack_state() په سمارټ قرارداد ذخیره کې.

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

اوس چې موږ د معلوماتو لیکلو او لوستلو لپاره مناسب فعالیتونه لرو، موږ کولی شو پرمخ لاړ شو.

موږ باید وګورو چې له بهر څخه راغلی پیغام د تړون د مالک لخوا لاسلیک شوی (یا بل کارونکي چې شخصي کیلي ته لاسرسی لري).

کله چې موږ یو سمارټ قرارداد خپور کړو، موږ کولی شو دا د هغه معلوماتو سره پیل کړو چې موږ یې په ذخیره کې اړتیا لرو، کوم چې د راتلونکي کارونې لپاره به خوندي شي. موږ به هلته عامه کیلي ثبت کړو ترڅو موږ تصدیق کړو چې راتلونکی پیغام د اړوند شخصي کیلي سره لاسلیک شوی و.

مخکې له دې چې دوام ورکړو، راځئ چې یو شخصي کیلي جوړ کړو او دا یې ولیکئ test/keys/owner.pk. د دې کولو لپاره ، راځئ چې په متقابل حالت کې Fifټ پیل کړو او څلور کمانډونه اجرا کړو.

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

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

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

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

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

راځئ چې یو فولډر جوړ کړو keys د فولډر دننه test او هلته شخصي کیلي ولیکئ.

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

موږ په اوسني فولډر کې یو فایل ګورو owner.pk.

موږ عامه کیلي له سټیک څخه لرې کوو او کله چې اړتیا وي موږ کولی شو دا له شخصي څخه ترلاسه کړو.

اوس موږ اړتیا لرو چې د لاسلیک تصدیق ولیکئ. راځئ چې د ازموینې سره پیل وکړو. لومړی موږ د فنکشن په کارولو سره د فایل څخه شخصي کیلي ولولئ file>B او یو متغیر ته یې ولیکئ owner_private_key، بیا د فنکشن په کارولو سره priv>pub شخصي کیلي عامه کیلي ته واړوئ او پایله یې ولیکئ 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 !

موږ به دواړه کیلي ته اړتیا ولرو.

موږ د سمارټ قرارداد ذخیره د خپل سري معلوماتو سره په ورته ترتیب کې د فنکشن په څیر پیل کوو pack_state()او په متغیر کې یې ولیکئ 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 !

بیا به موږ یو لاسلیک شوی پیغام جوړ کړو، دا به یوازې لاسلیک او د مقابل ارزښت ولري.

لومړی، موږ هغه معلومات رامینځته کوو چې موږ یې لیږدول غواړو، بیا موږ دا د شخصي کیلي سره لاسلیک کوو او په پای کې موږ یو لاسلیک شوی پیغام تولیدوو.

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 !  

د پایلې په توګه، هغه پیغام چې موږ به سمارټ قرارداد ته واستوو په متغیر کې ثبت شوی message_to_sendد دندو په اړه hashu, ed25519_sign_uint تاسو لوستلی شئ په پنځم سند کې.

او د ازموینې چلولو لپاره موږ بیا غږ کوو.

message_to_send @ 
recv_external 
code 
storage @
c7
runvmctx

لکه دغه د ازموینې سره فایل باید پدې مرحله کې داسې ښکاري.

راځئ چې ازموینه ترسره کړو او دا به ناکامه شي، نو موږ به سمارټ قرارداد بدل کړو ترڅو دا د دې فارمیټ پیغامونه ترلاسه کړي او لاسلیک تصدیق کړي.

لومړی، موږ د پیغام څخه د لاسلیک 512 بټونه شمیرو او په متغیر کې یې لیکو، بیا موږ د کاونټر متغیر 32 بټونه شمیرو.

څرنګه چې موږ د سمارټ قرارداد ذخیره کولو څخه د معلوماتو لوستلو لپاره فعالیت لرو، موږ به یې وکاروو.

بل د ذخیره کولو سره لیږدول شوي کاونټر چیک کول او لاسلیک چیک کول دي. که یو څه سره سمون نه خوري، نو موږ د مناسب کوډ سره یو استثنا وغورځوو.

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

اړونده ژمنه سمه ده.

راځئ چې ازموینې پرمخ بوځو او وګورو چې دویمه ازموینه ناکامه شوه. د دوو دلیلونو لپاره، په پیغام کې کافي بټونه شتون نلري او په ذخیره کې کافي بټونه شتون نلري، نو کوډ د پارس کولو پر مهال خرابیږي. موږ اړتیا لرو په هغه پیغام کې لاسلیک اضافه کړو چې موږ یې لیږو او د وروستي ازموینې څخه ذخیره کاپي کوو.

په دویمه ازموینه کې ، موږ به د پیغام لاسلیک اضافه کړو او د سمارټ قرارداد ذخیره بدل کړو. لکه دغه د ازموینې سره فایل اوس مهال داسې ښکاري.

راځئ چې څلورم ازموینه ولولو، په کوم کې چې موږ به د بل چا شخصي کیلي سره لاسلیک شوی پیغام واستوو. راځئ چې بله شخصي کیلي جوړه کړو او په فایل کې یې خوندي کړو not-owner.pk. موږ به پیغام د دې شخصي کیلي سره لاسلیک کړو. راځئ چې ازموینې پرمخ بوځو او ډاډ ترلاسه کړو چې ټولې ازموینې تیریږي. ژمن په همدې شیبه کې.

اوس موږ کولی شو په پای کې د سمارټ قرارداد منطق پلي کولو ته لاړ شو.
В recv_external() موږ به دوه ډوله پیغامونه ومنو.

څرنګه چې زموږ قرارداد به د لوبغاړو زیانونه راټول کړي، دا پیسې باید د لاټري جوړونکي ته لیږدول شي. د لاټري جوړونکي د والټ پته په ذخیره کې ثبت کیږي کله چې قرارداد رامینځته کیږي.

یوازې په دې حالت کې، موږ د پتې د بدلولو وړتیا ته اړتیا لرو چې موږ یې د ضایع کیدو ګرام لیږو. موږ باید د دې وړتیا هم ولرو چې د لاټري څخه ګرام د مالک ادرس ته واستوو.

راځئ چې د لومړي سره پیل وکړو. راځئ چې لومړی یوه ازموینه ولیکئ چې دا به وګوري چې د پیغام لیږلو وروسته، سمارټ قرارداد په ذخیره کې نوی ادرس خوندي کړی. مهرباني وکړئ په یاد ولرئ چې په پیغام کې، د کاونټر او نوي پتې سربیره، موږ هم لیږدوو action د 7-bit عدد غیر منفي شمیره، پدې پورې اړه لري، موږ به غوره کړو چې څنګه په سمارټ قرارداد کې پیغام پروسس کړو.

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

په ازموینه کې تاسو کولی شئ وګورئ چې د سمارټ قرارداد ذخیره څنګه غیر منظم کیږي storage په پنځم. د متغیرونو بې ترتیبه ​​کول په پنځم سند کې تشریح شوي.

لینک ژمن کړئ د اضافه شوي اوړو سره.

راځئ چې ازموینه ترسره کړو او ډاډ ترلاسه کړو چې دا ناکامیږي. اوس راځئ چې د لاټرۍ د مالک پته بدلولو لپاره منطق اضافه کړو.

په سمارټ قرارداد کې موږ تحلیل ته دوام ورکوو message, لوستل action. راځئ چې تاسو ته یادونه وکړو چې موږ به دوه ولرو action: پته بدله کړئ او ګرامه ولېږئ.

بیا موږ د قرارداد مالک نوی پته ولولو او په ذخیره کې یې خوندي کړو.
موږ ازموینې پرمخ وړو او ګورو چې دریمه ازموینه ناکامه شوه. دا د دې حقیقت له امله خرابیږي چې قرارداد اوس د پیغام څخه 7 بټونه هم پارس کوي، کوم چې په ازموینه کې ورک دي. په پیغام کې یو غیر موجود اضافه کړئ action. راځئ چې ازموینې پرمخ بوځو او وګورو چې هرڅه تیریږي. ټوټ بدلونونو ته ژمن. غوره.

اوس راځئ چې مخکې خوندي شوي پته ته د ټاکل شوي ګرامونو لیږلو منطق ولیکئ.

لومړی، راځئ چې ازموینه ولیکئ. موږ به دوه ازموینې ولیکو، یو کله چې کافي توازن شتون ونلري، دوهم کله چې هرڅه باید په بریالیتوب سره تیر شي. ازموینې لیدل کیدی شي په دې ژمنې کې.

اوس راځئ چې کوډ اضافه کړو. لومړی، راځئ چې دوه مرستندویه میتودونه ولیکئ. د ترلاسه کولو لومړۍ طریقه د سمارټ قرارداد اوسني توازن موندل دي.

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

او دوهم یو بل سمارټ قرارداد ته د ګرام لیږلو لپاره دی. ما دا طریقه په بشپړه توګه د بل سمارټ قرارداد څخه کاپي کړه.

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

راځئ چې دا دوه میتودونه په سمارټ قرارداد کې اضافه کړو او منطق ولیکئ. لومړی، موږ د پیغام څخه د ګرامو شمیره تجزیه کوو. بیا موږ بیلانس چیک کوو، که دا کافي نه وي موږ یو استثنا وغورځوو. که هرڅه سم وي، نو موږ ګرام خوندي شوي پته ته لیږو او کاونټر تازه کوو.

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

لکه دغه دا مهال د سمارټ قرارداد په څیر ښکاري. راځئ چې ازموینې ترسره کړو او ډاډ ترلاسه کړو چې دوی بریالي کیږي.

په هرصورت، د پروسس شوي پیغام لپاره هر ځل د سمارټ قرارداد څخه یو کمیسیون کمیږي. د غوښتنې پلي کولو لپاره د سمارټ تړون پیغامونو لپاره ، د لومړني چکونو وروسته تاسو اړتیا لرئ زنګ ووهئ accept_message().

اوس راځئ چې داخلي پیغامونو ته لاړ شو. په حقیقت کې، موږ به یوازې ګرام منو او لوبغاړي ته به دوه چنده پیسې بیرته واستوو که چیرې هغه وګټي او دریمه برخه مالک ته چې هغه له لاسه ورکړي.

لومړی، راځئ چې یو ساده ازموینه ولیکئ. د دې کولو لپاره، موږ د سمارټ قرارداد ازموینې پتې ته اړتیا لرو چې له هغې څخه موږ فکر کوو چې ګرام سمارټ قرارداد ته واستوو.

د سمارټ قرارداد پته دوه شمیرې لري، یو 32-bit انټیجر چې د ورک چین لپاره مسؤل دی او په دې کاري چین کې د 256-bit غیر منفي انټیجر ځانګړی حساب شمیره. د مثال په توګه، -1 او 12345، دا هغه پته ده چې موږ به یې په فایل کې خوندي کړو.

ما د پتې د خوندي کولو لپاره فنکشن کاپي کړ 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

راځئ چې وګورو چې فنکشن څنګه کار کوي، دا به پوهه ورکړي چې څنګه فیف کار کوي. په متقابل حالت کې Fif لانچ کړئ.

~/TON/build/crypto/fift -i 

لومړی موږ -1، 12345 فشار راوړو او د راتلونکي فایل نوم "sender.addr" په سټیک کې واچوو:

-1 12345 "sender.addr" 

بل ګام د فعالیت اجرا کول دي -rot، کوم چې سټیک په داسې ډول بدلوي چې د سټیک په پورتنۍ برخه کې یو ځانګړی سمارټ قرارداد شمیره شتون لري:

"sender.addr" -1 12345

256 u>B د 256-bit غیر منفي عدد په بایټونو بدلوي.

"sender.addr" -1 BYTES:0000000000000000000000000000000000000000000000000000000000003039

swap د سټیک پورتنۍ دوه عناصر بدلوي.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 -1

32 i>B 32-bit انټیجر په بایټ بدلوي.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 BYTES:FFFFFFFF

B+ د بایټ دوه سلسلې سره نښلوي.

 "sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF

بیا swap.

BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF "sender.addr" 

او په پای کې فایل ته بایټ لیکل کیږي B>file. له دې وروسته زموږ کڅوړه خالي ده. موږ ودروو Fift. په اوسني فولډر کې یو فایل جوړ شوی sender.addr. راځئ چې فایل جوړ شوي فولډر ته واړوو test/addresses/.

راځئ چې یو ساده ازموینه ولیکئ چې ګرام به یو سمارټ قرارداد ته واستوي. دلته ژمنه ده.

اوس راځئ چې د لاټري منطق وګورو.

لومړی شی چې موږ یې کوو پیغام چیک کول دي bounced که نه bounced، بیا موږ له پامه غورځوو. bounced پدې معنی چې قرارداد به ګرام بیرته راستانه کړي که چیرې کومه تېروتنه رامنځته شي. که ناڅاپه کومه تېروتنه رامنځ ته شي موږ به ګرام بیرته نه راګرځوو.

موږ ګورو، که توازن له نیم ګرام څخه کم وي، نو موږ په ساده ډول پیغام منو او له پامه غورځوو.

بیا، موږ د سمارټ قرارداد پته تجزیه کوو چې پیغام یې راغلی.

موږ د ذخیره کولو څخه ډاټا لوستلو او بیا د تاریخ څخه زاړه شرطونه حذف کوو که چیرې له شلو څخه ډیر وي. د اسانتیا لپاره، ما درې اضافي دندې لیکلي pack_order(), unpack_order(), remove_old_orders().

بیا، موږ ګورو چې که توازن د تادیې لپاره کافي نه وي، نو موږ فکر کوو چې دا شرط نه دی، مګر بیا ډکول او بیا ډکول خوندي کړئ. orders.

بیا په پای کې د سمارټ قرارداد جوهر.

لومړی، که لوبغاړی له لاسه ورکړي، موږ یې د بیټینګ په تاریخ کې خوندي کوو او که اندازه له 3 ګرامو څخه زیاته وي، موږ د سمارټ قرارداد مالک ته 1/3 لیږو.

که چیرې لوبغاړی وګټي، نو موږ د لوبغاړي پته ته دوه چنده پیسې لیږو او بیا په تاریخ کې د شرط په اړه معلومات خوندي کوو.

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

دا ټول دي. اړونده ژمنه.

اوس ټول هغه څه چې پاتې دي ساده دي ، راځئ چې د ترلاسه کولو میتودونه رامینځته کړو ترڅو موږ وکولی شو د بهرنۍ نړۍ څخه د تړون حالت په اړه معلومات ترلاسه کړو (په حقیقت کې د دوی د سمارټ قرارداد ذخیره کولو ډاټا ولولئ).

راځئ چې د ترلاسه کولو میتودونه اضافه کړو. موږ به لاندې د سمارټ قرارداد په اړه د معلوماتو ترلاسه کولو څرنګوالي په اړه ولیکئ.

ما د کوډ اضافه کول هم هیر کړل چې هغه به لومړۍ غوښتنه پروسس کړي چې د سمارټ قرارداد خپرولو پرمهال پیښیږي. اړونده ژمنه. او نور اصلاح شوی د مالک حساب ته د مقدار 1/3 لیږلو سره بګ.

بل ګام د سمارټ قرارداد خپرول دي. راځئ چې یو فولډر جوړ کړو requests.

ما د خپرونې کوډ د اساس په توګه واخیست simple-wallet-code.fc کوم موندلی شم په رسمي ذخیره کې.

یو څه چې د پاملرنې ارزښت لري. موږ د سمارټ قرارداد ذخیره او د ننوتلو پیغام تولید کوو. له دې وروسته ، د سمارټ قرارداد پته رامینځته کیږي ، دا دا دی چې پته حتی په TON کې د خپریدو دمخه پیژندل کیږي. بیا ، تاسو اړتیا لرئ دې پتې ته څو ګرامه واستوئ ، او یوازې له هغې وروسته تاسو اړتیا لرئ پخپله د سمارټ قرارداد سره فایل واستوئ ، ځکه چې شبکه د سمارټ قرارداد ذخیره کولو او په دې کې د عملیاتو لپاره کمیسیون اخلي) تایید کونکي چې سمارټ ذخیره کوي او اجرا کوي قراردادونه). کوډ دلته لیدل کیدی شي.

بیا موږ د خپرولو کوډ اجرا کوو او ترلاسه کوو lottery-query.boc د سمارټ قرارداد فایل او پته.

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

د تولید شوي فایلونو خوندي کول مه هیروئ: lottery-query.boc, lottery.addr, lottery.pk.

د نورو شیانو په مینځ کې ، موږ به د اعدام لاګونو کې د سمارټ قرارداد پته وګورو.

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

یوازې د ساتیرۍ لپاره ، راځئ چې TON ته غوښتنه وکړو

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

او موږ به وګورو چې د دې پتې حساب خالي دی.

account state is empty

موږ ادرس ته لیږو 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd 2 ګرام او د څو ثانیو وروسته موږ ورته کمانډ اجرا کوو. د ګرام لیږلو لپاره زه کاروم رسمي بټوه، او تاسو کولی شئ د چاټ څخه د ټیسټ ګرامونو لپاره پوښتنه وکړئ ، کوم چې زه به یې د مقالې په پای کې خبرې وکړم.

> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

داسې ښکاري چې یو غیر پیل شوی (state:account_uninit) د ورته پتې سره یو سمارټ قرارداد او د 1 نانوګرام توازن.

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

اوس راځئ چې سمارټ قرارداد خپور کړو. راځئ چې لایټ کلائنټ پیل کړو او اجرا یې کړو.

> 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 

راځئ وګورو چې قرارداد خپور شوی.

> last
> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

د نورو شیانو په منځ کې موږ ترلاسه کوو.

  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

موږ دا ګورو account_active.

د بدلونونو سره ورته ژمنې سمه ده.

اوس راځئ چې د سمارټ قرارداد سره د تعامل لپاره غوښتنې رامینځته کړو.

په دقیق ډول، موږ به لومړی د پتې د بدلولو لپاره د خپلواک کار په توګه پریږدو، او موږ به دویم د مالک پته ته د ګرام لیږلو لپاره ترسره کړو. په حقیقت کې، موږ به ورته کار وکړو لکه څنګه چې د ګرام لیږلو لپاره ازموینه کې.

دا هغه پیغام دی چې موږ به یې سمارټ قرارداد ته واستوو، چیرته msg_seqno 165، action د لیږلو لپاره 2 او 9.5 ګرامه.

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

د خپل شخصي کیلي سره پیغام لاسلیک کول مه هیروئ lottery.pk، کوم چې دمخه رامینځته شوی و کله چې د سمارټ قرارداد رامینځته کول. دلته اړونده ژمنه ده.

د ترلاسه کولو میتودونو په کارولو سره د سمارټ قرارداد څخه معلومات ترلاسه کول

اوس راځئ وګورو چې څنګه د سمارټ قرارداد ترلاسه کولو میتودونه پرمخ بوځي.

لانچ lite-client او د ترلاسه کولو میتودونه پرمخ وړئ چې موږ لیکلي.

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

В result هغه ارزښت لري چې فنکشن بیرته راګرځي balance() زموږ د سمارټ قرارداد څخه.
موږ به د څو نورو میتودونو لپاره ورته کار وکړو.

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

راځئ چې ستاسو د شرط تاریخ غوښتنه وکړو.

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

موږ به لایټ کلائنټ وکاروو او په سایټ کې د سمارټ قرارداد په اړه د معلوماتو ښودلو لپاره میتودونه ترلاسه کړو.

په ویب پاڼه کې د سمارټ قرارداد ډاټا ښودل

ما په Python کې یو ساده ویب پاڼه لیکلې ترڅو د سمارټ قرارداد څخه ډاټا په مناسبه طریقه ښکاره کړي. دلته به یې په تفصیل سره نه وایم او سایټ به یې خپور کړم په یوه ژمنه کې.

له TON څخه غوښتنه کیږي Python له لارې lite-client. د اسانتیا لپاره، سایټ په ډاکر کې بسته شوی او په ګوګل کلاوډ کې خپور شوی. لینک.

هڅه کوي

اوس راځئ هڅه وکړو چې د بیا ډکولو لپاره ګرام هلته واستوو واټن. موږ به 40 ګرامه لیږو. او راځئ چې د وضاحت لپاره یو څو شرطونه جوړ کړو. موږ ګورو چې سایټ د شرطونو تاریخ، د اوسني ګټونکي سلنه او نور ګټور معلومات ښیې.

موږ وینوچې لومړی مو وګټله او دوهم مو بایللو.

وروسته

مقاله زما د تمه کولو څخه ډیره اوږده شوه، شاید دا لنډه وي، یا شاید یوازې د هغه چا لپاره چې د TON په اړه هیڅ نه پوهیږي او غواړي د متقابل عمل وړتیا سره یو خورا ساده سمارټ قرارداد ولیکي او خپور کړي. دا شاید ځینې شیان په ساده ډول تشریح شوي وي.

ښایي د تطبیق ځینې اړخونه په ډیر اغیزمنه او په زړه پورې توګه ترسره شوي وای، مګر بیا به د مقالې چمتو کولو لپاره ډیر وخت نیولی وای. دا هم امکان لري چې ما په کوم ځای کې خطا کړې وي یا په یو څه نه پوهیږم ، نو که تاسو یو څه جدي کوئ ، نو تاسو اړتیا لرئ په رسمي اسنادو یا د TON کوډ سره رسمي ذخیره تکیه وکړئ.

دا باید په یاد ولرئ چې څنګه چې TON پخپله د پراختیا په فعاله مرحله کې دی، ممکن بدلونونه واقع شي چې پدې مقاله کې کوم مرحلې مات کړي (کوم چې پیښ شوي کله چې ما لیکلی و، دا لا دمخه سم شوی دی)، مګر عمومي تګلاره ده. د بدلون امکان نلري.

زه به د TON راتلونکي په اړه خبرې ونه کړم. شاید پلیټ فارم به یو څه لوی شي او موږ باید د دې مطالعې لپاره وخت تیر کړو او اوس زموږ د محصولاتو سره ځای ډک کړو.

د فیسبوک څخه لیبرا هم شتون لري، کوم چې د TON څخه لوی کاروونکو احتمالي لیدونکي لري. زه د لیبرا په اړه نږدې هیڅ نه پوهیږم ، د فورم لخوا قضاوت کول هلته د TON ټولنې په پرتله ډیر فعالیت شتون لري. که څه هم د TON پراختیا کونکي او ټولنه د ځمکې لاندې په څیر دي ، کوم چې هم ښه دی.

مرجع

  1. د TON رسمي اسناد: https://test.ton.org
  2. د TON رسمي ذخیره: https://github.com/ton-blockchain/ton
  3. د مختلف پلیټ فارمونو لپاره رسمي والټ: https://wallet.ton.org
  4. د دې مقالې څخه د سمارټ قرارداد ذخیره: https://github.com/raiym/astonished
  5. د سمارټ قرارداد ویب پاڼې ته لینک: https://ton-lottery.appspot.com
  6. د FunC لپاره د بصری سټوډیو کوډ لپاره د توسیع لپاره ذخیره: https://github.com/raiym/func-visual-studio-plugin
  7. په ټیلیګرام کې د TON په اړه خبرې وکړئ ، کوم چې واقعیا په لومړي مرحله کې د دې په موندلو کې مرسته کړې. زه فکر کوم چې دا به غلطه نه وي که زه ووایم چې هرڅوک چې د TON لپاره یو څه لیکلي وي هلته شتون لري. تاسو کولی شئ هلته د ټیسټ ګرامونو غوښتنه وکړئ. https://t.me/tondev_ru
  8. د TON په اړه بل چیټ چې ما ګټور معلومات وموندل: https://t.me/TONgramDev
  9. د سیالۍ لومړی پړاو: https://contest.com/blockchain
  10. د سیالۍ دوهم پړاو: https://contest.com/blockchain-2

سرچینه: www.habr.com

Add a comment