Fermer

juin 14, 2018

Débogage avec Truffle CLI –


Les débogueurs ont été des outils de développement logiciel cruciaux pendant plus de trente ans.

Un débogueur moderne nous permet de:

  • exécuter le code ligne par ligne
  • définir des points d'arrêt dans le code
  • mettre des conditions sur les points d'arrêt
  • évaluent les expressions pendant l'exécution.

La ​​plupart des débogueurs modernes sont également fortement intégrés dans les environnements de développement des langues qu'ils servent. Ils permettent de définir des points d'arrêt en cliquant sur les numéros de ligne, en évaluant les expressions en survolant des variables, en écrivant des points d'arrêt conditionnels dans les commentaires de code …

Alors, quel est l'état du débogueur et des débogueurs?

Comme pour la plupart des choses de blockchain, nous en sommes encore au stade de la petite enfance. Les débogueurs de base sont disponibles (et avancent à un rythme rapide), mais aucune intégration d'éditeurs n'est encore là, et le débogueur s'appuie fortement sur le cadre de choix.

Dans cet article, nous serons explorer le débogueur Solidity associé à la suite Truffle .

Mise en route

Nous allons d'abord installer tous les outils nécessaires. Heureusement pour nous, le framework Truffle est très bien intégré, nous aurons juste besoin de l'installer.

Tout d'abord, installez Node.js et NPM . Après avoir installé Node, vous pouvez vérifier qu'il est installé en vérifiant la version de l'outil comme ceci:

 ➜ ~ node -v
v10.2.1
➜ ~ npm -v
5.6.0

Si votre Node est opérationnel, installons le framework Truffle. Ceci est rendu assez simple par l'utilisation de npm alors lancez simplement ceci:

 npm install -g truffle

Vous pouvez vérifier si l'installation a réussi en vérifiant la version:

 version truffle
Truffle v4.1.11 (noyau: 4.1.11)
Solidité v0.4.24 (solc-js)

Configuration du projet

Maintenant que vous avez installé Truffle, créons un nouveau projet Truffle (vide). Ouvrez votre terminal, positionnez-vous dans le répertoire désiré et lancez truffle init . La sortie devrait être similaire à ceci:

 truffle init
Téléchargement...
Déballage...
Mise en place ...
Unbox réussi. Doux!

Commandes

  Compiler: compilation de truffes
  Migrer: la truffe migre
  Contrats d'essai: test à la truffe

Après avoir fait cela, vous devriez avoir une structure de contrat similaire à celle-ci:

.
├── contrats
Mig └── Migrations.sol
Mig── migrations
│ └── 1_initial_migration.js
├── test
├── truffle-config.js
└── truffle.js

Maintenant, ouvrez le fichier truffle.js et placez-y les données suivantes:

 module.exports = {
  réseaux: {
      développement: {
          port: 9545,
          hôte: "127.0.0.1",
          network_id: "*"
      }
  }
}

Enregistrez le fichier et lancez truffle develop . Vous devriez obtenir une sortie similaire à celle-ci:

 truffle develop
Truffle Develop a commencé à http://127.0.0.1:9545/

Comptes:
(0) 0x627306090abab3a6e1400e9345bc60c78a8bef57
(1) 0xf17f52151ebef6c7334fad080c5704d77216b732
(2) 0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef
(3) 0x821aea9a577a9b44299b9c15c88cf3087f3b5544
(4) 0x0d1d4e623d10f9fba5db95830f7d3839406c6af2
(5) 0x2932b7a2355d6fecc4b5c0b6bd44cc31df247a2e
(6) 0x2191ef87e392377ec08e7c08eb105ef5448eced5
(7) 0x0f4f2ac550a1b4e2280d04c21cea7ebd822934b5
(8) 0x6330a553fc93768f612722bb8c2ec78ac90b3bbc
(9) 0x5aeda56215b167893e80b4fe645ba6d5bab767de

