Hace más de un año se conocieron los planes de la mensajería Telegram para lanzar su propia red descentralizada Telegram Open Network. Entonces se hizo disponible un extenso documento técnico, que supuestamente fue escrito por Nikolai Durov y que describía la estructura de la futura red. Para aquellos que se lo perdieron, recomiendo revisar mi resumen de este documento (, ; la tercera parte, lamentablemente, aún está guardada en borradores).
Desde entonces, no ha habido noticias significativas sobre el estado del desarrollo de TON, hasta que hace un par de días (en uno de los ) apareció un enlace a la página , donde se encuentran:
◦ — los fuentes del cliente ligero para la red de pruebas TON;
◦ — archivo de configuración para conectarse a la red de pruebas;
◦ — información sobre la compilación y ejecución del cliente;
◦ — guía paso a paso sobre cómo crear un contrato inteligente utilizando el cliente;
◦ — un documento actualizado (del 2 de marzo de 2019) con una revisión técnica de la red TON;
◦ — descripción técnica de TVM (TON Virtual Machine, máquina virtual TON);
◦ — descripción técnica de la blockchain TON;
◦ — descripción del nuevo lenguaje Fift, diseñado para crear contratos inteligentes en TON.
Reitero, no ha habido confirmaciones oficiales de la página y de todos estos documentos por parte de Telegram, pero la cantidad de estos materiales los hace bastante plausibles. Lance el cliente publicado bajo su propio riesgo.
Compilación del cliente de prueba
Primero intentemos compilar y lanzar el cliente de prueba — afortunadamente, describe este proceso sencillo en detalle. Lo haré en el ejemplo de macOS 10.14.5, no puedo garantizar el éxito de la compilación en otros sistemas.
Descargamos y descomprimimos . Es importante descargar la última versión, ya que la compatibilidad hacia atrás en esta etapa no está garantizada.
Asegurémonos de que el sistema tenga las últimas versiones de make, cmake (versiones 3.0.2 o superiores), OpenSSL (incluidos los archivos de cabecera C), g++ o clang. No tuve necesidad de instalar nada adicional, todo se compiló directamente.
Supongamos que los fuentes están descomprimidos en la carpeta
~\/lite-client. Crearemos aparte una carpeta vacía para el proyecto compilado (por ejemplo,~\/liteclient-build), y desde ella (cd ~\/liteclient-build) ejecutamos los comandos:cmake ~\/lite-client cmake --build . --target test-lite-client
Para compilar el intérprete del lenguaje Fift para contratos inteligentes (del cual hablaremos más adelante), también ejecutamoscmake --build . --target fiftDescargamos la versión actual para conectarnos a la red de prueba y la colocamos en la carpeta con el cliente compilado.
Listo, se puede iniciar el cliente:
./test-lite-client -C ton-lite-client-test1.config.json
Si todo se ha hecho correctamente, deberías ver algo como esto:

Los comandos disponibles, como vemos, son pocos:
◦ help — mostrar esta lista de comandos;
◦ quit — salir;
◦ time — mostrar la hora actual en el servidor;
◦ status — mostrar el estado de la conexión y la base de datos local;
◦ last — actualizar el estado de la blockchain (cargar el último bloque). Es importante ejecutar este comando antes de cualquier solicitud para estar seguro de que estás viendo el estado actual de la red.
◦ sendfile <filename> — cargar un archivo local en la red TON. Esto permite la interacción con la red, incluyendo, por ejemplo, la creación de nuevos contratos inteligentes y solicitudes de transferencia de fondos entre cuentas;
◦ getaccount — mostrar el estado actual (en el momento de la ejecución del comando last) de la cuenta con la dirección especificada;
◦ privkey <filename> — cargar la clave privada desde un archivo local.
Si al iniciar el cliente se le pasa una carpeta con la opción -D, entonces se almacenará en ella el último bloque de la principal cadena:
./test-lite-client -C ton-lite-client-test1.config.json -D ~/ton-db-dirAhora podemos pasar a cosas más interesantes: estudiar el lenguaje Fift, intentar compilar un contrato inteligente (por ejemplo, crear una billetera de prueba), cargarlo en la red y probar la transferencia de fondos entre cuentas.
Lenguaje Fift
Del documento se puede aprender que para crear contratos inteligentes el equipo de Telegram creó un nuevo lenguaje de pila Fift (aparentemente, del numeral fifth, por analogía con Forth, un lenguaje del cual Fift tiene mucho en común).
El documento es bastante extenso, tiene 87 páginas, y no voy a resumir su contenido en detalle en este artículo (al menos, porque no lo he terminado de leer :). Me detendré en los puntos principales y daré un par de ejemplos de código en este lenguaje.
A un nivel básico, la sintaxis de Fift es bastante simple: su código se compone de palabras, generalmente separadas por espacios o saltos de línea (caso particular: algunas palabras no requieren separador después de sí mismas). Cualquier «replica» (por ejemplo, la función snd_ctl_add_slave() fue reemplazada por snd_ctl_add_replica()), lo que provocó — es una secuencia de caracteres que distingue entre mayúsculas y minúsculas, la cual corresponde a una cierta definición (en términos generales, lo que el intérprete debe hacer cuando encuentra esta palabra). Si no hay definición para la palabra, el intérprete intenta interpretarla como un número y ponerla en la pila. Por cierto, aquí los números son, sorprendentemente, enteros de 257 bits, y no hay fraccionarios en absoluto — más bien, se convierten directamente en un par de enteros que forman el numerador y el denominador de una fracción racional.
Las palabras generalmente interactúan con los valores que están en la parte superior de la pila. Un tipo separado de palabras es prefijo — utiliza no una pila, sino los caracteres que le siguen del archivo original. Por ejemplo, así se implementan los literales de cadena: el símbolo «comillas» (") es una palabra de prefijo que busca la siguiente (comillas de cierre) y coloca la cadena entre ellas en la pila. Del mismo modo, funcionan los comentarios de una línea (//) y de múltiples líneas (/*).
Con esto, casi termina la estructura interna del lenguaje. Todo lo demás (incluyendo las estructuras de control) se define como palabras (ya sea internas, como las operaciones aritméticas y la definición de nuevas palabras; o definidas en la «biblioteca estándar» Fift.fif, que se encuentra en la carpeta crypto/fift en las fuentes).
Un ejemplo simple de un programa en Fift:
{ dup =: x dup * =: y } : setxy
3 setxy x . y . x y + .
7 setxy x . y . x y + .En la primera línea se define una nueva palabra setxy (fíjate en el prefijo {, que crea un bloque hasta el cierre } y el prefijo :, que en realidad define la palabra). setxy Toma un número de la parte superior de la pila, lo define (o redefinió) como una constante global , y el cuadrado de este número — como una constante x(considerando que los valores de las constantes se pueden redefinir, preferiría llamarlas variables, pero sigo la nomenclatura del lenguaje). y En las siguientes dos líneas, se coloca un número en la pila, se llama a
, luego se muestran los valores de las constantes setxy(para la salida se utiliza la palabra x, y ), ambas constantes se colocan en la pila, se suman y el resultado también se muestra. Como resultado, veremos: .3 9 12 ok 7 49 56 ok
(La línea «ok» la muestra el intérprete cuando termina de procesar la línea actual en el modo de entrada interactiva)Y un ejemplo completo de código:
Este archivo de aspecto aterrador está destinado a crear un contrato inteligente: se colocará en el archivo
"Asm.fif" incluir
-1 constante wc \/\/ crear una billetera en workchain -1 (masterchain)
\/\/ Crear nueva billetera simple
<{ SETCP0 DUP IFNOTRET INC 32 THROWIF \/\/ devolver si recv_internal, fallar a menos que recv_external
512 INT LDSLICEX DUP 32 PLDU \/\/ firmar cs cnt
c4 PUSHCTR CTOS 32 LDU 256 LDU ENDS \/\/ firmar cs cnt cnt' pubk
s1 s2 XCPU \/\/ firmar cs cnt pubk cnt' cnt
EQUAL 33 THROWIFNOT \/\/ ( ¿desajuste seqno? )
s2 PUSH HASHSU \/\/ firmar cs cnt pubk hash
s0 s4 s4 XC2PU \/\/ pubk cs cnt hash firmar pubk
CHKSIGNU \/\/ pubk cs cnt ?
34 THROWIFNOT \/\/ desajuste de firma
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
\/\/ código
<b 0 32 u, newkeypair swap dup constant wallet_pk "new-wallet.pk" b>archivo
B,
b> \/\/ datos
\/\/ sin bibliotecas
<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>$ tipo cr
256 u>B "new-wallet.addr" B>archivo
<b 0 32 u, b>
dup ."firmando mensaje: " <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 ."El mensaje externo para inicialización es " <s csr. cr
2 boc+>B dup Bx. cr
"new-wallet-query.boc" tuck B>archivo
."(Guardado en archivo " tipo .")" crnew-wallet-query.boc después de la ejecución. Ten en cuenta que aquí se utiliza otro lenguaje, ensamblador, para la TON Virtual Machine (no entraré en detalles sobre ello), cuyas instrucciones se colocarán en la blockchain. Así, el ensamblador para TVM está escrito en Fift: las fuentes de este ensamblador se encuentran en el archivo
crypto/fift/Asm.fif y se conectan al comienzo del fragmento de código anterior. ¿Qué puedo decir? Parece que Nikolai Durov simplemente ama crear nuevos lenguajes de programación 🙂
Crear un contrato inteligente e interactuar con TON
Creación de un contrato inteligente e interacción con TON
Supongamos que hemos recopilado el cliente TON y el intérprete Fift, como se describió anteriormente, y nos hemos familiarizado con el lenguaje. ¿Cómo crear un contrato inteligente ahora? Esto se detalla en el archivo , adjunto a los archivos fuente.
Cuentas en TON
Como mencioné en , esta red contiene más de una cadena de bloques: hay una cadena común, conocida como «masterchain», así como una cantidad arbitraria de «workchains» adicionales, identificados por un número de 32 bits. La masterchain tiene un identificador de -1, además de eso, también se puede usar la «workchain base» con un identificador de 0. Cada workchain puede tener su propia configuración. Internamente, cada workchain se divide en shardchains, pero ese es un detalle de implementación que no es necesario recordar.
Dentro de una workchain se almacena una multitud de cuentas, que tienen sus propios identificadores account_id. Para la masterchain y la workchain cero, tienen una longitud de 256 bits. Así, el identificador de cuenta se escribe, por ejemplo, así:
-1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0dEste es el formato «crudo»: primero el identificador de la workchain, luego dos puntos, y el identificador de la cuenta en formato hexadecimal.
Además, hay un formato abreviado: el número de la workchain y la dirección de la cuenta se codifican en binario, se añade una suma de verificación y todo esto se codifica en Base64:
Ef+BVndbeTJeXWLnQtm5bDC2UVpc0vH2TF2ksZPAPwcODSkbConociendo este formato de registro, podemos solicitar el estado actual de alguna cuenta a través del cliente de pruebas usando el comando
getaccount -1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0dObtenemos aproximadamente esta respuesta:
[ 3][t 2][1558746708.815218925][test-lite-client.cpp:631][!testnode] solicitando estado de cuenta para -1:8156775B79325E5D62E742D9B96C30B6515A5CD2F1F64C5DA4B193C03F070E0D
[ 3][t 2][1558746708.858564138][test-lite-client.cpp:652][!testnode] se obtuvo el estado de cuenta para -1:8156775B79325E5D62E742D9B96C30B6515A5CD2F1F64C5DA4B193C03F070E0D respecto a los bloques (-1,8000000000000000,72355):F566005749C1B97F18EDE013EBA7A054B9014961BC1AD91F475B9082919A2296:1BD5DE54333164025EE39D389ECE2E93DA2871DA616D488253953E52B50DC03F y (-1,8000000000000000,72355):F566005749C1B97F18EDE013EBA7A054B9014961BC1AD91F475B9082919A2296:1BD5DE54333164025EE39D389ECE2E93DA2871DA616D488253953E52B50DC03F
el estado de cuenta es (cuenta
dir:(addr_std
anycast:nada workchain_id:-1 dirección:x8156775B79325E5D62E742D9B96C30B6515A5CD2F1F64C5DA4B193C03F070E0D)
storage_stat:(información_almacenamiento
usado:(almacenamiento_usado
celdas:(var_uint len:1 valor:3)
bits:(var_uint len:2 valor:539)
celdas_públicas:(var_uint len:0 valor:0)) último_pagado:0
pago_deuda:nada)
almacenamiento:(almacenamiento_cuenta último_trans_lt:74208000003
balance:(monedas
gramos:(nanogramas
cantidad:(var_uint len:7 valor:999928362430000))
otros:(monedas_extras
dict:hme_empty))
estado:(cuenta_activa
(
profundidad_particion:nada
especial:nada
código:(solo
valor:(crudo@^Cell
x{}
x{FF0020DDA4F260D31F01ED44D0D31FD166BAF2A1F80001D307D4D1821804A817C80073FB0201FB00A4C8CB1FC9ED54}
))
datos:(solo
valor:(crudo@^Cell
x{}
x{0000000D}
))
biblioteca:hme_empty))))
x{CFF8156775B79325E5D62E742D9B96C30B6515A5CD2F1F64C5DA4B193C03F070E0D2068086C000000000000000451C90E00DC0E35B7DB5FB8C134_}
x{FF0020DDA4F260D31F01ED44D0D31FD166BAF2A1F80001D307D4D1821804A817C80073FB0201FB00A4C8CB1FC9ED54}
x{0000000D}Vemos una estructura que se almacena en el DHT del workchain especificado. Por ejemplo, en el campo storage.balance se encuentra el balance actual de la cuenta, en storage.state.code — código del contrato inteligente, y en storage.state.data — sus datos actuales. Tenga en cuenta que el almacenamiento de datos de TON — Cell, celdas — es jerárquico, cada celda puede tener tanto sus propios datos como celdas secundarias. Esto se muestra como sangrías en las últimas líneas.
Construcción del contrato inteligente
Ahora vamos a crear tal estructura (se llama BOC — bag of cells) con el lenguaje Fift. Afortunadamente, no tendrás que escribir el contrato inteligente por tu cuenta — en la carpeta crypto/block del archivo con los fuentes hay un archivo new-wallet.fif, que nos ayudará a crear una nueva cartera. La copiaremos en la carpeta con el cliente construido (~\/liteclient-build, si seguiste las instrucciones anteriores). El contenido de este archivo ya lo proporcioné arriba como ejemplo de código en Fift.
Ejecutamos este archivo de la siguiente manera:
.\/crypto\/fift -I"\/crypto\/fift" new-wallet.fifAquí <source-directory> debe ser reemplazado por la ruta a los fuentes descomprimidos (desafortunadamente, no se puede usar el símbolo «~», se necesita la ruta completa). En lugar de usar la clave -I se puede definir la variable de entorno FIFTPATH y colocar esta ruta en ella.
Dado que hemos lanzado Fift con el nombre de archivo new-wallet.fif, se ejecutará y finalizará. Si se omite el nombre del archivo, se puede jugar con el intérprete en modo interactivo.
La consola debería mostrar algo como esto después de la ejecución:
StateInit: x{34_}
x{FF0020DDA4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54}
x{0000000055375F730EDC2292E8CB15C42E8036EE9C25AA958EE002D2DE48A205E3A3426B}
new wallet address = -1 : 4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2
0f9PzVILj8yglrVn1zS-NSjtxr7QBfaTCp7JrBqnFPIR8nhZ
signing message: x{00000000}
Mensaje externo para la inicialización es x{89FEE120E20C7E953E31546F64C23CD654002C1AA919ADD24DB12DDF85C6F3B58AE41198A28AD8DAF3B9588E7A629252BA3DB88F030D00BC1016110B2073359EAC3C13823C53245B65D056F2C070B940CDA09789585935C7ABA4D2AD4BED139281CFA1200000001_}
x{FF0020DDA4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54}
x{0000000055375F730EDC2292E8CB15C42E8036EE9C25AA958EE002D2DE48A205E3A3426B}
B5EE9C724104030100000000D60002CF89FEE120E20C7E953E31546F64C23CD654002C1AA919ADD24DB12DDF85C6F3B58AE41198A28AD8DAF3B9588E7A629252BA3DB88F030D00BC1016110B2073359EAC3C13823C53245B65D056F2C070B940CDA09789585935C7ABA4D2AD4BED139281CFA1200000001001020084FF0020DDA4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED5400480000000055375F730EDC2292E8CB15C42E8036EE9C25AA958EE002D2DE48A205E3A3426B6290698B
(Guardado en el archivo new-wallet-query.boc)Esto significa que la cartera con el identificador -1:4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2 (o, lo que es lo mismo, 0f9PzVILj8yglrVn1zS-NSjtxr7QBfaTCp7JrBqnFPIR8nhZ) ha sido creada exitosamente. El código correspondiente se encontrará en el archivo después de la ejecución. Ten en cuenta que aquí se utiliza otro lenguaje, ensamblador, para la TON Virtual Machine (no entraré en detalles sobre ello), cuyas instrucciones se colocarán en la blockchain., su dirección estará en new-wallet.addr, y la clave privada en new-wallet.pk (tenga cuidado: volver a ejecutar el script sobrescribirá estos archivos).
Por supuesto, la red TON aún no conoce esta cartera, ya que solo se almacena en estos archivos. Ahora hay que cargarla en la red. Sin embargo, el problema es que para crear un contrato inteligente es necesario pagar una comisión, y el saldo de su cuenta aún es cero.
En modo operativo, este problema se resolverá comprando gramos en el intercambio (o transfiriéndolos desde otra cartera). Pero en este modo de prueba actual, hay un contrato inteligente especial que se puede solicitar hasta 20 gramos de forma gratuita.
Formando una solicitud a un contrato inteligente ajeno
Hacemos la solicitud al contrato inteligente que distribuye gramos a diestro y siniestro de la siguiente manera. En la misma carpeta crypto/block buscamos el archivo 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 ."mensaje envolvente: " <s csr. cr
<b b{1000100} s, wc 8 i, wallet_addr 256 u, 0 gram, b{00} s,
swap <s b>
dup ."mensaje externo resultante: " <s csr. cr
2 boc+>B dup Bx. cr
"consulta-billetera.boc" B>archivoTambién lo guardaremos en la carpeta con el cliente compilado, pero modificaremos la quinta línea: antes de la línea «constant dest_addr« sustituiremos por la dirección de la cartera que ha creado anteriormente (completa, no abreviada). No es necesario escribir «-1:» al inicio, en su lugar escriba «0x» al comienzo.
Además, se puede cambiar la línea 6.666 Gramo* / cantidad constante — es la cantidad en gramos que solicitas (no más de 20). Incluso si indicas un número entero, deja el punto decimal.
Finalmente, necesitas corregir la línea 0x00000011 número de secuencia constante. El primer número aquí es el número de secuencia actual, que se almacena en la cuenta que emite gramos. ¿De dónde obtenerlo? Como se mencionó anteriormente, inicia el cliente y ejecuta:
last
getaccount -1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0dAl final de los datos del contrato inteligente estará
...
x{FF0020DDA4F260D31F01ED44D0D31FD166BAF2A1F80001D307D4D1821804A817C80073FB0201FB00A4C8CB1FC9ED54}
x{0000000D}El número 0000000D (tú tendrás un número mayor) es el número de secuencia que debes insertar en testgiver.fif.
Todo listo, guardamos el archivo y ejecutamos (./crypto/fift testgiver.fif). En la salida obtendremos el archivo wallet-query.boc. Esto es lo que se ha formulado mensaje a un contrato inteligente ajeno — solicitud «transfiere tantos gramos a esta cuenta».
Usando el cliente, lo cargamos en la red:
> sendfile wallet-query.boc
[ 1][t 1][1558747399.456575155][test-lite-client.cpp:577][!testnode] enviando consulta desde el archivo wallet-query.boc
[ 3][t 2][1558747399.500236034][test-lite-client.cpp:587][!query] el estado del mensaje externo es 1Si ahora llamamos last, y luego volvemos a solicitar el estado de la cuenta a la que pedimos los gramos, deberíamos ver que su número de secuencia ha aumentado en uno — esto significa que envió el dinero a nuestra cuenta.
Queda un último paso — cargamos el código de nuestra billetera (su saldo ya está acreditado, pero sin el código del contrato inteligente no podremos gestionarlo). Ejecutamos sendfile new-wallet-query.boc — y eso es todo, tienes tu propia billetera en la red TON (aunque sea solo de prueba).
Creación de transacciones salientes
Para transferir dinero desde el saldo de la cuenta creada, hay un archivo crypto/block/wallet.fif, que también debe colocarse en la carpeta con el cliente compilado.
Similar a los pasos anteriores, en él necesitas corregir la cantidad que estás transfiriendo, la dirección del destinatario (dest_addr), y el seqno de tu billetera (que es igual a 1 después de la inicialización de la billetera y aumenta en 1 después de cada transacción saliente — podrás verlo solicitando el estado de tu cuenta). Para pruebas, puedes usar, por ejemplo, mi billetera — 0x4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2.
Al iniciar (./crypto/fift wallet.fif) el script tomará la dirección de tu billetera (desde donde transfieres) y su clave privada de los archivos new-wallet.addr y new-wallet.pk, y el mensaje obtenido se escribirá en después de la ejecución. Ten en cuenta que aquí se utiliza otro lenguaje, ensamblador, para la TON Virtual Machine (no entraré en detalles sobre ello), cuyas instrucciones se colocarán en la blockchain..
Como antes, para realizar la transacción directamente, llamamos sendfile new-wallet-query.boc en el cliente. Después de esto, no olvidemos actualizar el estado de la blockchain (last) y comprobamos que el saldo y el seqno de nuestra billetera han cambiado (getaccount).

Y eso es todo, ahora sabemos cómo crear contratos inteligentes en TON y enviarles solicitudes. Como podemos ver, la funcionalidad actual es suficiente para, por ejemplo, crear una billetera más amigable con una interfaz gráfica (aunque se espera que esté disponible como parte del mensajero).
Solo los usuarios registrados pueden participar en la encuesta. , por favor.
¿Estás interesado en la continuación de artículos sobre TON, TVM, Fift?
Sí, estoy esperando la finalización del ciclo de artículos con una visión general de TON
Sí, me gustaría leer más sobre el lenguaje Fift
Sí, quiero saber más sobre la Máquina Virtual TON y el ensamblador para ella
No, no me interesa nada de esto
Votaron 39 usuarios. Se abstuvieron 12 usuarios.
¿Qué opinas sobre los planes de Telegram para lanzar TON?
Tengo grandes esperanzas para este proyecto
Solo sigo su desarrollo con interés
Estoy escéptico, dudo de su éxito
Tiendo a considerar esta iniciativa fallida, innecesaria para las masas
Votaron 47 usuarios. 12 usuarios se abstuvieron.
Fuente: habr.com

