ProHoster > Blog > Uprava > Preizkusite odjemalca TON (Telegram Open Network) in nov jezik Fift za pametne pogodbe
Preizkusite odjemalca TON (Telegram Open Network) in nov jezik Fift za pametne pogodbe
Pred več kot enim letom je postalo znano o načrtih messengerja Telegram za izdajo lastnega decentraliziranega omrežja Odprite omrežni telegram. Nato je postal na voljo obsežen tehnični dokument, ki naj bi ga napisal Nikolaj Durov in opisal strukturo prihodnjega omrežja. Za tiste, ki ste zamudili, priporočam, da preberete mojo pripoved tega dokumenta (Del 1, Del 2; tretji del, žal, še vedno nabira prah v osnutkih).
Od takrat ni bilo nobenih pomembnih novic o statusu razvoja TON do pred nekaj dnevi (v enem od neuradni kanali) se povezava do strani ni prikazala https://test.ton.org/download.html, kjer se nahajajo:
◦ ton-test-liteclient-full.tar.xz — viri lahkega odjemalca za testno omrežje TON;
◦ ton-lite-client-test1.config.json — konfiguracijska datoteka za povezavo s testnim omrežjem;
◦ README — informacije o izgradnji in zagonu stranke;
◦ KAKO — navodila po korakih za ustvarjanje pametne pogodbe z uporabo odjemalca;
◦ ton.pdf — posodobljen dokument (z dne 2) s tehničnim pregledom omrežja TON;
◦ tvm.pdf — tehnični opis TVM (TON Virtual Machine, TON virtualni stroj);
◦ tblkch.pdf — tehnični opis verige blokov TON;
◦ fifthbase.pdf — opis novega jezika Fift, zasnovanega za ustvarjanje pametnih pogodb v TON.
Ponavljam, uradne potrditve strani in vseh teh dokumentov iz Telegrama ni bilo, vendar je obseg teh materialov precej verjeten. Zaženite objavljenega odjemalca na lastno odgovornost.
Izdelava testnega odjemalca
Najprej poskusimo zgraditi in zagnati testnega odjemalca – na srečo, README podrobno opisuje ta preprost postopek. To bom naredil z uporabo macOS 10.14.5 kot primera; ne morem jamčiti za uspeh gradnje na drugih sistemih.
Prenesite in razpakirajte izvorni arhiv. Pomembno je, da prenesete najnovejšo različico, saj združljivost s prejšnjimi različicami na tej stopnji ni zagotovljena.
Prepričajte se, da so v sistemu nameščene najnovejše različice make, cmake (različica 3.0.2 ali novejša), OpenSSL (vključno z datotekami glave C), g++ ali clang. Ničesar mi ni bilo treba namestiti, vse se je takoj združilo.
Predpostavimo, da so viri razpakirani v mapo ~/lite-client. Ločeno od nje ustvarite prazno mapo za sestavljen projekt (npr. ~/liteclient-build), in iz njega (cd ~/liteclient-build) pokličite ukaze:
Če je vse narejeno pravilno, bi morali videti nekaj takega:
Kot lahko vidimo, je na voljo nekaj ukazov:
◦ help — prikaz tega seznama ukazov;
◦ quit - Pojdi ven;
◦ time — prikaz trenutnega časa na strežniku;
◦ status — prikaz povezave in stanja lokalne baze podatkov;
◦ last — posodobite stanje verige blokov (prenesite zadnji blok). Pomembno je, da zaženete ta ukaz pred kakršnimi koli zahtevami, da se prepričate, ali vidite trenutno stanje omrežja.
◦ sendfile<filename> — naložite lokalno datoteko v omrežje TON. Tako pride do interakcije z omrežjem – vključno z na primer ustvarjanjem novih pametnih pogodb in zahtev za prenos sredstev med računi;
◦ getaccount<address> — prikaži trenutno (v času, ko je bil ukaz izveden) last) stanje računa z navedenim naslovom;
◦ privkey<filename> — naloži zasebni ključ iz lokalne datoteke.
Če ob zagonu odjemalca vanj prenesete mapo z možnostjo -D, potem bo vanj dodal zadnji blok glavne verige:
Zdaj lahko preidemo na bolj zanimive stvari - naučite se jezika Fift, poskusite sestaviti pametno pogodbo (na primer ustvarite testno denarnico), jo naložite v omrežje in poskusite prenašati sredstva med računi.
Jezik peti
Iz dokumenta fifthbase.pdf ugotovite lahko, da je ekipa Telegrama ustvarila nov jezik sklada za ustvarjanje pametnih pogodb Petica (očitno iz številke peti, podobno kot Forth, jezik, s katerim ima Fifth veliko skupnega).
Dokument je precej obsežen, 87 strani, in njegove vsebine v okviru tega članka ne bom podrobno pripovedoval (vsaj zato, ker ga sam še nisem prebral :). Osredotočil se bom na glavne točke in podal nekaj primerov kode v tem jeziku.
Na osnovni ravni je sintaksa Fifta precej preprosta: koda je sestavljena iz besede, običajno ločeni s presledki ali prelomi vrstic (poseben primer: nekatere besede za seboj ne potrebujejo ločila). Kaj slovo je zaporedje znakov, ki razlikuje med velikimi in malimi črkami, ki ustreza določenemu določitev (približno, kaj naj naredi tolmač, ko naleti na to besedo). Če definicije besede ni, jo poskuša tolmač razčleniti kot število in dati na sklad. Mimogrede, številke so - nenadoma - 257-bitna cela števila in sploh ni ulomkov - natančneje, takoj se spremenijo v par celih števil, ki tvorita števec in imenovalec racionalnega ulomka.
Besede se nagibajo k interakciji z vrednostmi na vrhu sklada. Ločena vrsta besed - predpono — ne uporablja sklada, ampak naslednje znake iz izvorne datoteke. Tako so na primer implementirani nizovni literali - znak narekovaja (") je beseda s predpono, ki išče naslednji (zaključni) narekovaj in potisne niz med njimi na sklad. Enovrstičnice se obnašajo na enak način (//) in večvrstični (/*) komentarji.
Tu se konča skoraj celotna notranja zgradba jezika. Vse ostalo (vključno s kontrolnimi konstrukti) je definirano kot besede (bodisi interne, kot so aritmetične operacije in definicija novih besed; bodisi definirane v "standardni knjižnici" Fift.fif, ki je v mapi crypto/fift v virih).
Preprost primer programa v Fiftu:
{ dup =: x dup * =: y } : setxy
3 setxy x . y . x y + .
7 setxy x . y . x y + .
Prva vrstica določa novo besedo setxy (upoštevajte predpono {, ki ustvari blok pred zaključnim } in predpono :, ki pravzaprav definira besedo). setxy vzame številko z vrha sklada, jo definira (ali na novo definira) kot globalno konstantnax, kvadrat tega števila pa kot konstanto y (Glede na to, da je mogoče vrednosti konstant na novo definirati, bi jih raje imenoval spremenljivke, vendar sledim konvenciji poimenovanja v jeziku).
Naslednji dve vrstici postavita številko na sklad in kličeta setxy, potem se prikažejo vrednosti konstant x, y (beseda se uporablja za izpis .), se obe konstanti postavita na sklad, seštejeta in rezultat se prav tako natisne. Kot rezultat bomo videli:
3 9 12 ok
7 49 56 ok
(Vrstico »ok« natisne tolmač, ko konča obdelavo trenutne vrstice v interaktivnem načinu vnosa)
Ta strašljivo videti datoteka je namenjena ustvarjanju pametne pogodbe - postavljena bo v datoteko new-wallet-query.boc po izvršitvi. Upoštevajte, da se tukaj uporablja drug zbirni jezik za virtualni stroj TON (ne bom se podrobneje osredotočal nanj), katerega navodila bodo nameščena v verigi blokov.
Tako je asembler za TVM napisan v Fiftu - izvorni kodi tega asemblerja so v datoteki crypto/fift/Asm.fif in sta povezana na začetku zgornjega dela kode.
Kaj naj rečem, očitno Nikolaj Durov obožuje ustvarjanje novih programskih jezikov :)
Ustvarjanje pametne pogodbe in interakcija s TON
Torej, predpostavimo, da smo sestavili odjemalca TON in tolmača Fift, kot je opisano zgoraj, in se seznanili z jezikom. Kako zdaj ustvariti pametno pogodbo? To je opisano v datoteki KAKO, v prilogi virov.
Računi v TON
Kot sem opisal v TON pregled, to omrežje vsebuje več kot eno verigo blokov – obstaja ena skupna, tako imenovana. "glavna veriga", kot tudi poljubno število dodatnih "delovnih verig", označenih z 32-bitnim številom. Glavna veriga ima identifikator -1, poleg nje pa se lahko uporablja tudi "osnovna" delovna veriga z identifikatorjem 0. Vsaka delovna veriga ima lahko svojo konfiguracijo. Notranje je vsaka delovna veriga razdeljena na verige drobcev, vendar je to podrobnost izvedbe, ki je ni treba upoštevati.
Znotraj ene delovne verige je shranjenih veliko računov, ki imajo lastne identifikatorje account_id. Za glavno verigo in verigo ničelnega dela sta dolgi 256 bitov. Tako je identifikator računa zapisan na primer takole:
To je »surova« oblika: najprej ID delovne verige, nato dvopičje in ID računa v šestnajstiškem zapisu.
Poleg tega obstaja skrajšan format - številka delovne verige in naslov računa sta kodirana v binarni obliki, dodana jima je kontrolna vsota in vse to je kodirano v Base64:
Ef+BVndbeTJeXWLnQtm5bDC2UVpc0vH2TF2ksZPAPwcODSkb
Če poznamo to obliko zapisa, lahko prek testnega odjemalca z ukazom zahtevamo trenutno stanje računa
[ 3][t 2][1558746708.815218925][test-lite-client.cpp:631][!testnode] requesting account state for -1:8156775B79325E5D62E742D9B96C30B6515A5CD2F1F64C5DA4B193C03F070E0D
[ 3][t 2][1558746708.858564138][test-lite-client.cpp:652][!testnode] got account state for -1:8156775B79325E5D62E742D9B96C30B6515A5CD2F1F64C5DA4B193C03F070E0D with respect to blocks (-1,8000000000000000,72355):F566005749C1B97F18EDE013EBA7A054B9014961BC1AD91F475B9082919A2296:1BD5DE54333164025EE39D389ECE2E93DA2871DA616D488253953E52B50DC03F and (-1,8000000000000000,72355):F566005749C1B97F18EDE013EBA7A054B9014961BC1AD91F475B9082919A2296:1BD5DE54333164025EE39D389ECE2E93DA2871DA616D488253953E52B50DC03F
account state is (account
addr:(addr_std
anycast:nothing workchain_id:-1 address:x8156775B79325E5D62E742D9B96C30B6515A5CD2F1F64C5DA4B193C03F070E0D)
storage_stat:(storage_info
used:(storage_used
cells:(var_uint len:1 value:3)
bits:(var_uint len:2 value:539)
public_cells:(var_uint len:0 value:0)) last_paid:0
due_payment:nothing)
storage:(account_storage last_trans_lt:74208000003
balance:(currencies
grams:(nanograms
amount:(var_uint len:7 value:999928362430000))
other:(extra_currencies
dict:hme_empty))
state:(account_active
(
split_depth:nothing
special:nothing
code:(just
value:(raw@^Cell
x{}
x{FF0020DDA4F260D31F01ED44D0D31FD166BAF2A1F80001D307D4D1821804A817C80073FB0201FB00A4C8CB1FC9ED54}
))
data:(just
value:(raw@^Cell
x{}
x{0000000D}
))
library:hme_empty))))
x{CFF8156775B79325E5D62E742D9B96C30B6515A5CD2F1F64C5DA4B193C03F070E0D2068086C000000000000000451C90E00DC0E35B7DB5FB8C134_}
x{FF0020DDA4F260D31F01ED44D0D31FD166BAF2A1F80001D307D4D1821804A817C80073FB0201FB00A4C8CB1FC9ED54}
x{0000000D}
Vidimo strukturo, ki je shranjena v DHT podane delovne verige. Na primer na terenu storage.balance je stanje na tekočem računu, v storage.state.code - kodo pametne pogodbe in v storage.state.data - svoje trenutne podatke. Upoštevajte, da je shramba podatkov TON - celica, celice - drevesna, vsaka celica ima lahko svoje podatke in podrejene celice. To je prikazano kot zamik v zadnjih vrsticah.
Gradnja pametne pogodbe
Zdaj pa ustvarimo takšno strukturo sami (imenuje se BOC - vrečka celic) z uporabo jezika Fift. Na srečo vam pametne pogodbe ni treba napisati sami - v mapi crypto/block obstaja datoteka iz izvornega arhiva new-wallet.fif, ki nam bo pomagal ustvariti novo denarnico. Kopirajmo ga v mapo s sestavljenim odjemalcem (~/liteclient-build, če ste sledili zgornjim navodilom). Njegovo vsebino sem navedel zgoraj kot primer kode na Fiftu.
Tukaj <source-directory> je treba zamenjati s potjo do nepakiranih izvornih kod (simbola »~« tukaj žal ni mogoče uporabiti, potrebna je celotna pot). Namesto uporabe ključa -I lahko definirate spremenljivko okolja FIFTPATH in to pot položite vanj.
Ker smo zagnali Fift z imenom datoteke new-wallet.fif, ga bo izvršil in zapustil. Če izpustite ime datoteke, se lahko igrate s tolmačem interaktivno.
Po izvedbi bi moralo biti v konzoli prikazano nekaj takega:
StateInit: x{34_}
x{FF0020DDA4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54}
x{0000000055375F730EDC2292E8CB15C42E8036EE9C25AA958EE002D2DE48A205E3A3426B}
new wallet address = -1 : 4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2
0f9PzVILj8yglrVn1zS-NSjtxr7QBfaTCp7JrBqnFPIR8nhZ
signing message: x{00000000}
External message for initialization is x{89FEE120E20C7E953E31546F64C23CD654002C1AA919ADD24DB12DDF85C6F3B58AE41198A28AD8DAF3B9588E7A629252BA3DB88F030D00BC1016110B2073359EAC3C13823C53245B65D056F2C070B940CDA09789585935C7ABA4D2AD4BED139281CFA1200000001_}
x{FF0020DDA4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54}
x{0000000055375F730EDC2292E8CB15C42E8036EE9C25AA958EE002D2DE48A205E3A3426B}
B5EE9C724104030100000000D60002CF89FEE120E20C7E953E31546F64C23CD654002C1AA919ADD24DB12DDF85C6F3B58AE41198A28AD8DAF3B9588E7A629252BA3DB88F030D00BC1016110B2073359EAC3C13823C53245B65D056F2C070B940CDA09789585935C7ABA4D2AD4BED139281CFA1200000001001020084FF0020DDA4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED5400480000000055375F730EDC2292E8CB15C42E8036EE9C25AA958EE002D2DE48A205E3A3426B6290698B
(Saved to file new-wallet-query.boc)
To pomeni, da denarnica z ID -1:4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2 (ali, kar je isto, 0f9PzVILj8yglrVn1zS-NSjtxr7QBfaTCp7JrBqnFPIR8nhZ) uspešno ustvarjeno. Ustrezna koda bo v datoteki new-wallet-query.boc, njegov naslov je v new-wallet.addrin zasebni ključ je notri new-wallet.pk (bodite previdni – ponovni zagon skripta bo te datoteke prepisal).
Seveda omrežje TON še ne pozna te denarnice, shranjena je le v obliki teh datotek. Zdaj ga je treba naložiti v omrežje. Vendar je težava v tem, da morate za ustvarjanje pametne pogodbe plačati provizijo, stanje na vašem računu pa je še vedno nič.
V delovnem načinu bo ta težava rešena z nakupom gramov na borzi (ali prenosom iz druge denarnice). No, v trenutnem testnem načinu je bila ustvarjena posebna pametna pogodba, od katere lahko kar tako zahtevate do 20 gramov.
Ustvarjanje zahteve za pametno pogodbo nekoga drugega
Postavimo zahtevo pametni pogodbi, ki razdeli grame levo in desno takole. V isti mapi crypto/block najdi datoteko testgiver.fif:
// "testgiver.addr" file>B 256 B>u@
0x8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0d
dup constant wallet_addr ."Test giver address = " x. cr
0x4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2
constant dest_addr
-1 constant wc
0x00000011 constant seqno
1000000000 constant Gram
{ Gram swap */ } : Gram*/
6.666 Gram*/ constant amount
// b x --> b' ( serializes a Gram amount )
{ -1 { 1+ 2dup 8 * ufits } until
rot over 4 u, -rot 8 * u, } : Gram,
// create a message (NB: 01b00.., b = bounce)
<b b{010000100} s, wc 8 i, dest_addr 256 u, amount Gram, 0 9 64 32 + + 1+ 1+ u, "GIFT" $, b>
<b seqno 32 u, 1 8 u, swap ref, b>
dup ."enveloping message: " <s csr. cr
<b b{1000100} s, wc 8 i, wallet_addr 256 u, 0 Gram, b{00} s,
swap <s s, b>
dup ."resulting external message: " <s csr. cr
2 boc+>B dup Bx. cr
"wallet-query.boc" B>file
Shranili ga bomo tudi v mapo z sestavljenim odjemalcem, vendar bomo popravili peto vrstico - pred vrstico “constant dest_addr". Zamenjajmo ga z naslovom denarnice, ki ste jo ustvarili prej (polno, ne skrajšano). Na začetku ni treba pisati »-1:«, namesto tega na začetek vnesite »0x«.
Linijo lahko tudi spremenite 6.666 Gram*/ constant amount — to je količina v gramih, ki jo zahtevate (ne več kot 20). Tudi če navedete celo število, pustite decimalno vejico.
Nazadnje morate popraviti črto 0x00000011 constant seqno. Prva številka tukaj je trenutna zaporedna številka, ki je shranjena v gramih izdaje računa. Kje ga lahko dobim? Kot je navedeno zgoraj, zaženite odjemalca in zaženite:
last
getaccount -1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0d
Čisto na koncu bodo podatki o pametni pogodbi vsebovali
Število 0000000D (vaše bo večje) je zaporedna številka, ki jo je treba nadomestiti v testgiver.fif.
To je to, shranite datoteko in zaženite (./crypto/fift testgiver.fif). Izhod bo datoteka wallet-query.boc. To je tisto, kar se oblikuje sporočilo na pametno pogodbo nekoga drugega - zahteva "prenesi toliko gramov na tak in tak račun."
S pomočjo odjemalca ga naložimo v omrežje:
> sendfile wallet-query.boc
[ 1][t 1][1558747399.456575155][test-lite-client.cpp:577][!testnode] sending query from file wallet-query.boc
[ 3][t 2][1558747399.500236034][test-lite-client.cpp:587][!query] external message status is 1
Če zdaj pokličete last, in nato znova zahtevati status računa, s katerega smo prosili za grame, potem bi morali videti, da se je njegova zaporedna številka povečala za eno - to pomeni, da je poslal denar na naš račun.
Ostaja še zadnji korak - prenesite kodo naše denarnice (njeno stanje je že napolnjeno, vendar brez kode pametne pogodbe z njo ne bomo mogli upravljati). Izvajamo sendfile new-wallet-query.boc - in to je to, v omrežju TON imate svojo denarnico (čeprav zaenkrat le testno).
Ustvarjanje odhodnih transakcij
Za prenos denarja iz stanja ustvarjenega računa obstaja datoteka crypto/block/wallet.fif, ki ga je treba prav tako postaviti v mapo s sestavljenim odjemalcem.
Podobno kot v prejšnjih korakih morate prilagoditi znesek, ki ga prenašate, naslov prejemnika (dest_addr) in zaporedje vaše denarnice (je enako 1 po inicializaciji denarnice in se poveča za 1 po vsaki odhodni transakciji – lahko si ga oglejte tako, da zahtevate stanje svojega računa). Za teste lahko uporabite na primer mojo denarnico - 0x4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2.
Na začetku (./crypto/fift wallet.fif) bo skript iz datotek vzel naslov vaše denarnice (od koder prenašate) in njen zasebni ključ new-wallet.addr и new-wallet.pkin prejeto sporočilo bo zapisano na new-wallet-query.boc.
Kot prej, za neposredno izvedbo transakcije, pokličite sendfile new-wallet-query.boc v stranki. Po tem ne pozabite posodobiti stanja verige blokov (last) in preverimo, ali sta se stanje in zaporedje naše denarnice spremenila (getaccount <account_id>).
To je vse, zdaj lahko ustvarimo pametne pogodbe v TON in jim pošljemo zahteve. Kot lahko vidite, je trenutna funkcionalnost že dovolj za na primer izdelavo bolj prijazne denarnice z grafičnim vmesnikom (vendar je pričakovati, da bo na voljo že kot del messengerja).
V anketi lahko sodelujejo samo registrirani uporabniki. Prijaviti se, prosim.
Vas zanima nadaljevanje člankov z analizo TON, TVM, Fift?
Da, čakam na zaključek serije člankov s splošnim pregledom TON
Da, zanimivo je prebrati več o jeziku Fift
Da, želim izvedeti več o virtualnem stroju TON in sestavljalniku zanj
Ne, nič od tega ni zanimivo
Glasovalo je 39 uporabnikov. 12 uporabnikov se je vzdržalo.
Kaj menite o načrtih Telegrama za lansiranje TON?
Veliko si obetam od tega projekta
Samo z zanimanjem spremljam njen razvoj.
Sem skeptičen in dvomim v njegov uspeh.
Nagnjen sem k temu, da je ta pobuda neuspešna in nepotrebna za široke množice
Glasovalo je 47 uporabnikov. 12 uporabnikov se je vzdržalo.