创建一个文件夹来存储你的私链数据
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
geth geth.ipc keystore
保持节点的运行,不要关闭终端,重新打开一个终端,使用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
。手续费大概为99866
gas。
部署合约
创建一个账号
> personal.newAccount('123456')
"0xb12334742271e17c50d49cf04a2bccc0bd693b7b"
查看余额
> web3.eth.getBalance("0xb12334742271e17c50d49cf04a2bccc0bd693b7b")
0
查看该账号是否是矿工账号
> 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)
作者:黎跃春