以太坊开发(十九)使用Geth建立私链|以太坊开发(十九)使用Geth建立私链 ,编译以及部署合约

创建一个文件夹来存储你的私链数据

yuyangdeMacBook-Pro:~ yuyang$ mkdir privatechain yuyangdeMacBook-Pro:~ yuyang$ cd privatechain

使用geth开启
yuyangdeMacBook-Pro:privatechain yuyang$ geth --networkid 123 --dev --datadir data1

如果你切换到data1文件夹里面,你会看到geth, geth.ipc, 和 keystore
yuyangdeMacBook-Pro:data1 yuyang$ ls gethgeth.ipckeystore

保持节点的运行,不要关闭终端,重新打开一个终端,使用geth attach连接节点,并且打开geth console
yuyangdeMacBook-Pro:~ yuyang$ geth attach ipc:/Users/yuyang/privatechain/data1/geth.ipc Welcome to the Geth JavaScript console!instance: Geth/v1.8.1-stable/darwin-amd64/go1.10 coinbase: 0x12c7be0d310a9851317b4cd8b976cf33d5456bf1 at block: 0 (Thu, 01 Jan 1970 08:00:00 CST) datadir: /Users/yuyang/privatechain/data1 modules: admin:1.0 clique:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 shh:1.0 txpool:1.0 web3:1.0

准备智能合约代码,字节码,ABI
pragma solidity ^0.4.4; contract test { function multiply(uint a) returns(uint d){return a * 7; } }

代码拷贝到https://remix.ethereum.org,编译,然后拷贝字节码和ABI(编译后点击Publish on Swarm,然后点击 Details,字节码和ABI都在其中)。
  • 字节码
6060604052341561000f57600080fd5b60b18061001d6000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c6888fa1146044575b600080fd5b3415604e57600080fd5b606260048080359060200190919050506078565b6040518082815260200191505060405180910390f35b60006007820290509190505600a165627a7a723058208b4b34b5adf7ee471715fd019a96a400495b0aa026580c670af16bb6eee1f2290029

  • ABI
