Mengenai cara menulis dan menerbitkan kontrak pintar di TON
Artikel ini tentang apa?
Dalam artikel itu saya akan bercakap tentang bagaimana saya mengambil bahagian dalam pertandingan blockchain Telegram pertama (daripada dua), tidak mengambil hadiah, dan memutuskan untuk merekodkan pengalaman saya dalam artikel supaya ia tidak tenggelam dalam kelalaian dan, mungkin, membantu seseorang.
Memandangkan saya tidak mahu menulis kod abstrak, tetapi untuk melakukan sesuatu yang berkesan, untuk artikel itu saya menulis kontrak pintar untuk loteri segera dan tapak web yang menunjukkan data kontrak pintar terus daripada TON tanpa menggunakan storan perantaraan.
Artikel itu akan berguna kepada mereka yang ingin membuat kontrak pintar pertama mereka di TON, tetapi tidak tahu di mana untuk bermula.
Menggunakan loteri sebagai contoh, saya akan beralih daripada memasang persekitaran kepada menerbitkan kontrak pintar, berinteraksi dengannya dan menulis tapak web untuk menerima dan menerbitkan data.
Mengenai penyertaan dalam pertandingan
Oktober lalu, Telegram mengumumkan pertandingan blockchain dengan bahasa baharu Fift и FunC. Ia adalah perlu untuk memilih daripada menulis mana-mana daripada lima kontrak pintar yang dicadangkan. Saya fikir adalah bagus untuk melakukan sesuatu yang berbeza, belajar bahasa dan membuat sesuatu, walaupun saya tidak perlu menulis apa-apa lagi pada masa hadapan. Tambahan pula, topik itu sentiasa di bibir.
Perlu dikatakan bahawa saya tidak mempunyai pengalaman membangunkan kontrak pintar.
Saya merancang untuk mengambil bahagian sehingga akhir sehingga saya boleh dan kemudian menulis artikel ulasan, tetapi saya gagal serta-merta pada yang pertama. saya dengan berbilang tandatangan dihidupkan FunC dan ia secara amnya berhasil. Saya mengambilnya sebagai asas .
Pada masa itu, saya fikir ini sudah cukup untuk mengambil sekurang-kurangnya beberapa tempat hadiah. Hasilnya, kira-kira 40 daripada 60 peserta menjadi pemenang hadiah dan saya tidak termasuk dalam kalangan mereka. Secara umum, tidak ada yang salah dengan ini, tetapi satu perkara yang mengganggu saya. Pada masa pengumuman keputusan, semakan ujian kontrak saya belum dilakukan, saya bertanya kepada peserta dalam sembang jika ada orang lain yang tidak memilikinya, tidak ada.
Nampaknya memberi perhatian kepada mesej saya, dua hari kemudian hakim menerbitkan ulasan dan saya masih tidak faham sama ada mereka secara tidak sengaja terlepas kontrak pintar saya semasa penghakiman atau hanya menganggap bahawa ia sangat teruk sehingga tidak memerlukan ulasan. Saya bertanya soalan pada halaman, tetapi tidak menerima jawapan. Walaupun bukan rahsia siapa yang menilai, saya menganggap ia tidak perlu untuk menulis mesej peribadi.
Banyak masa dihabiskan untuk memahami, jadi diputuskan untuk menulis artikel. Memandangkan belum ada banyak maklumat, artikel ini akan membantu menjimatkan masa untuk semua orang yang berminat.
Konsep kontrak pintar dalam TON
Sebelum anda menulis apa-apa, anda perlu memikirkan pihak mana untuk mendekati perkara ini. Oleh itu, sekarang saya akan memberitahu anda bahagian yang terdiri daripada sistem. Lebih tepat lagi, bahagian apa yang perlu anda ketahui untuk menulis sekurang-kurangnya beberapa jenis kontrak kerja.
Kami akan menumpukan pada menulis kontrak pintar dan bekerja dengannya TON Virtual Machine (TVM), Fift и FunC, jadi artikel itu lebih seperti penerangan tentang pembangunan program biasa. Kami tidak akan memikirkan cara platform itu sendiri berfungsi di sini.
Secara umum tentang cara ia berfungsi TVM dan bahasa Fift terdapat dokumentasi rasmi yang baik. Semasa menyertai pertandingan dan kini semasa menulis kontrak semasa, saya sering menoleh kepadanya.
Bahasa utama di mana kontrak pintar ditulis ialah FunC. Tiada dokumentasi mengenainya pada masa ini, jadi untuk menulis sesuatu, anda perlu mengkaji contoh kontrak pintar dari repositori rasmi dan pelaksanaan bahasa itu sendiri di sana, serta anda boleh melihat contoh kontrak pintar dari dua masa lalu pertandingan. Pautan pada akhir artikel.
Katakan kita telah pun menulis kontrak pintar untuknya FunC, selepas itu kami menyusun kod ke dalam Fift assembler.
Kontrak pintar yang disusun masih akan diterbitkan. Untuk melakukan ini, anda perlu menulis fungsi dalam Fift, yang akan mengambil kod kontrak pintar dan beberapa parameter lain sebagai input, dan output akan menjadi fail dengan sambungan .boc (yang bermaksud "beg sel"), dan, bergantung pada cara kami menulisnya, kunci dan alamat peribadi, yang dijana berdasarkan kod kontrak pintar. Anda sudah boleh menghantar gram ke alamat kontrak pintar yang masih belum diterbitkan.
Untuk menerbitkan kontrak pintar dalam TON diterima .boc fail itu perlu dihantar ke blockchain menggunakan klien ringan (lebih lanjut mengenai perkara di bawah). Tetapi sebelum menerbitkan, anda perlu memindahkan gram ke alamat yang dijana, jika tidak, kontrak pintar tidak akan diterbitkan. Selepas penerbitan, anda boleh berinteraksi dengan kontrak pintar dengan menghantarnya mesej dari luar (contohnya, menggunakan klien ringan) atau dari dalam (contohnya, satu kontrak pintar menghantar satu lagi mesej di dalam TON).
Sebaik sahaja kami memahami cara kod diterbitkan, ia menjadi lebih mudah. Kami secara kasarnya tahu apa yang ingin kami tulis dan bagaimana program kami akan berfungsi. Dan semasa menulis, kami mencari cara ini telah dilaksanakan dalam kontrak pintar sedia ada, atau kami melihat ke dalam kod pelaksanaan Fift и FunC dalam repositori rasmi, atau lihat dalam dokumentasi rasmi.
Selalunya saya mencari kata kunci dalam sembang Telegram di mana semua peserta pertandingan dan pekerja Telegram berkumpul, dan kebetulan semasa pertandingan semua orang berkumpul di sana dan mula membincangkan Fift dan FunC. Pautan pada akhir artikel.
Sudah tiba masanya untuk beralih dari teori kepada amalan.
Menyediakan persekitaran untuk bekerja dengan TON
Saya telah melakukan semua yang akan diterangkan dalam artikel di MacOS dan menyemaknya semula dengan bersih Ubuntu 18.04 LTS pada Docker.
Perkara pertama yang perlu anda lakukan ialah memuat turun dan memasang lite-client yang mana anda boleh menghantar permintaan kepada TON.
Arahan di laman web rasmi menerangkan proses pemasangan dengan teliti dan jelas, tanpa memasukkan beberapa butiran. Di sini kita mengikuti arahan, memasang sebarang kebergantungan yang hilang. Saya tidak mengkompil setiap projek sendiri dan memasangnya dari repositori rasmi. Ubuntu (pada MacOS yang saya gunakan 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 Setelah semua kebergantungan dipasang, anda boleh memasang lite-client, Fift, FunC.
Mula-mula, kami mengklonkan repositori TON bersama-sama dengan kebergantungannya. Untuk kemudahan, kami akan melakukan segala-galanya dalam folder ~/TON.
cd ~/TON
git clone https://github.com/ton-blockchain/ton.git
cd ./ton
git submodule update --init --recursiveRepositori juga menyimpan pelaksanaan Fift и FunC.
Sekarang kami bersedia untuk memasang projek itu. Kod repositori diklon ke dalam folder ~/TON/ton. В ~/TON buat folder build dan kumpulkan projek di dalamnya.
mkdir ~/TON/build
cd ~/TON/build
cmake ../tonOleh kerana kita akan menulis kontrak pintar, kita bukan sahaja perlu lite-clientTetapi Fift с FunC, jadi mari kita kumpulkan semuanya. Ia bukan proses yang cepat, jadi kami menunggu.
cmake --build . --target lite-client
cmake --build . --target fift
cmake --build . --target funcSeterusnya, muat turun fail konfigurasi yang mengandungi data tentang nod yang lite-client akan menyambung.
wget https://test.ton.org/ton-lite-client-test1.config.jsonMembuat permintaan pertama kepada TON
Sekarang mari kita lancarkan lite-client.
cd ~/TON/build
./lite-client/lite-client -C ton-lite-client-test1.config.jsonJika binaan berjaya, maka selepas pelancaran anda akan melihat log sambungan klien ringan ke nod.
[ 1][t 2][1582054822.963129282][lite-client.h:201][!testnode] conn ready
[ 2][t 2][1582054823.085654020][lite-client.cpp:277][!testnode] server version is 1.1, capabilities 7
[ 3][t 2][1582054823.085725069][lite-client.cpp:286][!testnode] server time is 1582054823 (delta 0)
...Anda boleh menjalankan arahan help dan lihat arahan yang tersedia.
helpMari kita senaraikan arahan yang akan kita gunakan dalam artikel ini.
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 parameterslast получает последний созданный блок с сервера.
sendfile <filename> отправляет в TON файл с сообщением, именно с помощью этой команды публикуется смарт-контракт и запрсосы к нему.
getaccount <addr> загружает текущее состояние смарт-контракта с указанным адресом.
runmethod <addr> [<block-id-ext>] <method-id> <params> запускает get-методы смартконтракта. Kini kami bersedia untuk menulis kontrak itu sendiri.
Реализация
Idea
Seperti yang saya tulis di atas, kontrak pintar yang kami tulis adalah loteri.
Lebih-lebih lagi, ini bukan loteri di mana anda perlu membeli tiket dan menunggu sejam, hari atau bulan, tetapi segera di mana pengguna memindahkan ke alamat kontrak N gram, dan serta-merta mendapatkannya kembali 2 * N gram atau kerugian. Kami akan membuat kebarangkalian untuk menang kira-kira 40%. Jika tidak cukup gram untuk pembayaran, maka kami akan menganggap transaksi sebagai tambah nilai.
Selain itu, adalah penting bahawa pertaruhan boleh dilihat dalam masa nyata dan dalam bentuk yang mudah, supaya pengguna dapat segera memahami sama ada dia menang atau kalah. Oleh itu, anda perlu membuat laman web yang akan menunjukkan pertaruhan dan keputusan terus dari TON.
Menulis kontrak pintar
Untuk kemudahan, saya telah menyerlahkan kod untuk FunC; pemalam itu boleh ditemui dan dipasang dalam carian Kod Visual Studio; jika anda tiba-tiba ingin menambah sesuatu, saya telah menyediakan pemalam itu secara terbuka. Selain itu, seseorang sebelum ini membuat pemalam untuk bekerja dengan Fift, anda juga boleh memasangnya dan mencarinya dalam VSC.
Mari segera buat repositori di mana kita akan melakukan hasil perantaraan.
Untuk menjadikan hidup kami lebih mudah, kami akan menulis kontrak pintar dan mengujinya secara tempatan sehingga ia siap. Hanya selepas itu kami akan menerbitkannya dalam TON.
Kontrak pintar mempunyai dua kaedah luaran yang boleh diakses. pertama, recv_external() fungsi ini dilaksanakan apabila permintaan kepada kontrak datang dari dunia luar, iaitu, bukan dari TON, sebagai contoh, apabila kita sendiri menjana mesej dan menghantarnya melalui lite-client. Kedua, recv_internal() inilah apabila, dalam TON sendiri, sebarang kontrak merujuk kepada kontrak kami. Dalam kedua-dua kes, anda boleh menghantar parameter kepada fungsi.
Mari kita mulakan dengan contoh mudah yang akan berfungsi jika diterbitkan, tetapi tiada beban berfungsi di dalamnya.
() recv_internal(slice in_msg) impure {
;; TODO: implementation
}
() recv_external(slice in_msg) impure {
;; TODO: implementation
}Di sini kita perlu menerangkan apa itu slice. Semua data yang disimpan dalam TON Blockchain adalah koleksi TVM cell atau hanya cell, dalam sel sedemikian anda boleh menyimpan sehingga 1023 bit data dan sehingga 4 pautan ke sel lain.
TVM cell slice atau slice ini adalah sebahagian daripada yang sedia ada cell digunakan untuk menghuraikannya, ia akan menjadi jelas kemudian. Perkara utama bagi kami ialah kami boleh memindahkan slice dan bergantung pada jenis mesej, proses data masuk recv_external() atau recv_internal().
impure — kata kunci yang menunjukkan bahawa fungsi itu mengubah suai data kontrak pintar.
Mari simpan kod kontrak lottery-code.fc dan menyusun.
~/TON/build/crypto/func -APSR -o lottery-compiled.fif ~/TON/ton/crypto/smartcont/stdlib.fc ./lottery-code.fc Maksud bendera boleh dilihat menggunakan arahan
~/TON/build/crypto/func -helpKami telah menyusun kod pemasang Fift dalam 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>cIa boleh dilancarkan secara tempatan, untuk ini kami akan menyediakan persekitaran.
Perhatikan bahawa baris pertama bersambung Asm.fif, ini adalah kod yang ditulis dalam Fift for the Fift assembler.
Memandangkan kami ingin menjalankan dan menguji kontrak pintar secara tempatan, kami akan mencipta fail lottery-test-suite.fif dan salin kod yang disusun di sana, menggantikan baris terakhir di dalamnya, yang menulis kod kontrak pintar kepada pemalar codeuntuk kemudian memindahkannya ke mesin maya:
"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
Setakat ini nampak jelas, sekarang mari kita tambahkan pada fail yang sama kod yang akan kita gunakan untuk melancarkan 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 kami merekodkan konteks, iaitu, data yang dengannya TVM (atau keadaan rangkaian) akan dilancarkan. Malah semasa pertandingan, salah seorang pembangun menunjukkan cara mencipta c7 dan saya salin. Dalam artikel ini kita mungkin perlu berubah rand_seed memandangkan penjanaan nombor rawak bergantung padanya dan jika tidak diubah, nombor yang sama akan dikembalikan setiap kali.
recv_internal и recv_external pemalar dengan nilai 0 dan -1 akan bertanggungjawab untuk memanggil fungsi yang sepadan dalam kontrak pintar.
Kini kami bersedia untuk membuat ujian pertama untuk kontrak pintar kosong kami. Untuk kejelasan, buat masa ini kami akan menambah semua ujian pada fail yang sama lottery-test-suite.fif.
Mari buat pembolehubah storage dan tulis satu kosong ke dalamnya cell, ini akan menjadi storan kontrak pintar.
message Ini adalah mesej yang akan kami sampaikan kepada kenalan pintar dari luar. Kami juga akan menjadikannya kosong buat masa ini.
variable storage
<b b> storage !
variable message
<b b> message ! Selepas kami menyediakan pemalar dan pembolehubah, kami melancarkan TVM menggunakan arahan runvmctx dan hantar parameter yang dibuat kepada input.
message @
recv_external
code
storage @
c7
runvmctx Akhirnya kita akan berjaya kod perantaraan untuk Fift.
Sekarang kita boleh menjalankan kod yang terhasil.
export FIFTPATH=~/TON/ton/crypto/fift/lib // выполняем один раз для удобства
~/TON/build/crypto/fift -s lottery-test-suite.fif Program ini harus berjalan tanpa ralat dan dalam output kita akan melihat log pelaksanaan:
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=0Bagus, kami telah menulis versi pertama kontrak pintar yang berfungsi.
Sekarang kita perlu menambah fungsi. Mula-mula mari kita berurusan dengan mesej yang datang dari dunia luar kepada recv_external()
Pembangun sendiri memilih format mesej yang boleh diterima oleh kontrak.
Tetapi selalunya
- pertama, kami ingin melindungi kontrak kami daripada dunia luar dan menjadikannya supaya hanya pemilik kontrak boleh menghantar mesej luaran kepadanya.
- kedua, apabila kami menghantar mesej yang sah kepada TON, kami mahu ini berlaku tepat sekali dan apabila kami menghantar mesej yang sama sekali lagi, kontrak pintar menolaknya.
Jadi hampir setiap kontrak menyelesaikan dua masalah ini, kerana kontrak kami menerima mesej luar, kami juga perlu menjaganya.
Kami akan melakukannya dalam urutan terbalik. Pertama, mari kita selesaikan masalah dengan pengulangan; jika kontrak telah menerima mesej sedemikian dan memprosesnya, ia tidak akan melaksanakannya untuk kali kedua. Dan kemudian kami akan menyelesaikan masalah itu supaya hanya kalangan orang tertentu boleh menghantar mesej kepada kontrak pintar.
Terdapat pelbagai cara untuk menyelesaikan masalah dengan mesej pendua. Begini cara kami akan melakukannya. Dalam kontrak pintar, kami memulakan kaunter mesej yang diterima dengan nilai awal 0. Dalam setiap mesej kepada kontrak pintar, kami akan menambah nilai kaunter semasa. Jika nilai pembilang dalam mesej tidak sepadan dengan nilai dalam kontrak pintar, maka kami tidak memprosesnya; jika ia berlaku, maka kami memprosesnya dan meningkatkan pembilang dalam kontrak pintar sebanyak 1.
Mari kita kembali ke lottery-test-suite.fif dan tambahkan ujian kedua kepadanya. Jika kami menghantar nombor yang salah, kod itu harus membuang pengecualian. Sebagai contoh, biarkan data kontrak menyimpan 166, dan kami akan menghantar 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"Jom lancarkan.
~/TON/build/crypto/fift -s lottery-test-suite.fif Dan kita akan melihat bahawa ujian itu dilaksanakan dengan ralat.
[ 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 passedPada peringkat ini lottery-test-suite.fif sepatutnya kelihatan seperti .
Sekarang mari tambah logik kaunter pada kontrak pintar masuk 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 terletak mesej yang kami hantar.
Perkara pertama yang kami lakukan ialah menyemak sama ada mesej mengandungi data, jika tidak, maka kami hanya keluar.
Seterusnya kita menghuraikan mesej itu. in_msg~load_uint(32) memuatkan nombor 165, 32-bit unsigned int daripada mesej yang dihantar.
Seterusnya kami memuatkan 32 bit daripada storan kontrak pintar. Kami menyemak sama ada nombor yang dimuatkan sepadan dengan nombor yang diluluskan; jika tidak, kami membuang pengecualian. Dalam kes kami, kerana kami melepasi bukan perlawanan, pengecualian harus dilemparkan.
Sekarang mari kita susun.
~/TON/build/crypto/func -APSR -o lottery-compiled.fif ~/TON/ton/crypto/smartcont/stdlib.fc ./lottery-code.fc Salin kod yang terhasil ke lottery-test-suite.fif, tidak lupa untuk menggantikan baris terakhir.
Kami menyemak bahawa ujian itu lulus:
~/TON/build/crypto/fift -s lottery-test-suite.fifAnda boleh melihat komitmen yang sepadan dengan hasil semasa.
Ambil perhatian bahawa adalah menyusahkan untuk sentiasa menyalin kod terkumpul kontrak pintar ke dalam fail dengan ujian, jadi kami akan menulis skrip yang akan menulis kod ke pemalar untuk kami, dan kami hanya akan menyambungkan kod yang disusun ke ujian kami menggunakan "include".
Buat fail dalam folder projek build.sh dengan kandungan berikut.
#!/bin/bash
~/TON/build/crypto/func -SPA -R -o lottery-compiled.fif ~/TON/ton/crypto/smartcont/stdlib.fc ./lottery-code.fcMari jadikan ia boleh dilaksanakan.
chmod +x ./build.shSekarang, jalankan sahaja skrip kami untuk menyusun kontrak. Tetapi selain ini, kita perlu menulisnya menjadi pemalar code. Jadi kami akan membuat fail baru lotter-compiled-for-test.fif, yang akan kami sertakan dalam fail lottery-test-suite.fif.
Mari tambahkan kod skirpt ke sh, yang hanya akan menduplikasi fail yang disusun lotter-compiled-for-test.fif dan tukar baris terakhir di dalamnya.
# 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.fifSekarang, untuk menyemak, mari jalankan skrip yang terhasil dan fail akan dihasilkan lottery-compiled-for-test.fif, yang akan kami sertakan dalam kami lottery-test-suite.fif
В lottery-test-suite.fif padam kod kontrak dan tambah baris "lottery-compiled-for-test.fif" include.
Kami menjalankan ujian untuk memastikan mereka lulus.
~/TON/build/crypto/fift -s lottery-test-suite.fifBagus, sekarang untuk mengautomasikan pelancaran ujian, mari buat fail test.sh, yang akan dilaksanakan terlebih dahulu build.sh, dan kemudian jalankan ujian.
touch test.sh
chmod +x test.shKami menulis di dalam
./build.sh
echo "nCompilation completedn"
export FIFTPATH=~/TON/ton/crypto/fift/lib
~/TON/build/crypto/fift -s lottery-test-suite.fifJom buat test.sh dan jalankannya untuk memastikan ujian berfungsi.
chmod +x ./test.sh
./test.shKami menyemak bahawa kontrak disusun dan ujian dilaksanakan.
Hebat, kini dimulakan test.sh Ujian akan disusun dan dijalankan serta-merta. Berikut adalah pautan ke .
Okay, sebelum kita meneruskan, mari kita lakukan satu perkara lagi untuk kemudahan.
Mari buat folder build di mana kami akan menyimpan kontrak yang disalin dan klonnya ditulis ke dalam pemalar lottery-compiled.fif, lottery-compiled-for-test.fif. Mari buat folder juga test di manakah fail ujian akan disimpan? lottery-test-suite.fif dan kemungkinan fail sokongan lain. .
Mari teruskan membangunkan kontrak pintar.
Seterusnya perlu ada ujian yang menyemak mesej diterima dan kaunter dikemas kini di kedai apabila kami menghantar nombor yang betul. Tetapi kita akan melakukannya kemudian.
Sekarang mari kita fikirkan tentang struktur data dan data apa yang perlu disimpan dalam kontrak pintar.
Saya akan menerangkan semua yang kami simpan.
`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` переменная типа словарь, хранит последние двадцать ставок. Seterusnya anda perlu menulis dua fungsi. Mari kita hubungi yang pertama pack_state(), yang akan membungkus data untuk simpanan seterusnya dalam storan kontrak pintar. Mari kita panggil yang kedua unpack_state() akan membaca dan mengembalikan data daripada storan.
_ 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;
}Kami menambah dua fungsi ini pada permulaan kontrak pintar. Ia akan berjaya keputusan pertengahan.
Untuk menyimpan data anda perlu memanggil fungsi terbina dalam set_data() dan ia akan menulis data daripada pack_state() dalam storan kontrak pintar.
cell packed_state = pack_state(arg_1, .., arg_n);
set_data(packed_state);Sekarang kita mempunyai fungsi yang mudah untuk menulis dan membaca data, kita boleh meneruskan.
Kita perlu menyemak bahawa mesej yang masuk dari luar ditandatangani oleh pemilik kontrak (atau pengguna lain yang mempunyai akses kepada kunci persendirian).
Apabila kami menerbitkan kontrak pintar, kami boleh memulakannya dengan data yang kami perlukan dalam storan, yang akan disimpan untuk kegunaan masa hadapan. Kami akan merekodkan kunci awam di sana supaya kami boleh mengesahkan bahawa mesej masuk telah ditandatangani dengan kunci peribadi yang sepadan.
Sebelum meneruskan, mari buat kunci peribadi dan tuliskannya test/keys/owner.pk. Untuk melakukan ini, mari lancarkan Fift dalam mod interaktif dan laksanakan empat arahan.
`newkeypair` генерация публичного и приватного ключа и запись их в стек.
`drop` удаления из стека верхнего элемента (в данном случае публичный ключ)
`.s` просто посмотреть что лежит в стеке в данный момент
`"owner.pk" B>file` запись приватного ключа в файл с именем `owner.pk`.
`bye` завершает работу с Fift. Mari buat folder keys di dalam folder test dan tulis kunci peribadi di sana.
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
byeKami melihat fail dalam folder semasa owner.pk.
Kami mengalih keluar kunci awam daripada timbunan dan apabila diperlukan kami boleh mendapatkannya daripada kunci peribadi.
Sekarang kita perlu menulis pengesahan tandatangan. Mari kita mulakan dengan ujian. Mula-mula kita membaca kunci peribadi dari fail menggunakan fungsi tersebut file>B dan tuliskannya kepada pembolehubah owner_private_key, kemudian menggunakan fungsi priv>pub tukar kunci persendirian kepada kunci awam dan tulis hasilnya 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 !Kami akan memerlukan kedua-dua kunci.
Kami memulakan storan kontrak pintar dengan data arbitrari dalam urutan yang sama seperti dalam fungsi pack_state()dan tuliskannya ke dalam pembolehubah 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 !Seterusnya, kami akan mengarang mesej yang ditandatangani, ia hanya akan mengandungi tandatangan dan nilai kaunter.
Mula-mula, kami mencipta data yang ingin kami hantar, kemudian kami menandatanganinya dengan kunci peribadi dan akhirnya kami menjana mesej yang ditandatangani.
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 ! Akibatnya, mesej yang akan kami hantar kepada kontrak pintar direkodkan dalam pembolehubah message_to_send, tentang fungsi hashu, ed25519_sign_uint anda boleh membaca .
Dan untuk menjalankan ujian kami memanggil semula.
message_to_send @
recv_external
code
storage @
c7
runvmctxFail dengan ujian sepatutnya kelihatan seperti ini pada peringkat ini.
Mari jalankan ujian dan ia akan gagal, jadi kami akan menukar kontrak pintar supaya ia boleh menerima mesej format ini dan mengesahkan tandatangan.
Mula-mula, kita mengira 512 bit tandatangan daripada mesej dan menulisnya kepada pembolehubah, kemudian kita mengira 32 bit pembolehubah pembilang.
Memandangkan kami mempunyai fungsi untuk membaca data daripada storan kontrak pintar, kami akan menggunakannya.
Seterusnya menyemak kaunter yang dipindahkan dengan storan dan menyemak tandatangan. Jika sesuatu tidak sepadan, maka kami membuang pengecualian dengan kod yang sesuai.
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));Komitmen yang berkaitan .
Mari jalankan ujian dan lihat bahawa ujian kedua gagal. Atas dua sebab, bit tidak mencukupi dalam mesej dan bit tidak mencukupi dalam storan, jadi kod ranap apabila menghuraikan. Kami perlu menambah tandatangan pada mesej yang kami hantar dan menyalin storan daripada ujian terakhir.
Dalam ujian kedua, kami akan menambah tandatangan mesej dan menukar storan kontrak pintar. fail dengan ujian kelihatan seperti pada masa ini.
Mari tulis ujian keempat, di mana kami akan menghantar mesej yang ditandatangani dengan kunci peribadi orang lain. Mari buat kunci peribadi lain dan simpan ke fail not-owner.pk. Kami akan menandatangani mesej dengan kunci peribadi ini. Mari jalankan ujian dan pastikan semua ujian lulus. pada saat ini.
Kini kita akhirnya boleh meneruskan untuk melaksanakan logik kontrak pintar.
В recv_external() kami akan menerima dua jenis mesej.
Oleh kerana kontrak kami akan mengumpul kerugian pemain, wang ini mesti dipindahkan kepada pencipta loteri. Alamat dompet pencipta loteri direkodkan dalam storan apabila kontrak dibuat.
Untuk berjaga-jaga, kami memerlukan keupayaan untuk menukar alamat yang kami hantar gram orang yang kalah. Kita juga sepatutnya boleh menghantar gram dari loteri ke alamat pemilik.
Mari kita mulakan dengan yang pertama. Mari mula-mula tulis ujian yang akan menyemak bahawa selepas menghantar mesej, kontrak pintar menyimpan alamat baharu dalam storan. Sila ambil perhatian bahawa dalam mesej, sebagai tambahan kepada kaunter dan alamat baharu, kami juga menghantar action Nombor bukan negatif integer 7-bit, bergantung padanya, kami akan memilih cara memproses mesej dalam kontrak pintar.
<b 0 32 u, 1 @ 7 u, new_owner_wc @ 32 i, new_owner_account_id @ 256 u, b> message_to_sign !Dalam ujian, anda boleh melihat cara storan kontrak pintar dinyahsiri storage dalam Lima. Penyahserialisasian pembolehubah diterangkan dalam dokumentasi Fift.
dengan adunan tambahan.
Mari jalankan ujian dan pastikan ia gagal. Sekarang mari tambah logik untuk menukar alamat pemilik loteri.
Dalam kontrak pintar kami terus menghuraikan message, baca masuk action. Marilah kami ingatkan anda bahawa kami akan mempunyai dua action: tukar alamat dan hantar gram.
Kemudian kami membaca alamat baharu pemilik kontrak dan menyimpannya dalam storan.
Kami menjalankan ujian dan melihat bahawa ujian ketiga gagal. Ia ranap disebabkan oleh fakta bahawa kontrak kini juga menghuraikan 7 bit daripada mesej, yang tiada dalam ujian. Tambahkan yang tidak wujud pada mesej action. Mari jalankan ujian dan lihat bahawa semuanya lulus. komited kepada perubahan. Hebat.
Sekarang mari kita tulis logik untuk menghantar bilangan gram yang ditentukan ke alamat yang disimpan sebelum ini.
Pertama, mari kita tulis ujian. Kami akan menulis dua ujian, satu apabila tidak ada baki yang mencukupi, yang kedua apabila semuanya harus lulus dengan jayanya. Ujian boleh dilihat .
Sekarang mari tambah kod. Pertama, mari kita tulis dua kaedah pembantu. Kaedah mendapatkan pertama adalah untuk mengetahui baki semasa kontrak pintar.
int balance() inline_ref method_id {
return get_balance().pair_first();
}Dan yang kedua adalah untuk menghantar gram ke kontrak pintar yang lain. Saya menyalin sepenuhnya kaedah ini daripada kontrak pintar yang lain.
() 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
}Mari tambahkan dua kaedah ini pada kontrak pintar dan tulis logiknya. Pertama, kami menghuraikan bilangan gram daripada mesej. Seterusnya kita semak baki, jika tidak mencukupi kita buang pengecualian. Jika semuanya baik-baik saja, maka kami menghantar gram ke alamat yang disimpan dan mengemas kini kaunter.
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));kelihatan seperti kontrak pintar pada masa ini. Mari jalankan ujian dan pastikan mereka lulus.
By the way, komisen ditolak daripada kontrak pintar setiap kali untuk mesej yang diproses. Untuk membolehkan mesej kontrak pintar melaksanakan permintaan, selepas semakan asas anda perlu menghubungi accept_message().
Sekarang mari kita beralih kepada mesej dalaman. Malah, kami hanya akan menerima gram dan menghantar semula dua kali ganda jumlah kepada pemain jika dia menang dan satu pertiga kepada pemilik jika dia kalah.
Pertama, mari kita tulis ujian mudah. Untuk melakukan ini, kami memerlukan alamat ujian kontrak pintar yang kononnya kami menghantar gram ke kontrak pintar.
Alamat kontrak pintar terdiri daripada dua nombor, integer 32-bit yang bertanggungjawab untuk rantaian kerja dan nombor akaun unik integer 256-bit bukan negatif dalam rantaian kerja ini. Sebagai contoh, -1 dan 12345, ini adalah alamat yang akan kami simpan pada fail.
Saya menyalin fungsi untuk menyimpan alamat daripada .
// ( wc addr fname -- ) Save address to file in 36-byte format
{ -rot 256 u>B swap 32 i>B B+ swap B>file } : save-addressMari kita lihat bagaimana fungsi berfungsi, ini akan memberi pemahaman tentang cara Fift berfungsi. Lancarkan Fift dalam mod interaktif.
~/TON/build/crypto/fift -i Mula-mula kita tolak -1, 12345 dan nama fail masa depan "sender.addr" ke dalam tindanan:
-1 12345 "sender.addr" Langkah seterusnya ialah melaksanakan fungsi tersebut -rot, yang mengalihkan tindanan sedemikian rupa sehingga di bahagian atas tindanan terdapat nombor kontrak pintar yang unik:
"sender.addr" -1 12345256 u>B menukar integer bukan negatif 256-bit kepada bait.
"sender.addr" -1 BYTES:0000000000000000000000000000000000000000000000000000000000003039swap menukar dua elemen teratas timbunan.
"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 -132 i>B menukar integer 32-bit kepada bait.
"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 BYTES:FFFFFFFFB+ menghubungkan dua jujukan bait.
"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFFSekali lagi swap.
BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF "sender.addr" Dan akhirnya bait ditulis pada fail B>file. Selepas ini timbunan kami kosong. kita berhenti Fift. Fail telah dibuat dalam folder semasa sender.addr. Mari alihkan fail ke folder yang dibuat test/addresses/.
Mari tulis ujian mudah yang akan menghantar gram ke kontrak pintar. .
Sekarang mari kita lihat logik loteri.
Perkara pertama yang kami lakukan ialah menyemak mesej bounced atau tidak jika bounced, maka kita mengabaikannya. bounced bermakna kontrak akan mengembalikan gram jika berlaku kesilapan. Kami tidak akan mengembalikan gram jika ralat tiba-tiba berlaku.
Kami semak, jika bakinya kurang daripada setengah gram, maka kami hanya menerima mesej itu dan mengabaikannya.
Seterusnya, kami menghuraikan alamat kontrak pintar dari mana mesej itu datang.
Kami membaca data dari storan dan kemudian memadamkan pertaruhan lama daripada sejarah jika terdapat lebih daripada dua puluh daripadanya. Untuk kemudahan, saya menulis tiga fungsi tambahan pack_order(), unpack_order(), remove_old_orders().
Seterusnya, kami melihat jika baki tidak mencukupi untuk pembayaran, maka kami menganggap bahawa ini bukan pertaruhan, tetapi penambahan dan simpan penambahan dalam orders.
Kemudian akhirnya intipati kontrak pintar.
Pertama, jika pemain kalah, kami menyimpannya dalam sejarah pertaruhan dan jika jumlahnya melebihi 3 gram, kami menghantar 1/3 kepada pemilik kontrak pintar.
Jika pemain menang, maka kami menghantar dua kali ganda jumlah ke alamat pemain dan kemudian menyimpan maklumat tentang pertaruhan dalam sejarah.
() 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));
}Itu sahaja. .
Sekarang semua yang tinggal adalah mudah, mari kita cipta kaedah dapatkan supaya kita boleh mendapatkan maklumat tentang keadaan kontrak dari dunia luar (malah, baca data dari storan kontrak pintar mereka).
. Kami akan menulis di bawah tentang cara menerima maklumat tentang kontrak pintar.
Saya juga terlupa untuk menambah kod yang akan memproses permintaan pertama yang berlaku apabila menerbitkan kontrak pintar. . Dan seterusnya pepijat dengan menghantar 1/3 daripada jumlah ke akaun pemilik.
Langkah seterusnya ialah menerbitkan kontrak pintar. Mari buat folder requests.
Saya mengambil kod penerbitan sebagai asas который dalam repositori rasmi.
Sesuatu yang patut diberi perhatian. Kami menjana storan kontrak pintar dan mesej input. Selepas ini, alamat kontrak pintar dijana, iaitu, alamat diketahui sebelum diterbitkan dalam TON. Seterusnya, anda perlu menghantar beberapa gram ke alamat ini, dan hanya selepas itu anda perlu menghantar fail dengan kontrak pintar itu sendiri, kerana rangkaian mengambil komisen untuk menyimpan kontrak pintar dan operasi di dalamnya (pengesah yang menyimpan dan melaksanakan pintar kontrak). .
Seterusnya kita laksanakan kod penerbitan dan dapatkan lottery-query.boc fail kontrak pintar dan alamat.
~/TON/build/crypto/fift -s requests/new-lottery.fif 0Jangan lupa simpan fail yang dijana: lottery-query.boc, lottery.addr, lottery.pk.
Antara lain, kita akan melihat alamat kontrak pintar dalam log pelaksanaan.
new wallet address = 0:044910149dbeaf8eadbb2b28722e7d6a2dc6e264ec2f1d9bebd6fb209079bc2a
(Saving address to file lottery.addr)
Non-bounceable address (for init): 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd
Bounceable address (for later access): kQAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8KpFYSekadar suka-suka, jom buat permintaan kepada TON
$ ./lite-client/lite-client -C ton-lite-client-test1.config.json
getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8KsydDan kita akan melihat bahawa akaun dengan alamat ini kosong.
account state is emptyKami hantar ke alamat 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd 2 Gram dan selepas beberapa saat kami melaksanakan arahan yang sama. Untuk menghantar gram saya gunakan , dan anda boleh meminta seseorang daripada sembang untuk gram ujian, yang akan saya bincangkan di penghujung artikel.
> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8KsydKelihatan seperti tidak dimulakan (state:account_uninit) kontrak pintar dengan alamat yang sama dan baki 1 nanogram.
account state is (account
addr:(addr_std
anycast:nothing workchain_id:0 address:x044910149DBEAF8EADBB2B28722E7D6A2DC6E264EC2F1D9BEBD6FB209079BC2A)
storage_stat:(storage_info
used:(storage_used
cells:(var_uint len:1 value:1)
bits:(var_uint len:1 value:103)
public_cells:(var_uint len:0 value:0)) last_paid:1583257959
due_payment:nothing)
storage:(account_storage last_trans_lt:3825478000002
balance:(currencies
grams:(nanograms
amount:(var_uint len:4 value:2000000000))
other:(extra_currencies
dict:hme_empty))
state:account_uninit))
x{C00044910149DBEAF8EADBB2B28722E7D6A2DC6E264EC2F1D9BEBD6FB209079BC2A20259C2F2F4CB3800000DEAC10776091DCD650004_}
last transaction lt = 3825478000001 hash = B043616AE016682699477FFF01E6E903878CDFD6846042BA1BFC64775E7AC6C4
account balance is 2000000000ngSekarang mari terbitkan kontrak pintar. Mari kita lancarkan lite-client dan laksanakan.
> 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 Mari semak sama ada kontrak itu telah diterbitkan.
> last
> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8KsydAntara lain yang kita dapat.
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_activeKita nampak itu account_active.
Komit yang sepadan dengan perubahan .
Sekarang mari buat permintaan untuk berinteraksi dengan kontrak pintar.
Lebih tepat lagi, kami akan meninggalkan yang pertama untuk menukar alamat sebagai kerja bebas, dan kami akan melakukan yang kedua untuk menghantar gram ke alamat pemilik. Malah, kita perlu melakukan perkara yang sama seperti dalam ujian untuk menghantar gram.
Ini adalah mesej yang akan kami hantar kepada kontrak pintar, di mana msg_seqno 165, action 2 dan 9.5 gram untuk dihantar.
<b 165 32 u, 2 7 u, 9500000000 Gram, b>Jangan lupa untuk menandatangani mesej dengan kunci peribadi anda lottery.pk, yang dijana lebih awal apabila mencipta kontrak pintar. .
Menerima maklumat daripada kontrak pintar menggunakan kaedah dapatkan
Sekarang mari kita lihat cara menjalankan kaedah perolehan kontrak pintar.
Kami melancarkan lite-client dan jalankan kaedah dapatkan yang kami tulis.
$ ./lite-client/lite-client -C ton-lite-client-test1.config.json
> runmethod 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd balance
arguments: [ 104128 ]
result: [ 64633878952 ]
...В result mengandungi nilai yang dikembalikan oleh fungsi balance() daripada kontrak pintar kami.
Kami akan melakukan perkara yang sama untuk beberapa kaedah lagi.
> runmethod 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd get_seqno
...
arguments: [ 77871 ]
result: [ 1 ] Mari tanya sejarah pertaruhan anda.
> 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]) ] Kami akan menggunakan lite-client dan mendapatkan kaedah untuk memaparkan maklumat tentang kontrak pintar di tapak.
Memaparkan data kontrak pintar di tapak web
Saya menulis laman web mudah dalam Python untuk memaparkan data daripada kontrak pintar dengan cara yang mudah. Di sini saya tidak akan membincangkannya secara terperinci dan akan menerbitkan laman web ini .
Permintaan kepada TON dibuat daripada Python melalui lite-client. Untuk kemudahan, tapak ini dibungkus dalam Docker dan diterbitkan di Google Cloud. .
Mencuba
Sekarang mari cuba hantar gram ke sana untuk diisi semula . Kami akan menghantar 40 gram. Dan mari buat beberapa pertaruhan untuk kejelasan. Kami melihat bahawa tapak menunjukkan sejarah pertaruhan, peratusan kemenangan semasa dan maklumat berguna yang lain.
bahawa kita menang yang pertama, kalah yang kedua.
afterword
Artikel itu ternyata lebih panjang daripada yang saya jangkakan, mungkin ia mungkin lebih pendek, atau mungkin hanya untuk orang yang tidak tahu apa-apa tentang TON dan mahu menulis dan menerbitkan kontrak pintar yang tidak begitu mudah dengan keupayaan untuk berinteraksi dengan ia. Mungkin beberapa perkara boleh dijelaskan dengan lebih ringkas.
Mungkin beberapa aspek pelaksanaan boleh dilakukan dengan lebih cekap dan elegan, tetapi ia akan mengambil lebih banyak masa untuk menyediakan artikel. Mungkin juga saya membuat kesilapan di suatu tempat atau tidak memahami sesuatu, jadi jika anda melakukan sesuatu yang serius, anda perlu bergantung pada dokumentasi rasmi atau repositori rasmi dengan kod TON.
Perlu diingatkan bahawa memandangkan TON sendiri masih dalam peringkat aktif pembangunan, perubahan mungkin berlaku yang akan memecahkan mana-mana langkah dalam artikel ini (yang berlaku semasa saya menulis, ia telah diperbetulkan), tetapi pendekatan umum adalah tidak mungkin berubah.
Saya tidak akan bercakap tentang masa depan TON. Mungkin platform itu akan menjadi sesuatu yang besar dan kita harus meluangkan masa untuk mengkajinya dan mengisi niche dengan produk kita sekarang.
Terdapat juga Libra dari Facebook, yang mempunyai potensi khalayak pengguna yang lebih besar daripada TON. Saya hampir tidak tahu tentang Libra, berdasarkan forum terdapat lebih banyak aktiviti di sana berbanding komuniti TON. Walaupun pemaju dan komuniti TON lebih seperti bawah tanah, yang juga keren.
rujukan
- Dokumentasi rasmi TON:
- Repositori rasmi TON:
- Dompet rasmi untuk platform yang berbeza:
- Repositori kontrak pintar daripada artikel ini:
- Pautan ke tapak web kontrak pintar:
- Repositori untuk sambungan untuk Kod Visual Studio untuk FunC:
- Sembang tentang TON dalam Telegram, yang sangat membantu untuk mengetahuinya pada peringkat awal. Saya fikir ia tidak akan menjadi satu kesilapan jika saya mengatakan bahawa semua orang yang menulis sesuatu untuk TON ada di sana. Anda juga boleh meminta gram ujian di sana.
- Sembang lain tentang TON yang saya temui maklumat berguna:
- Peringkat pertama pertandingan:
- Peringkat kedua pertandingan:
Sumber: www.habr.com
