Client de test TON (Telegram Open Network) et le nouveau langage Fift pour les contrats intelligents

Il y a plus d'un an, il est devenu connu des projets du messager Telegram de publier son propre réseau décentralisé Telegram Open Network . Puis un volumineux document technique est devenu disponible, qui, vraisemblablement, a été écrit par Nikolai Durov et décrit la structure du futur réseau. Pour ceux qui ont raté, je vous recommande de vous familiariser avec mon récit de ce document ( partie 1 , partie 2 ; la troisième partie, hélas, continue à accumuler de la poussière dans les ébauches).


Depuis lors, il n'y a eu aucune nouvelle significative sur l'état de développement de TON, jusqu'à il y a quelques jours (dans l'un des canaux non officiels ) un lien vers la page https://test.ton.org/download.html est apparu , où sont:


ton-test-liteclient-full.tar.xz - code source du client léger pour le réseau de test TON;
ton-lite-client-test1.config.json - fichier de configuration pour la connexion à un réseau de test;
README - informations sur la construction et le démarrage du client;
HOWTO - instructions étape par étape sur la création d'un contrat intelligent à l'aide d'un client;
ton.pdf - document mis à jour (daté du 2 mars 2019) avec un aperçu technique du réseau TON;
tvm.pdf - description technique de TVM (TON Virtual Machine, TON virtual machine);
tblkch.pdf - description technique de la blockchain TON;
fiftbase.pdf - une description du nouveau langage Fift, conçu pour créer des contrats intelligents dans TON.


Je le répète, il n'y a pas eu de confirmation officielle de la page et de tous ces documents par le Télégramme, mais le volume de ces documents les rend tout à fait plausibles. Exécutez un client publié à vos propres risques .


Tester la génération du client


