ProHoster > Blog > administração > Cliente de teste TON (Telegram Open Network) e nova linguagem Fift para contratos inteligentes
Cliente de teste TON (Telegram Open Network) e nova linguagem Fift para contratos inteligentes
Há mais de um ano, soube-se dos planos do mensageiro Telegram de lançar sua própria rede descentralizada Rede Aberta Telegram. Foi então disponibilizado um volumoso documento técnico, supostamente escrito por Nikolai Durov e que descrevia a estrutura da futura rede. Para quem perdeu, recomendo que leia minha releitura deste documento (parte 1, parte 2; a terceira parte, infelizmente, ainda está acumulando poeira nas correntes de ar).
Desde então, não houve nenhuma notícia significativa sobre o estado do desenvolvimento da TON até alguns dias atrás (em um dos canais não oficiais) o link para a página não apareceu https://test.ton.org/download.html, onde estão localizados:
◦ ton-test-liteclient-full.tar.xz — fontes de um cliente leve para a rede de testes TON;
◦ ton-lite-client-test1.config.json — arquivo de configuração para conexão à rede de teste;
◦ README — informações sobre a construção e lançamento do cliente;
◦ HOWTO — instruções passo a passo sobre como criar um contrato inteligente usando um cliente;
◦ ton.pdf — documento atualizado (datado de 2 de março de 2019) com uma visão técnica da rede TON;
◦ tvm.pdf — descrição técnica do TVM (TON Virtual Machine, máquina virtual TON);
◦ tblkch.pdf — descrição técnica da blockchain TON;
◦ quintabase.pdf — descrição da nova linguagem Fift, projetada para criar contratos inteligentes em TON.
Repito, não houve confirmação oficial da página e de todos esses documentos do Telegram, mas o volume desses materiais os torna bastante plausíveis. Inicie o cliente publicado por sua própria conta e risco.
Construindo um cliente de teste
Primeiro, vamos tentar construir e executar um cliente de teste - felizmente, README descreve esse processo simples em detalhes. Farei isso usando o macOS 10.14.5 como exemplo; não posso garantir o sucesso da compilação em outros sistemas.
Baixe e descompacte arquivo de origem. É importante baixar a versão mais recente, pois a compatibilidade com versões anteriores não é garantida neste estágio.
Certifique-se de que as versões mais recentes do make, cmake (versão 3.0.2 ou superior), OpenSSL (incluindo arquivos de cabeçalho C), g++ ou clang estejam instaladas no sistema. Não precisei instalar nada, tudo se encaixou na hora.
Vamos supor que as fontes estejam descompactadas em uma pasta ~/lite-client. Separadamente dela, crie uma pasta vazia para o projeto montado (por exemplo, ~/liteclient-build), e a partir dele (cd ~/liteclient-build) chame os comandos:
Se tudo for feito corretamente, você deverá ver algo assim:
Como podemos ver, existem poucos comandos disponíveis:
◦ help — exibe esta lista de comandos;
◦ quit - sair;
◦ time — mostra a hora atual no servidor;
◦ status — mostra a conexão e o status do banco de dados local;
◦ last — atualize o estado do blockchain (baixe o último bloco). É importante executar este comando antes de qualquer solicitação para ter certeza de ver o estado atual da rede.
◦ sendfile<filename> — carregue um arquivo local para a rede TON. É assim que ocorre a interação com a rede – incluindo, por exemplo, a criação de novos contratos inteligentes e solicitações de transferência de fundos entre contas;
◦ getaccount<address> — mostra a corrente (no momento em que o comando foi executado) last) o status da conta com o endereço especificado;
◦ privkey<filename> — carregue a chave privada de um arquivo local.
Se, ao iniciar o cliente, você transferir uma pasta para ele usando a opção -D, então ele adicionará o último bloco do masterchain:
Agora podemos passar para coisas mais interessantes - aprender a linguagem Fift, tentar compilar um contrato inteligente (por exemplo, criar uma carteira de teste), carregá-lo na rede e tentar transferir fundos entre contas.
Idioma Quinto
Do documento quintabase.pdf você pode descobrir que a equipe do Telegram criou uma nova linguagem de pilha para criar contratos inteligentes Quinto (aparentemente pelo numeral quinto, semelhante ao Forth, uma linguagem com a qual o Fifth tem muito em comum).
O documento é bastante volumoso, 87 páginas, e não vou recontar detalhadamente o seu conteúdo no âmbito deste artigo (pelo menos porque ainda não terminei de lê-lo :). Vou me concentrar nos pontos principais e dar alguns exemplos de código nesta linguagem.
Em um nível básico, a sintaxe do Fift é bastante simples: seu código consiste em palavras, geralmente separados por espaços ou quebras de linha (caso especial: algumas palavras não requerem um separador depois de si mesmas). Qualquer palavra é uma sequência de caracteres que diferencia maiúsculas de minúsculas que corresponde a um determinado definição (aproximadamente, o que o intérprete deve fazer ao encontrar esta palavra). Se não houver definição de uma palavra, o intérprete tenta analisá-la como um número e colocá-la na pilha. A propósito, os números aqui são - de repente - inteiros de 257 bits, e não há frações - mais precisamente, eles imediatamente se transformam em um par de inteiros, formando o numerador e o denominador de uma fração racional.
As palavras tendem a interagir com os valores no topo da pilha. Um tipo separado de palavras - prefixo — não usa a pilha, mas os caracteres subsequentes do arquivo de origem. Por exemplo, é assim que os literais de string são implementados - o caractere de aspas (") é uma palavra de prefixo que procura a próxima cotação (de fechamento) e coloca a string entre elas na pilha. One-liners se comportam da mesma maneira (//) e multilinha (/*) comentários.
É aqui que termina quase toda a estrutura interna da linguagem. Todo o resto (incluindo construções de controle) é definido como palavras (sejam internas, como operações aritméticas e a definição de novas palavras; ou definidas na "biblioteca padrão" Fift.fif, que está na pasta crypto/fift nas fontes).
Um programa de exemplo simples no Fift:
{ dup =: x dup * =: y } : setxy
3 setxy x . y . x y + .
7 setxy x . y . x y + .
A primeira linha define uma nova palavra setxy (observe o prefixo {, que cria um bloco antes do de fechamento } e prefixo :, que na verdade define a palavra). setxy pega um número do topo da pilha e o define (ou redefine) como global constantex, e o quadrado deste número como uma constante y (Dado que os valores das constantes podem ser redefinidos, prefiro chamá-las de variáveis, mas sigo a convenção de nomenclatura da linguagem).
As próximas duas linhas colocam um número na pilha e chamam setxy, então os valores das constantes são exibidos x, y (a palavra é usada para saída .), ambas as constantes são colocadas na pilha, somadas e o resultado também é impresso. Como resultado veremos:
3 9 12 ok
7 49 56 ok
(A linha “ok” é impressa pelo intérprete quando termina de processar a linha atual no modo de entrada interativo)
Este arquivo de aparência assustadora serve para criar um contrato inteligente - ele será colocado em um arquivo new-wallet-query.boc após a execução. Observe que outra linguagem assembly é usada aqui para a Máquina Virtual TON (não vou me alongar sobre ela em detalhes), cujas instruções serão colocadas no blockchain.
Assim, o montador para TVM é escrito em Fift - as fontes deste montador estão no arquivo crypto/fift/Asm.fif e estão conectados no início do código acima.
O que posso dizer, aparentemente Nikolai Durov adora criar novas linguagens de programação :)
Criando um contrato inteligente e interagindo com a TON
Então, vamos supor que montamos o cliente TON e o intérprete Fift conforme descrito acima e nos familiarizamos com a linguagem. Como criar um contrato inteligente agora? Isso está descrito no arquivo HOWTO, anexado às fontes.
Contas em TON
Como descrevi em Revisão de TONELADAS, esta rede contém mais de um blockchain - existe um comum, o chamado. "cadeia mestre", bem como um número arbitrário de "cadeias de trabalho" adicionais, identificadas por um número de 32 bits. O masterchain possui identificador -1, além dele também pode ser utilizado um workchain “base” com identificador 0. Cada workchain pode ter sua própria configuração. Internamente, cada workchain é dividida em shardchains, mas esse é um detalhe de implementação que não precisa ser lembrado.
Dentro de uma cadeia de trabalho, muitas contas são armazenadas e possuem seus próprios identificadores account_id. Para a cadeia mestre e a cadeia de trabalho zero, elas têm 256 bits de comprimento. Assim, o identificador da conta é escrito, por exemplo, assim:
Este é o formato “bruto”: primeiro o ID da cadeia de trabalho, depois dois pontos e o ID da conta em notação hexadecimal.
Além disso, existe um formato abreviado - o número da cadeia de trabalho e o endereço da conta são codificados em formato binário, uma soma de verificação é adicionada a eles e tudo isso é codificado em Base64:
Ef+BVndbeTJeXWLnQtm5bDC2UVpc0vH2TF2ksZPAPwcODSkb
Conhecendo este formato de registro, podemos solicitar o estado atual de uma conta através de um cliente de teste utilizando o comando
[ 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}
Vemos a estrutura que está armazenada no DHT da cadeia de trabalho especificada. Por exemplo, no campo storage.balance é o saldo da conta corrente, em storage.state.code - código de contrato inteligente, e em storage.state.data - seus dados atuais. Observe que o armazenamento de dados TON - Célula, células - é semelhante a uma árvore, cada célula pode ter seus próprios dados e células filhas. Isso é mostrado como recuo nas últimas linhas.
Construindo um contrato inteligente
Agora vamos criar nós mesmos essa estrutura (chama-se BOC - saco de células) usando a linguagem Fift. Felizmente, você não precisa redigir um contrato inteligente - na pasta crypto/block existe um arquivo do arquivo de origem new-wallet.fif, o que nos ajudará a criar uma nova carteira. Vamos copiá-lo para a pasta com o cliente montado (~/liteclient-build, se você seguiu as instruções acima). Citei seu conteúdo acima como um exemplo de código no Fift.
é <source-directory> deve ser substituído pelo caminho para as fontes descompactadas (o símbolo “~”, infelizmente, não pode ser usado aqui, é necessário o caminho completo). Em vez de usar uma chave -I você pode definir uma variável de ambiente FIFTPATH e coloque esse caminho nele.
Desde que lançamos o Fift com o nome do arquivo new-wallet.fif, ele irá executá-lo e sair. Se você omitir o nome do arquivo, poderá brincar interativamente com o intérprete.
Após a execução, algo assim deverá ser exibido no console:
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)
Isso significa que a carteira com o ID -1:4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2 (ou, o que é o mesmo, 0f9PzVILj8yglrVn1zS-NSjtxr7QBfaTCp7JrBqnFPIR8nhZ) criado com sucesso. O código correspondente estará no arquivo new-wallet-query.boc, o endereço dele está em new-wallet.addr, e a chave privada está em new-wallet.pk (tenha cuidado - executar o script novamente substituirá esses arquivos).
É claro que a rede TON ainda não conhece esta carteira, ela é armazenada apenas na forma desses arquivos. Agora ele precisa ser carregado na rede. Porém, o problema é que para criar um contrato inteligente você precisa pagar uma comissão e o saldo da sua conta ainda é zero.
No modo de trabalho, esse problema será resolvido comprando gramas na bolsa (ou transferindo de outra carteira). Pois bem, no modo de teste atual, foi criado um contrato inteligente especial, do qual você pode solicitar até 20 gramas sem mais nem menos.
Gerando uma solicitação para o contrato inteligente de outra pessoa
Fazemos uma solicitação a um contrato inteligente que distribui gramas a torto e a direito assim. Na mesma pasta crypto/block achar arquivo 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
Também salvaremos na pasta com o cliente montado, mas corrigiremos a quinta linha - antes da linha “constant dest_addr". Vamos substituí-lo pelo endereço da carteira que você criou anteriormente (completo, não abreviado). Não há necessidade de escrever “-1:” no início, em vez disso coloque “0x” no início.
Você também pode alterar a linha 6.666 Gram*/ constant amount — esta é a quantidade em gramas que você está solicitando (não mais que 20). Mesmo se você especificar um número inteiro, deixe a vírgula decimal.
Finalmente, você precisa corrigir a linha 0x00000011 constant seqno. O primeiro número aqui é o número de sequência atual, que é armazenado na conta que emite gramas. Onde posso obtê-lo? Conforme declarado acima, inicie o cliente e execute:
last
getaccount -1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0d
No final, os dados do contrato inteligente conterão
O número 0000000D (o seu será maior) é o número de sequência que deve ser substituído em testgiver.fif.
É isso, salve o arquivo e execute (./crypto/fift testgiver.fif). A saída será um arquivo wallet-query.boc. Isto é o que é formado сообщение para o contrato inteligente de outra pessoa - uma solicitação “transfira tantos gramas para tal e tal conta”.
Usando o cliente, fazemos o upload para a rede:
> 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
Se você ligar agora laste, em seguida, solicitar novamente o status da conta da qual solicitamos gramas, veremos que seu número de sequência aumentou em um - isso significa que ele enviou dinheiro para nossa conta.
Resta o último passo - baixar o código da nossa carteira (seu saldo já foi reposto, mas sem o código do contrato inteligente não poderemos gerenciá-lo). Nós realizamos sendfile new-wallet-query.boc — e pronto, você tem sua própria carteira na rede TON (mesmo que seja apenas uma carteira de teste por enquanto).
Criando transações de saída
Para transferir dinheiro do saldo da conta criada, existe um arquivo crypto/block/wallet.fif, que também precisa ser colocado na pasta com o cliente montado.
Semelhante às etapas anteriores, você precisa ajustar o valor que está transferindo, o endereço do destinatário (dest_addr) e o seqno da sua carteira (é igual a 1 após a inicialização da carteira e aumenta em 1 após cada transação de saída - você pode veja solicitando o status da sua conta). Para testes, você pode usar, por exemplo, minha carteira - 0x4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2.
No arranque (./crypto/fift wallet.fif) o script pegará o endereço da sua carteira (de onde você transfere) e sua chave privada dos arquivos new-wallet.addr и new-wallet.pk, e a mensagem recebida será gravada em new-wallet-query.boc.
Como antes, para realizar a transação diretamente, ligue sendfile new-wallet-query.boc no cliente. Depois disso, não esqueça de atualizar o estado do blockchain (last) e verifique se o saldo e o seqno da nossa carteira foram alterados (getaccount <account_id>).
Só isso, agora podemos criar contratos inteligentes no TON e enviar solicitações para eles. Como você pode ver, a funcionalidade atual já é suficiente para, por exemplo, tornar uma carteira mais amigável e com interface gráfica (porém, espera-se que ela já esteja disponível como parte do mensageiro).
Apenas usuários registrados podem participar da pesquisa. Entrarpor favor
Tem interesse em continuar os artigos com análises de TON, TVM, Fift?
Sim, estou aguardando a conclusão da série de artigos com uma visão geral do TON
Sim, é interessante ler mais sobre a linguagem Fift
Sim, quero aprender mais sobre a TON Virtual Machine e seu montador
Não, nada disso é interessante
39 usuários votaram. 12 usuários se abstiveram.
O que você acha dos planos do Telegram para lançar o TON?
Tenho grandes esperanças neste projeto
Estou apenas acompanhando seu desenvolvimento com interesse.
Sou cético e duvido do seu sucesso.
Estou inclinado a considerar esta iniciativa um fracasso e desnecessária para as grandes massas