Clés privées:
(0) c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3
(1) ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f
(2) 0dbbe8e4ae425a6d2687f1a7e3ba17bc98c673636790f1b8ad91193c05875ef1
(3) c88b703fb08cbea894b6aeff5a544fb92e78a18e19814cd85da83b71f772aa6c
(4) 388c684f0ba1ef5017716adb5d21a053ea8e90277d0868337519f97bede61418
(5) 659cbb0e2411a44db63778987b1e22153c086a95eb6b18bdf89de078917abc63
(6) 82d052c865f5763aad42add438569276c00d3d88a2d062d36b2bae914d58b8c8
(7) aa3680d5d48a8283413f7a108367c7299ca73f553735860a87b08f39395618b7
(8) 0f62d96d6675f32685bbdb8ac13cda7c23436f63efbb9d07700d8669ff12b7c4
(9) 8d5366123cb560bb606379f90a0bfd4769eecc0557f1b362dcae9012b548b1e5

Mnémonique: bonbon érable gâteau sucre pudding crème miel riche lisse crumble douce friandise

⚠️ Important ⚠️: Ce mnémonique a été créé pour vous par Truffle. Ce n'est pas sécurisé.
Assurez-vous de ne pas l'utiliser sur les blockchains de production, sinon vous risquez de perdre des fonds.

Ceci a commencé une instance de la blockchain de développement de truffe soutenue par ganache-cli (anciennement TestRPC )

Rédaction et déploiement du contrat

Dans le répertoire des contrats, faites un fichier appelé Storage.sol . Dans ce fichier, mettez le code suivant:

 pragma solidity ^ 0.4.23;


contrat de stockage {

    uint [] private _numberStorage;

    event AddedNewNumber (position uint);

    function addNumber (uint newNumber) public returns (uint) {
        _numberStorage.push (newNumber);

        uint numberPosition = _numberStorage.length;

        emit AddedNewNumber (numberPosition);
        return numberPosition;
    }

    function getNumber (position uint) public constant retourne (uint) {
        return _numberStorage [position];
    }

}

Une fois que vous avez terminé, votre structure de fichier devrait ressembler à ceci:

 ├── contrats
Mig ├── Migrations.sol
Storage └── Storage.sol
Mig── migrations
│ └── 1_initial_migration.js
├── test
├── truffle-config.js
└── truffle.js

Dans le répertoire migrations créez un nouveau fichier appelé 2_deploy_migrations.js et placez le code suivant:

 var Storage = artefacts.require ("./ Storage .sol");

module.exports = function (déployer) {

    deployer.deploy (Stockage);

}

Ce code définit comment Truffle va migrer notre projet vers la blockchain.

