Tietoja älykkään sopimuksen kirjoittamisesta ja julkaisemisesta Telegram Open Networkissa (TON)

Tietoja älykkään sopimuksen kirjoittamisesta ja julkaisemisesta TONissa

Mistä tämä artikkeli kertoo?

Artikkelissa puhun siitä, kuinka osallistuin ensimmäiseen (kahdesta) Telegram-lohkoketjukilpailuun, en ottanut palkintoa ja päätin tallentaa kokemukseni artikkeliin, jotta se ei uppoisi unohduksiin ja ehkä auttaisi joku.

Koska en halunnut kirjoittaa abstraktia koodia, vaan tehdä jotain toimivaa, kirjoitin artikkelia varten älykkään sopimuksen pikaarvontaan ja verkkosivustolle, joka näyttää älykkäiden sopimusten tiedot suoraan TON:sta ilman välimuistia.

Artikkeli on hyödyllinen niille, jotka haluavat tehdä ensimmäisen älykkään sopimuksensa TONissa, mutta eivät tiedä mistä aloittaa.

Arpajaisten esimerkkiä käyttäen siirryn ympäristön asentamisesta älysopimuksen julkaisemiseen, sen kanssa vuorovaikutukseen sekä verkkosivuston kirjoittamiseen tietojen vastaanottamista ja julkaisemista varten.

Tietoja kilpailuun osallistumisesta

Viime lokakuussa Telegram julkaisi lohkoketjukilpailun uusilla kielillä Fift и FunC. Oli tarpeen valita kirjoittamisesta mikä tahansa viidestä ehdotetusta älykkäästä sopimuksesta. Ajattelin, että olisi mukavaa tehdä jotain erilaista, opetella kieltä ja tehdä jotain, vaikka minun ei enää tarvitsisikaan kirjoittaa mitään muuta. Lisäksi aihe on jatkuvasti huulilla.

On syytä sanoa, että minulla ei ollut kokemusta älykkäiden sopimusten kehittämisestä.

Ajattelin osallistua loppuun asti, kunnes ehdin, ja sitten kirjoittaa arvosteluartikkelin, mutta epäonnistuin heti ensimmäisessä. minä kirjoitti lompakon moni allekirjoitus päällä FunC ja se yleensä toimi. Otin sen pohjaksi älykäs sopimus Soliditysta.

Tuolloin ajattelin, että tämä riittää varmasti ainakin jonkin palkinnon saamiseen. Tuloksena noin 40 osallistujasta 60:stä tuli palkinnon voittajia, enkä ollut heidän joukossaan. Yleisesti ottaen tässä ei ole mitään vikaa, mutta yksi asia vaivasi minua. Tulosjulkistushetkellä sopimukseni testin tarkistus oli vielä tekemättä, kysyin chatin osallistujilta, onko muita, joilla ei ollut sitä, ei ollut.

Ilmeisesti viesteihini kiinnittäen huomiota, kaksi päivää myöhemmin tuomarit julkaisivat kommentin, enkä edelleenkään ymmärrä, jäikö he vahingossa huomioimatta älykästä sopimustani tuomitsemisen aikana vai vain luulivat sen olevan niin huono, ettei se tarvinnut kommenttia. Esitin kysymyksen sivulla, mutta en saanut vastausta. Vaikka ei olekaan mikään salaisuus, kuka tuomitsi, pidin tarpeettomana kirjoittaa henkilökohtaisia ​​viestejä.

Ymmärtämiseen käytettiin paljon aikaa, joten päätettiin kirjoittaa artikkeli. Koska tietoa ei ole vielä paljon, tämä artikkeli auttaa säästämään aikaa kaikille kiinnostuneille.

Älykkäiden sopimusten käsite TONissa

Ennen kuin kirjoitat mitään, sinun on selvitettävä, kummalta puolelta lähestyä asiaa. Siksi nyt kerron sinulle, mistä osista järjestelmä koostuu. Tarkemmin sanottuna mitkä osat sinun tulee tietää, jotta voit kirjoittaa ainakin jonkinlaisen työsopimuksen.

Keskitymme älykkään sopimuksen kirjoittamiseen ja kanssakäymiseen TON Virtual Machine (TVM), Fift и FunC, joten artikkeli on enemmän kuin kuvaus tavallisen ohjelman kehittämisestä. Emme käsittele tässä sitä, miten alusta itse toimii.

Yleisesti siitä, miten se toimii TVM ja kieli Fift on hyvä virallinen dokumentaatio. Osallistuessani kilpailuun ja nyt nykyistä sopimusta kirjoittaessani käännyin usein hänen puoleen.

Älykkäiden sopimusten pääkieli on FunC. Asiasta ei tällä hetkellä ole dokumentaatiota, joten kirjoittaaksesi jotain sinun on tutkittava esimerkkejä älykkäistä sopimuksista virallisesta arkistosta ja itse kielen toteutusta siellä, sekä voit katsoa esimerkkejä älykkäistä sopimuksista kahdelta viimeiseltä ajalta. kilpailuja. Linkit artikkelin lopussa.

Oletetaan, että olemme jo kirjoittaneet älykkään sopimuksen FunC, sen jälkeen kokoamme koodin Fift-asentajaan.

