Les migrations de truffes expliquées –
Les migrations, en général, sont des moyens pour les développeurs d'automatiser le déploiement des données et de leurs structures de support. Ils sont très utiles pour gérer le déploiement de nouvelles versions logicielles, et ne sont donc pas exclusifs au développement de blockchain.
Les migrations truffle nous permettent de "pousser" les contrats intelligents vers la blockchain Ethereum (soit local, tesnet ou mainnet ) et de mettre en place les étapes nécessaires pour lier des contrats avec d'autres contrats et peupler des contrats avec des données initiales.
Là où les migrations brillent vraiment, c'est la gestion des adresses de contrat sur la blockchain. Ce travail habituellement fastidieux est presque entièrement abstrait avec Truffle
Pré-requis
Assurez-vous que vous avez installé le Truffle Framework et Ganache CLI . 19659005] Pour commencer, choisissez un dossier de projet, puis exécutez truffle init
. Vous devriez obtenir une sortie similaire à celle-ci:
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
Cette commande crée un projet truffe barebones dans le répertoire où vous êtes positionné. Le répertoire ressemble à ceci:
.
├── contrats
Mig └── Migrations.sol
Mig── migrations
│ └── 1_initial_migration.js
├── test
├── truffle-config.js
└── truffle.js
Pour commencer, dans le répertoire contracts
créez un nouveau fichier appelé Storage.sol
qui devrait ressembler à ceci:
pragma solidity ^ 0.4.21;
contrat de stockage {
mapping (chaîne => chaîne) private _store;
function addData (clé de chaîne, valeur de chaîne) public {
require (octets (_store [key]). length == 0);
_store [key] = valeur;
}
function removeData (clé de chaîne) public returns (chaîne) {
require (octets (_store [key]). length! = 0);
chaîne prev = _store [key];
delete _store [key];
return prev;
}
function changeData (chaîne de caractères, chaîne newValue) public {
require (octets (_store [key]). length! = 0);
_store [key] = nouvelle valeur;
}
}
Premières migrations
Comme vous avez pu le remarquer, deux fichiers sont créés lorsque vous exécutez truffle init
. Ils sont Migrations.sol
et 1_initial_migration.js
.
Les fichiers de migration initiaux doivent rarement être modifiés. Ce qu'ils font est essentiellement de garder une trace des adresses sur la blockchain.
Le fichier Migrations.sol
peut ressembler à tout ce que vous voulez, mais il doit se conformer à une interface fixe qui ressemble à l'interface créée par la commande truffle init
. Ce que vous pouvez faire dans ces fichiers est un certain mangling avancé des migrations, mais comme je l'ai dit, c'est rarement nécessaire.
Il en va de même pour le fichier 1_initial_migration.js
. Ce qui est c'est il suffit de pousser le fichier Migrations.sol
vers la blockchain désirée
Migrations Data
Pour déployer les contrats intelligents dans la blockchain Ethereum, vous devez première écriture des migrations. Pour commencer, dans votre répertoire de migrations
créez un fichier appelé 2_deploy_contracts.js
. Votre structure de projet devrait maintenant ressembler à ceci:
.
├── contrats
Mig ├── Migrations.sol
Storage └── Storage.sol
Mig── migrations
│ ├── 1_initial_migration.js
│ └── 2_deploy_contracts.js
├── test
├── truffle-config.js
└── truffle.js
Afin de déployer des contrats intelligents avec les migrations, nous devons d'abord accéder à leurs artefacts . Ce sont des fichiers qui décrivent les adresses des contrats, les réseaux sur lesquels les contrats ont été déployés et les fonctions des contrats
D'où vient donc l'ensemble de ces données?
Dans le répertoire de votre projet, exécutez compilation de truffes
. Si tout se passe bien, vous devriez avoir une sortie similaire à celle-ci:
Compiling ./contracts/Migrations.sol ...
Compiler ./contracts/Storage.sol ...
Ecriture d'artefacts dans ./build/contracts
Selon la version du compilateur, vous pourriez recevoir des avertissements, mais tant qu'il n'y a pas d'erreur, vous pouvez y aller
Maintenant, vérifiez de nouveau la structure de votre répertoire de projet: [19659008]
├── construire
│ └── contrats
Mig ├── Migrations.json
Storage └── Storage.json
├── contrats
Mig ├── Migrations.sol
Storage └── Storage.sol
Mig── migrations
│ ├── 1_initial_migration.js
│ └── 2_deploy_contracts.js
├── test
├── truffle-config.js
└── truffle.js
Notez qu'il existe désormais un dossier build
contenant deux fichiers – Migrations.json
et Storage.json
– qui correspondent aux fichiers de contrats intelligents dans
répertoire
Ces fichiers * .json
contiennent des descriptions de leurs contrats intelligents respectifs. La description comprend:
- Nom du contrat
- Contrat ABI (Application Binary Interface – une liste de toutes les fonctions dans les contrats intelligents avec leurs paramètres et valeurs de retour)
- Contrat bytecode (données de contrat compilées)
- Contrat déployé bytecode (la dernière version du bytecode qui a été déployée dans la blockchain)
- La version du compilateur avec laquelle le contrat a été compilé pour la dernière fois
- Une liste des réseaux sur lesquels le contrat a été déployé et l'adresse du contrat sur chacun de ces réseaux.
Ce fichier permet à Truffle de créer un wrapper JavaScript pour communiquer avec le contrat smart. Par exemple, lorsque vous appelez contract.address
dans votre code JavaScript, l'infrastructure Truffle lit l'adresse du fichier * .json
et permet des transitions sans effort entre les versions de contrat et les réseaux. [19659037] Writing Migrations
Forts de cette connaissance, écrivons notre première migration. Dans le fichier 2_deploy_contracts.js
écrivez ceci:
// Récupère les données du contrat de stockage du fichier Storage.json
var Storage = artefacts.require ("./ Storage.sol");
// Export JavaScript
module.exports = function (déployer) {
// Deployer est l'enveloppe Truffle pour le déploiement
// contrats au réseau
// Déployer le contrat sur le réseau
deployer.deploy (Stockage);
}
Écrire des migrations est aussi simple que cela. Pour exécuter le script de migration, exécutez les opérations suivantes dans le terminal:
truffle migrate
Vous devriez obtenir une erreur en disant:
Erreur: Aucun réseau spécifié. Impossible de déterminer le réseau actuel.
Cela signifie que Truffle n'a pas pu trouver le réseau sur lequel vous voulez déployer.
Pour utiliser une chaîne de blocs Ethereum simulée, ouvrez un nouvel onglet dans le terminal et exécutez ganache-cli
. Vous devriez obtenir une sortie similaire à celle-ci:
Ganache CLI v6.1.0 (ganache-core: 2.1.0)
Comptes disponibles
=================
(0) 0x828da2e7b47f9480838f2077d470d39906ad1d8e
(1) 0xa4928865329324560185f1c93b5ebafd7ae6c9e8
(2) 0x957b8b855bed52e11b2d7e9b3e6427771f299f3f
(3) 0xf4b6bcabedaf1ccb3d0c89197c4b961460f1f63d
(4) 0x4bcae97be4a0d1f9a6dea4c23df8a2bffdb51291
(5) 0xe855c7cccac3a65ad24f006bf084c85c0197a779
(6) 0x168cb232283701a816a3d118897eedfcae2aec9d
(7) 0x49563e64868e1d378e20b6ab89813c1bbaa0fd48
(8) 0x467c6f6f526eee9f66776197e3a9798c1cbf78e0
(9) 0xf65b47a3c663e2cc17ded8f197057a091686da43
Clés privées
=================
(0) 8729d0f1d876d692f2f454f564042bd11c1e6d0c9b1808954f171f6f7b926fd6
(1) 452dfeee16e5a0e34fa5348f0ef11f39a8b4635e5f454f77fc228ca9598f6997
(2) 9196ad9fd6234f09ee13726cb889dcbc438c15f98e8ff1feb36a93758fa6d10a
(3) fa47edd832e896314544b98d7e297ac2ce2097b49f8a9d7e7ae0e38154db8760
(4) 7ba1a96db190c14aaee5401dd5faab1af9074d7e6f24bc2f24b5084514bbf405
(5) 90088ce271f227db6be251c3055872c0d3dbdda9fc23ed119cf9d55db7c91259
(6) c36afd6f8f291b45e94ef0059576a86602e9a982b87e0c6fb25cfab4d68e9030
(7) 2766ac8aee110e9ad1ea68d1f28aaafb464fb1ef2a759bf5b2f628d256043c15
(8) 51ccf45f87806e8e9f30f487d6cdd0b44de3ad103f0d8daf9f1e20d9a4728dd9
(9) 398c0f079448c1e3724c9267f07ca4ab88233fc995a3d463c7c64d1a191688f5
Portefeuille HD
=================
Mnémonique: void août insigne future commune guerre rejeter gagner chien coquille vintage dés
Base HD Path: m / 44 '/ 60' / 0 '/ 0 / {account_index}
Écoute sur localhost: 8545
Cela signifie que vous avez créé une blockchain privée et qu'elle fonctionne sur localhost: 8545
. Maintenant, configurons Truffle pour le déployer sur ce réseau.
Placez ce qui suit dans le fichier truffle.js
:
module.exports = {
réseaux: {
développement: {
hôte: "127.0.0.1",
port: 8545,
network_id: "*"
}
}
}
Cela signifie simplement que vous déployez votre contrat sur le réseau tournant sur localhost: 8545
.
Exécutez maintenant truffle migrate
. Vous devriez obtenir une sortie similaire à celle-ci:
Utilisation du développement de réseau.
Migration en cours: 1_initial_migration.js
Déploiement de migrations ...
... 0x06595c0eccde8cb0cf642df07beefea11e3e96bfb470e8dbaf6567cecc37aed8
Migrations: 0x6008e9a2c213d51093d0f18536d1aa3b00a7e058
Enregistrement d'une migration réussie vers le réseau ...
... 0x392fb34c755970d1044dc83c56df6e51d5c4d4011319f659026ba27884126d7b
Enregistrement d'artefacts ...
Migration en cours: 2_deploy_contracts.js
Déploiement du stockage ...
... 0xb8ec575a9f3eca4a11a3f61170231a1816f7c68940d8487e56567adcf5c0a21e
Stockage: 0xd8e2af5be9af2a45fc3ee7cdcb68d9bcc37a3c81
Enregistrement d'une migration réussie vers le réseau ...
... 0x15498a1f9d2ce0f867b64cdf4b22ddff56f76aee9cd3d3a92b03b7aa4d881bac
Enregistrement d'artefacts ...
Truffle a migré votre contrat vers le réseau et sauvegardé les artefacts. Dans le répertoire build, dans le fichier Storage.json
vérifiez que cela est correct en inspectant l'objet networks
. Vous devriez voir quelque chose de similaire à ceci:
"networks": {
"1525343635906": {
"événements": {},
"liens": {},
"adresse": "0xd8e2af5be9af2a45fc3ee7cdcb68d9bcc37a3c81",
"transactionHash": "0xb8ec575a9f3eca4a11a3f61170231a1816f7c68940d8487e56567adcf5c0a21e"
}
}
1525343635906
est l'identifiant du réseau. (Le réseau principal Ethereum et tous les principaux testnets ont des identifiants fixes comme 1,2,3 etc.)
adresse
est l'adresse à laquelle le contrat a été déployé.
transactionHash
est le hash de la transaction qui a été utilisé pour le déploiement du contrat
Nous verrons comment cela sera utile plus tard dans le tutoriel
Contrats multiples
Où les migrations Truffle brillent vraiment quand il y a plusieurs les contrats à compiler, déployer et suivre (dont presque tous les projets blockchain ont).
Non seulement les migrations nous permettent de déployer plusieurs contrats avec une seule commande, elles nous permettent d'exécuter des fonctions arbitraires sur les contrats, d'obtenir des valeurs de retour de ces fonctions et passez-les à des contrats ultérieurs.
Dans votre répertoire
créez un fichier appelé InfoManager.sol
. Dans le fichier, écrivez un contrat comme celui-ci:
pragma solidity ^ 0.4.21;
importer "./Storage.sol";
contrat InfoManager {
Stockage privé _dataStore;
uint private _lastAdded;
function InfoManager (Stockage de données de stockage) public {
_dataStore = dataStore;
}
function addData (clé de chaîne, valeur de chaîne) public {
require ((maintenant - 1 jours)> _lastAdded);
_dataStore.addData (clé, valeur);
}
}
Comme nous pouvons le voir, ce contrat dépend du contrat Storage
. Non seulement cela, il prend le contrat Storage
en tant que paramètre dans son constructeur. Examinons les migrations qui rendront cela possible. Les migrations sont contenues dans le même fichier appelé 2_deploy_contracts.js
:
var Storage = artefacts.require ("./ Storage.sol");
var InfoManager = artefacts.require ("./ InfoManager.sol");
module.exports = function (déployer) {
// Déployer le contrat de stockage
deployer.deploy (Stockage)
// Attendre que le contrat de stockage soit déployé
.then (() => Storage.deployed ())
// Déployer le contrat InfoManager en passant l'adresse du
// Contrat de stockage
.then (() => deployer.deploy (InfoManager, Storage.address));
}
La syntaxe de déploiement est:
...
deployer.deploy (`ContractName`, [`constructor params`]) // Renvoie une promesse
...
Puisque la fonction deploy (...)
renvoie une promesse, vous pouvez la gérer comme vous le souhaitez, à l'exception notable de async
ne travaillant pas dans les migrations pour une raison quelconque .
Vous pouvez également exécuter des étapes personnalisées après le déploiement du contrat. Par exemple, la migration pourrait ressembler à ceci:
deployer.deploy (Storage)
.then (() => Storage.deployed ())
.then ((instance) => {
instance.addData ("Bonjour", "monde")
}). then (() => deployer.deploy (InfoManager, Storage.address));
Cela remplirait le contrat Storage
avec une chaîne world
à la clé data
avant de déployer le contrat InfoManager
. Ceci est utile parce que parfois l'interdépendance entre les contrats peut être telle que certaines données doivent être récupérées ou insérées en dehors de la portée du constructeur du contrat.
Réseaux
Vous pouvez conditionnellement exécuter certaines migrations selon le réseau vous êtes sur. Cela peut être très utile soit pour peupler des données fictives dans la phase de développement ou pour entrer des contrats mainnet déjà déployés dans vos contrats.
Cela se fait en "développant" les paramètres insérés de la fonction module.exports
:
module.exports = fonction (déployeur, réseau) {
if (network == "live") {
// fais une chose
} else if (network == "développement") {
// fait autre chose
}
}
Comptes
La fonction par défaut module.exports
expose également les comptes auxquels vous avez accès via votre noeud Ethereum ou le fournisseur de portefeuille. Voici un exemple:
module.exports = function (deployer, network, accounts) {
var defaultAccount;
if (network == "live") {
defaultAccount = accounts [0]
} autre {
defaultAccount = accounts [1]
}
}
Bibliothèques
Vous pouvez également lier des bibliothèques existantes (déjà déployées), en utilisant la fonction deployer.link (...)
:
...
deployer.deploy (MyLibrary);
déployer.link (MyLibrary, MyContract);
deployer.deploy (MyContract);
...
Conclusion
En utilisant les techniques décrites ci-dessus, vous pouvez automatiser la plupart de vos déploiements de blockchain et réduire une grande partie du travail requis pour le développement d'applications décentralisées.