首先要保证geth客户端安装成功
1 、创建初始配置文件genesis.json
{
"config": {
"chainId": 15,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"alloc": {
"0x0000000000000000000000000000000000000001": {"balance": "111111111"},
"0x0000000000000000000000000000000000000002": {"balance": "222222222"}
},
"coinbase" : "0x0000000000000000000000000000000000000000",
"difficulty" : "0x20000",
"extraData" : "",
"gasLimit" : "0x2fefd8",
"nonce" : "0x0000000000001993",
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00"
}
参数 | 描述 |
---|---|
alloc | 可以预置账号以及账号的以太币数量 |
coinbase | 区块受益者地址,可以设置成已存在的账户。后面挖出的区块的受益者将是挖掘出那个区块的账户(矿工) |
difficulty | 代表当前区块的难度等级(十六进制),这里定义创世区块的难度等级,难度等级越高,挖矿越难。后面生成的区块难度等级根据前一个区块的难度等级和时间戳计算得到 |
extraData | 附加信息,在 POA 挖矿中用于投票 |
gasLimit | 该值设置区块对 GAS 的消耗总量限制,用来限制区块能包含的交易数量,gasLimit会动态调整,命令行可以指定targetGasLimit用于限制区块gas的上限 |
nonce | nonce 就是一个 64 位随机数,用于挖矿 |
mixhash | 与 nonce 配合用于挖矿,有助于对候选区块头的nonce进行验证 |
parentHash | 上一个区块的 hash 值,因为是创世块,所以这个值是 0 |
timestamp | 设置创世块的时间戳 |
2、启动第一个节点,执行命令,创建创世区块
geth --datadir data init genesis.json geth --datadir ./data/ --networkid 1114 console 2>> myEth.log
转账交易测试
3、创建账户account1和account2以便进行转账交易,输入账户密码
personal.newAccount("account1") personal.newAccount("account2") eth.coinbase eth.getBalance(eth.accounts[0]) eth.getBalance(eth.accounts[1])
4、开启挖矿,挖矿收入进入coinbase账户,因为coinbase默认为第一个创建的账户即account1,所以挖到矿后account1中就有奖励的以太币了。
miner.start()
5、执行转账,先要解锁转出账户,解锁时需要输入账户密码
personal.unlockAccount(eth.accounts[0]) eth.sendTransaction({from:eth.accounts[0],to:"0xdb2e9d8b44b8e52b276cb3b81764076d77bea6fb",value:web3.toWei(0.005, "ether")})
转账金额以wei为单位,如果以实际以太币个数为单位,可以使用web3提供的换算函数
部署合约测试
6、以同一份初始配置文件启动第二个节点,另建一个工作目录
geth --datadir ./data init genesis.json geth --datadir ./data/ --networkid 1114 --port 30304 console 2>> myEth.log personal.newAccount("account1")
因为要与第一个节点建立集群,所以在同步之前先不要开启挖矿,否则可能会出现几本不致的情况。
7、与第一个节点建立联系,形成集群
7.a 获取第一个节点的enode ID
admin.nodeInfo.enode
"enode://06bee9e9086c173c6fb4d92fefac741877353753162a9d9a2d4314790ccebfafccfd225eff3d875ec5b8ca1e2fafd922708ef7c832e2c037c488b4b63ef99ee7@[::]:30303"
7.b 在第二个节点上执行联系第一个节点的操作
admin.addPeer("enode://06bee9e9086c173c6fb4d92fefac741877353753162a9d9a2d4314790ccebfafccfd225eff3d875ec5b8ca1e2fafd922708ef7c832e2c037c488b4b63ef99ee7@127.0.0.1:30303")
7.c 查看节点连接情况
admin.peers
7.d 查看块几步状态,如果为false则表示同步已经完成
eth.syncing
7.e 查看区块链高度,同步完成的情况下两个节点的区块高度是一致的。
eth.blockNumber
8. 同步完成后即可开始挖矿
miner.start()
9.编辑一个简单的set/get存储状态的合约
contract SimpleStorage { uint storedData; function set(uint x) { storedData = x; } function get() constant returns (uint retVal) { return storedData; } }
10.合约通过Remix 编译,复制WEB3DEPLOY部分的代码到geth终端下
var simplestorageContract = web3.eth.contract([{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false ,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false ,"stateMutability":"view","type":"function"}]); var simplestorage = simplestorageContract.new( { from: web3.eth.accounts[0], data: '0x608060405234801561001057600080fd5b5060bf8061001f6000396000f30060806040526004361060485763ffffffff7c010000000000000000000000000000000000000000000000 000000000060003504166360fe47b18114604d5780636d4ce63c146064575b600080fd5b348015605857600080fd5b5060626004356088565b005b348015606f57600080fd5b506076608d565b60 408051918252519081900360200190f35b600055565b600054905600a165627a7a723058208ca304d64f593c38cff5043b5fb84c3a3f237e0c8c44f8bc5983d02037af9d990029', gas: '4700000' }, function (e, contract){ console.log(e, contract); if (typeof contract.address !== 'undefined') { console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash); } })
其中,from指定部署合约的账户,需要保证该账户有以太币并且处于解锁状态。返回如下提示表明合约部署成功:
11. 调用合约有三种方式(参考),合约实例为simplestorage,直接调用合约实现的get函数可以获取内部状态变量:
simplestorage.get()
使用set函数修改内部状态变量值:
simplestorage.set(10)
12. 作为服务的提供者,也即合约的创建者,需要提供合约地址和ABI接口给用户,用户才能调用合约的接口。ABI是一个固定格式的字符串,包含了合约中各函数的函数名、参数数目和类型、返回值数目和类型等信息。
获取合约地址
simplestorage.address
加载合约实例的命令格式为:
var simplestorage = eth.contract(ABI).at(Address);
本例的实际命令为:
var simplestorage = eth.contract([ { "constant": false, "inputs": [ { "name": "x", "type": "uint256" } ], "name": "set", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": true, "inputs": [], "name": "get", "outputs": [ { "name": "retVal", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }]).at("0x15f77989370a0984f999568af266046f6ac731d2");
测试调用正常。