详解 Truffle Migrations(迁移)- 合约部署不再困惑

这篇文章主要介绍了详解 Truffle Migrations(迁移)- 合约部署不再困惑 ,文中通过代码以及文档配合进行讲解,很详细,它对在座的每个人的研究和工作具有很经典的参考价值。 如果需要,让我们与区块链资料网一起学习。

https://www.interchains.cc/20857.html

详解 Truffle Migrations(迁移)- 合约部署不再困惑是很好的区块链资料,他说明了区块链当中的经典原理,可以给我们提供资料,详解 Truffle Migrations(迁移)- 合约部署不再困惑学习起来其实是很简单的,

不多的几个较为抽象的概念也很容易理解,之所以很多人感觉详解 Truffle Migrations(迁移)- 合约部署不再困惑比较复杂,一方面是因为大多数的文档没有做到由浅入深地讲解,概念上没有注意先后顺序,给读者的理解带来困难

详解 Truffle Migrations(迁移)- 合约部署不再困惑

  • Truffle

全面了解 Truffle Migrations(迁移)的使用

通过本文可以学习到:

  1. Truffle 的迁移合约 Migrations.sol 有啥作用?
  2. 多个合约如何一起部署;
  3. 如果针对不同网络、不同账号进行条件部署;
  4. 如何链接库。

Migrations(迁移)是开发人员使数据及其支持结构的一套自动化部署的方法, 它们对于管理新软件版本的部署非常有用,因此并非仅限于区块链blockchain开发。

Truffle migrations 可以让我们把合约推到以太坊eth链上(不管是本地网络、测试网络还是主网),以及与其他合约链接或使用初始化合约数据。

migrations(迁移)真正最赞的地方是对区块链blockchain上合同地址的管理。 Truffle 几乎完全抽象化这项乏味的工作。

准备

确保安装好了 Truffle Framework 和 Ganache CLI.

开始

新建(或选择)一个项目目录,然后运行 truffle init ,会有类似下面的输出:

Downloading... Unpacking... Setting up... Unbox successful. Sweet!  Commands:    Compile:        truffle compile   Migrate:        truffle migrate   Test contracts: truffle test 

init 命令在当前目录中初始化了一个 Truffle 项目。 目录看起来像这样:

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

contracts 目录下, 创建一个合约文件: Storage.sol 代码如下:

pragma solidity > 0.4.21;  contract Storage {      mapping (string => string) private _store;      function addData(string key, string value) public {         require(bytes(_store[key]).length == 0);         _store[key] = value;     }      function removeData(string key) public returns (string) {         require(bytes(_store[key]).length != 0);         string prev = _store[key];         delete _store[key];         return prev;     }      function changeData(string key, string newValue) public {         require(bytes(_store[key]).length != 0);         _store[key] = newValue;     }  } 

初始的迁移(Migrations)文件及部署规则

你可以能已经看到了在运行 truffle init 时生成的Migrations.sol1_initial_migration.js

初始迁移合约一般不需要修改,他们是跟踪部署在区块链blockchain上的地址。当然也可以按照自己的需要修改 Migrations.sol 合约文件,进行一些高级的迁移管理,但需要保留truffle init命令创建的接口。

1_initial_migration.js 迁移文件,仅仅是说明如何把 Migrations.sol 合约部署到对应的链上。

1_initial_migration.js 迁移文件名,前面的序号,代表着truffle migrate 运行迁移文件的顺序,1 表示第一个运行的迁移文件(从 1 开始)。 我们可以创建其他的迁移文件: 2_mycontract_migration.js ,在每个合约部署完成,Truffle 会把迁移序号保存到 Migrations 合约的 last_completed_migration

假设 migrations 就这两个迁移文件,truffle migrate运行时实际会发生 4 笔交易:

  1. 运行 1_initial_migration.js 进行部署
  2. 把序号 1 写入到合约 Migrations
  3. 运行 2_mycontract_migration.js 进行部署
  4. 把序号 2 写入到合约Migrations

last_completed_migration 表示的是最后部署的迁移,之后再加入其它的迁移文件:3_yourcontract.js 时, 运行truffle migrate时Truffle 会首先读取 last_completed_migration 状态变量,参看之前部署到了哪些,在部署比 last_completed_migration 序号大的(所有)迁移文件,这样就可以保证不会重复部署。

注意,如果修改一个已有的合约,需要重新部署的话,直接运行 truffle migrate 是不会自动部署的,需要新加(或修改)一个更高序号的迁移文件,再运行 truffle migrate

truffle migrate 可以接一个-f 序号 来强制重从一个需要开始执行迁移(此时会忽略 last_completed_migration的值)。 例如: truffle migrate -f 2 会从第 2 个迁移文件开始部署。

迁移的相关数据

为了将智能合约部署到以太坊eth区块链blockchain,首先需要编写迁移文件,在migrations目录下,创建一个迁移文件 2_deploy_contracts.js, 现在项目的结构如下:

. ├── contracts │   ├── Migrations.sol │   └── Storage.sol ├── migrations │   ├── 1_initial_migration.js │   └── 2_deploy_contracts.js ├── test ├── truffle-config.js └── truffle.js 

使用migrations 部署合约,需要读取合约的artifacts(构建)。构建文件会描述合同部署的网络及地址以及合约所包含的函数等。

而 artifacts(构建) 的数据从哪来呢?

在项目目录下,运行 truffle compile, 如果没有错误的话,会有下面的输出:

Compiling ./contracts/Migrations.sol... Compiling ./contracts/Storage.sol...  Writing artifacts to ./build/contracts 

或许在不同的编译器版本下,可以会有一些警告,只要没有错误就 OK 。

再次查看项目的目录结构,会多出一个build 目录,如下:

. ├── build │   └── contracts │       ├── Migrations.json │       └── Storage.json ├── contracts │   ├── Migrations.sol │   └── Storage.sol ├── migrations │   ├── 1_initial_migration.js │   └── 2_deploy_contracts.js ├── test ├── truffle-config.js └── truffle.js 

build 目录包含两个文件:Migrations.jsonStorage.json 他们对应着 contracts 目录下的两个合约文件。

*.json 文件描述了他们对应的合约,包含:

  • 合约名称
  • 合约 ABI (应用二进制接口 — 描述合约的所有的方法及其对应的参数及返回值)
  • 合约字节码bytecode (编译后的合约数据)
  • 合约部署的 bytecode (已经部署在链上的最新的bytecode)
  • 合约最后编译使用的编译器版本
  • 已部署合约的网络列表,以及每个网络上的合约地址。

这个文件使 Truffle 能够创建一个JavaScript 包装器(即 truffle-contract)来与智能合约通信。例如,当在JavaScript代码中调用contract.address 时,Truffle 框架从 *.json 文件读取地址,并让我们方便的在不同的合约版本和网络之间进行转换。

编写迁移文件

有了这些知识,让我们写下我们的第一个迁移文件 2_deploy_contracts.js, 代码如下:

// 获取对应的合约文件 var Storage = artifacts.require("./Storage.sol");  // JavaScript export module.exports = function(deployer) {     // deployer 是用来部署      // 部署     deployer.deploy(Storage); } 

编写迁移就这么简单。 为了运行迁移脚本,请在终端中运行以下命令:

truffle migrate 

不过这时候,会得到一个错误:

Error: No network specified. Cannot determine current network. 

意思是 Truffle 找不到要部署到的网络,这时可以在命令行终端打开一个新的 tab 运行 ganache-cli来启动一个模拟的区块链blockchain,启动后,有会类似输出:

Ganache CLI v6.9.0 (ganache-core: 2.10.0)  Available Accounts ================== (0) 0x828da2e7b47f9480838f2077d470d39906ad1d8e (1) 0xa4928865329324560185f1c93b5ebafd7ae6c9e8 (2) 0x957b8b855bed52e11b2d7e9b3e6427771f299f3f (3) 0xf4b6bcabedaf1ccb3d0c89197c4b961460f1f63d ...  Private Keys ================== (0) 8729d0f1d876d692f2f454f564042bd11c1e6d0c9b1808954f171f6f7b926fd6 (1) 452dfeee16e5a0e34fa5348f0ef11f39a8b4635e5f454f77fc228ca9598f6997 (2) 9196ad9fd6234f09ee13726cb889dcbc438c15f98e8ff1feb36a93758fa6d10a (3) fa47edd832e896314544b98d7e297ac2ce2097b49f8a9d7e7ae0e38154db8760 ....  HD Wallet ================== Mnemonic:      void august badge future common warfxlb ... Base HD Path:  m/44'/60'/0'/0/{account_index}  Listening on localhost:8545 

现在已经建立了一个私有区块链blockchain,它运行在localhost:8545上。现在让我们配置 Truffle 以便部署合约到该网络。

打开 truffle-config.js 文件,加入以下内容:

module.exports = {   networks: {     development: {       host: "127.0.0.1",       port: 8545,       network_id: "*"     }   } }; 

上面配置的含义是把编译的合约部署到 localhost:8545 所在的网络上。

现在运行 truffle migrate , 得到以下输出:

Using network 'development'.  Running migration: 1_initial_migration.js   Deploying Migrations...   ... 0x06595c0eccde8cb0cf642df07beefea11e3e96bfb470e8tinyxiong6567cecc37aed8   Migrations: 0x6008e9a2c213d51093d0f18536d1aa3b00a7e058 Saving successful migration to network...   ... 0x392fb34c755970d1044dc83c56df6e51d5c4d4011319f659026ba27884126d7b Saving artifacts... Running migration: 2_deploy_contracts.js   Deploying Storage...   ... 0xb8ec575a9f3eca4a11a3f61170231a1816f7c68940d8487e56567adcf5c0a21e   Storage: 0xd8e2af5be9af2a45fc3ee7cdcb68d9bcc37a3c81 Saving successful migration to network...   ... 0x15498a1f9d2ce0f867b64cdf4b22ddff56f76xlbcd3d3a92b03b7aa4d881bac Saving artifacts... 

