Testați clientul TON (Telegram Open Network) și noua limbă Fift pentru contractele inteligente

În urmă cu mai bine de un an, a devenit cunoscut planurile messengerului Telegram de a-și lansa propria rețea descentralizată Open Telegram Network. Apoi a devenit disponibil un document tehnic voluminos, care ar fi fost scris de Nikolai Durov și a descris structura viitoarei rețele. Pentru cei care l-au ratat, vă recomand să citiți repovestirea mea a acestui document (parte 1, parte 2; a treia parte, din păcate, încă aduna praf în curenți).

De atunci, nu au existat vești semnificative despre stadiul dezvoltării TON până acum câteva zile (într-una dintre canale neoficiale) nu a apărut linkul către pagină https://test.ton.org/download.html, unde se află:
ton-test-liteclient-full.tar.xz — sursele unui client de lumină pentru rețeaua de testare TON;
ton-lite-client-test1.config.json — fișier de configurare pentru conectarea la rețeaua de testare;
README — informații despre construirea și lansarea clientului;
HOWTO — instrucțiuni pas cu pas pentru crearea unui contract inteligent folosind un client;
tonă.pdf — document actualizat (din 2 martie 2019) cu o prezentare tehnică a rețelei TON;
tvm.pdf — descrierea tehnică a TVM (TON Virtual Machine, TON virtual machine);
tblkch.pdf — descrierea tehnică a blockchain-ului TON;
fifthbase.pdf — descrierea noului limbaj Fift, conceput pentru crearea de contracte inteligente în TON.

Repet, nu a existat nicio confirmare oficială a paginii și a tuturor acestor documente de la Telegram, dar volumul acestor materiale le face destul de plauzibile. Lansați clientul publicat pe propriul risc.

Construirea unui client de testare

Mai întâi, să încercăm să construim și să rulăm un client de testare - din fericire, README descrie acest proces simplu în detaliu. Voi face acest lucru folosind macOS 10.14.5 ca exemplu. Nu pot garanta succesul construirii pe alte sisteme.

  1. Descărcați și despachetați arhiva sursă. Este important să descărcați cea mai recentă versiune, deoarece compatibilitatea cu versiunea anterioară nu este garantată în această etapă.

  2. Asigurați-vă că cele mai recente versiuni de make, cmake (versiunea 3.0.2 sau mai mare), OpenSSL (inclusiv fișierele de antet C), g++ sau clang sunt instalate pe sistem. Nu a trebuit să instalez nimic, totul s-a adunat imediat.

  3. Să presupunem că sursele sunt dezambalate într-un folder ~/lite-client. Separat de acesta, creați un folder gol pentru proiectul asamblat (de exemplu, ~/liteclient-build), iar din ea (cd ~/liteclient-build) apelați comenzile:

    cmake ~/lite-client
    cmake --build . --target test-lite-client

    Testați clientul TON (Telegram Open Network) și noua limbă Fift pentru contractele inteligente

    Pentru a construi interpretul de limbă Fift pentru contractele inteligente (mai multe despre el mai jos), sunăm, de asemenea

    cmake --build . --target fift

  4. Descărcați-o pe cea actuală Fișier de configurare pentru a vă conecta la rețeaua de testare și a o pune în folderul cu clientul asamblat.

  5. Termina, puteți porni clientul:

    ./test-lite-client -C ton-lite-client-test1.config.json

Dacă totul este făcut corect, ar trebui să vedeți ceva de genul acesta:

Testați clientul TON (Telegram Open Network) și noua limbă Fift pentru contractele inteligente

După cum putem vedea, există puține comenzi disponibile:
help — afișați această listă de comenzi;
quit - ieși;
time — arată ora curentă pe server;
status — arată conexiunea și starea bazei de date locală;
last — actualizați starea blockchain-ului (descărcați ultimul bloc). Este important să rulați această comandă înainte de orice solicitare pentru a vă asigura că vedeți starea curentă a rețelei.
sendfile <filename> — încărcați un fișier local în rețeaua TON. Așa are loc interacțiunea cu rețeaua – inclusiv, de exemplu, crearea de noi contracte inteligente și solicitări de transfer de fonduri între conturi;
getaccount <address> — arată curentul (la momentul în care comanda a fost executată) last) starea contului cu adresa specificată;
privkey <filename> — încărcați cheia privată dintr-un fișier local.

