Il y a un peu plus d’un an Ă  prĂ©sent, nous avons dĂ©veloppĂ© une solution d’horodatage basĂ©e sur une blockchain. Elle permet de prouver l’antĂ©rioritĂ© d’un contenu (une idĂ©e ou une crĂ©ation par exemple) via l’utilisation d’une blockchain publique Ethereum directement depuis son navigateur. Donc sans organe central de contrĂŽle. Il s’agit d’un cas d’usage simple mais parfaitement applicable aux besoins mĂ©tiers des applications de nos clients : sceller un contenu et ses mĂ©tadonnĂ©es de maniĂšre sĂ»re et pĂ©renne. Le code source est publiĂ© sous la licence Apache 2.

Pour faciliter la lecture, nous vous proposons une sĂ©rie de cinq articles qui prĂ©sentent trois points de vue complĂ©mentaires de l’outil :

  1. Point de vue conceptuel : 🎹 Comprendre les notions de base d’une blockchain publique
  2. Point de vue utilisateur : đŸ•ș Interagir avec l’application dĂ©centralisĂ©e
  3. Point de vue dĂ©veloppeur : 🏭 Configurer son environnement de dĂ©veloppement
  4. Point de vue dĂ©veloppeur : đŸ€ Comprendre le dĂ©veloppement du smart contract
  5. Point de vue dĂ©veloppeur : đŸ’» Comprendre le dĂ©veloppement du client

Ce quatriĂšme article fournit des explications sur l’écriture des smart contracts et sur la maniĂšre de les dĂ©ployer dans une blockchain de dĂ©veloppements ou une blockchain publique.

Le code source des smarts contracts est dans le sous projet smart-contracts. Les smart contracts sont Ă©crits dans le langage dĂ©diĂ© solidity et compilĂ©s pour ĂȘtre exĂ©cutĂ©s dans une machine virtuelle Ethereum (EVM). Nous vous invitons Ă  lire la documentation de rĂ©fĂ©rence du langage : https://solidity.readthedocs.io.

Commençons par expliciter le code source du smart contract mĂ©tier. 

# Smart contract métier AntProver

Il s’agit du smart contract principal qui rĂ©alise la preuve d’antĂ©rioritĂ©. Il permet de stocker les informations de maniĂšre structurĂ©e et de les requĂȘter via une sorte d’API de services. Pour faciliter la lecture de cet article, nous explicitons le coeur de ce smart contract : une fonction d’écriture des informations et une fonction de consultation.

Le smart contract est défini dans le fichier smart-contracts/contracts/AntProver.sol.

# Squelette du contrat

Afin d’éviter un changement bloquant potentiel d’une version future (relativement au moment du dĂ©veloppement), nous bornons les versions acceptĂ©es du compilateur. La directive suivante indique que le compilateur doit ĂȘtre en version 0.5.X :

Nous commençons par dĂ©finir le contrat AntProver. Ici, nous n’avons pas de comportement particulier Ă  la crĂ©ation :

# Structure et variables

Afin de porter les donnĂ©es d’un enregistrement, nous dĂ©finissons la structure de donnĂ©es Record. Les types que nous utilisons ici sont tous simples. Nous avons des entiers non signĂ©s pour l’horodatage et le numĂ©ro de bloc, une chaĂźne de caractĂšres pour le commentaire et une adresse pour l’émetteur :

Nous crĂ©ons la variable hashesMetadata dans laquelle nous faisons correspondre un Record Ă  chaque empreinte de fichier enregistrĂ©e. Dans la mesure oĂč nous souhaitons que cette variable ne soit visible que par le contrat, nous utilisons l’accesseur private :

# Fonction d’écriture

Pour rĂ©fĂ©rencer un contenu Ă  partir de son empreinte hash et du commentaire associĂ© comment, nous dĂ©finissons la fonction d’écriture addDocHash, accessible depuis l’extĂ©rieur, grĂące Ă  l’accesseur public :

Nous aurions pu omettre le mot clĂ© memory pour le paramĂštre comment, qui est le mode de passage d’arguments activĂ© par dĂ©faut. Avec ce mode, les arguments sont passĂ©s par valeur, contrairement au passage par rĂ©fĂ©rence activĂ© avec le mot clĂ© storage.

Notons que pour crĂ©er l’instance de Record, nous utilisons des informations rĂ©cupĂ©rĂ©es Ă  partir des paramĂštres et de propriĂ©tĂ©s :

  • Les informations du bloc sont disponibles dans la propriĂ©tĂ© block.
    • now est un alias de block.timestamp. Il s’agit de l’horodatage du bloc courant.
    • bloc.number permet de connaĂźtre le numĂ©ro de bloc.
  • Les informations du message sont disponibles dans la propriĂ©tĂ© msg
    • msg.sender permet de rĂ©cupĂ©rer l’adresse de l’émetteur

D’autres propriĂ©tĂ©s sont disponibles.

L’enregistrement fraĂźchement crĂ©Ă© newRecord est stockĂ© en face de son hash dans dans variable d’association hashesMetadata.

# Fonction de lecture

La recherche d’un contenu est rĂ©alisĂ©e avec la fonction de lecture findDocHash. Elle permet de retrouver les informations Ă©ventuellement associĂ©es Ă  une empreinte. On la dĂ©clare comme Ă©tant une view function de maniĂšre Ă  s’assurer qu’elle ne modifiera pas l’état : variable, production d’Ă©vĂ©nement, crĂ©ation d’un contrat, etc. De ce fait, un appel Ă  cette fonction ne gĂ©nĂ©rera aucun frais.