Koottu älysopimus on vielä julkistamatta. Tätä varten sinun on kirjoitettava sisään funktio Fift, joka ottaa syötteeksi älykkään sopimuskoodin ja joitain muita parametreja, ja tulosteena on tiedosto, jonka pääte .boc (joka tarkoittaa "solupussia"), ja riippuen siitä, miten kirjoitamme, yksityinen avain ja osoite, joka luodaan älykkään sopimuskoodin perusteella. Voit jo lähettää grammoja sellaisen älysopimuksen osoitteeseen, jota ei ole vielä julkaistu.

Julkaista älykäs sopimus TON vastaanotettu .boc tiedosto on lähetettävä lohkoketjuun kevyellä asiakasohjelmalla (lisätietoja alla). Mutta ennen julkaisua sinun on siirrettävä grammat luotuun osoitteeseen, muuten älysopimusta ei julkaista. Julkaisemisen jälkeen voit olla vuorovaikutuksessa älysopimuksen kanssa lähettämällä sille viestejä ulkopuolelta (esimerkiksi kevyellä asiakasohjelmalla) tai sisältä (esim. yksi älysopimus lähettää toiselle viestin TON:n sisällä).

Kun ymmärrämme, kuinka koodi julkaistaan, siitä tulee helpompaa. Tiedämme suunnilleen mitä haluamme kirjoittaa ja kuinka ohjelmamme toimii. Ja kirjoittaessamme etsimme, kuinka tämä on jo toteutettu olemassa olevissa älykkäissä sopimuksissa, tai tutkimme toteutuskoodia Fift и FunC virallisessa arkistossa tai katso virallisesta dokumentaatiosta.

Hyvin usein etsin avainsanoja Telegramin chatista, johon kaikki kilpailun osallistujat ja Telegramin työntekijät kokoontuivat, ja niin tapahtui, että kilpailun aikana kaikki kokoontuivat sinne ja alkoivat keskustella Fiftistä ja FunC:sta. Linkki artikkelin lopussa.

On aika siirtyä teoriasta käytäntöön.

Ympäristön valmistelu TONin kanssa työskentelyä varten

Tein kaiken, mitä MacOS-artikkelissa kuvataan, ja tarkistin sen puhtaassa Ubuntu 18.04 LTS:ssä Dockerissa.

Ensimmäinen asia, joka sinun on tehtävä, on ladata ja asentaa lite-client jolla voit lähettää pyyntöjä TON:lle.