Tout d'abord, essayons de créer et d'exécuter un client de test - heureusement, README décrit ce processus simple en détail. Je vais le faire en utilisant l'exemple macOS 10.14.5, je ne peux pas garantir le succès de l'assemblage sur d'autres systèmes.


  1. Téléchargez et décompressez l' archive avec les codes sources . Il est important de télécharger la dernière version, car la compatibilité descendante n'est pas garantie à ce stade.


  2. Nous nous assurons que les dernières versions de make, cmake (version 3.0.2 ou supérieure), OpenSSL (y compris les fichiers d'en-tête C), g ++ ou clang sont installées sur le système. Je n'ai pas eu à réinstaller quoi que ce soit, tout s'est rassemblé tout de suite.


  3. Supposons que les sources soient décompressées dans le dossier ~/lite-client . Séparément, nous créons un dossier vide pour le projet assemblé (par exemple, ~/liteclient-build ), et à partir de lui ( cd ~/liteclient-build ) nous cd ~/liteclient-build commandes:


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

    Construction client réussie

    Pour construire l'interpréteur de langue Fift pour les contrats intelligents (voir ci-dessous), nous appelons également


     cmake --build . --target fift 

  4. Téléchargez le fichier de configuration actuel pour vous connecter au réseau de test et placez-le dans le dossier avec le client assemblé.


  5. Terminé , vous pouvez démarrer le client:


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


Si tout est fait correctement, vous devriez voir quelque chose comme ceci:


Client de lancement


Comme vous pouvez le voir, il existe peu de commandes disponibles:


help - affiche cette liste de commandes;
quit - quitter;
time - affiche l'heure actuelle sur le serveur;
status - affiche l'état de la connexion et de la base de données locale;
last - met à jour l'état de la blockchain (charge le dernier bloc). Il est important d'exécuter cette commande avant toute demande afin d'être sûr que vous voyez exactement l'état actuel du réseau.
sendfile <filename> - téléchargez un fichier local sur le réseau TON. Il s'agit de l'interaction avec le réseau - y compris, par exemple, la création de nouveaux contrats intelligents et les demandes de transfert de fonds entre les comptes;
getaccount <address> - affiche l'état actuel du compte (au moment où la last commande a été exécutée) avec l'adresse spécifiée;
privkey <filename> - charge la clé privée à partir du fichier local.


Si au lancement du client, vous lui passez le dossier en utilisant l'option -D , il y ajoutera le dernier bloc de la chaîne principale:


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

Maintenant, nous pouvons passer à des choses plus intéressantes - apprendre la langue Fift, essayer de compiler un contrat intelligent (par exemple, créer un portefeuille de test), le télécharger sur le réseau et essayer de transférer des fonds entre les comptes.


Cinquante langue


À partir du document fiftbase.pdf, vous pouvez découvrir que pour créer des contrats intelligents, l'équipe Telegram a créé un nouveau langage de pile Fift (apparemment, à partir du cinquième chiffre, par analogie avec Forth - un langage avec lequel Fift a beaucoup en commun).


Le document est assez volumineux, avec 87 pages, et je ne reviendrai pas sur son contenu en détail dans le cadre de cet article (du moins parce que moi-même je n'ai pas fini de le lire :). Je m'attarderai sur les points principaux et donnerai quelques exemples de code dans ce langage.


Au niveau de base, la syntaxe de Fift est assez simple: son code est constitué de mots , généralement séparés par des espaces ou des sauts de ligne (cas particulier: certains mots ne nécessitent pas de délimiteur après eux). Tout mot est une séquence de caractères sensible à la casse qui correspond à une certaine définition (grosso modo, ce que l'interprète doit faire lorsqu'il rencontre ce mot). S'il n'y a pas de définition du mot, l'interpréteur essaie de l'analyser comme un nombre et de le mettre sur la pile. Soit dit en passant, les nombres ici sont - tout à coup - des entiers de 257 bits, mais il n'y a aucun nombre fractionnaire - plus précisément, ils se transforment immédiatement en une paire d'entiers, formant le numérateur et le dénominateur d'une fraction rationnelle.


Les mots interagissent généralement avec les significations en haut de la pile. Un type distinct de mots - préfixe - n'utilise pas la pile, mais les caractères suivants du fichier source. Par exemple, les littéraux de chaîne sont implémentés de cette manière - le caractère "guillemet" ( " ) est un mot préfixe qui recherche le guillemet suivant (fermant) et place la chaîne entre eux sur la pile. Une seule ligne ( // ) et plusieurs lignes ( /* ) se comportent de la même manière. commentaires.


Sur cela, presque toute la structure interne de la langue se termine. Tout le reste (y compris les structures de contrôle) est défini comme des mots (soit internes, tels que les opérations arithmétiques et la définition de nouveaux mots; soit définis dans la "bibliothèque standard" Fift.fif , qui se trouve dans le crypto/fift de la source).


Un exemple simple d'un programme Fift:


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

La première ligne définit le nouveau mot setxy (notez le préfixe { , qui crée le bloc avant la fermeture } et le préfixe setxy qui définit en fait le mot). setxy prend un nombre en haut de la pile, le définit (ou le redéfinit) comme une constante globale x , et le carré de ce nombre comme une constante y (étant donné que les valeurs des constantes peuvent être redéfinies, je préfère les appeler des variables, mais je respecte le nom dans la langue).


Dans les deux lignes suivantes, un nombre est placé sur la pile, setxy est setxy , puis les valeurs des constantes x , y sont affichées (le mot est utilisé pour la sortie . ), Les deux constantes sont placées sur la pile, additionnées et le résultat est également affiché. En conséquence, nous verrons:


 3 9 12 ok 7 49 56 ok 

(L'interpréteur imprime la ligne «ok» lorsqu'il a fini de traiter la ligne actuelle en mode de saisie interactive)


Eh bien, un exemple de code 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 <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 

Ce fichier d'apparence effrayante est conçu pour créer un contrat intelligent - il sera placé dans le new-wallet-query.boc après exécution. Veuillez noter qu'ici est utilisé un autre langage d'assemblage pour la machine virtuelle TON (je ne m'y attarderai pas en détail), dont les instructions seront placées sur la blockchain.


Ainsi, l'assembleur pour TVM est écrit en Fift - les sources de cet assembleur sont dans le fichier crypto/fift/Asm.fif et sont connectées au début du morceau de code ci-dessus.


Que puis-je dire, apparemment, Nikolai Durov aime juste créer de nouveaux langages de programmation :)


Créer un contrat intelligent et interagir avec TON


Supposons donc que nous ayons réuni un client TON et un interprète Fift, comme décrit ci-dessus, et que nous nous soyons familiarisés avec la langue. Comment créer un contrat intelligent maintenant? Ceci est décrit dans le fichier HOWTO joint à la source.


Comptes TON


