Truffle 4.0、Geth 1.7.2、TestRPC在私有链上搭建智能合约

来源:互联网 发布:linux配置ip地址命令 编辑:程序博客网 时间:2024/05/22 01:49

目录

  • 目录
  • 1什么是 Truffle
  • 2适合 Truffle 开发的客户端
  • 3Truffle的源代码地址
  • 4如何安装
    • 1安装 Go-Ethereum 172
    • 2安装 Truffle 40
    • 3安装 TestRPC
  • 5使用 Truffle 进行智能合约的开发
    • 1初始化一个 Truffle 项目
    • 2编译合约
    • 3创建一个 Hello mshktop 的合约并编译
  • 6部署智能合约
    • 1将智能合约部署到 TestRPC 中测试
      • 12启动 TestRPC
      • 13通过 truffle migrate 命令对合约进行部署
      • 14测试部署成功的智能合约
    • 2将智能合约部署到 Geth 172 私有链
      • 21新建 Geth 的创世区块文件并初始化
      • 22使用 RPC 方式运行 Geth
      • 23在 Geth 中新建帐户开始挖矿
      • 24在 Geth 中部署合约
      • 25测试部署成功的智能合约
  • 7代币合约高级代币合约众筹合约项目地址
  • 8扩展阅读

1、什么是 Truffle?

  Truffle 是最流行的开发框架,能够在本地编译、部署智能合约,使命是让开发更容易。

  Truffle 需要以太坊客户端支持,需要支持标准的JSON RPC API。

2、适合 Truffle 开发的客户端

  有许多的以太坊客户端可以选择。我们推荐在开发和部署时使用不同客户端。

  适用开发的客户端

  • EtherumJS TestRPC

      适用正式发布的客户端

  • Geth (go-ethereum)

      当开发基于 Truffle 的应用时,推荐使用EthereumJS TestRPC。它是一个完整的在内存中的区块链仅仅存在于你开发的设备上。相对于 GethTestRPC 它在执行交易时是实时返回,而不等待默认的出块时间,这样你可以快速验证你新写的代码,当出现错误时,也能即时反馈给你。它同时还是一个支持自动化测试的功能强大的客户端。Truffle 充分利用它的特性,能将测试运行时间提速近90%。

3、Truffle的源代码地址

  https://github.com/trufflesuite/truffle

4、如何安装?

  接下来的例子,我们会使用 Truffle 分别连接 GethTestRPC 测试智能合约的部署,首先我们先分别安装TruffleGethTestRPC

4.1、安装 Go-Ethereum 1.7.2

  Go-Ethereum 的安装参考这篇文章:使用 Go-Ethereum 1.7.2搭建以太坊私有链

4.2、安装 Truffle 4.0

  依赖环境:
* NodeJS 5.0+
* Windows,Linux,或Mac OS X

  安装很简单:

npm install -g truffle@4.0.0

  查看安装的版本:

➜ /Users/lion >truffle versionTruffle v4.0.0 (core: 4.0.0)Solidity v0.4.18 (solc-js)

4.3、安装 TestRPC

➜ /Users/lion >npm install -g ethereumjs-testrpc/usr/local/bin/testrpc -> /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js+ ethereumjs-testrpc@6.0.1added 1 package and updated 2 packages in 10.648s

5、使用 Truffle 进行智能合约的开发

5.1、初始化一个 Truffle 项目

  通过truffle init命令,可以初始化一个默认的以太坊代币合约项目,后面我们可以通过这个项目来快速学习:

➜ /Users/lion/my_project/_eth >mkdir test_truffle➜ /Users/lion/my_project/_eth >cd test_truffle➜ /Users/lion/my_project/_eth/test_truffle >truffle initDownloading...Unpacking...Setting up...Unbox successful. Sweet!Commands:  Compile:        truffle compile  Migrate:        truffle migrate  Test contracts: truffle test

  完成后,你将拥有如下目录:
* contracts 智能合约目录
* migrations 发布脚本目录
* test 存放测试文件
* truffle.js Truffle的配置文件

5.2、编译合约

  要编译合约,使用truffle compile命令,可以将原始代码编译成以太坊认可的字节码:

➜ /Users/lion/my_project/_eth/test_truffle >truffle compileCompiling ./contracts/Migrations.sol...Writing artifacts to ./build/contracts

  Truffle仅默认编译自上次编译后被修改过的文件,来减少不必要的编译。如果你想编译全部文件,可以使用--compile-all选项

truffle compile --compile-all

  Truffle需要定义的合约名称和文件名准确匹配,这种匹配是区分大小写的,也就是说大小写也要一致。推荐大写每一个开头字母。

  文件之间的相互依赖,可以使用import进行合约间的引用,Truffle将会按正确顺序依次编译合约,并在需要的时候自动关联库。例如:

import "./AnotherContract.sol";

5.3、创建一个 Hello mshk.top 的合约并编译

  在contracts目录中新建一个Hello_mshk_top.sol文件,代码如下:

pragma solidity ^0.4.17;contract Hello_mshk_top {  //say hello mshk.top  function say() public pure returns (string) {    return "Hello mshk.top";  }  //print name  function print(string name) public pure returns (string) {    return name;  }}

  代码中有两个方法:say()方法是输出一段文字Hello mshk.topprint(string name)方法是输出传入的内容。

  编辑migrations/1_initial_migration.js部署脚本,将我们刚才创建的Hello_mshk_top.sol文件设置到发布配置文件中,内容如下:

var Migrations = artifacts.require("./Migrations.sol");var Hello_mshk_top = artifacts.require("./Hello_mshk_top.sol");module.exports = function(deployer) {  deployer.deploy(Migrations);  deployer.deploy(Hello_mshk_top);};

  将项目使用truffle compile命令进行编译,编译后的文件都放在了./build/contracts目录下:

➜ /Users/lion/my_project/_eth/test_truffle >truffle compileCompiling ./contracts/Hello_mshk_top.sol...Compiling ./contracts/Migrations.sol...Writing artifacts to ./build/contracts

  Hello_mshk_top.sol编译后的文件是./build/contracts/Hello_mshk_top.json中,后面在部署到geth中,我们会用到。

6、部署智能合约

  编辑truffle.js配置文件,设置我们稍后要部署智能合约的位置,内容如下:

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

  接下来,我们会使用上面的智能合约,分别在testRPCgeth中进行部署测试。

  truffle的智能合约项目部署,使用下面的命令:

truffle migrate

  这个命令会执行所有migrations目录下的js文件。如果之前执行过truffle migrate命令,再次执行,只会部署新的js文件,如果没有新的js文件,不会起任何作用。如果使用--reset参数,则会重新的执行所有脚本的部署。

  如果要部署到指定的网络,可以使用--network参数,例如:

truffle migrate --network live

  多个网络的配置格式如下:

networks: {  development: {    host: "localhost",    port: 8545,    network_id: "*" // match any network  },  live: {    host: "178.25.19.88", // Random IP for example purposes (do not use)    port: 80,    network_id: 1,        // Ethereum public network    // optional config values:    // gas  Gas limit used for deploys. Default is 4712388    // gasPrice Gas price used for deploys. Default is 100000000000 (100 Shannon).    // from - default address to use for any transaction Truffle makes during migrations    // provider - web3 provider instance Truffle should use to talk to the Ethereum network.    //          - if specified, host and port are ignored.  }}

6.1、将智能合约部署到 TestRPC 中测试

6.1.2、启动 TestRPC

  直接输入testrpc命令,就可以调用起 TestRPC 客户端,启动 testrpc 经后,会默认创建10个帐号,Available Accounts是帐号列表,Private Keys是相对应的帐号密钥:

➜ /Users/lion >testrpc --gasLimit 0x800000000EthereumJS TestRPC v6.0.1 (ganache-core: 2.0.0)Available Accounts==================(0) 0x74650142c29e358b8f94a8c5d43345649009a4cd......Private Keys==================(0) f11fa29910cd639aeb6de6126f2f16e091c1da51956fefccafca0afc476fbc41......HD Wallet==================Mnemonic:      inquiry sense exit ice craft evoke april gym settle social cat uniformBase HD Path:  m/44'/60'/0'/0'/{account_index}Gas Limit==================34359738368Listening on localhost:8545

6.1.3、通过 truffle migrate 命令,对合约进行部署

  使用truffle migrate命令,发布项目:

➜ /Users/lion/my_project/_eth/test_truffle >truffle migrateUsing network 'development'.Running migration: 1_initial_migration.js  Deploying Migrations...  ... 0xd9e5fa242d29362e57e3da7b0bf6f71b72767972fc15240ed3a02d341e814a44  Migrations: 0x4bedd1bb517ff9a54f6f3df8eba821ff16a4109b  Deploying Hello_mshk_top...  ... 0xc22ff050e189c2561d40250077ee4bf628f957899dfa8d0b5fa50e3ab7a896b0  Hello_mshk_top: 0xa7ef5037ff81d7932e01b68a503ca4587f00b35cSaving successful migration to network...  ... 0x49505a54042f5f74146fbfafef63dd408cb0a7a0c66214ebbaa3217e443d792aSaving artifacts...

6.1.4、测试部署成功的智能合约

  输入以下命令打开truffle控制台,测试刚才我们部署的Hello_mshk_top合约:

truffle(development)> var contract;undefinedtruffle(development)> Hello_mshk_top.deployed().then(function(instance){contract= instance;});undefinedtruffle(development)> contract.say()'Hello mshk.top'truffle(development)> contract.print("https://mshk.top")'https://mshk.top'

  var contractjavascript语法一样,表示声明一个contract变量。Hello_mshk_top.deployed().then(function(instance){contract= instance;})表示,将Hello_mshk_top合约主体,传递给contract变量。后面我们就可以直接使用变量contract分别调用say()方法和print(''),得到我们想要的结果。

6.2、将智能合约部署到 Geth 1.7.2 私有链

6.2.1、新建 Geth 的创世区块文件,并初始化

  新建一个test_truffle_geth目录,同时新建我们的创世区块文件genesis.json

➜ /Users/lion/my_project/_eth >mkdir test_truffle_geth➜ /Users/lion/my_project/_eth >cd test_truffle_geth➜ /Users/lion/my_project/_eth/test_truffle_geth >vi genesis.json

  genesis.json:

{  "config": {        "chainId": 10,        "homesteadBlock": 0,        "eip155Block": 0,        "eip158Block": 0    },  "coinbase"   : "0x0000000000000000000000000000000000000000",  "difficulty" : "0x20000",  "extraData"  : "",  "gasLimit"   : "0x8000000",  "nonce"      : "0x0000000000000042",  "mixhash"    : "0x0000000000000000000000000000000000000000000000000000000000000000",  "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",  "timestamp"  : "0x00",  "alloc": {}}

  初始化创世区块

➜ /Users/lion/my_project/_eth/test_truffle_geth >geth init ./genesis.json --datadir "./chain"WARN [11-07|10:17:11] No etherbase set and no accounts found as defaultINFO [11-07|10:17:11] Allocated cache and file handles         database=/Users/lion/my_project/_eth/test_truffle_geth/chain/geth/chaindata cache=16 handles=16INFO [11-07|10:17:11] Writing custom genesis blockINFO [11-07|10:17:11] Successfully wrote genesis state         database=chaindata                                                          hash=ecf271…5269d6INFO [11-07|10:17:11] Allocated cache and file handles         database=/Users/lion/my_project/_eth/test_truffle_geth/chain/geth/lightchaindata cache=16 handles=16INFO [11-07|10:17:11] Writing custom genesis blockINFO [11-07|10:17:11] Successfully wrote genesis state         database=lightchaindata                                                          hash=ecf271…5269d6

6.2.2、使用 RPC 方式运行 Geth

  使用rpc方式运行geth

➜ /Users/lion/my_project/_eth/test_truffle_geth >geth \  --identity "mshk.top etherum" \  --rpcaddr 0.0.0.0 \  --rpc \  --rpcport 8545 \  --maxpeers 2 \  --rpcapi "db,eth,net,web3,debug" \  --networkid 100 \  --datadir "./chain" \  --nodiscoverWARN [11-07|10:21:56] No etherbase set and no accounts found as defaultINFO [11-07|10:21:56] Starting peer-to-peer node               instance="Geth/mshk.top etherum/v1.7.2-stable-1db4ecdc/darwin-amd64/go1.9.1"INFO [11-07|10:21:56] Allocated cache and file handles         database=/Users/lion/my_project/_eth/test_truffle_geth/chain/geth/chaindata cache=128 handles=1024WARN [11-07|10:21:56] Upgrading database to use lookup entriesINFO [11-07|10:21:56] Initialised chain configuration          config="{ChainID: 10 Homestead: 0 DAO: <nil> DAOSupport: false EIP150: <nil> EIP155: 0 EIP158: 0 Byzantium: <nil> Engine: unknown}"INFO [11-07|10:21:56] Disk storage enabled for ethash caches   dir=/Users/lion/my_project/_eth/test_truffle_geth/chain/geth/ethash count=3INFO [11-07|10:21:56] Disk storage enabled for ethash DAGs     dir=/Users/lion/.ethash                                             count=2INFO [11-07|10:21:56] Initialising Ethereum protocol           versions="[63 62]" network=100INFO [11-07|10:21:56] Database deduplication successful        deduped=0INFO [11-07|10:21:56] Loaded most recent local header          number=0 hash=ecf271…5269d6 td=131072INFO [11-07|10:21:56] Loaded most recent local full block      number=0 hash=ecf271…5269d6 td=131072INFO [11-07|10:21:56] Loaded most recent local fast block      number=0 hash=ecf271…5269d6 td=131072INFO [11-07|10:21:56] Regenerated local transaction journal    transactions=0 accounts=0INFO [11-07|10:21:56] Starting P2P networkingINFO [11-07|10:21:56] RLPx listener up                         self="enode://eee1025474554baf3d42dc72fb6f13df8246b5ed879ca6a7764d3147c422ca2d10eba1dc6a9e609d3535794668d1e064548550683a8c34cfefbcf879b9cbaf2b@[::]:30303?discport=0"INFO [11-07|10:21:56] IPC endpoint opened: /Users/lion/my_project/_eth/test_truffle_geth/chain/geth.ipcINFO [11-07|10:21:56] HTTP endpoint opened: http://0.0.0.0:8545INFO [11-07|10:21:56] Mapped network port                      proto=tcp extport=30303 intport=30303 interface=NAT-PMP(10.0.0.1)

  
  启动私有节点需要的参数:

参数名称 参数描述 identity 区块链的标示,随便填写,用于标示目前网络的名字 init 指定创世块文件的位置,并创建初始块 datadir 设置当前区块链网络数据存放的位置 port 网络监听端口 默认是30303 rpc 启动rpc通信,可以进行智能合约的部署和调试 maxpeers 网络节点的最大数量,默认是25 rpcapi 设置允许连接的rpc的客户端,一般为db,eth,net,web3 networkid 设置当前区块链的网络ID,用于区分不同的网络,是一个数字 console 启动命令行模式,可以在Geth中执行命令 dev 开发者模式,带调试模式的专有网络 nodiscover 私有链地址,不会被网上看到

  
  rpc方式启动geth以后,会一直停止在那里,没有办法在geth中进行任何输入。浏览一下我们刚才创建区块链数据的文件夹,会发现有一个geth.ipc文件。

➜ /Users/lion >ll /Users/lion/my_project/_eth/test_truffle_geth/chaintotal 0drwxr-xr-x  7 lion  staff  224 Nov  7 10:21 gethsrw-------  1 lion  staff    0 Nov  7 10:21 geth.ipcdrwx------  2 lion  staff   64 Nov  7 10:17 keystore

  然后用下面这个命令,进入geth控制台:

➜ /Users/lion >geth attach ipc://Users/lion/my_project/_eth/test_truffle_geth/chain/geth.ipcWelcome to the Geth JavaScript console!instance: Geth/mshk.top etherum/v1.7.2-stable-1db4ecdc/darwin-amd64/go1.9.1 modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0>

6.2.3、在 Geth 中新建帐户,开始挖矿

  创建一个帐户,并解锁用户一段时间(单位是秒),然后启动挖矿

> web3.personal.newAccount("123456")"0x0a67659a161410a4a1e0a5889ff05a1417915172"> personal.unlockAccount(eth.accounts[0], "123456", 15000)true> miner.start(1)null

  过一会后查看下帐户地址的余额,将帐户地址赋值给变量acc0,可以看到里面有了以太币:

> acc0 = web3.eth.accounts[0]"0xc90747b99362c41fa89d2e7dea1b5b8d9567b741"> web3.eth.getBalance(acc0)415000000000000000000

6.2.4、在 Geth 中部署合约

  这时,我们就要用到刚刚编译后的Hello_mshk_top.json文件了,打开https://www.bejson.com网址,把abi部分取出并转义。然后在geth中输入以下内容,将json转义后的内容,赋值给mshk_abi变量:

mshk_abi=JSON.parse('[{\"constant\":true,\"inputs\":[{\"name\":\"name\",\"type\":\"string\"}],\"name\":\"print\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"say\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"}]')

  会得到下面的返回值:

[{    constant: true,    inputs: [{        name: "name",        type: "string"    }],    name: "print",    outputs: [{        name: "",        type: "string"    }],    payable: false,    stateMutability: "pure",    type: "function"}, {    constant: true,    inputs: [],    name: "say",    outputs: [{        name: "",        type: "string"    }],    payable: false,    stateMutability: "pure",    type: "function"}]

  找到Hello_mshk_top.json文件中的bytecode部分,然后在geth中,将值赋值给mshk_bytecode变量,在geth中输入以下内容:

mshk_bytecode="0x6060604052341561000f57600080fd5b6102488061001e6000396000f30060606040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806311114af114610051578063954ab4b214610127575b600080fd5b341561005c57600080fd5b6100ac600480803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919050506101b5565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100ec5780820151818401526020810190506100d1565b50505050905090810190601f1680156101195780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561013257600080fd5b61013a6101c5565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561017a57808201518184015260208101905061015f565b50505050905090810190601f1680156101a75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101bd610208565b819050919050565b6101cd610208565b6040805190810160405280600e81526020017f48656c6c6f206d73686b2e746f70000000000000000000000000000000000000815250905090565b6020604051908101604052806000815250905600a165627a7a72305820aa448d81e0f4bf12f805920c9cefd0d3cc6f053d87dd8547663721256179ebcd0029"

  评估下创建合约需要的手续费是207296gas

> web3.eth.estimateGas({data: mshk_bytecode})207296

  部署合约,并将合约传递给mshk变量,在geth中输入以下内容:

mshk_Contract = web3.eth.contract(abi);mshk_hello = mshk_Contract.new({from:acc0, data:mshk_bytecode, gas:300000}, function(e, contract){    if(!e) {      if(!contract.address) {        console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined...");      } else {        console.log("Contract mined! Address: " + contract.address);        console.log(contract);      }    }});

  输入成功后,会看到下面的信息,0x1d055281899007cbe6865a48d0a79239dac8e486是合约创建成功的地址:

> Contract mined! Address: 0x1d055281899007cbe6865a48d0a79239dac8e486[object Object]

6.2.5、测试部署成功的智能合约

  恭喜你,如果能看到上面的信息,说明智能合约已经部署成功了。接下来,我们可以使用下面的命令在geth中调用,刚刚部署成功的合约:

> mshk_hello.say()"Hello mshk.top"> mshk_hello.print("Hello https://mshk.top")"Hello https://mshk.top"

  通过这些章节的练习,你可以将之前章节中的代币合约、众筹合约进行部署。

7、代币合约、高级代币合约、众筹合约项目地址

  文章中使用的完整代码,存放在了github上面:https://github.com/idoall/truffle_solidity_contractsExample

8、扩展阅读

upgrading-from-truffle-2-to-3

Full Stack Hello World Voting Ethereum Dapp Tutorial

Truffle Documentation

Building a smart contract using the command line

truffle3.0-integrate-nodejs


博文作者:迦壹
博客地址:Truffle 4.0、Geth 1.7.2、TestRPC在私有链上搭建智能合约
转载声明:可以转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明,谢谢合作!


阅读全文
0 0
原创粉丝点击