Dacă, la pornirea clientului, transferați un folder în acesta folosind opțiunea -D, apoi va adăuga ultimul bloc al masterchain-ului în el:

./test-lite-client -C ton-lite-client-test1.config.json -D ~/ton-db-dir

Acum putem trece la lucruri mai interesante - învățați limba Fift, încercați să compilați un contract inteligent (de exemplu, creați un portofel de testare), încărcați-l în rețea și încercați să transferați fonduri între conturi.

Limba Cinci

Din document fifthbase.pdf puteți afla că echipa Telegram a creat un nou limbaj de stivă pentru a crea contracte inteligente Cinci (aparent de la numeral a cincea, similar cu Forth, o limbă cu care Fifth are multe în comun).

Documentul este destul de voluminos, 87 de pagini, și nu-i voi repeta conținutul în detaliu în cadrul acestui articol (cel puțin pentru că nu l-am terminat eu de citit :). Mă voi concentra pe punctele principale și voi da câteva exemple de cod în acest limbaj.

La un nivel de bază, sintaxa lui Fift este destul de simplă: codul său este format din cuvinte, de obicei separate prin spații sau întreruperi de linie (caz special: unele cuvinte nu necesită un separator după ele). Orice слово este o secvență de caractere sensibilă la majuscule și minuscule care corespunde unui anumit determinarea (aproximativ, ce ar trebui să facă interpretul când întâlnește acest cuvânt). Dacă nu există o definiție a unui cuvânt, interpretul încearcă să îl analizeze ca număr și să îl pună în stivă. Apropo, numerele de aici sunt - brusc - numere întregi de 257 de biți și nu există deloc fracții - mai precis, se transformă imediat într-o pereche de numere întregi, formând numărătorul și numitorul unei fracții raționale.