La fonction findDocHash prend une empreinte en paramĂštre et retourne un quadruplet correspondant aux valeurs de l’instance de Record associĂ©e. GrĂące Ă  la variable d’association, l’accĂšs est direct :

# PrĂ©requis d’un smart contract

Pour sĂ©curiser le rĂ©fĂ©rencement d’un contenu, on souhaite s’assurer que l’empreinte du fichier n’existe pas dĂ©jĂ . Au dĂ©but de la fonction addDocHash, on ajoute un prĂ©requis de maniĂšre Ă  provoquer une erreur en cas de besoin :

Puis on crĂ©e la fonction exists qui teste si l’empreinte a dĂ©jĂ  Ă©tĂ© enregistrĂ©e :

Lorsqu’une empreinte n’existe pas dans hashesMetadata, la propriĂ©tĂ© blockNumber a la valeur 0. En effet, il n’existe pas de valeur nulle dans le langage solidity et toute variable a la valeur par dĂ©faut.

# Gestion d’évĂ©nements

Un smart contract peut gĂ©nĂ©rer des Ă©vĂ©nements que des applications peuvent Ă©couter via une interface RPC (Remote Procedure Call). Dans le cas prĂ©sent, nous allons ajouter le type d’évĂ©nement HashAdded :

AprĂšs l’enregistrement d’une empreinte Ă  la fin de addDocHash, on Ă©met une occurrence de l’évĂ©nement avec l’appel suivant :

Nous verrons dans l’article suivant que nous pouvons Ă©couter ce type d’évĂ©nement depuis le client. Dans l’exemple prĂ©sent, le frontal utilisateur affichera l’évĂ©nement lorsque la transaction aura Ă©tĂ© validĂ©e de maniĂšre Ă  ce que l’utilisateur soit en mesure de rĂ©cupĂ©rer le certificat final au format pdf Ă  conserver avec le document initial.

# Gestion des migrations / déploiement

Maintenant que nous avons expliquĂ© le fonctionnement interne du smart contract mĂ©tier, revenons Ă  l’initialisation du sous projet. Ceci a Ă©tĂ© fait avec l’outil truffle et sa commande unbox. Le projet a Ă©tĂ© initialisĂ© avec l’arborescence suivante :

  • contracts : source des smart contracts solidity
  • migrations : scripts de dĂ©ploiement
  • test : fichiers de tests
  • truffle-config.js : configuration du projet

Pour la gestion des migrations, les fichiers suivants sont utilisés :

En complément de ceux-ci et du smart contract AntProver.sol, nous avons écrit le script migrations/1567466298_ant_prover.js qui permet de déployer le smart contract AntProver :

La configuration truffle-config.js suivante permet de dĂ©ployer dans la blockchain Ganache mise en place telle que dĂ©crite dans l’article prĂ©cĂ©dent :

Pour rappel, nous avons déployé dans la blockchain de développement avec la commande :

# DĂ©ploiement dans une blockchain publique

Pour dĂ©ployer le smart contract dans une blockchain publique, nous allons utiliser le wallet Infura. Dans la suite, nous dĂ©ploierons le smart contract sur l’instance testnet (rĂ©seau de tests) Ropsten.

Infura est une API qui permet d’accĂ©der au rĂ©seau Ethereum. Avant de pouvoir dĂ©ployer, il faut se crĂ©er un compte, un projet puis rĂ©cupĂ©rer le PROJECT ID.

La définition des variables est nécessaire pour le déploiement final (exemple) :

En effet, nous les exploitons dans la configuration truffle-config.js qui est complĂ©tĂ©e avec la configuration ropsten. Pour celle-ci, nous profitons du provider web3 truffle-hdwallet-provider (renommĂ© @truffle/hdwallet-provider depuis) : 

Puis nous prĂ©cisons le rĂ©seau “ropsten” plutĂŽt que “development” lors de la migration :

# Métadonnées du smart contract

Lorsque le smart contract Ă©crit en solidity est compilĂ©, un fichier de  mĂ©tadonnĂ©es est gĂ©nĂ©rĂ©. Par exemple, nous avons versionnĂ© le fichier smart-contracts/build/contracts/AntProver.json produit car il prĂ©sente un intĂ©rĂȘt particulier.

Ce fichier est riche en informations. Par exemple, nous retrouvons la version du compilateur utilisĂ©e (ex : 0.5.8+commit.23d335f2), les sources ou encore le contrat ABI (Application Binary Interface). Ce dernier dĂ©finit l’interface pour une utilisation en dehors de la blockchain ou au sein de la blockchain dans une communication entre smart contracts.

Nous retrouvons Ă©galement les informations sur le contrat dĂ©ployĂ© dans les rĂ©seaux dans “networks”. Par exemple on retrouve l’adresse de dĂ©ploiement du smart contract 0xA22fe2812085cf1b755796F5dA60EdFDc6E8dEe6 dans le rĂ©seau Ropsten qui porte l’identifiant 3 :

# Pour continuer

Dans cet article, nous avons couvert le dĂ©veloppement cĂŽtĂ© blockchain du projet. Nous avons commencĂ© par expliciter la maniĂšre dont nous avons conçu le smart contract en partant du squelette et en l’enrichissant avec la dĂ©finition des structures de donnĂ©es, des donnĂ©es et des fonctions d’écriture et de lecture. Puis nous avons vu comment l’enrichir en le sĂ©curisant et ajoutant une gestion d’évĂ©nements.

Enfin, nous avons expliqué comment déployer le smart contract dans une blockchain de développements puis dans une blockchain publique.

Le prochain article et dernier de la sĂ©rie sera dĂ©diĂ© au dĂ©veloppement du client web qui permet d’interagir avec le smart contract Ă©crit et dĂ©ployĂ©.