待补充。
很多朋友照着教程部署合约会遇到一些问题,我觉得主要是在获取abi这一步。
var Multiply7 = eth.contract(contract.info.abiDefinition);
所以这里记录一下用browser-solidity编译。
首先需要准备一个创世区块信息用于初始化私有链,其中difficulty
为挖矿难度,建议设置低一点方便挖矿测试,保存为init.json。
{
"nonce": "0×0000000000000042",
"mixhash": "0×0000000000000000000000000000000000000000000000000000000000000000",
"difficulty": "0×20000",
"alloc": {},
"coinbase": "0×0000000000000000000000000000000000000000",
"timestamp": "0×00",
"parentHash": "0×0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "blossom",
"gasLimit": "0xffffffff" }
进入终端,创建私有链。命令中--datadir
后的参数根据你放置init.json
的路径自行更改。
geth --datadir "/home/swb/test" init init.json
进入私有链console。--identity
和--datadir
需要根据你的需要而定。
geth --identity "blossom" --rpc --rpccorsdomain "*" --datadir "/home/swb/test" --port 30303 --rpcapi "db,eth,net,web3" --networkid 123456 console 2>> /home/swb/test/geth.log
这一步不多说,具体的合约代码自己编写。以下是Solidity的官方文档:链接
本文以一个简单的加法合约为例介绍部署步骤。
还可以参考wiki中给的教程案例:Contracts and Transactions
pragma solidity ^0.4.0;
contract test {
/// @notice Will multiply `a` by 7.
function multiply(uint a) returns(uint d) {
return a * 7;
}
}
如前文中提到的,想要部署合约需要得到合约代码的ABI和EVM code。很多朋友看教程是在geth控制台里编译合约的,但是有一个问题是:
MyContract = eth.contract(contract.info.abiDefinition)
无法获得contract的abi。导致接下来的步骤出错。所以这里推荐使用browser-solidity网页编译。
上图中Bytecode和interface就是我们需要的结果。
在部署合约前,我们要明确需要以下几项条件:
所以首先需要做以下工作:
//创建账户
personal.newAccount('密码')
//挖矿获取Ether。其中miner.start(4)应该是CPU数,admin.sleepBlock()可以指定挖的区块数
miner.start(4);admin.sleepBlocks(10);miner.stop();
//账户解锁
personal.unlockAccount(eth.coinbase,'密码',10000)
之后可以进行部署了。
//获取abi信息,即上述编译得到的interface
> abi = [{constant:false,inputs:[{name:'a',type:'uint256'}],name:'multiply',outputs:[{name:'d',type:'uint256'}],type:'function'}]
[{
constant: false,
inputs: [{
name: "a",
type: "uint256"
}],
name: "multiply",
outputs: [{
name: "d",
type: "uint256"
}],
type: "function"
}]
//创建合约。
> multiplyContract = web3.eth.contract(abi)
{
abi: [{
constant: false,
inputs: [{...}],
name: "multiply",
outputs: [{...}],
type: "function"
}],
eth: {
accounts: ["0xae5a780f8d162b7687869f9f6d4bdbda5056832d"],
blockNumber: 10,
coinbase: "0xae5a780f8d162b7687869f9f6d4bdbda5056832d",
compile: {
lll: function(),
serpent: function(),
solidity: function()
},
defaultAccount: undefined,
defaultBlock: "latest",
gasPrice: 20000000000,
hashrate: 0,
mining: false,
pendingTransactions: [],
protocolVersion: "0x3f",
syncing: false,
call: function(),
contract: function(abi),
estimateGas: function(),
filter: function(fil, callback),
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()
}
//解锁账户
> personal.unlockAccount(eth.coinbase, '111', 10000)
true
//部署合约。data为上述编译得到的Bytecode
> multiply = multiplyContract.new({from: eth.coinbase, data: "0x60606040523415600b57fe5b5b60788061001a6000396000f300606060405263ffffffff60e060020a600035041663c6888fa181146020575bfe5b3415602757fe5b60306004356042565b60408051918252519081900360200190f35b600781025b9190505600a165627a7a7230582007a6259ba3d57941abda2e261e9a67958a3eda78b779d9dd8d42518791fddd590029"})
{
abi: [{
constant: false,
inputs: [{...}],
name: "multiply",
outputs: [{...}],
type: "function"
}],
address: undefined,
transactionHash: "0x2c61f267d9578d312dd0b0455db97ff615bb0c052c2b0f7ca3ea5946d57e210b"
}
//我们知道部署合约的过程实际也是由创建合约的账户发送的一笔交易(即eth.coinbase账户)。需要挖矿进行确认。
> miner.start(4);admin.sleepBlocks(2);miner.stop();
true
至此合约已经存在于区块链中,可以查看区块信息获取合约的地址和交易hash。
//获取合约对象
> MyContract = eth.contract(abi)
{
abi: [{
constant: false,
inputs: [{...}],
name: "multiply",
outputs: [{...}],
type: "function"
}],
eth: {
accounts: ["0xae5a780f8d162b7687869f9f6d4bdbda5056832d"],
blockNumber: 15,
coinbase: "0xae5a780f8d162b7687869f9f6d4bdbda5056832d",
compile: {
lll: function(),
serpent: function(),
solidity: function()
},
defaultAccount: undefined,
defaultBlock: "latest",
gasPrice: 20000000000,
hashrate: 0,
mining: false,
pendingTransactions: [],
protocolVersion: "0x3f",
syncing: false,
call: function(),
contract: function(abi),
estimateGas: function(),
filter: function(fil, callback),
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()
}
//实例化合约
> myContract = MyContract.at(multiply.address)
{
abi: [{
constant: false,
inputs: [{...}],
name: "multiply",
outputs: [{...}],
type: "function"
}],
address: "0xe6c436f2964bd57692a7c3929e5451916a491401",
transactionHash: null,
allEvents: function(),
multiply: function()
}
//调用合约
> myContract.multiply.call(5)
35