Več kot leto dni je bilo znanih načrtov aplikacije Telegram za izdajo lastne decentralizirane mreže Telegram Open Network. Takrat je bil na voljo obsežen tehnični dokument, ki naj bi ga napisal Nikolaj Durov in je opisoval strukturo prihodnje mreže. Za tiste, ki ste zamudili — priporočam, da si preberete moj povzetek tega dokumenta (, ; tretji del, na žalost, še vedno leži v osnutkih).
Od takrat ni bilo pomembnejših novic o statusu razvoja TON, dokler pred nekaj dnevi (v eni od ) ni bila objavljena povezava na stran , kjer so objavljeni:
◦ — izvorna koda lahkega odjemalca za testno mrežo TON;
◦ — konfiguracijska datoteka za povezavo s testno mrežo;
◦ — informacije o sestavljanju in zagonu odjemalca;
◦ — navodila po korakih za ustvarjanje pametne pogodbe s pomočjo odjemalca;
◦ — posodobljen dokument (od 2. marca 2019) s tehničnim pregledom mreže TON;
◦ — tehnični opis TVM (TON Virtual Machine, virtualni stroj TON);
◦ — tehnični opis blokchaina TON;
◦ — opis novega jezika Fift, namenjenega za ustvarjanje pametnih pogodb v TON-u.
Ponovno poudarjam, da uradnih potrditev strani in vseh teh dokumentov s strani Telegrama ni bilo, vendar pa obseg teh materialov daje dovolj verodostojnosti. Zaženi objavljenega odjemalca na vlastitu odgovornost.
Zbirka testnega odjemalca
Najprej poskusimo sestaviti in zagnati testni odjemalec — na srečo, podrobno opisuje ta preprost postopek. To bom storil na primeru macOS 10.14.5, za uspešnost sestavljanja na drugih sistemih ne morem jamčiti.
Prenesemo in razpakiramo . Pomembno je, da prenesete najnovejšo različico, saj nazaj kompatibilnost v tej fazi ni zagotovljena.
Preverimo, če so v sistemu nameščene najnovejše različice make, cmake (različice 3.0.2 ali višje), OpenSSL (vključno z glavnimi datotekami C), g++ ali clang. Meni ni bilo treba ničesar dodatno namestiti, vse je bilo sestavljeno takoj.
Predpostavimo, da je izvorna koda razpakirana v mapo
~\/lite-client. Ločeno od nje ustvarimo prazno mapo za zgrajen projekt (na primer,~\/liteclient-build), in iz nje (cd ~\/liteclient-build) pokličemo ukaze:cmake ~\/lite-client cmake --build . --target test-lite-client
Za sestavljanje interpreterja programski jezik Fift za pametne pogodbe (o njem spodaj) prav tako pokličemocmake --build . --target fiftPrenesemo aktualen za povezavo s testno mrežo in ga postavimo v mapo z zgrajenim odjemalcem.
Končano, lahko zaženete odjemalca:
./test-lite-client -C ton-lite-client-test1.config.json
Če je vse narejeno pravilno, bi morali videti nekaj takega:

Na voljo je le nekaj ukazov, kot lahko vidite:
◦ help — prikaži ta seznam ukazov;
◦ quit — izhod;
◦ time — pokaži trenutno čas na strežniku;
◦ status — pokaži stanje povezave in lokalno BDP;
◦ zadnje — posodobite stanje blockchaina (naložite zadnji blok). To ukaz je pomembno izvesti pred vsakim povpraševanjem, da boste prepričani, da vidite dejansko stanje omrežja.
◦ sendfile <filename> — naložite lokalno datoteko v omrežje TON. Tako poteka interakcija z omrežjem — vključno z ustvarjanjem novih pametnih pogodb in zahtevki za prenos sredstev med računi;
◦ getaccount — prikaže trenutno (ob času izvajanja ukaza zadnje) stanje računa z navedenim naslovom;
◦ privkey <filename> — naložite zasebni ključ iz lokalne datoteke.
Če ob zagonu odjemalca posredujete mapo z možnostjo -D, bo vanjo shranil zadnji blok masterchaina:
.\/test-lite-client -C ton-lite-client-test1.config.json -D ~\/ton-db-dirZdaj se lahko premaknemo k bolj zanimivim stvarem — raziskovanju jezika Fift, poskusimo skompilirati pametno pogodbo (na primer, ustvariti testno denarnico), naložiti jo v omrežje in poskusiti prenos sredstev med računi.
Jezik Fift
Iz dokumenta lahko izvemo, da je ekipa Telegram ustvarila nov stopenjski jezik za ustvarjanje pametnih pogodb Fift (verjetno iz števila fifth, po analogiji s Forth — jezikom, s katerim ima Fift veliko skupnega).
Dokument je dovolj obsežen, z 87 stranmi, in ne bom podrobno povzel njegove vsebine v okviru tega članka (vsaj ne, ker ga sam še nisem dokončal :). Osredotočil se bom na glavne točke in priložil par primerov kode v tem jeziku.
Na osnovni ravni je sintaksa Fifta dovolj preprosta: njegova koda je sestavljena iz besed, ki so v večini primerov ločene z presledki ali prelomi vrstic (poseben primer: nekatere besede ne zahtevajo ločila za seboj). Kakršna koli „replica“ (na primer, funkcija snd_ctl_add_slave() je bila zamenjana z snd_ctl_add_replica()), kar je povzročilo — to je velika črkovno občutljiva zaporedje znakov, ki ji ustreza določena opredelitev (na grob način, to, kar mora interpreter narediti, ko naleti na to besedo). Če ni definicije besede, se interpreter poskuša razparati kot število in ga položiti na sklad. Mimogrede, številke tukaj so — presenetljivo — 257-bitna cela števila, decimalnih pa sploh ni — natančneje, takoj se spremenijo v par celih števil, ki tvorita števec in imenovalec racionalnega ulomka.
Besede se običajno ukvarjajo z vrednostmi, ki ležijo na vrhu sklada. Posebna vrsta besed — prefiksne — ne uporablja stek, temveč naslednje simbole iz izvorne datoteke. Na primer, tako so implementirane nizovne literale — simbol „navajaj“ (") je predpono beseda, ki išče naslednjo (zaključno) navajaj in postavi niz med njima na stek. Podobno se obnašajo enovrstni (//) in večvrstni (/*) komentarji.
S tem skoraj končamo notranjo zasnovo jezika. Vse ostalo (vključno z upravljalnimi strukturami) je opredeljeno kot besede (bodisi notranje, kot so aritmetične operacije in definiranje novih besed; bodisi tiste, ki so opredeljene v „standardni knjižnici“ Fift.fif, ki se nahaja v mapi crypto/fift v izvornih datotekah).
Enostaven primer programa v Fiftu:
{ dup =: x dup * =: y } : setxy
3 setxy x . y . x y + .
7 setxy x . y . x y + .V prvem vrstici se definira nova beseda setxy (uporabite pozornost predpono {, ki ustvarja blok do zaključnega } in predpono :, ki dejansko definira besedo). setxy vzame število z vrha steka, ga določi (ali ponovno določi) kot globalno konstantno x, kvadrat tega števila — kot konstantno y (glede na to, da se vrednosti konstant lahko ponovno določijo, bi jih raje imenoval spremenljivke, vendar sledim poimenovanju v jeziku).
V naslednjih dveh vrsticah se na stek polaga število, pokliče se setxy, nato se prikažejo vrednosti konstant x, y (za izhod se uporablja beseda .), obe konstantni se postavita na stek, se seštejeta in rezultat se tudi prikaže. Rezultat bo:
3 9 12 ok
7 49 56 ok(Niz „ok“ prikaže interpreter, ko konča obdelavo trenutne vrstice v interaktivnem načinu vnosa)
In zdaj celoten primer kode:
"Asm.fif" включить
-1 константа wc \/\/ создать кошелек в рабочей цепочке -1 (главной цепочке)
\/\/ Создать новый простой кошелек
<{ SETCP0 DUP IFNOTRET INC 32 THROWIF \/\/ возвращаем, если recv_internal, ошибка, если recv_external
512 INT LDSLICEX DUP 32 PLDU \/\/ подписать cs cnt
c4 PUSHCTR CTOS 32 LDU 256 LDU ENDS \/\/ подписать cs cnt cnt' pubk
s1 s2 XCPU \/\/ подписать cs cnt pubk cnt' cnt
EQUAL 33 THROWIFNOT \/\/ ( несоответствие seqno? )
s2 PUSH HASHSU \/\/ подписать cs cnt pubk hash
s0 s4 s4 XC2PU \/\/ pubk cs cnt hash подписать pubk
CHKSIGNU \/\/ pubk cs cnt ?
34 THROWIFNOT \/\/ несоответствие подписи
ACCEPT
SWAP 32 LDU NIP
DUP SREFS IF:<{
8 LDU LDREF // pubk cnt mode msg cs
s0 s2 XCHG SENDRAWMSG // pubk cnt cs ; ( message sent )
}>
ENDS
INC NEWC 32 STU 256 STU ENDC c4 POPCTR
}>c
\/\/ код
<b 0 32 u, newkeypair swap dup constant wallet_pk "new-wallet.pk" b>файл
B,
b> \/\/ данные
\/\/ нет библиотек
<b b{00110} s, rot ref, swap b> // create StateInit
dup ."StateInit: " <s csr. cr
dup hash dup constant wallet_addr
."new wallet address = " wc . .": " x. cr
wc over 7 smca>$ тип cr
256 u>B "new-wallet.addr" B>file
<b 0 32 u, b>
dup ."подписываю сообщение: " <s csr. cr
dup hash wallet_pk ed25519_sign_uint rot
<b b{1000100} s, wc 8 i, wallet_addr 256 u, b{000010} swap <s b{0} b, b>
dup ."Внешнее сообщение для инициализации: " <s csr. cr
2 boc+>B dup Bx. cr
"new-wallet-query.boc" tuck B>file
."(Сохранено в файл " type .")" crTa grozno videti datoteka je namenjena ustvarjanju pametnega pogodbe — ta bo shranjena v datoteko new-wallet-query.boc po zaključku. Upoštevajte, da se tu uporablja še en, assemblerni jezik za TON Virtual Machine (o njem ne bom podrobneje govoril), katerih ukazi bodo v dodani v blockchain.
Tako je assembler za TVM napisan v Fiftu — izvorne datoteke tega assemblerja se nahajajo v datoteki crypto/fift/Asm.fif in se vključijo na začetku prej omenjenega dela kode.
Kaj lahko rečem, očitno Nikolaj Durov preprosto obožuje ustvarjati nove programske jezike 🙂
Ustvarjanje pametne pogodbe in interakcija s TON
Torej, predpostavimo, da smo sestavili stranko TON in interpreter Fift, kot je opisano zgoraj, in se seznanili z jezikom. Kako zdaj ustvariti pametno pogodbo? O tem govori datoteka , priložena viru.
Računi v TON
Kot sem opisal v , ta mreža vsebuje več kot en blok chain - obstaja en skupni, t. i. "masterchain", poleg tega pa poljubno število dodatnih "workchains", ki jih identificira 32-bitna številka. Masterchain ima identifikator -1, poleg njega se lahko uporablja tudi "osnovni" workchain z identifikatorjem 0. Vsak workchain ima lahko svojo konfiguracijo. Znotraj vsakega workchains je razdeljen na shardchains, vendar je to že podrobnost implementacije, ki je ne gre nujno imeti v mislih.
Znotraj enega workchain-a se shranjuje več računov, ki imajo svoje identifikatorje account_id. Za masterchain in ničelni workchain so dolgi 256 bitov. Tako je identifikator računa zapisan, na primer, tako:
-1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0dTo je "surov" format: najprej identifikator workchain-a, nato dvopičje, in identifikator računa v hex zapis.
Poleg tega je krajši format - številka workchain-a in naslov računa sta kodirana v binarni obliki, k njima je dodana kontrolna vsota in vse to je kodirano v Base64:
Ef+BVndbeTJeXWLnQtm5bDC2UVpc0vH2TF2ksZPAPwcODSkbPoznajoč ta zapis, lahko preko testnega odjemalca zahtevamo trenutno stanje kateregakoli računa s pomočjo ukaza
getaccount -1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0dPridobili bomo približno tak odgovor:
[ 3][t 2][1558746708.815218925][test-lite-client.cpp:631][!testnode] запрос состояния учетной записи для -1:8156775B79325E5D62E742D9B96C30B6515A5CD2F1F64C5DA4B193C03F070E0D
[ 3][t 2][1558746708.858564138][test-lite-client.cpp:652][!testnode] получено состояние учетной записи для -1:8156775B79325E5D62E742D9B96C30B6515A5CD2F1F64C5DA4B193C03F070E0D с учетом блоков (-1,8000000000000000,72355):F566005749C1B97F18EDE013EBA7A054B9014961BC1AD91F475B9082919A2296:1BD5DE54333164025EE39D389ECE2E93DA2871DA616D488253953E52B50DC03F и (-1,8000000000000000,72355):F566005749C1B97F18EDE013EBA7A054B9014961BC1AD91F475B9082919A2296:1BD5DE54333164025EE39D389ECE2E93DA2871DA616D488253953E52B50DC03F
состояние учетной записи (учетная запись
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 se hrani v DHT določenega delovnega veriga. Na primer, na polju storage.balance se nahaja trenutna bilanca računa, v storage.state.code — koda pametne pogodbe, medtem ko je v storage.state.data — njeni trenutni podatki. Upoštevajte, da je shranjevanje podatkov TON — Cell, celice — drevesna struktura, kjer ima vsaka celica lahko svoje podatke in podcelice. To je prikazano s povečanjem zamikov v zadnjih vrsticah.
Zbiranje pametne pogodbe
Zdaj pa naredimo to strukturo (imenuje se BOC — bag of cells) s pomočjo jezika Fift. Na srečo nam ni treba samostojno pisati pametne pogodbe — v mapi crypto/block iz arhiva z izvorno kodo je datoteka new-wallet.fif, ki nam bo pomagala ustvariti novo denarnico. Kopirajmo jo v mapo s sestavljenim odjemalcem (~\/liteclient-build, če ste sledili navodilom zgoraj). Njeno vsebino sem omenil zgoraj kot primer kode v Fiftu.
Izvedemo to datoteko na naslednji način:
./crypto/fift -I"/crypto/fift" new-wallet.fifTukaj <source-directory> je treba zamenjati s potjo do razpakiranih izvornih datotek (simbol «~» tukaj, na žalost, ni mogoče uporabiti, potrebna je popolna pot). Namesto uporabe ključa -I lahko določite okoljsko spremenljivko FIFTPATH in vanjo dodate to pot.
Ker je Fift zagnan s številko datoteke new-wallet.fif, jo bo izvedel in končal. Če števila datoteke ne navedete, lahko igramo z interpretatorjem v interaktivnem načinu.
V konzolo po izvedbi bi se moralo izpisati nekaj takega:
StateInit: x{34_}
x{FF0020DDA4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54}
x{0000000055375F730EDC2292E8CB15C42E8036EE9C25AA958EE002D2DE48A205E3A3426B}
nova naslov denarnice = -1 : 4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2
0f9PzVILj8yglrVn1zS-NSjtxr7QBfaTCp7JrBqnFPIR8nhZ
podpis sporočila: x{00000000}
Zunanje sporočilo za inicializacijo je x{89FEE120E20C7E953E31546F64C23CD654002C1AA919ADD24DB12DDF85C6F3B58AE41198A28AD8DAF3B9588E7A629252BA3DB88F030D00BC1016110B2073359EAC3C13823C53245B65D056F2C070B940CDA09789585935C7ABA4D2AD4BED139281CFA1200000001_}
x{FF0020DDA4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54}
x{0000000055375F730EDC2292E8CB15C42E8036EE9C25AA958EE002D2DE48A205E3A3426B}
B5EE9C724104030100000000D60002CF89FEE120E20C7E953E31546F64C23CD654002C1AA919ADD24DB12DDF85C6F3B58AE41198A28AD8DAF3B9588E7A629252BA3DB88F030D00BC1016110B2073359EAC3C13823C53245B65D056F2C070B940CDA09789585935C7ABA4D2AD4BED139281CFA1200000001001020084FF0020DDA4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED5400480000000055375F730EDC2292E8CB15C42E8036EE9C25AA958EE002D2DE48A205E3A3426B6290698B
(Shranjeno v datoteko new-wallet-query.boc)To pomeni, da je denarnica z identifikatorjem -1:4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2 (ali, kar je enako, 0f9PzVILj8yglrVn1zS-NSjtxr7QBfaTCp7JrBqnFPIR8nhZ) uspešno ustvarjena. Ustrezna koda se bo nahajala v datoteki new-wallet-query.boc, njen naslov pa v new-wallet.addr, privatni ključ pa v new-wallet.pk (bodite previdni - ponovni zagon skripte bo prepisal te datoteke).
Seveda o tej denarnici omrežje TON še ne ve, shranjena je samo v obliki teh datotek. Zdaj jo je treba nalagati v omrežje. Kljub temu je težava, da je za ustvarjanje pametne pogodbe potrebna pristojbina, vaš račun pa ima trenutno ničelno stanje.
V delovnem načinu se ta težava reši z nakupom gramov na borzi (ali prenosom z druge denarnice). V trenutnem testnem načinu pa je ustanovljena posebna pametna pogodba, pri kateri lahko zahtevate do 20 gramov kar tako.
Oblikovanje zahtevka za tujo pametno pogodbo
Zahtevek za pametno pogodbo, ki deli grame levo in desno, naredimo tako. V isti mapi crypto/block najdemo 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+ "gift" $, b>
<b seqno 32 u, 1 8 swap ref, b>
dup ."sporočilo o ovijanju: " <s csr. cr
<b b{1000100} s, wc 8 i, wallet_addr 256 u, 0 gram, b{00} s,
swap <s b>
dup ."rezultantno zunanje sporočilo: " <s csr. cr
2 boc+>B dup Bx. cr
"vprašanje-denarnice.boc" B>datotekaTo bomo prav tako shranili v mapo z zbranima klientoma, vendar bomo spremenili peto vrstico - pred vrstico „constant dest_addr«. Zamenjamo jo z naslovom tiste denarnice, ki ste jo ustvarili prej (polni, ne krajši). „-1:“ na začetku ni potrebno pisati, namesto tega na začetku postavite „0x“.
Lahko pa spremenite vrstico 6.666 Gram* / konstantna količina — to je količina u gramima koju tražite (ne više od 20). Čak i ako navedete celu brojku, ostavite decimalnu tačku.
Na kraju, treba ispraviti red 0x00000011 konstantni seqno. Prvo broj ovde — trenutni sequence number, koji se čuva u nalogu koji deli gramove. Kako ga dobiti? Kao što je rečeno ranije, pokrenite klijent i izvršite:
last
getaccount -1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0dNa samom kraju u podacima pametnog ugovora biće
...
x{FF0020DDA4F260D31F01ED44D0D31FD166BAF2A1F80001D307D4D1821804A817C80073FB0201FB00A4C8CB1FC9ED54}
x{0000000D}Broj 0000000D (biće veći kod vas) jeste sequence number koji treba uneti u testgiver.fif.
Sve, sačuvamo datoteku i pokrećemo (. /crypto/fift testgiver.fif). Na izlazu dobijamo datoteku wallet-query.boc. To je oblikovano sporočilo za stranu pametnog ugovora — zahtev "prevedi toliko grama na taj račun."
Pomoću klijenta učitajte je u mrežu:
> sendfile wallet-query.boc
[ 1][t 1][1558747399.456575155][test-lite-client.cpp:577][!testnode] slanje zahteva iz datoteke wallet-query.boc
[ 3][t 2][1558747399.500236034][test-lite-client.cpp:587][!query] spoljašnji status poruke je 1Ako sada pozovete zadnje, a zatim ponovo zatražite status računa na koji smo tražili grame, trebali bismo videti da se njegov sequence number povećao za jedan — to znači da je poslao novac našem računu.
Ostao je poslednji korak — učitavamo kod našeg novčanika (njegov balans je već dopunjen, ali bez koda pametnog ugovora ne možemo njime upravljati). Izvršavamo sendfile new-wallet-query.boc — i sve, imate vlastiti novčanik u TON mreži (neka to bude za sada samo testni).
Kreiranje odlaznih transakcija
Da biste prenosili novac sa bilansa kreiranog računa, postoji datoteka crypto/block/wallet.fif, koju takođe treba staviti u folder sa prikupljenim klijentom.
Slično prethodnim koracima, u njoj treba ispraviti količinu koju prenosite, adresu primaoca (dest_addr), i seqno vašeg novčanika (jednak je 1 nakon inicijalizacije novčanika i povećava se za 1 nakon svake odlazne transakcije — moći ćete ga videti tako da zatražite stanje svog računa). Za test možete koristiti, na primer, moj novčanik — 0x4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2.
Kada pokrenete (. /crypto/fift wallet.fif) skript će uzeti adresu vašeg novčanika (odakle prenosite) i njegov privatni ključ iz datoteka new-wallet.addr in new-wallet.pk, a dobijenu poruku zapisati u new-wallet-query.boc.
Kao i ranije, da bismo direktno izvršili transakciju, pozivamo sendfile new-wallet-query.boc v stranki. Po tem ne pozabite posodobiti stanja verige blokov (zadnje) in preverite, da sta se bilanca in seqno našega denarnice spremenila (getaccount).

To je to, zdaj znamo ustvarjati pametne pogodbe v TON in pošiljati zahteve zanje. Kot vidimo, je trenutna funkcionalnost že dovolj, da lahko, na primer, izdelamo bolj prijazno denarnico z grafičnim vmesnikom (vendar se pričakuje, da bo ta že na voljo kot del sporočilnika).
Samo registrovani korisnici mogu učestvovati u anketi. , molim vas.
Ali vas zanima nadaljevanje člankov o TON, TVM, Fift?
Ja, pričakujem zaključek cikla člankov z splošnim pregledom TON
Ja, zanimivo bi bilo prebrati več o jeziku Fift
Ja, želim izvedeti več o TON Virtual Machine in assemblerju zanj
Ne, me ne zanima nič od tega
Glasovali so 39 uporabnikov. 12 uporabnikov se je vzdržalo.
Kakšno je vaše mnenje o načrtih Telegrama za zagon TON?
Na ta projekt polagam velike nade
S preprostim interesom spremljam njegov razvoj
Sem skeptičen, dvomim o njegovem uspehu
Menim, da je ta iniciativa propadla in nepotrebna širokim množicam
47 users voted. 12 users abstained.
Izvor: habr.com