Comme je l'ai décrit dans la revue TON , ce réseau contient plus d'une blockchain - il y a une commune, la soi-disant «Chaîne principale», ainsi qu'un nombre arbitraire de «chaînes de travail» supplémentaires identifiées par un nombre de 32 bits. La chaîne maître a un identifiant de -1, en plus de cela, une chaîne de travail «de base» avec l'identifiant 0 peut également être utilisée Chaque chaîne de travail peut avoir sa propre configuration. En interne, chaque groupe de travail est divisé en chaînes de partage, mais c'est déjà un détail de l'implémentation, qui ne doit pas être gardé à l'esprit.


De nombreux comptes sont stockés dans une même chaîne de travail, qui ont leurs propres identifiants account_id. Pour la chaîne principale et la chaîne de travail zéro, ils ont une longueur de 256 bits. Ainsi, l'identifiant de compte est écrit, par exemple, comme ceci:


 -1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0d 

Il s'agit d'un format «brut»: d'abord, l'identifiant de la chaîne de travail, puis les deux points et l'identifiant du compte en notation hexadécimale.


De plus, il existe un format raccourci - le numéro de la chaîne de travail et l'adresse du compte sont codés sous forme binaire, une somme de contrôle leur est ajoutée et tout cela est codé en Base64:


 Ef+BVndbeTJeXWLnQtm5bDC2UVpc0vH2TF2ksZPAPwcODSkb 

Connaissant ce format d'enregistrement, nous pouvons demander l'état actuel d'un compte via un client de test en utilisant la commande


 getaccount -1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0d 

Nous obtenons une réponse comme celle-ci:


 [ 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} pour -1: 8156775B79325E5D62E742D9B96C30B6515A5CD2F1F64C5DA4B193C03F070E0D par rapport aux blocs (-1,8000000000000000,72355): F566005749C1B97F18EDE013EBA7A054B9014961BC1AD91F475B9082919A2296: 1BD5DE54333164025EE39D389ECE2E93DA2871DA616D488253953E52B50DC03F et [ 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} 

Nous voyons la structure qui est stockée dans la DHT de la chaîne de travail spécifiée. Par exemple, dans le champ storage.balance est le solde du compte courant, dans storage.state.code est le code de contrat intelligent et dans storage.state.data est ses données actuelles. Notez que le magasin de données TON - Cellule, cellules - est un arbre, chaque cellule peut avoir ses propres données, ainsi que des cellules enfants. Ceci est indiqué comme une indentation dans les dernières lignes.


Assemblage de contrat intelligent


Créons maintenant une telle structure nous-mêmes (elle s'appelle BOC - sac de cellules ) en utilisant le langage Fift. Heureusement, vous n'aurez pas à rédiger un contrat intelligent vous-même - dans le dossier crypto/block de l'archive source, il y a un fichier new-wallet.fif qui nous aidera à créer un nouveau portefeuille. Copiez-le dans le dossier avec le client assemblé ( ~/liteclient-build , si vous avez ~/liteclient-build instructions ci-dessus). J'ai cité son contenu ci-dessus comme un exemple de code sur Fift.


Nous exécutons ce fichier comme suit:


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

Ici, <source-directory> doit être remplacé par le chemin d'accès aux sources décompressées (le symbole "~" ne peut pas être utilisé ici, malheureusement, vous avez besoin du chemin complet). Au lieu d'utiliser le -I vous pouvez définir la FIFTPATH environnement FIFTPATH et y mettre ce chemin.


Depuis que nous avons lancé Fift avec le nom de fichier new-wallet.fif , il l'exécutera et se terminera. Si vous omettez le nom du fichier, vous pouvez jouer avec l'interpréteur en mode interactif.


Après l'exécution, quelque chose comme ceci devrait s'afficher dans la 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) l' 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) 

Cela signifie que le portefeuille avec l'identificateur -1:4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2 (ou, qui est la même chose, 0f9PzVILj8yglrVn1zS-NSjtxr7QBfaTCp7JrBqnFPIR8nhZ ) Le code correspondant new-wallet-query.boc dans le new-wallet-query.boc , son adresse dans new-wallet.addr et la clé privée dans new-wallet.pk (attention - le redémarrage du script écrasera ces fichiers).


