Truffle 3.0部署智能合约至Ethereum节点

如下内容全是都是创建在MacOS X平台上,在正式开始此以前,但愿你对BlockChain的内容有所了解,对truffle,contract,Solidity,web3.js等概念有所认识,假如毫无概念,那么请严格按照如下步骤顺序操做javascript

准备工做

Truffle 3.X安装

Truffle安装教程
安装truffle以前确保你已经安装了Nodejs环境,推荐NodeJS 5.0+。新建终端,执行:html

$ npm install -g trufflejava

Ethereum安装

Ethereum安装教程
安装以前确保你安装了Homebrew
新建终端,执行:node

brew tap ethereum/ethereum
    brew install ethereum复制代码

创建节点和帐户


正式开始

新建项目

新建文件夹,命名为truffleProject,而后新建一个终端,咱们将其命名为终端1,从终端1进入此文件夹下,执行:git

truffle initgithub

此时truffleProject文件夹下会出现contracts migrations test 三个文件夹和truffle.js文件web

编写合约

contracts 就是智能合约存放的目录,默认状况下已经帮你建立好ConvertLib.sol MetaCoin.sol Migrations.sol合约,不用管它npm

contracts文件夹下建立一个新文件Test.sol,文件内容以下:json

pragma solidity ^0.4.4;
contract Test {
    function multiply(uint a) returns(uint d) {
        return a * 7;
    }
}复制代码

合约内容很简单,就是输入一个整数,返回它乘以7的结果api

修改配置

修改migrateions文件中2_deploy_contracts.js的内容,以下:

var Test = artifacts.require("./Test.sol");

module.exports = function(deployer) {
  deployer.deploy(Test);
};复制代码

修改truffle.js的文件内容以下:

module.exports = {
  networks: {
    live: {
      host: "localhost", //本地地址,由于是在本机上创建的节点
      port: 8545,        //Ethereum的rpc监听的端口号,默认是8545
      network_id: 999    // 自定义网络号
    }
  }
};复制代码

咱们把合约部署在本身的私有网络上,因此自定义网络号。解释一下,Ethereum自己有一个主网络,假如你的节点没有链接到这个网络上去,那意味着你创建的是私有的Ethereum网络。network_id的设置可参见:github.com/ethereum/go…

启动节点

新建一个终端,咱们称为终端2,输入:

geth --identity "newEth" --rpc --rpccorsdomain "*" --datadir "你的节点的path" --port 30303 --rpcapi "db,eth,net,web3" --networkid 999 console

把上面命令中的“你的节点的path”替换成你本身创建的节点的目录,例如“/Users/JerryMissTom/Documents/blockchain/node1”。注意,network-id后的内容999和你上面在truffle.js文件中设置的保持一致

解锁帐户:

部署以前必须先解锁帐户,否则会报错Error encountered, bailing. Network state unknown. Review successful transactions manually.

在终端2上输入以下命令来解锁帐户:

personal.unlockAccount("0x4c00224faec439c08abe669bd2b15e3530a6e754", "111111", 10000)

其中"0x4c00224faec439c08abe669bd2b15e3530a6e754"是帐户地址,须要替换成你的,假如不知道,可先在终端2上输入:

personal.listAccounts

会返回你当前全部的帐户,选择第一个就好,假如不存在,则新建帐户,见准备工做中的创建节点和帐户的内容。"111111"是帐户相对应的密码,10000是解锁时间。

部署合约以前要保证你的帐户里有余额,使用eth.getBalance("0x4c00224faec439c08abe669bd2b15e3530a6e754")查看余额,假如为0,则先执行miner.start()进行挖矿,等待一段时间执行miner.stop(),挖矿中止,继续查询余额,不为0,可进行下一步。

部署合约

切换到终端1,编译合约,输入:

truffle compile

此时truffleProject文件夹下会多出一个build文件夹

而后部署合约,输入:

truffle migrate --network live