Cuvintele tind să interacționeze cu valorile din partea de sus a stivei. Un tip separat de cuvinte - prefix — nu folosește stiva, ci caracterele ulterioare din fișierul sursă. De exemplu, așa sunt implementate literalele șir - caracterul ghilimele (") este un cuvânt prefix care caută următorul citat (de închidere) și împinge șirul dintre ele pe stivă. One-liners se comportă în același mod (//) și multilinie (/*) comentarii.

Aici se termină aproape întreaga structură internă a limbajului. Toate celelalte (inclusiv constructele de control) sunt definite ca cuvinte (fie interne, cum ar fi operațiile aritmetice și definirea cuvintelor noi; fie definite în „biblioteca standard” Fift.fif, care se află în folder crypto/fift în surse).

Un exemplu de program simplu în Fift:

{ dup =: x dup * =: y } : setxy
3 setxy x . y . x y + .
7 setxy x . y . x y + .

Prima linie definește un cuvânt nou setxy (rețineți prefixul {, care creează un bloc înaintea celui de închidere } și prefix :, care definește de fapt cuvântul). setxy ia un număr din partea de sus a stivei, îl definește (sau îl redefinește) ca global constant x, iar pătratul acestui număr ca o constantă y (Având în vedere că valorile constantelor pot fi redefinite, le-aș numi mai degrabă variabile, dar respect convenția de denumire în limbaj).

Următoarele două linii pun un număr pe stivă și apelează setxy, apoi sunt afișate valorile constantelor x, y (cuvântul este folosit pentru ieșire .), ambele constante sunt plasate pe stivă, însumate, iar rezultatul este și imprimat. Ca rezultat vom vedea:

3 9 12 ok
7 49 56 ok

(Linia „ok” este tipărită de interpret când termină procesarea liniei curente în modul de introducere interactiv)

Ei bine, un exemplu de cod complet:

"Asm.fif" include

-1 constant wc  // create a wallet in workchain -1 (masterchain)

// Create new simple wallet
<{  SETCP0 DUP IFNOTRET INC 32 THROWIF  // return if recv_internal, fail unless recv_external
    512 INT LDSLICEX DUP 32 PLDU   // sign cs cnt
    c4 PUSHCTR CTOS 32 LDU 256 LDU ENDS  // sign cs cnt cnt' pubk
    s1 s2 XCPU            // sign cs cnt pubk cnt' cnt
    EQUAL 33 THROWIFNOT   // ( seqno mismatch? )
    s2 PUSH HASHSU        // sign cs cnt pubk hash
    s0 s4 s4 XC2PU        // pubk cs cnt hash sign pubk
    CHKSIGNU              // pubk cs cnt ?
    34 THROWIFNOT         // signature mismatch
    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
// code
<b 0 32 u, 
   newkeypair swap dup constant wallet_pk 
   "new-wallet.pk" B>file
   B, 
b> // data
// no libraries
<b b{00110} s, rot ref, swap ref, b>  // create StateInit
dup ."StateInit: " <s csr. cr
dup hash dup constant wallet_addr
."new wallet address = " wc . .": " dup x. cr
wc over 7 smca>$ type cr
256 u>B "new-wallet.addr" B>file
<b 0 32 u, b>
dup ."signing message: " <s csr. cr
dup hash wallet_pk ed25519_sign_uint rot
<b b{1000100} s, wc 8 i, wallet_addr 256 u, b{000010} s, swap <s s, b{0} s, swap B, swap <s s, b>
dup ."External message for initialization is " <s csr. cr
2 boc+>B dup Bx. cr
"new-wallet-query.boc" tuck B>file
."(Saved to file " type .")" cr

Acest fișier cu aspect înfricoșător este pentru crearea unui contract inteligent - va fi plasat într-un fișier new-wallet-query.boc dupa executare. Vă rugăm să rețineți că aici este folosit un alt limbaj de asamblare pentru TON Virtual Machine (nu mă voi opri asupra lui în detaliu), ale cărui instrucțiuni vor fi plasate pe blockchain.

Astfel, asamblatorul pentru TVM este scris în Fift - sursele acestui asamblator sunt în fișier crypto/fift/Asm.fif și sunt conectate la începutul piesei de cod de mai sus.

Ce pot să spun, se pare că lui Nikolai Durov îi place să creeze noi limbaje de programare :)

Crearea unui contract inteligent și interacțiunea cu TON

Deci, să presupunem că am asamblat clientul TON și interpretul Fift așa cum este descris mai sus și ne-am familiarizat cu limbajul. Cum să creezi un contract inteligent acum? Acest lucru este descris în dosar HOWTO, atașat la surse.

Conturi în TON

După cum am descris în TON recenzie, această rețea conține mai mult de un blockchain - există unul comun, așa-numitul. „lanț principal”, precum și un număr arbitrar de „lanțuri de lucru” suplimentare, identificate printr-un număr de 32 de biți. Masterchain-ul are un identificator de -1, poate fi folosit și un workchain „de bază” cu un identificator de 0. Fiecare workchain poate avea propria configurație. Pe plan intern, fiecare lanț de lucru este împărțit în shardchain, dar acesta este un detaliu de implementare care nu trebuie reținut.

Într-un singur lanț de lucru, sunt stocate multe conturi care au propriile identificatori account_id. Pentru lanțul principal și lanțul de lucru zero, acestea au o lungime de 256 de biți. Astfel, identificatorul contului este scris, de exemplu, astfel:

-1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0d

Acesta este formatul „raw”: mai întâi ID-ul lanțului de lucru, apoi două puncte și ID-ul contului în notație hexazecimală.

În plus, există un format scurtat - numărul lanțului de lucru și adresa contului sunt codificate în formă binară, li se adaugă o sumă de control și toate acestea sunt codificate în Base64:

Ef+BVndbeTJeXWLnQtm5bDC2UVpc0vH2TF2ksZPAPwcODSkb

Cunoscând acest format de înregistrare, putem solicita starea curentă a unui cont printr-un client de testare folosind comanda

getaccount -1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0d

Vom obține ceva de genul acesta:

[ 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}

Vedem structura care este stocată în DHT al lanțului de lucru specificat. De exemplu, pe teren storage.balance este soldul contului curent, în storage.state.code - cod de contract inteligent și în storage.state.data - datele sale curente. Vă rugăm să rețineți că stocarea datelor TON - Celulă, celule - este asemănătoare unui arbore, fiecare celulă poate avea atât propriile date, cât și celulele copil. Aceasta este afișată ca indentare în ultimele rânduri.

Construirea unui contract inteligent

Acum să creăm noi înșine o astfel de structură (se numește BOC - pungă de celule) folosind limba Cinci. Din fericire, nu trebuie să scrieți singur un contract inteligent - în dosar crypto/block există un fișier din arhiva sursă new-wallet.fif, care ne va ajuta să creăm un nou portofel. Să-l copiem în folderul cu clientul asamblat (~/liteclient-build, dacă ați urmat instrucțiunile de mai sus). Am citat mai sus conținutul său ca exemplu de cod pe Fift.

Executați acest fișier după cum urmează:

./crypto/fift -I"<source-directory>/crypto/fift" new-wallet.fif

Aici <source-directory> trebuie înlocuit cu calea către sursele dezambalate (simbolul „~”, din păcate, nu poate fi folosit aici, este nevoie de calea completă). În loc să folosești o cheie -I puteți defini o variabilă de mediu FIFTPATH și pune această cale în ea.

De când am lansat Fift cu numele fișierului new-wallet.fif, îl va executa și va ieși. Dacă omiteți numele fișierului, puteți juca cu interpretul în mod interactiv.

După execuție, ceva de genul acesta ar trebui să fie afișat în consolă:

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)