Truffle 将合约迁移到网络并保存了构件(artifacts)。 在构建目录的 Storage.json文件中,通过检查 networks 对象来检查它是否正确。 您应该看到类似以下内容:

"networks": {   "1525343635906": {     "events": {},     "links": {},     "address": "0xd8e2af5be9af2a45fc3ee7cdcb68d9bcc37a3c81",     "transactionHash": "0xb8ec575a9f3eca4a11a3f61170231a1816f7c68940d8487e56567adcf5c0a21e"   } }

1525343635906 是网络的 ID,以太坊eth网络主网和测试网都有固定的 ID(主网是 1)。

address 是部署合约的地址。 transactionHash 是部署合约的交易hash。

在后面会看到如何使用。

部署多合约

Truffle 迁移的真正亮点是能进行多个合约的编译、部署和跟踪(几乎所有区块链blockchain项目都是这样)。

迁移文件不仅允许我们使用单个命令部署多个合约,还允许我们调用合约的函数,如获取这些函数的返回值并将其传递给后续合约。

我们在 contracts 目录下,添加一个新合约 InfoManager.sol, 代码如下:

pragma solidity >0.4.21;  import "./Storage.sol";  contract InfoManager {      Storage private _dataStore;      uint private _lastAdded;      constructor(Storage dataStore) public {         _dataStore = dataStore;     }      function addData(string key, string value) public {         require((now - 1 days) > _lastAdded);         _dataStore.addData(key, value);     }  } 

可以看出,InfoManager 依赖 Storage 合约,不仅如此InfoManager的构造函数还叙需要 Storage 合约作为参数。

重新修改一下 2_deploy_contracts.js 让它可以完成 InfoManager 的部署:

var Storage = artifacts.require("./Storage.sol"); var InfoManager = artifacts.require("./InfoManager.sol");  module.exports = function(deployer) {      // 部署 Storage     deployer.deploy(Storage)         // 等待、直到合约部署完成         .then(() => Storage.deployed())         // 传递 Storage 合约地址,部署 InfoManager 合约         .then(() => deployer.deploy(InfoManager, Storage.address)); } 

部署的语法是:

... deployer.deploy(`ContractName`, [`constructor params`]) // 返回一个 promise ... 

因为 deploy(...) 返回一个 promise, 我们可以按自己喜欢的方式处理它,不要注意的是在部署文件里,还不支持 async

我们还可以在部署合约后自定义调用函数。例如,迁移还可以这样:

deployer.deploy(Storage)     .then(() => Storage.deployed())     .then((instance) => {         instance.addData("Hello", "world")     }).then(() => deployer.deploy(InfoManager, Storage.address)); 

这样在部署 InfoManager 之前,先给Storage 添加一条数据。

这个技巧很有用,因为有时相互依赖的合约可能需要在构造函数的之外写入。

根据网络进行部署

还可以根据所处的网络不同,进行不同的部署。这对于在开发阶段使用模拟链的数据而在主网上线是使用已部署的主网合约作为输入参数到合约中都非常有用。

通过导出函数 module.exports 扩展一个参数 network

module.exports = function(deployer, network) {     if (network == "live") {         // do one thing     } else if (network == "development") {         // do other thing     } } 

选择账号进行部署

module.exports 默认函数还可以公开一个账号参数,这些账号是以太坊eth节点或钱包provider “暴露” 出来的,看看下面的例子:

module.exports = function(deployer, network, accounts) {     var defaultAccount;     if (network == "live") {         defaultAccount = accounts[0]     } else {         defaultAccount = accounts[1]     } } 

链接库

你还可以通过 deployer.link(...) 连接已经存在(部署)的库:

... deployer.deploy(MyLibrary); deployer.link(MyLibrary, MyContract); deployer.deploy(MyContract); ... 

结论

通过使用上面的这些技术,可以把大部分区块链blockchain部署工作自动化,并减少开发去中心化应用程序涉及的大量重复工作。

参考文章:

  1. https://www.sitepoint.com/truffle-migrations-explained/
  2. Truffle 中文文档

部分转自网络,侵权联系删除www.interchains.cchttps://www.interchains.cc/20857.html

区块链毕设网(www.interchains.cc)全网最靠谱的原创区块链毕设代做网站 部分资料来自网络,侵权联系删除! 最全最大的区块链源码站 ! QQ3039046426
区块链知识分享网, 以太坊dapp资源网, 区块链教程, fabric教程下载, 区块链书籍下载, 区块链资料下载, 区块链视频教程下载, 区块链基础教程, 区块链入门教程, 区块链资源 » 详解 Truffle Migrations(迁移)- 合约部署不再困惑

提供最优质的资源集合

立即查看 了解详情