Bien sûr, le réseau TON ne connaît pas encore ce portefeuille, il n'est stocké que sous forme de ces fichiers. Vous devez maintenant le télécharger sur le réseau. Certes, le problème est que pour créer un contrat intelligent, vous devez payer une commission et le solde de votre compte est toujours nul.


En mode de travail, ce problème sera résolu en achetant des grammes sur la bourse (ou en effectuant un transfert à partir d'un autre portefeuille). Eh bien, dans le mode de test actuel, un contrat intelligent spécial a été institué, à partir duquel vous pouvez demander jusqu'à 20 grammes comme ça.


Formation d'une demande au contrat intelligent de quelqu'un d'autre


Demandez un contrat intelligent, distribuant des grammes à gauche et à droite, faites-le. Dans le même dossier crypto/block , nous trouvons le fichier 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 

Nous l'enregistrons également dans le dossier avec le client assemblé, mais fixons la cinquième ligne - avant la ligne " constant dest_addr ". Remplacez-le par l'adresse du portefeuille que vous avez créé auparavant (complet, non abrégé). "-1:" vous n'avez pas besoin d'écrire au début, mettez plutôt "0x" au début.


Vous pouvez également modifier la ligne 6.666 Gram*/ constant amount - c'est la quantité en grammes que vous demandez (pas plus de 20). Même si vous spécifiez un entier, laissez le point décimal.


Enfin, vous devez corriger la ligne 0x00000011 constant seqno . Le premier numéro ici est le numéro de séquence actuel, qui est stocké dans le compte émettant les grammes. D'où l'obtenir? Comme mentionné ci-dessus, démarrez le client et exécutez:


 last getaccount -1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0d 

À la toute fin dans les données du contrat intelligent sera


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

Le numéro 0000000D (vous en aurez plus) est le numéro de séquence, qui doit être substitué dans testgiver.fif .


Voilà, enregistrez le fichier et exécutez ( ./crypto/fift testgiver.fif ). La sortie sera le wallet-query.boc . C'est le message formé au contrat intelligent de quelqu'un d'autre - la demande est «transférer autant de grammes vers tel ou tel compte».


En utilisant le client, nous le téléchargeons sur le réseau:


 > 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 

Si nous appelons maintenant en last , puis demandons à nouveau le statut du compte à partir duquel nous avons demandé des grammes, nous devrions voir que son numéro de séquence a augmenté de un - cela signifie qu'il a envoyé de l'argent sur notre compte.


La dernière étape reste - nous chargeons le code de notre portefeuille (son solde a déjà été réapprovisionné, mais sans le code de contrat intelligent nous ne pourrons pas le gérer). sendfile new-wallet-query.boc - et c'est tout, vous avez votre propre portefeuille dans le réseau TON (mais pour l'instant seulement un test).


Créer des transactions sortantes


Pour transférer de l'argent du solde du compte créé, il existe un crypto/block/wallet.fif , qui doit également être placé dans le dossier avec le client collecté.


Comme pour les étapes précédentes, vous devez corriger le montant que vous transférez, l'adresse du destinataire (dest_addr) et le seqno de votre portefeuille (il est de 1 après l'initialisation du portefeuille et augmente de 1 après chaque transaction sortante - vous pouvez le voir en demandant le statut de votre compte) . Pour les tests, vous pouvez utiliser, par exemple, mon portefeuille - 0x4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2 .


Lorsque vous exécutez ( ./crypto/fift wallet.fif ), le script prendra l'adresse de votre portefeuille (d'où vous le transférez) et sa clé privée à partir des fichiers new-wallet.addr et new-wallet.pk , et new-wallet.pk le message reçu dans new-wallet-query.boc .


Comme précédemment, pour exécuter directement la transaction, nous appelons sendfile new-wallet-query.boc dans le client. Après cela, n'oubliez pas de mettre à jour l'état de la blockchain ( last ) et vérifiez que l'équilibre et le seqno de notre portefeuille ont changé ( getaccount <account_id> ).


Description du compte


C'est tout, maintenant nous pouvons créer des contrats intelligents dans TON et leur envoyer des demandes. Comme vous pouvez le voir, la fonctionnalité actuelle est déjà suffisante pour, par exemple, créer un portefeuille plus convivial avec une interface graphique (cependant, il est prévu qu'elle deviendra disponible dans le cadre du messager).

Source: https://habr.com/ru/post/fr453714/


All Articles