Há mais de um ano, ficou conhecido o plano do messenger Telegram de lançar sua própria rede descentralizada Telegram Open Network . Então, um volumoso documento técnico ficou disponível, o qual, presumivelmente, foi escrito por Nikolai Durov e descreveu a estrutura da futura rede. Para aqueles que perderam, recomendo que você leia minha recontagem deste documento ( parte 1 , parte 2 ; a terceira parte, infelizmente, ainda está acumulando poeira nas cópias de rascunho).
Desde então, não havia notícias significativas sobre o status de desenvolvimento da TON, até alguns dias atrás (em um dos canais não oficiais ) um link para a página https://test.ton.org/download.html apareceu , onde estão:
◦ ton-test-liteclient-full.tar.xz - fontes de clientes leves para a rede de teste TON;
◦ ton-lite-client-test1.config.json - arquivo de configuração para conectar-se a uma rede de teste;
AD README - informações sobre como construir e iniciar o cliente;
TO COMO FAZER - instruções passo a passo sobre como criar um contrato inteligente usando um cliente;
◦ ton.pdf - documento atualizado (2 de março de 2019) com uma visão geral técnica da rede TON;
◦ tvm.pdf - descrição técnica do TVM (TON Virtual Machine, TON virtual machine);
Bl tblkch.pdf - descrição técnica da blockchain TON;
◦ fiftbase.pdf - uma 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 pelo Telegram, mas o volume desses materiais os torna bastante plausíveis. Execute um cliente publicado por sua conta e risco .
Compilação do cliente de teste
Primeiro, vamos tentar criar e executar um cliente de teste - felizmente, o README descreve esse processo simples em detalhes. Farei isso no exemplo do macOS 10.14.5, não posso garantir o sucesso da montagem em outros sistemas.
Baixe e descompacte o arquivo com os códigos-fonte . É importante fazer o download da versão mais recente, pois a compatibilidade com versões anteriores não é garantida neste estágio.
Garantimos 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 reinstalar nada, tudo reunido imediatamente.
Suponha que as fontes sejam descompactadas na pasta ~/lite-client
. Separadamente, criamos uma pasta vazia para o projeto montado (por exemplo, ~/liteclient-build
) e a partir dela ( cd ~/liteclient-build
) chamamos os comandos:
cmake ~/lite-client cmake --build . --target test-lite-client

Para criar o intérprete de linguagem Fift para contratos inteligentes (veja abaixo), também chamamos
cmake --build . --target fift
Faça o download do arquivo de configuração atual para conectar-se à rede de teste e coloque-o na pasta com o cliente montado.
Feito , você pode iniciar o cliente:
./test-lite-client -C ton-lite-client-test1.config.json
Se tudo for feito corretamente, você deverá ver algo assim:

Como você pode ver, existem alguns comandos disponíveis:
◦ help
- exibe esta lista de comandos;
quit
- sair;
◦ time
- mostra a hora atual no servidor;
◦ status
- mostra o status da conexão e o banco de dados local;
◦ last
- atualiza o estado da blockchain (carrega o último bloco). É importante executar este comando antes de qualquer solicitação para garantir que você veja exatamente o estado atual da rede.
◦ sendfile
<filename>
- carrega um arquivo local na rede TON. Essa é 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 o status da conta atual (no momento em que o last
comando foi executado) com o endereço especificado;
Key privkey
<filename>
- carrega a chave privada do arquivo local.
Se, no lançamento do cliente, você passa a pasta para ela usando a opção -D
, ela adiciona o último bloco da cadeia principal nele:
./test-lite-client -C ton-lite-client-test1.config.json -D ~/ton-db-dir
Agora podemos avançar para coisas mais interessantes - aprender a linguagem Fift, tentar compilar um contrato inteligente (por exemplo, criar uma carteira de teste), carregá-la na rede e tentar transferir fundos entre contas.
Fift language
No documento fiftbase.pdf, você pode descobrir que, para criar contratos inteligentes, a equipe do Telegram criou uma nova linguagem de pilha Fift (aparentemente, a partir do quinto do numeral, por analogia com a Forth - uma linguagem com a qual a Fift tem muito em comum).
O documento é bastante volumoso, com 87 páginas, e não vou recontar seu conteúdo em detalhes na estrutura deste artigo (pelo menos porque eu mesmo não terminei de lê-lo :). Vou abordar os pontos principais e dar alguns exemplos de código nessa linguagem.
Em um nível básico, a sintaxe de Fift é bastante simples: seu código consiste em palavras , geralmente separadas por espaços ou quebras de linha (caso especial: algumas palavras não requerem um delimitador depois de si). Qualquer palavra é uma sequência de caracteres que diferencia maiúsculas de minúsculas que corresponde a alguma definição (grosso modo, o que o intérprete deve fazer quando encontra essa palavra). Se não houver definição da 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 - números inteiros de 257 bits, mas não há números fracionários - mais precisamente, eles imediatamente se transformam em um par de números inteiros, formando o numerador e o denominador de uma fração racional.
As palavras normalmente interagem com os significados no topo da pilha. Um tipo separado de palavras - prefixo - não usa a pilha, mas os caracteres subseqüentes do arquivo de origem. Por exemplo, literais de string são implementados dessa maneira - o caractere "aspas" ( "
) é uma palavra de prefixo que procura a próxima aspas (de fechamento) e coloca a string entre eles na pilha. As linhas simples ( //
) e as múltiplas linhas ( /*
) se comportam da mesma maneira. comentários.
Sobre isso, quase toda a estrutura interna da linguagem termina. Todo o resto (incluindo estruturas de controle) é definido como palavras (internas, como operações aritméticas e a definição de novas palavras; ou definidas na "biblioteca padrão" Fift.fif
, que fica na crypto/fift
na fonte).
Um exemplo simples de um programa Fift:
{ dup =: x dup * =: y } : setxy 3 setxy x . y . xy + . 7 setxy x . y . xy + .
A primeira linha define a nova palavra setxy
(observe o prefixo {
, que cria o bloco antes do fechamento }
e o prefixo setxy
que realmente define a palavra). setxy
pega um número no topo da pilha, define (ou redefine) como uma constante global x
o quadrado desse número como uma constante y
(dado que os valores das constantes podem ser redefinidos, prefiro chamá-los de variáveis, mas sigo a nomeação no idioma).
Nas próximas duas linhas, um número é colocado na pilha, setxy
é setxy
, em seguida, os valores das constantes x
, y
são exibidos (a palavra é usada para saída .
) .
Ambas as constantes são colocadas na pilha, somadas e o resultado também é exibido. Como resultado, veremos:
3 9 12 ok 7 49 56 ok
(O intérprete imprime a linha "ok" quando termina de processar a linha atual no modo de entrada interativa)
Bem, um exemplo de código completo:
"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 <bb{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 <bb{1000100} s, wc 8 i, wallet_addr 256 u, b{000010} s, swap <ss, b{0} s, swap B, swap <ss, 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
Este arquivo de aparência assustadora foi projetado para criar um contrato inteligente - será colocado no new-wallet-query.boc
após a execução. Observe que aqui é usada outra linguagem de montagem para a máquina virtual TON (não vou me deter nela em detalhes), cujas instruções serão colocadas na blockchain.
Portanto, o assembler para TVM é escrito em Fift - as fontes desse assembler estão no arquivo crypto/fift/Asm.fif
e estão conectadas 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 o TON
Portanto, suponha que reunamos um cliente TON e um intérprete Fift, conforme descrito acima, e nos familiarizamos com o idioma. Como criar um contrato inteligente agora? Isso é descrito no arquivo HOWTO anexado à fonte.
Contas TON
Como descrevi na revisão TON , essa rede contém mais de um blockchain - há um comum, o chamado “Cadeia principal”, bem como um número arbitrário de “cadeias de trabalho” adicionais identificadas por um número de 32 bits. A cadeia mestre possui um identificador -1, além disso, também pode ser usada uma cadeia de trabalho "básica" com o identificador 0. Cada cadeia de trabalho pode ter sua própria configuração. Internamente, cada grupo de trabalho é dividido em shardchains, mas esse já é um detalhe da implementação, que não precisa ser lembrado.
Muitas contas são armazenadas em uma cadeia de trabalho, com seus próprios identificadores account_id. Para a cadeia mestre e a cadeia de trabalho zero, eles têm um comprimento de 256 bits. Assim, o identificador da conta é escrito, por exemplo, assim:
-1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0d
Este é um formato "bruto": primeiro, o identificador da cadeia de trabalho, depois dois pontos e o identificador da conta em notação hexadecimal.
Além disso, há um formato reduzido - 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 esse formato de gravação, podemos solicitar o status atual de uma conta através de um cliente de teste usando o comando
getaccount -1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0d
Temos uma resposta como esta:
[ 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}
-client.cpp: [ 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}
por -1: 8156775B79325E5D62E742D9B96C30B6515A5CD2F1F64C5DA4B193C03F070E0D com respeito a blocos (-1,8000000000000000,72355): F566005749C1B97F18EDE013EBA7A054B9014961BC1AD91F475B9082919A2296: 1BD5DE54333164025EE39D389ECE2E93DA2871DA616D488253953E52B50DC03F e [ 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 é armazenada no DHT da cadeia de trabalho especificada. Por exemplo, no campo storage.balance
é o saldo da conta atual, em storage.state.code
é o código do contrato inteligente e em storage.state.data
são seus dados atuais. Observe que o armazenamento de dados TON - célula, células - é uma árvore, cada célula pode ter seus próprios dados, bem como células filho. Isso é mostrado como recuo nas últimas linhas.
Montagem de contrato inteligente
Agora vamos criar essa estrutura (ela é chamada BOC - saco de células ) usando a linguagem Fift. Felizmente, você não precisará escrever um contrato inteligente - na pasta de crypto/block
do arquivo de origem, há um arquivo new-wallet.fif
que nos ajudará a criar uma nova carteira. Copie-o para a pasta com o cliente montado ( ~/liteclient-build
, se você ~/liteclient-build
instruções acima). Eu citei seu conteúdo acima como um exemplo de código no Fift.
Executamos este arquivo da seguinte maneira:
./crypto/fift -I"<source-directory>/crypto/fift" new-wallet.fif
Aqui, <source-directory>
deve ser substituído pelo caminho para as fontes descompactadas (o símbolo "~" não pode ser usado aqui, infelizmente, você precisa do caminho completo). Em vez de usar a -I
você pode definir a FIFTPATH
ambiente FIFTPATH
e colocar esse caminho nela.
Desde que lançamos o Fift com o nome de arquivo new-wallet.fif
, ele será executado e concluído. Se você omitir o nome do arquivo, poderá tocar com o intérprete no modo interativo.
Após a execução, algo como isto deve 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)
} 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 identificador -1:4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2
(ou, que é a mesma coisa, 0f9PzVILj8yglrVn1zS-NSjtxr7QBfaTCp7JrBqnFPIR8nhZ
). O código correspondente new-wallet-query.boc
no new-wallet-query.boc
, seu endereço em new-wallet.addr
e a chave privada em new-wallet.pk
(cuidado: reiniciar o script substituirá esses arquivos).
Obviamente, a rede TON ainda não conhece essa carteira, ela é armazenada apenas na forma desses arquivos. Agora você precisa enviá-lo para a rede. É verdade que 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). Bem, no modo de teste atual, foi instituído um contrato inteligente especial, no qual você pode solicitar até 20 gramas assim.
Solicite um contrato inteligente, distribuindo gramas à esquerda e à direita, faça-o. Na mesma pasta de crypto/block
, encontramos o 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 // bx --> 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) <bb{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 <bb{1000100} s, wc 8 i, wallet_addr 256 u, 0 Gram, b{00} s, swap <ss, b> dup ."resulting external message: " <s csr. cr 2 boc+>B dup Bx. cr "wallet-query.boc" B>file
Também o salvamos na pasta com o cliente montado, mas constant dest_addr
a quinta linha - antes da linha " constant dest_addr
". Substitua-o pelo endereço da carteira que você criou anteriormente (cheio, não abreviado). "-1:" você não precisa escrever 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ê solicita (não mais que 20). Mesmo se você especificar um número inteiro, deixe o ponto 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 os gramas. De onde obtê-lo? Como mencionado acima, inicie o cliente e execute:
last getaccount -1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0d
No final, os dados do contrato inteligente serão
... x{FF0020DDA4F260D31F01ED44D0D31FD166BAF2A1F80001D307D4D1821804A817C80073FB0201FB00A4C8CB1FC9ED54} x{0000000D}
O número 0000000D (você terá mais) é o número da sequência, que deve ser substituído em testgiver.fif
.
É isso, salve o arquivo e execute ( ./crypto/fift testgiver.fif
). A saída será o wallet-query.boc
. Esta é a mensagem formada para o contrato inteligente de outra pessoa - a solicitação é "transferir 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 agora ligarmos por last
e depois solicitar novamente o status da conta da qual solicitamos gramas, veremos que o número de sequência aumentou em um - isso significa que ele enviou dinheiro para nossa conta.
O último passo permanece - carregamos o código da nossa carteira (seu saldo já foi reabastecido, mas sem o código do contrato inteligente, não poderemos gerenciá-lo). sendfile new-wallet-query.boc
- e é isso, você tem sua própria carteira na rede TON (embora por enquanto apenas uma de teste).
Criar transações de saída
Para transferir dinheiro do saldo da conta criada, existe um crypto/block/wallet.fif
, que também precisa ser colocado na pasta com o cliente coletado.
Semelhante às etapas anteriores, você precisa ajustar o valor que transfere, o endereço do destinatário (dest_addr) e o número da sua carteira (é 1 após a inicialização da carteira e aumenta em 1 após cada transação de saída - você pode vê-la solicitando o status da sua conta) . Para testes, você pode usar, por exemplo, minha carteira - 0x4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2
.
Quando você executa ( ./crypto/fift wallet.fif
), o script pega o endereço da sua carteira (de onde você a transfere) e sua chave privada dos arquivos new-wallet.addr
e new-wallet.pk
e grava a mensagem recebida em new-wallet-query.boc
.
Como antes, para executar a transação diretamente, chamamos sendfile new-wallet-query.boc
no cliente. Depois disso, não se esqueça de atualizar o estado da blockchain ( last
) e verifique se o saldo e o seqno da nossa carteira mudaram ( getaccount <account_id>
).

Isso é tudo, agora podemos criar contratos inteligentes em TON e enviar solicitações a eles. Como você pode ver, a funcionalidade atual já é suficiente para, por exemplo, criar uma carteira mais amigável com uma interface gráfica (no entanto, espera-se que ela fique disponível como parte do messenger).