Virallisilla verkkosivuilla olevat ohjeet kuvaavat asennusprosessia melko yksityiskohtaisesti ja selkeästi ja jättävät pois joitakin yksityiskohtia. Tässä noudatamme ohjeita ja asennamme puuttuvat riippuvuudet matkan varrella. En kääntänyt jokaista projektia itse ja asensin virallisesta Ubuntu-arkistosta (käytin MacOS:ssa 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 

Kun kaikki riippuvuudet on asennettu, voit asentaa lite-client, Fift, FunC.

Ensin kloonaamme TON-arkiston ja sen riippuvuudet. Mukavuuden vuoksi teemme kaiken kansiossa ~/TON.

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

Arkisto tallentaa myös toteutukset Fift и FunC.

Nyt olemme valmiita kokoamaan projektin. Arkiston koodi kloonataan kansioon ~/TON/ton. Sisään ~/TON luoda kansion build ja kerätä projekti siihen.

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

Koska aiomme kirjoittaa älykkään sopimuksen, meidän ei tarvitse vain lite-clientMutta Fift с FunC, joten kootaan kaikki. Se ei ole nopea prosessi, joten odotamme.

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

Lataa seuraavaksi määritystiedosto, joka sisältää tiedot solmusta, johon lite-client muodostaa yhteyden.

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

Ensimmäisten pyyntöjen tekeminen TON:lle

Nyt käynnistetään lite-client.

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

Jos rakentaminen onnistui, käynnistämisen jälkeen näet lokin kevyen asiakkaan yhteydestä solmuun.

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

Voit suorittaa komennon help ja katso, mitä komentoja on saatavilla.

help

Listataan komennot, joita käytämme tässä artikkelissa.

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

Nyt olemme valmiita kirjoittamaan itse sopimuksen.

Реализация

Ajatus

Kuten edellä kirjoitin, kirjoittamamme älykäs sopimus on arpajaisia.

Lisäksi tämä ei ole lotto, jossa sinun täytyy ostaa lippu ja odottaa tunti, päivä tai kuukausi, vaan välitön, jossa käyttäjä siirtyy sopimusosoitteeseen N grammaa, ja saa sen heti takaisin 2 * N grammaa tai menettää. Teemme voiton todennäköisyyden noin 40%. Jos grammat eivät riitä maksamiseen, katsomme tapahtuman lisäyksenä.

Lisäksi on tärkeää, että vedot näkyvät reaaliajassa ja kätevässä muodossa, jotta käyttäjä voi heti ymmärtää, voittiko vai hävisikö hän. Siksi sinun on tehtävä verkkosivusto, joka näyttää vedot ja tulokset suoraan TON:lta.

Älykkään sopimuksen kirjoittaminen

Mukavuussyistä olen korostanut FunC:n koodin; laajennus löytyy ja asennetaan Visual Studio Code -haussa; jos haluat yhtäkkiä lisätä jotain, olen tehnyt laajennuksen julkisesti saataville. Lisäksi joku on aiemmin tehnyt laajennuksen Fiftin kanssa työskentelemiseen, voit myös asentaa sen ja löytää sen VSC:stä.

Luodaan välittömästi arkisto, johon sitomme välitulokset.

Elämämme helpottamiseksi kirjoitamme älykkään sopimuksen ja testaamme sitä paikallisesti, kunnes se on valmis. Vasta sen jälkeen julkaisemme sen TONissa.

Älykkäässä sopimuksessa on kaksi ulkoista menetelmää, joihin pääsee käsiksi. Ensimmäinen, recv_external() tämä toiminto suoritetaan, kun sopimuspyyntö tulee ulkopuolelta, eli ei esimerkiksi TON:lta, kun luomme itse viestin ja lähetämme sen lite-asiakkaan kautta. Toinen, recv_internal() tämä on silloin, kun itse TONissa mikä tahansa sopimus viittaa meidän sopimukseen. Molemmissa tapauksissa voit siirtää parametreja funktiolle.

Aloitetaan yksinkertaisella esimerkillä, joka toimii, jos se julkaistaan, mutta siinä ei ole toiminnallista kuormaa.

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

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

Tässä meidän on selitettävä, mikä se on slice. Kaikki TON Blockchainiin tallennetut tiedot ovat kokoelma TVM cell tai yksinkertaisesti cell, tällaiseen soluun voit tallentaa jopa 1023 bittiä tietoa ja enintään 4 linkkiä muihin soluihin.

TVM cell slice tai slice tämä on osa olemassa olevaa cell käytetään sen jäsentämiseen, se selviää myöhemmin. Meille tärkeintä on, että voimme siirtää slice ja käsittele tiedot viestin tyypistä riippuen recv_external() tai recv_internal().

impure — avainsana, joka osoittaa, että toiminto muuttaa älykkäitä sopimustietoja.

Tallennetaan sopimuskoodi sisään lottery-code.fc ja koota.

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

Lippujen merkitys voidaan tarkastella komennolla

~/TON/build/crypto/func -help

Olemme koonneet Fift-asentajakoodin 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

Se voidaan käynnistää paikallisesti, tätä varten valmistelemme ympäristön.

Huomaa, että ensimmäinen rivi yhdistää Asm.fif, tämä on koodi, joka on kirjoitettu Fift-kielellä Fift-asentajalle.

Koska haluamme ajaa ja testata älykästä sopimusta paikallisesti, luomme tiedoston lottery-test-suite.fif ja kopioi käännetty koodi sinne korvaamalla sen viimeisen rivin, joka kirjoittaa älykkään sopimuskoodin vakioon codesiirtääksesi sen sitten virtuaalikoneeseen:

"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

Toistaiseksi näyttää selvältä, nyt lisätään samaan tiedostoon koodi, jota käytämme TVM:n käynnistämiseen.

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 tallennamme kontekstin, eli tiedot, joilla TVM (tai verkon tila) käynnistetään. Jo kilpailun aikana yksi kehittäjistä osoitti kuinka luoda c7 ja kopioin. Tässä artikkelissa saatamme joutua muuttamaan rand_seed koska satunnaisluvun luominen riippuu siitä ja jos sitä ei muuteta, sama numero palautetaan joka kerta.

recv_internal и recv_external vakiot arvoilla 0 ja -1 vastaavat vastaavien funktioiden kutsumisesta älykkäässä sopimuksessa.

Nyt olemme valmiita luomaan ensimmäisen testin tyhjälle älysopimuksellemme. Selvyyden vuoksi lisäämme toistaiseksi kaikki testit samaan tiedostoon lottery-test-suite.fif.

Luodaan muuttuja storage ja kirjoita siihen tyhjä cell, tämä on älykäs sopimustallennus.

message Tämä on viesti, jonka välitämme älykkäälle kontaktille ulkopuolelta. Teemme sen myös toistaiseksi tyhjäksi.

variable storage 
<b b> storage ! 

variable message 
<b b> message ! 

Kun vakiot ja muuttujat on valmisteltu, käynnistämme TVM:n komennolla runvmctx ja välitä luodut parametrit tuloon.

message @ 
recv_external 
code 
storage @ 
c7 
runvmctx 

Lopulta onnistumme niin välikoodi Fift.

Nyt voimme suorittaa tuloksena olevan koodin.

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

Ohjelman pitäisi toimia ilman virheitä ja lähdössä näemme suorituslokin:

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

Hienoa, olemme kirjoittaneet älysopimuksen ensimmäisen toimivan version.

Nyt meidän on lisättävä toimintoja. Ensin käsitellään viestejä, jotka tulevat ulkomaailmasta recv_external()

Kehittäjä itse valitsee viestin muodon, jonka sopimus voi hyväksyä.

Mutta yleensä

  • Ensinnäkin haluamme suojata sopimustamme ulkomaailmalta ja tehdä siitä niin, että vain sopimuksen omistaja voi lähettää sille ulkoisia viestejä.
  • toiseksi, kun lähetämme kelvollisen viestin TON:lle, haluamme tämän tapahtuvan täsmälleen kerran ja kun lähetämme saman viestin uudelleen, älykäs sopimus hylkää sen.

Joten lähes jokainen sopimus ratkaisee nämä kaksi ongelmaa, koska sopimuksemme hyväksyy ulkopuoliset viestit, meidän on myös huolehdittava siitä.

Teemme sen käänteisessä järjestyksessä. Ensin ratkaistaan ​​ongelma toistolla; jos sopimus on jo vastaanottanut tällaisen viestin ja käsitellyt sen, se ei suorita sitä toista kertaa. Ja sitten ratkaisemme ongelman niin, että vain tietty joukko ihmisiä voi lähettää viestejä älysopimukseen.

On olemassa erilaisia ​​tapoja ratkaista ongelma päällekkäisten viestien kanssa. Näin teemme sen. Älykkäässä sopimuksessa alustamme vastaanotettujen viestien laskurin alkuarvolla 0. Jokaiseen älykkään sopimuksen viestiin lisäämme nykyisen laskurin arvon. Jos sanoman laskurin arvo ei vastaa älykkään sopimuksen arvoa, emme käsittele sitä; jos on, käsittelemme sen ja nostamme älysopimuksen laskuria yhdellä.

Palaamme kohteeseen lottery-test-suite.fif ja lisää siihen toinen testi. Jos lähetämme väärän numeron, koodin pitäisi tehdä poikkeus. Esimerkiksi, anna sopimustietojen tallentaa 166, niin lähetämme 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"

Aloitetaan.

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

Ja näemme, että testi suoritetaan virheellä.

[ 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

Tässä vaiheessa lottery-test-suite.fif pitäisi näyttää по ссылке.

Lisätään nyt vastalogiikka älykkääseen sopimukseen 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 on lähettämämme viesti.

Ensimmäinen asia, jonka teemme, on tarkistaa, sisältääkö viesti dataa, jos ei, niin poistumme.

Seuraavaksi jäsennämme viestin. in_msg~load_uint(32) lataa numeron 165, 32-bittinen unsigned int lähetetystä viestistä.

Seuraavaksi lataamme 32 bittiä älykkäästä sopimusvarastosta. Tarkistamme, että ladattu numero vastaa ohitettua numeroa; jos ei, teemme poikkeuksen. Meidän tapauksessamme, koska ohitamme ei-ottelun, pitäisi tehdä poikkeus.

Nyt kootaan.

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

Kopioi tuloksena oleva koodi kohteeseen lottery-test-suite.fif, unohtamatta korvata viimeistä riviä.

Tarkistamme, että testi läpäisee:

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

Täällä Näet vastaavan sitoumuksen nykyisten tulosten kanssa.

Huomaa, että älysopimuksen käännetty koodi on hankalaa jatkuvasti kopioida tiedostoon testeillä, joten kirjoitamme komentosarjan, joka kirjoittaa koodin vakioksi meille ja yhdistämme käännetyn koodin testeihimme käyttämällä "include".

Luo tiedosto projektikansioon build.sh seuraavalla sisällöllä.

#!/bin/bash

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

Tehdään siitä suoritettava.

chmod +x ./build.sh

Suorita nyt vain komentosarjamme laatiaksesi sopimus. Mutta tämän lisäksi meidän on kirjoitettava se vakioksi code. Joten luomme uuden tiedoston lotter-compiled-for-test.fif, jonka sisällytämme tiedostoon lottery-test-suite.fif.

Lisätään skirpt-koodi sh:hon, joka yksinkertaisesti kopioi käännetyn tiedoston lotter-compiled-for-test.fif ja muuta sen viimeistä riviä.

# 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

Suoritetaan nyt tuloksena oleva komentosarja tarkistaaksesi, ja tiedosto luodaan lottery-compiled-for-test.fif, jonka sisällytämme omaan lottery-test-suite.fif

В lottery-test-suite.fif poista sopimuskoodi ja lisää rivi "lottery-compiled-for-test.fif" include.

Suoritamme testejä varmistaaksemme, että ne läpäisevät.

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

Hienoa, nyt automatisoidaksesi testien käynnistämisen, luodaan tiedosto test.sh, joka suoritetaan ensin build.shja suorita sitten testit.

touch test.sh
chmod +x test.sh

Kirjoitamme sisällä

./build.sh 

echo "nCompilation completedn"

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

Tehdään test.sh ja suorita se varmistaaksesi, että testit toimivat.

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

Tarkistamme, että sopimus kootaan ja testit suoritetaan.

Hienoa, nyt käynnistyy test.sh Testit kootaan ja suoritetaan välittömästi. Tässä linkki kohteeseen tehdä.

Okei, ennen kuin jatkamme, tehdään vielä yksi asia mukavuuden vuoksi.

Luodaan kansio build johon tallennamme kopioidun sopimuksen ja sen kloonin, joka on kirjoitettu vakioksi lottery-compiled.fif, lottery-compiled-for-test.fif. Luodaan myös kansio test mihin testitiedosto tallennetaan? lottery-test-suite.fif ja mahdollisesti muita tukitiedostoja. Linkki asiaankuuluviin muutoksiin.

Jatketaan älysopimuksen kehittämistä.

Seuraavaksi pitäisi tehdä testi, joka tarkistaa, että viesti on vastaanotettu ja laskuri päivittyy myymälässä, kun lähetämme oikean numeron. Mutta teemme sen myöhemmin.

Mietitään nyt, mikä tietorakenne ja mitä tietoja älysopimukseen pitää tallentaa.

Kuvailen kaiken, mitä varastoimme.

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

Seuraavaksi sinun on kirjoitettava kaksi funktiota. Soitetaan ensimmäiselle pack_state(), joka pakkaa tiedot myöhempää tallennusta varten älykkään sopimustallennustilaan. Soitetaan toiselle unpack_state() lukee ja palauttaa tietoja tallennustilasta.

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

Lisäämme nämä kaksi toimintoa älykkään sopimuksen alkuun. Se selviää niin välitulos.

Tietojen tallentamiseksi sinun on kutsuttava sisäänrakennettu toiminto set_data() ja se kirjoittaa tietoja pack_state() älykkäässä sopimusvarastossa.

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

Nyt kun meillä on käteviä toimintoja tietojen kirjoittamiseen ja lukemiseen, voimme siirtyä eteenpäin.

Meidän on tarkistettava, että ulkopuolelta tuleva viesti on sopimuksen omistajan (tai muun käyttäjän, jolla on pääsy yksityiseen avaimeen) allekirjoittama.

Kun julkaisemme älysopimuksen, voimme alustaa sen tarvitsemillamme tiedoilla, jotka tallennetaan tulevaa käyttöä varten. Tallennamme julkisen avaimen sinne, jotta voimme varmistaa, että saapuva viesti on allekirjoitettu vastaavalla yksityisellä avaimella.

Ennen kuin jatkat, luodaan yksityinen avain ja kirjoitetaan se siihen test/keys/owner.pk. Tehdään tämä käynnistämällä Fift interaktiivisessa tilassa ja suorittamalla neljä komentoa.

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

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

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

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

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

Luodaan kansio keys kansion sisällä test ja kirjoita yksityinen avain sinne.

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

Näemme tiedoston nykyisessä kansiossa owner.pk.

Poistamme julkisen avaimen pinosta ja saamme sen tarvittaessa yksityisestä.

Nyt meidän on kirjoitettava allekirjoituksen vahvistus. Aloitetaan testistä. Ensin luemme yksityisen avaimen tiedostosta funktiolla file>B ja kirjoita se muuttujaan owner_private_key, ja käytä sitten toimintoa priv>pub Muunna yksityinen avain julkiseksi avaimeksi ja kirjoita tulos sisään 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 !

Tarvitsemme molemmat avaimet.

Alustamme älykkään sopimustallennustilan mielivaltaisilla tiedoilla samassa järjestyksessä kuin funktiossa pack_state()ja kirjoita se muuttujaan 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 !

Seuraavaksi kirjoitamme allekirjoitetun viestin, joka sisältää vain allekirjoituksen ja laskurin arvon.

Ensin luomme tiedot, jotka haluamme lähettää, sitten allekirjoitamme sen yksityisellä avaimella ja lopuksi luomme allekirjoitetun viestin.

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 !  

Tämän seurauksena viesti, jonka lähetämme älysopimukseen, tallennetaan muuttujaan message_to_send, toiminnoista hashu, ed25519_sign_uint osaa lukea Fift-dokumentaatiossa.

Ja suorittaaksesi testin soitamme uudelleen.

message_to_send @ 
recv_external 
code 
storage @
c7
runvmctx

näin Testejä sisältävän tiedoston pitäisi näyttää tässä vaiheessa tältä.

Suoritetaan testi ja se epäonnistuu, joten muutamme älykästä sopimusta niin, että se voi vastaanottaa tämän muotoisia viestejä ja vahvistaa allekirjoituksen.

Ensin lasketaan 512 bittiä allekirjoitusta viestistä ja kirjoitetaan se muuttujaan, sitten lasketaan 32 bittiä laskurimuuttujaa.

Koska meillä on toiminto tietojen lukemiseen älykkäiden sopimusten tallennustilasta, käytämme sitä.

Seuraavaksi tarkistetaan tallennustilan mukana siirretty laskuri ja tarkistetaan allekirjoitus. Jos jokin ei täsmää, teemme poikkeuksen sopivalla koodilla.

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

Asiaankuuluva sitoumus täällä.

Suoritetaan testit ja katsotaan, että toinen testi epäonnistuu. Kahdesta syystä viestissä ei ole tarpeeksi bittejä ja muistissa ei ole tarpeeksi bittejä, joten koodi kaatuu jäsennettäessä. Meidän on lisättävä allekirjoitus lähetettävään viestiin ja kopioitava tallennustila edellisestä testistä.

Toisessa testissä lisäämme viestin allekirjoituksen ja muutamme älykkään sopimuksen tallennustilaa. näin testitiedosto näyttää tällä hetkellä tältä.

Kirjoitetaan neljäs testi, jossa lähetämme jonkun toisen yksityisellä avaimella allekirjoitetun viestin. Luodaan toinen yksityinen avain ja tallennetaan se tiedostoon not-owner.pk. Allekirjoitamme viestin tällä yksityisellä avaimella. Suoritetaan testit ja varmistetaan, että kaikki testit läpäisevät. Tehdä tällä hetkellä.

Nyt voimme vihdoin siirtyä älykkään sopimuslogiikan toteuttamiseen.
В recv_external() otamme vastaan ​​kahdenlaisia ​​viestejä.

Koska sopimukseemme kertyy pelaajien tappioita, nämä rahat on siirrettävä loton tekijälle. Arpajaisten luojan lompakko-osoite kirjataan varastoon sopimusta laadittaessa.

Varmuuden vuoksi tarvitsemme mahdollisuuden muuttaa osoitetta, johon lähetämme häviäjien grammat. Meidän pitäisi myös pystyä lähettämään grammoja lotosta omistajan osoitteeseen.

Aloitetaan ensimmäisestä. Kirjoitetaan ensin testi, joka tarkistaa, että älysopimus on tallentanut uuden osoitteen muistiin viestin lähettämisen jälkeen. Huomaa, että viestissä välitämme laskurin ja uuden osoitteen lisäksi myös action 7-bittinen kokonaisluku ei-negatiivinen luku, siitä riippuen valitsemme kuinka viesti käsitellään älysopimuksessa.

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

Testissä näet kuinka smartcontract-tallennus sarjoitetaan storage Fiftissä. Muuttujien sarjoittaminen on kuvattu Fift-dokumentaatiossa.

Sitouta linkki lisätyn taikinan kanssa.

Suoritetaan testi ja varmistetaan, että se epäonnistuu. Lisätään nyt logiikka lotto-omistajan osoitteen muuttamiseen.

Älykkäässä sopimuksessa jatkamme jäsentämistä message, lue sisään action. Muistutetaan, että meillä on kaksi action: vaihda osoite ja lähetä grammoja.

Sitten luemme sopimusomistajan uuden osoitteen ja tallennamme sen varastoon.
Suoritamme testit ja näemme, että kolmas testi epäonnistuu. Se kaatuu johtuen siitä, että sopimus jäsentää nyt lisäksi 7 bittiä viestistä, jotka puuttuvat testistä. Lisää viestiin olematon action. Suoritetaan testit ja katsotaan, että kaikki menee läpi. Täällä sitoutua muutoksiin. Loistava.

Kirjoita nyt logiikka määritetyn grammamäärän lähettämiseksi aiemmin tallennettuun osoitteeseen.

Ensin kirjoitetaan testi. Kirjoitamme kaksi testiä, yhden kun tasapaino ei ole tarpeeksi, toisen kun kaiken pitäisi läpäistä onnistuneesti. Testit ovat katsottavissa tässä sitoumuksessa.

Lisätään nyt koodi. Ensin kirjoitetaan kaksi apumenetelmää. Ensimmäinen hakumenetelmä on selvittää älykkään sopimuksen nykyinen saldo.

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

Ja toinen on tarkoitettu grammojen lähettämiseen toiseen älysopimukseen. Kopioin tämän menetelmän kokonaan toisesta älykkäästä sopimuksesta.

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

Lisätään nämä kaksi menetelmää älykkääseen sopimukseen ja kirjoitetaan logiikka. Ensin jäsennämme grammamäärän viestistä. Seuraavaksi tarkastetaan saldo, jos se ei riitä, teemme poikkeuksen. Jos kaikki on kunnossa, lähetämme grammat tallennettuun osoitteeseen ja päivitämme laskurin.

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

näin näyttää älykkäältä sopimukselta tällä hetkellä. Suoritetaan testit ja varmistetaan, että ne läpäisevät.

Älysopimuksesta muuten vähennetään provisio joka kerta käsitellystä viestistä. Jotta älykkäät sopimusviestit voivat suorittaa pyynnön, sinun on soitettava perustarkistusten jälkeen accept_message().

Siirrytään nyt sisäisiin viesteihin. Itse asiassa hyväksymme vain grammoja ja lähetämme takaisin kaksinkertaisen summan pelaajalle, jos hän voittaa, ja kolmanneksen omistajalle, jos hän häviää.

Ensin kirjoitetaan yksinkertainen testi. Tätä varten tarvitsemme älysopimuksen testiosoitteen, josta oletettavasti lähetämme grammoja älysopimukseen.

Älykäs sopimusosoite koostuu kahdesta numerosta, 32-bittisestä kokonaisluvusta, joka vastaa työketjusta, ja 256-bittisestä ei-negatiivinen kokonaisluku yksilöllinen tilinumero tässä työketjussa. Esimerkiksi -1 ja 12345, tämä on osoite, jonka tallennamme tiedostoon.

Kopioin osoitteen tallennustoiminnon 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

Katsotaanpa, miten toiminto toimii, tämä antaa käsityksen siitä, kuinka Fift toimii. Käynnistä Fift interaktiivisessa tilassa.

~/TON/build/crypto/fift -i 

Ensin työnnetään -1, 12345 ja tulevan tiedoston nimi "sender.addr" pinoon:

-1 12345 "sender.addr" 

Seuraava vaihe on toiminnon suorittaminen -rot, joka siirtää pinoa siten, että pinon yläosassa on yksilöllinen älykäs sopimusnumero:

"sender.addr" -1 12345

256 u>B muuntaa 256-bittisen ei-negatiivisen kokonaisluvun tavuiksi.

"sender.addr" -1 BYTES:0000000000000000000000000000000000000000000000000000000000003039

swap vaihtaa pinon kaksi ylintä elementtiä.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 -1

32 i>B muuntaa 32-bittisen kokonaisluvun tavuiksi.

"sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039 BYTES:FFFFFFFF

B+ yhdistää kaksi tavusarjaa.

 "sender.addr" BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF

uudelleen swap.

BYTES:0000000000000000000000000000000000000000000000000000000000003039FFFFFFFF "sender.addr" 

Ja lopuksi tavut kirjoitetaan tiedostoon B>file. Tämän jälkeen pinomme on tyhjä. Pysähdymme Fift. Nykyiseen kansioon on luotu tiedosto sender.addr. Siirretään tiedosto luotuun kansioon test/addresses/.

Kirjoitetaan yksinkertainen testi, joka lähettää grammoja älykkääseen sopimukseen. Tässä on sitoumus.

Katsotaanpa nyt arpajaisten logiikkaa.

Ensimmäinen asia, jonka teemme, on tarkistaa viesti bounced tai ei jos bounced, jätämme sen huomiotta. bounced tarkoittaa, että sopimus palauttaa grammoja, jos jokin virhe tapahtuu. Emme palauta grammoja, jos yhtäkkiä tapahtuu virhe.

Tarkistamme, jos saldo on alle puoli grammaa, niin hyväksymme viestin ja jätämme sen huomiotta.

Seuraavaksi jäsennämme sen älykkään sopimuksen osoitteen, josta viesti tuli.

Luemme tiedot tallennustilasta ja poistamme sitten vanhat vedot historiasta, jos niitä on yli kaksikymmentä. Mukavuuden vuoksi kirjoitin kolme lisätoimintoa pack_order(), unpack_order(), remove_old_orders().

Seuraavaksi katsomme, jos saldo ei riitä maksuun, niin katsomme, että tämä ei ole veto, vaan täydennys ja tallenna täydennys orders.

Sitten lopulta älykkään sopimuksen ydin.

Ensin, jos pelaaja häviää, tallennamme sen vedonlyöntihistoriaan ja jos summa on yli 3 grammaa, lähetämme 1/3 älysopimuksen omistajalle.

Jos pelaaja voittaa, lähetämme kaksinkertaisen summan pelaajan osoitteeseen ja tallennamme vedon tiedot historiaan.

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

Siinä kaikki. Vastaava sitoumus.

Nyt ei jää muuta kuin yksinkertaista, luodaan get-metodeja, jotta voimme saada tietoa sopimuksen tilasta ulkopuolelta (itse asiassa lukea tiedot heidän älykkäästä sopimusvarastosta).

Lisätään vielä hakumenetelmät. Kirjoitamme alla kuinka saada tietoa älykkäästä sopimuksesta.

Unohdin myös lisätä koodin, joka käsittelee aivan ensimmäisen älysopimuksen julkaisemisen yhteydessä esiintyvän pyynnön. Vastaava sitoumus. Ja kauemmas korjattu virhe lähettää 1/3 summasta omistajan tilille.

Seuraava askel on julkaista älykäs sopimus. Luodaan kansio requests.

Otin lähtökohtana julkaisukoodin simple-wallet-code.fc который voi löytää virallisessa arkistossa.

Jotain, johon kannattaa kiinnittää huomiota. Luomme älykkään sopimusvaraston ja syöttöviestin. Tämän jälkeen luodaan älysopimuksen osoite, eli osoite tiedetään jo ennen TON-julkaisua. Seuraavaksi sinun on lähetettävä useita grammoja tähän osoitteeseen ja vasta sen jälkeen sinun on lähetettävä tiedosto itse älykkäällä sopimuksella, koska verkko ottaa palkkion älykkään sopimuksen ja toimintojen tallentamisesta siihen (validaattorit, jotka tallentavat ja suorittavat älykkään sopimuksen sopimukset). Koodi on katsottavissa täältä.

Seuraavaksi suoritamme julkaisukoodin ja saamme lottery-query.boc älykäs sopimustiedosto ja osoite.

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

Muista tallentaa luodut tiedostot: lottery-query.boc, lottery.addr, lottery.pk.

Näemme muun muassa älysopimuksen osoitteen toteutuslokeissa.

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

Tehdään TONille pyyntö huvin vuoksi

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

Ja näemme, että tili tällä osoitteella on tyhjä.

account state is empty

Lähetämme osoitteeseen 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd 2 grammaa ja muutaman sekunnin kuluttua suoritamme saman komennon. Käytän grammojen lähettämiseen virallinen lompakko, ja voit pyytää joltakin chatista testigrammaa, josta puhun artikkelin lopussa.

> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Näyttää alustamattomalta (state:account_uninit) älykäs sopimus, jolla on sama osoite ja jonka saldo on 1 000 000 000 nanogrammaa.

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

Nyt julkaistaan ​​älykäs sopimus. Käynnistetään lite-client ja suoritetaan.

> 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 

Tarkastetaan, että sopimus on julkaistu.

> last
> getaccount 0QAESRAUnb6vjq27KyhyLn1qLcbiZOwvHZvr1vsgkHm8Ksyd

Muun muassa saamme.

  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

Näemme sen account_active.

Vastaava sitoumus muutoksineen täällä.

Luodaan nyt pyyntöjä ollakseen vuorovaikutuksessa älykkään sopimuksen kanssa.

Tarkemmin sanottuna jätämme ensimmäisen osoitteenmuutoksen itsenäiseksi työksi ja toisen teemme grammojen lähettämiseen omistajan osoitteeseen. Itse asiassa meidän on tehtävä sama asia kuin grammojen lähetystestissä.

Tämä on viesti, jonka lähetämme älysopimukseen, missä msg_seqno 165, action 2 ja 9.5 grammaa lähetettäväksi.

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

Muista allekirjoittaa viesti yksityisellä avaimellasi lottery.pk, joka luotiin aiemmin älykästä sopimusta luotaessa. Tässä on vastaava sitoumus.

Tietojen vastaanottaminen älykkäästä sopimuksesta hakumenetelmillä

Katsotaanpa nyt, kuinka älykkäiden sopimusten hakumenetelmiä käytetään.

Tuoda markkinoille lite-client ja suorita kirjoittamamme hakumenetelmät.

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

В result sisältää arvon, jonka funktio palauttaa balance() älykkäästä sopimuksestamme.
Teemme samoin useille muille menetelmille.

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

Kysytään vetohistoriaasi.

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

Käytämme lite-asiakasta ja hankimme menetelmiä älysopimuksen tietojen näyttämiseen sivustolla.

Älykkäiden sopimustietojen näyttäminen verkkosivustolla

Kirjoitin yksinkertaisen verkkosivuston Pythonissa näyttääkseni älysopimuksen tiedot kätevästi. Tässä en käsittele sitä yksityiskohtaisesti ja julkaisen sivuston yhdessä sitoumuksessa.

Pyynnöt TON:lle tehdään Python kautta lite-client. Mukavuuden vuoksi sivusto on pakattu Dockeriin ja julkaistu Google Cloudissa. Linkki.

Yritetään

Yritetään nyt lähettää grammoja sinne täydennystä varten kukkaro. Lähetämme 40 grammaa. Ja tehdään pari vetoa selvyyden vuoksi. Näemme, että sivusto näyttää vetohistorian, nykyisen voittoprosentin ja muuta hyödyllistä tietoa.

Me näemmeettä voitimme ensimmäisen, hävisimme toisen.

loppusanat

Artikkeli osoittautui paljon pidemmäksi kuin odotin, ehkä se olisi voinut olla lyhyempi, tai ehkä vain henkilölle, joka ei tiedä mitään TONista ja haluaa kirjoittaa ja julkaista ei-niin yksinkertaisen älykkään sopimuksen, jolla on mahdollisuus olla vuorovaikutuksessa se. Ehkä jotkut asiat olisi voitu selittää yksinkertaisemmin.

Ehkä jotkut toteutuksen osa-alueet olisi voitu tehdä tehokkaammin ja tyylikkäämmin, mutta silloin artikkelin valmistelu olisi vienyt vielä enemmän aikaa. On myös mahdollista, että tein virheen jossain tai en ymmärtänyt jotain, joten jos teet jotain vakavaa, sinun on luotettava viralliseen dokumentaatioon tai viralliseen arkistoon TON-koodilla.

On huomattava, että koska TON itse on vielä aktiivisessa kehitysvaiheessa, saattaa tapahtua muutoksia, jotka rikkovat minkä tahansa tämän artikkelin vaiheista (joka tapahtui kirjoittaessani, se on jo korjattu), mutta yleinen lähestymistapa on tuskin muuttuu.

En puhu TONin tulevaisuudesta. Ehkä alustasta tulee jotain suurta ja meidän pitäisi käyttää aikaa sen tutkimiseen ja täyttää markkinarako tuotteillamme nyt.

Facebookista löytyy myös Libra, jonka potentiaalinen yleisö on suurempi kuin TON. En tiedä Librasta juuri mitään, foorumin perusteella siellä on paljon enemmän toimintaa kuin TON-yhteisössä. Vaikka TONin kehittäjät ja yhteisö ovat enemmän kuin maanalaisia, mikä on myös siistiä.

viittaukset

  1. Virallinen TON-dokumentaatio: https://test.ton.org
  2. Virallinen TON-arkisto: https://github.com/ton-blockchain/ton
  3. Virallinen lompakko eri alustoille: https://wallet.ton.org
  4. Älykäs sopimusvarasto tästä artikkelista: https://github.com/raiym/astonished
  5. Linkki älykkäiden sopimusten verkkosivustolle: https://ton-lottery.appspot.com
  6. Visual Studio Code for FunC -laajennuksen arkisto: https://github.com/raiym/func-visual-studio-plugin
  7. Keskustele TONista Telegramissa, mikä todella auttoi sen ymmärtämisessä alkuvaiheessa. Mielestäni ei ole virhe, jos sanon, että kaikki, jotka kirjoittivat jotain TONille, ovat siellä. Voit myös kysyä testigrammoja sieltä. https://t.me/tondev_ru
  8. Toinen TON-keskustelu, josta löysin hyödyllistä tietoa: https://t.me/TONgramDev
  9. Kilpailun ensimmäinen vaihe: https://contest.com/blockchain
  10. Kilpailun toinen vaihe: https://contest.com/blockchain-2

Lähde: will.com

Lisää kommentti