Maintenant, ouvre un nouvel onglet dans le terminal (laissant la truffe développer en cours d'exécution) et lance ] la truffe migre . Cela va compiler et migrer vos contrats vers la blockchain de développement. Vous devriez obtenir un résultat comme celui-ci:

 Utilisation du développement de réseau.

Migration en cours: 1_initial_migration.js
  Déploiement de migrations ...
  ... 0x819678a9812313714a27b52c30f065544a331ec5c79ec6c251bc97cd09398d08
  Migrations: 0x8cdaf0cd259887258bc13a92c0a6da92698644c0
Enregistrement d'une migration réussie vers le réseau ...
  ... 0xd7bc86d31bee32fa3988f1c1eabce403a1b5d570340a3a9cdba53a472ee8c956
Enregistrement d'artefacts ...

Maintenant, écrivez console de la truffe . Cela va ouvrir une console interactive pour vous permettre de tester vos contrats. Dans la console, procédez comme suit:

 ~> Storage.deployed (). Then ((i) => {iStorage = i}) // Stocker l'instance de contrat dans la variable iStorage

~> iStorage.AddedNewNumber ({}). watch ((err, res) => {console.log ("NUMBER POSITION:" + res.args.position.numéro ())}) // S'abonner au nouveau numéro ajouté un événement

Filtre {
  requestManager:
   RequestManager {
     provider: Fournisseur {fournisseur: [HttpProvider]},
     les sondages: {},
     timeout: null},
  options:
   { les sujets:
      [ '0x197006a61de03a2f3b4de7f4c4fab6e30ebedef7c1a42d716b2140f184c718b7' ],
     de: undefined,
     à: indéfini,
     adresse: '0xdda6327139485221633a1fcd65f4ac932e60a2e1',
     fromBlock: non défini,
     toBlock: non défini},
  la mise en oeuvre:
   {nouveauFiltre:
      {[Function: send] demande: [Function: bound ]appelez: [Function: newFilterCall]},
     uninstallFilter:
      {[Function: send] demande: [Function: bound ]appelez: 'eth_uninstallFilter'},
     getLogs:
      {[Function: send] demande: [Function: bound ]appelez: 'eth_getFilterLogs'},
     sondage:
      {[Function: send] request: [Function: bound ]appelez: 'eth_getFilterChanges'}},
  filterId: null,
  rappels: [ [Function]],
  getLogsCallbacks: [],
  pollFilters: [],
  formateur: [Function: bound ]}

~> iStorage.addNumber (13) // Ajouter un nouveau numéro

{tx:
   '0xad3f82a6a6cec39dff802f2f16e73bbbc8eff3b68c2ac4da4c371a4c84345a4f',
  le reçu:
   {transactionHash:
      '0xad3f82a6a6cec39dff802f2f16e73bbbc8eff3b68c2ac4da4c371a4c84345a4f',
     transactionIndex: 0,
     blockHash:
      '0x464bc0075036cf95484dec165f0248fb0a7db929d14068a312076be14d43d1fe',
     blockNumber: 5,
     GasUsed: 63362,
     cumulativeGasUsed: 63362,
     contratAddress: null,
     grumes: [ [Object]],
     statut: '0x01',
     logsBloom:
      '0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000},
  logs:
   [ { logIndex: 0,
       transactionIndex: 0,
       transactionHash:
        '0xad3f82a6a6cec39dff802f2f16e73bbbc8eff3b68c2ac4da4c371a4c84345a4f',
       blockHash:
        '0x464bc0075036cf95484dec165f0248fb0a7db929d14068a312076be14d43d1fe',
       blockNumber: 5,
       address: '0x345ca3e014aaf5dca488057592ee47305d9b3e10',
       type: 'mined',
       event: 'AddedNewNumber',
       args: [Object]}]}

Après avoir exécuté la fonction iStorage.addNumber (...) l'événement auquel nous nous sommes abonnés aurait dû être déclenché. Si c'est le cas, la sortie devrait contenir quelque chose comme ceci:

 truffle (développement)> NUMBER POSITION: 1

Essayons maintenant d'aller chercher le numéro de la position où nous l'avons stocké:

 ~> iStorage.getNumber (1)
iStorage.getNumber (1)
Erreur: Exception de VM lors du traitement de la transaction: opcode invalide
    à XMLHttpRequest._onHttpResponseEnd (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:509:1)
    à XMLHttpRequest._setReadyState (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:354:1)
    à XMLHttpRequestEventTarget.dispatchEvent (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:64:1)
    à XMLHttpRequest.request.onreadystatechange (/usr/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/httpprovider.js:128:1)
    à /usr/local/lib/node_modules/truffle/build/webpack:/~/truffle-provider/wrapper.js:134:1
    à /usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/requestmanager.js:86:1
    à Object.InvalidResponse (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/errors.js:38:1)

Nous avons une erreur! C'est pratique: il semble que nous pouvons maintenant utiliser le débogueur. C'est presque comme si c'était prévu!

Utiliser le débogueur

Pour déboguer les transactions, vous devez trouver le hash de transaction de la transaction que vous souhaitez déboguer. Copiez le hachage de la transaction et, dans le terminal, entrez-le sous la forme:

 truffle debug tx_hash

Nous allons déboguer la fonction qui ajoute le numéro au stockage. Le hash tx sera différent pour vous, mais la forme globale sera similaire à ceci. Et la sortie devrait être la même:

 truffle debug 0x34d26b8bcf01f23dfbef0de28384623ca3ed3e3e7fe28f1a0968d363cf38765f
Compiler ./contracts/Migrations.sol ...
Compiler ./contracts/Storage.sol ...

Collecte des données de transaction ...

Adresses affectées:
 0x345ca3e014aaf5dca488057592ee47305d9b3e10 - Stockage

Commandes
(entrer) la dernière commande entrée (étape suivante)
(o) pas, (i) pas, (u) pas, (n) pas suivant
(;) instruction d'étape, (p) instruction d'impression, (h) impression de cette aide, (q) abandon
(b) basculer le point d'arrêt, (c) continuer jusqu'au point d'arrêt
(+) ajouter l'expression de la montre (`+: `), (-) supprimer l'expression de la montre (-: )
(?) liste des expressions de surveillance existantes
(v) imprimer les variables et les valeurs, (:) évaluer l'expression - voir `v`


Storage.sol:

2:
3:
4: contrat de stockage {
   ^^^^^^^^^^^^^^^

déboguer (développement: 0x34d26b8b ...)>

Ici, nous pouvons voir la console de débogage. C'est beaucoup plus primitif que les débogueurs modernes auxquels la plupart des développeurs sont habitués, mais il a toutes les fonctionnalités requises. Explorons la fonctionnalité.

Dans la console, exécutez la série de commandes suivante:

 debug (développement: 0x34d26b8b ...)> o

Storage.sol:

 8: event AddedNewNumber (position uint);
 9:
10: function addNumber (uint newNumber) public returns (uint) {
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^

En tapant o nous avons franchi la ligne de fonction - ce qui signifie que nous n'avons pas entré le corps de la fonction que nous avons appelée.

Maintenant nous sommes positionnés à la ligne 10 - ou l'en-tête de la fonction pour ajouter un nombre. Allons plus loin. Tapez o à nouveau.

 Storage.sol:

 9:
10: function addNumber (uint newNumber) public returns (uint) {
11: _numberStorage.push (newNumber);
            ^^^^^^^^^^^^^^

Maintenant, nous poussons le nombre dans le tableau. Tapez o à nouveau.

 Storage.sol:

11: _numberStorage.push (newNumber);
12:
13: uint numberPosition = _numberStorage.length;

Nous avons poussé le nombre et obtenons la position du nombre dans le tableau. Appuyez de nouveau sur o .

 Storage.sol:

13: uint numberPosition = _numberStorage.length;
14:
15: Emission AddedNewNumber (numberPosition);
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Nous sommes à la ligne émettant la position. Maintenant, au lieu de presser ou inspectons nos variables et essayons de récupérer le nombre du tableau. Nous pouvons utiliser l'une des deux façons. La première, plus générique, consiste simplement à taper v et inspecter toutes les variables disponibles dans le contexte de la fonction

Faites-le en tapant v . La sortie devrait être ceci:

 numberPosition: 1
     nouveauNumber: 12
              : 189
_numberStorage: [ 12 ]

L'autre façon de le faire est plus spécifique, et nous pouvons le faire en tapant : . Faites-le en tapant : numberPosition . Vous devriez obtenir 1 en sortie.

Essayons maintenant d'évaluer une expression. Vous pouvez le faire avec la construction : aussi.

Essayons de récupérer notre numéro avec le : _ numberStorage [numberPosition]:

 debug (développement: 0x34d26b8b ...)>: _numberStockage [numberPosition]
indéfini

En l'exécutant, nous obtenons la sortie indéfinie . Cela signifie qu'il n'y a pas de nombre là-bas.

Pour tous les développeurs, l'erreur devrait être raisonnablement évidente. Nous avons essayé d'accéder au premier élément à la position un. Puisque dans Solidity, comme dans la plupart des langages, les tableaux sont indexés à zéro, nous devons y accéder avec le numéro zéro

Pressez q pour quitter le débogueur et corrigeons le code. Dans votre Storage.sol modifiez ceci:

 uint numberPosition = _numberStorage.length;

à ceci:

 uint numberPosition = _numberStorage.length - 1;

Exécutez maintenant truffle migrate et une fois terminé, exécutez console truffle . Dans la console, réexécutez les commandes:

 ~> Storage.deployed (). Then ((i) => {iStorage = i})
~> iStorage.AddedNewNumber ({}). watch ((err, res) => {console.log ("NUMBER POSITION:" + res.args.position.numéro ())});
~> iStorage.addNumber (12);
~> sortie: "POSITION NOMBRE: 0"
~> iStorage.getNumber (0)
~> iStorage.getNumber (0) .then ((res) => {console.log (res.toNumber ())})
~> sortie: 12

Mislav Javor " class="avatar avatar-96 wp-user-avatar wp-user-avatar-96 alignnone photo"/>

Mislav Javor est ingénieur logiciel et PDG (dans cet ordre). Il écrit des contrats intelligents, dirige des conférences et des blogs à mislavjavor.com .




Source link