没有错误的话,终端1上会出现:

Running migration: 1_initial_migration.js
  Deploying Migrations...复制代码

geth的控制台,也就是终端2上,会出现:

I0421 10:29:58.671910 internal/ethapi/api.go:1141] Tx(0x66643d8dd37a4d8c8b13ad6aa933cb069fb30eae5e3a6e1b4309496d34b9c17a) created: 0x8b6deb996f11d9d463d5db3d2bd4de9193c1a14f复制代码

合约正在部署,在终端2上输入:txpool.status
结果是

{
  pending: 1,
  queued: 0
}复制代码

代表有一个交易在等待确认,须要继续挖矿,把交易打包到下一个区块,在终端2上继续执行:miner.start()
如今等待一段时间,成功部署后,会在终端1上出现:

Running migration: 1_initial_migration.js
  Deploying Migrations...
  Migrations: 0x8b6deb996f11d9d463d5db3d2bd4de9193c1a14f
Saving successful migration to network...
Saving artifacts...
Running migration: 2_deploy_contracts.js
  Deploying Test...
  Test: 0x98cd084074fe3f15890c55822070ac8274d8f7f6
Saving successful migration to network...
Saving artifacts...复制代码

代表部署成功
在终端2上执行:miner.stop(),中止挖矿

调用合约

打开truffleProject/build/contracts/Test.json文件,内容以下:

{
  "contract_name": "Test",
  "abi": [
    {
      "constant": false,
      "inputs": [
        {
          "name": "a",
          "type": "uint256"
        }
      ],
      "name": "multiply",
      "outputs": [
        {
          "name": "d",
          "type": "uint256"
        }
      ],
      "payable": false,
      "type": "function"
    }
  ],
  "unlinked_binary": "0x6060604052346000575b6077806100176000396000f300606060405263ffffffff60e060020a600035041663c6888fa181146022575b6000565b34600057602f6004356041565b60408051918252519081900360200190f35b600781025b9190505600a165627a7a72305820cf7ecb7716fc2496cf81a1249a8d74354554a193016fbeb30b18f473a6b989090029",
  "networks": {
    "999": {
      "events": {},
      "links": {},
      "address": "0x98cd084074fe3f15890c55822070ac8274d8f7f6",
      "updated_at": 1492742008225
    }
  },
  "schema_version": "0.0.5",
  "updated_at": 1492742008225
}复制代码

把abi内容拿出来先在线压缩,而后在终端2中输入:

abi=[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"payable":false,"type":"function"}]复制代码

结果显示:

[{
    constant: false,
    inputs: [{
        name: "a",
        type: "uint256"
    }],
    name: "multiply",
    outputs: [{
        name: "d",
        type: "uint256"
    }],
    payable: false,
    type: "function"
}]复制代码

建立合约的实例,在终端2中继续输入:

test=eth.contract(abi).at("0x98cd084074fe3f15890c55822070ac8274d8f7f6")复制代码

其中"0x98cd084074fe3f15890c55822070ac8274d8f7f6"就是合约存储的地址,能够在truffleProject/build/contracts/Test.json中找到.

在终端2中输入:

test.multiply.call(3)

结果会显示:
21


总结

以前我已经知道如何使用Truffle编写和编译智能合约,在TestRPC上运行官方的例子,也知道如何创建Ethereum节点和帐户,最后卡在如何使用Truffle合约部署在我创建的私有链上。如今终于解决这个问题,下一步就是研究如何与合约进行通讯。

致谢

安利

我在研究BlockChain的过程当中,也在着手把Ethereum Frontier Guide翻译成中文版,已经翻译一小部分了,因为我对Ethereum的理解还不够深刻,不少地方都是照字面意思翻译,因此读起来比较突兀,我会继续完善。翻译量还蛮大的,我只能在天天下班后翻译一点儿,我尽可能抽更多的时间吧。GitHub地址以下,欢迎Fork或者PR。
github.com/JerryMissTo…