Aceasta înseamnă că portofelul cu ID-ul -1:4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2 (sau, ce este la fel, 0f9PzVILj8yglrVn1zS-NSjtxr7QBfaTCp7JrBqnFPIR8nhZ) creat cu succes. Codul corespunzător va fi în fișier new-wallet-query.boc, adresa lui este în new-wallet.addr, iar cheia privată este în new-wallet.pk (aveți grijă - rularea din nou a scriptului va suprascrie aceste fișiere).

Desigur, rețeaua TON nu știe încă despre acest portofel, acesta este stocat doar sub forma acestor fișiere. Acum trebuie să fie încărcat în rețea. Cu toate acestea, problema este că pentru a crea un contract inteligent trebuie să plătești un comision, iar soldul contului tău este încă zero.

În modul de lucru, această problemă va fi rezolvată prin achiziționarea de grame pe schimb (sau transferul din alt portofel). Ei bine, în modul actual de testare a fost creat un smart contract special, din care poți cere până la 20 de grame exact așa.

Generarea unei cereri către contractul inteligent al altcuiva

Facem o cerere către un contract inteligent care distribuie grame în stânga și în dreapta astfel. În același folder crypto/block găsiți fișierul 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

De asemenea, îl vom salva în folderul cu clientul asamblat, dar vom corecta a cincea linie - înainte de linia „constant dest_addr". Să-l înlocuim cu adresa portofelului pe care l-ați creat înainte (complet, nu prescurtat). Nu este nevoie să scrieți „-1:” la început, în schimb puneți „0x” la început.

De asemenea, puteți schimba linia 6.666 Gram*/ constant amount — aceasta este cantitatea în grame pe care o solicitați (nu mai mult de 20). Chiar dacă specificați un număr întreg, lăsați punctul zecimal.

În cele din urmă, trebuie să corectați linia 0x00000011 constant seqno. Primul număr de aici este numărul de secvență curent, care este stocat în gramele de emitere a contului. De unde pot lua? După cum sa menționat mai sus, porniți clientul și rulați:

last
getaccount -1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0d

La final, datele contractului inteligent vor conține

...
x{FF0020DDA4F260D31F01ED44D0D31FD166BAF2A1F80001D307D4D1821804A817C80073FB0201FB00A4C8CB1FC9ED54}
 x{0000000D}

Numărul 0000000D (al tău va fi mai mare) este numărul secvenței care trebuie înlocuit în testgiver.fif.

Asta e, salvează fișierul și rulează (./crypto/fift testgiver.fif). Ieșirea va fi un fișier wallet-query.boc. Acesta este ceea ce se formează сообщение la contractul inteligent al altcuiva - o solicitare „transferă atât de multe grame într-un astfel de cont”.

Folosind clientul, îl încărcăm în rețea:

> 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

Dacă suni acum last, iar apoi solicitați din nou starea contului de la care am cerut grame, apoi ar trebui să vedem că numărul său de secvență a crescut cu unu - asta înseamnă că a trimis bani în contul nostru.

Ultimul pas rămâne - descărcați codul portofelului nostru (soldul acestuia a fost deja completat, dar fără codul smart contract nu îl vom putea gestiona). Realizam sendfile new-wallet-query.boc - și gata, ai propriul tău portofel în rețeaua TON (chiar dacă deocamdată este doar unul de test).

Crearea tranzacțiilor de ieșire

Pentru a transfera bani din soldul contului creat, există un fișier crypto/block/wallet.fif, care trebuie de asemenea plasat în folderul cu clientul asamblat.

Similar cu pașii anteriori, trebuie să ajustați suma pe care o transferați, adresa destinatarului (dest_addr) și seqno-ul portofelului dvs. (este egal cu 1 după inițializarea portofelului și crește cu 1 după fiecare tranzacție de ieșire - puteți vedeți-l solicitând starea contului dvs.) . Pentru teste, puteți folosi, de exemplu, portofelul meu - 0x4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2.

La inceput (./crypto/fift wallet.fif) scriptul va prelua adresa portofelului dvs. (de unde transferați) și cheia sa privată din fișiere new-wallet.addr и new-wallet.pk, iar mesajul primit va fi scris la new-wallet-query.boc.

Ca și înainte, pentru a efectua direct tranzacția, sunați sendfile new-wallet-query.boc în client. După aceasta, nu uitați să actualizați starea blockchain-ului (last) și verificați dacă soldul și seqno-ul portofelului nostru s-au schimbat (getaccount <account_id>).

Testați clientul TON (Telegram Open Network) și noua limbă Fift pentru contractele inteligente

Asta e tot, acum putem crea contracte inteligente în TON și le putem trimite cereri. După cum puteți vedea, funcționalitatea actuală este deja suficientă pentru, de exemplu, a face un portofel mai prietenos cu o interfață grafică (cu toate acestea, este de așteptat ca acesta să devină deja disponibil ca parte a messengerului).

Numai utilizatorii înregistrați pot participa la sondaj. Loghează-te, Vă rog.

Ești interesat să continui articolele cu analiză TON, TVM, Fift?

  • Da, aștept finalizarea seriei de articole cu o prezentare generală a TON

  • Da, este interesant să citiți mai multe despre limba Cinci

  • Da, vreau să aflu mai multe despre TON Virtual Machine și asamblatorul pentru aceasta

  • Nu, nimic din toate astea nu este interesant

Au votat 39 utilizatori. 12 utilizatori s-au abținut.

Ce părere aveți despre planurile Telegram de a lansa TON?

  • Am mari speranțe în acest proiect

  • Îi urmăresc evoluția cu interes.

  • Sunt sceptic și mă îndoiesc de succesul ei.

  • Înclin să consider această inițiativă un eșec și inutilă pentru masele largi

Au votat 47 utilizatori. 12 utilizatori s-au abținut.

Sursa: www.habr.com

Adauga un comentariu