[ { "constant": false, "inputs": [ { "name": "a", "type": "uint256" } ], "name": "multiply", "outputs": [ { "name": "d", "type": "uint256" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" } ]

在bejson中转义成字符串
http://www.bejson.com/jsonviewernew/
[{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"multiply\",\"outputs\":[{\"name\":\"d\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]

通过abi创建合约对象
> var abi = JSON.parse('[{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"multiply\",\"outputs\":[{\"name\":\"d\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]') undefined > myContract = web3.eth.contract(abi) { abi: [{ constant: false, inputs: [{...}], name: "multiply", outputs: [{...}], payable: false, stateMutability: "nonpayable", type: "function" }], eth: { accounts: ["0x12c7be0d310a9851317b4cd8b976cf33d5456bf1"], blockNumber: 0, coinbase: "0x12c7be0d310a9851317b4cd8b976cf33d5456bf1", compile: { lll: function(), serpent: function(), solidity: function() }, defaultAccount: undefined, defaultBlock: "latest", gasPrice: 1, hashrate: 0, mining: true, pendingTransactions: [], protocolVersion: "0x3f", syncing: false, call: function(), contract: function(abi), estimateGas: function(), filter: function(options, callback, filterCreationErrorCallback), getAccounts: function(callback), getBalance: function(), getBlock: function(), getBlockNumber: function(callback), getBlockTransactionCount: function(), getBlockUncleCount: function(), getCode: function(), getCoinbase: function(callback), getCompilers: function(), getGasPrice: function(callback), getHashrate: function(callback), getMining: function(callback), getPendingTransactions: function(callback), getProtocolVersion: function(callback), getRawTransaction: function(), getRawTransactionFromBlock: function(), getStorageAt: function(), getSyncing: function(callback), getTransaction: function(), getTransactionCount: function(), getTransactionFromBlock: function(), getTransactionReceipt: function(), getUncle: function(), getWork: function(), iban: function(iban), icapNamereg: function(), isSyncing: function(callback), namereg: function(), resend: function(), sendIBANTransaction: function(), sendRawTransaction: function(), sendTransaction: function(), sign: function(), signTransaction: function(), submitTransaction: function(), submitWork: function() }, at: function(address, callback), getData: function(), new: function() }

预估手续费
> bytecode = "0x6060604052341561000f57600080fd5b60b18061001d6000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c6888fa1146044575b600080fd5b3415604e57600080fd5b606260048080359060200190919050506078565b6040518082815260200191505060405180910390f35b60006007820290509190505600a165627a7a723058208b4b34b5adf7ee471715fd019a96a400495b0aa026580c670af16bb6eee1f2290029" "0x6060604052341561000f57600080fd5b60b18061001d6000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c6888fa1146044575b600080fd5b3415604e57600080fd5b606260048080359060200190919050506078565b6040518082815260200191505060405180910390f35b60006007820290509190505600a165627a7a723058208b4b34b5adf7ee471715fd019a96a400495b0aa026580c670af16bb6eee1f2290029" > web3.eth.estimateGas({data: bytecode}) 99866

备注:字节码前面需要添加0x。手续费大概为99866gas。
部署合约 创建一个账号
> personal.newAccount('123456') "0xb12334742271e17c50d49cf04a2bccc0bd693b7b"

查看余额
> web3.eth.getBalance("0xb12334742271e17c50d49cf04a2bccc0bd693b7b") 0

【以太坊开发(十九)使用Geth建立私链|以太坊开发(十九)使用Geth建立私链 ,编译以及部署合约】查看该账号是否是矿工账号
> web3.eth.coinbase "0x12c7be0d310a9851317b4cd8b976cf33d5456bf1"

发现不是,将我们新建的账号设置为挖矿账号
> miner.setEtherbase(eth.accounts[1]) true > eth.coinbase "0xb12334742271e17c50d49cf04a2bccc0bd693b7b"

开启挖矿,以便可以支付部署费用
> miner.start()

或者直接从另一个账号转账
> eth.sendTransaction({from:"0x12c7be0d310a9851317b4cd8b976cf33d5456bf1",to:"0xb12334742271e17c50d49cf04a2bccc0bd693b7b",value:web3.toWei(3,"ether")}) "0x489e219ef97ae1fda3e1ff0f17774c655f6dac88cf5c27e615c0aceceddebf27" > web3.eth.getBalance("0xb12334742271e17c50d49cf04a2bccc0bd693b7b") 3000000000000000000

解锁账号
> personal.unlockAccount("0xb12334742271e17c50d49cf04a2bccc0bd693b7b", '123456') true

部署合约,为了方便理解,设置一个回调函数
> contractInstance = myContract.new({data: bytecode, gas: 1000000, from: "0xb12334742271e17c50d49cf04a2bccc0bd693b7b"}, function(e, contract){ ......if(!e){ .........if(!contract.address){ ............console.log("Contract transaction send: Transaction Hash: "+contract.transactionHash+" waiting to be mined..."); ............}else{ ............console.log("Contract mined! Address: "+contract.address); ............console.log(contract); ............} .........}else{ .........console.log(e) .........} ...... }) Contract transaction send: Transaction Hash: 0x8b38f4a3f2c3829b179b3b9c2a69e82deccf56b03d5af17e9f2c781bc0dd7587 waiting to be mined... { abi: [{ constant: false, inputs: [{...}], name: "multiply", outputs: [{...}], payable: false, stateMutability: "nonpayable", type: "function" }], address: undefined, transactionHash: "0x8b38f4a3f2c3829b179b3b9c2a69e82deccf56b03d5af17e9f2c781bc0dd7587" }

挖矿以便写入区块:
> miner.start() null > Contract mined! Address: 0x9eeda351114088044715e6e4c0e09e02e97d26b3 [object Object]

查看是否部署成功:
> eth.getCode(contractInstance.address) "0x606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c6888fa1146044575b600080fd5b3415604e57600080fd5b606260048080359060200190919050506078565b6040518082815260200191505060405180910390f35b60006007820290509190505600a165627a7a723058208b4b34b5adf7ee471715fd019a96a400495b0aa026580c670af16bb6eee1f2290029"

调用合约方法:
> contractInstance.multiply(6) 42 >

参考:以太坊(Ethereum)私链建立 、合约编译、部署完全教程(1)
作者:黎跃春

    推荐阅读