以太坊私有链搭建

客户端geth安装

1
2
3
4
5
apt-get install software-properties-common  // 安装工具包
add-apt-repository -y ppa: ethereum/ethereum // 添加以太坊源
apt-get update // 更新
apt-get install ethereum // 安装go-ethereum
geth version // 查看geth版本

搭建私有链

初始状态文件genesis.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"config": {
"chainId": 88,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"alloc" : {},
"coinbase" : "0x0000000000000000000000000000000000000000",
"difficulty" : "0x400",
"extraData" : "",
"gasLimit" : "0xffffffff",
"nonce" : "0x0000000000000042",
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00"
}
参数名称 参数描述
mixhash 与nonce配合用于挖矿,由上一个区块的一部分生成的hash。
nonce nonce就是一个64位随机数,用于挖矿。
difficulty 设置当前区块的难度,如果难度过大,cpu挖矿就很难,这里设置较小难度
alloc 用来预置账号以及账号的以太币数量,因为私有链挖矿比较容易,所以我们不需要预置有币的账号,需要的时候自己创建即可以。
coinbase 矿工的账号,随便填
timestamp 设置创世块的时间戳
parentHash 上一个区块的hash值,因为是创世块,所以这个值是0
extraData 附加信息,随便填,可以填你的个性信息
gasLimit 该值设置对GAS的消耗总量限制,用来限制区块能包含的交易信息总和,因为我们是私有链,所以填最大。

初始化区块链

1
2
cd privatechain
geth --datadir data0 init genesis.json

--datadir 选项后面跟一个目录名,这里为 data0,表示指定数据存放目录为 data0,genesis.json 是 init 命令的参数。

1530692029244

启动区块链

1
geth --identity "TestNode" --networkid "99" --rpc --rpccorsdomain "*" --rpcapi "db,eth,net,web3" --rpcport "8545" --datadir data0 --port "30303" --nodiscover console

1530771728423

参数名称 参数描述
identity 区块链的标示,随便填写,用于标示目前网络的名字
init 指定创世块文件的位置,并创建初始块
datadir 设置当前区块链网络数据存放的位置
port 网络监听端口
rpc 启动rpc通信,可以进行智能合约的部署和调试
rpcapi 设置允许连接的rpc的客户端,一般为db,eth,net,web3
networkid 设置当前区块链的网络ID,用于区分不同的网络,是一个数字
console 启动命令行模式,可以在Geth中执行命令

智能合约部署与调用

创建账号、挖矿

  • 创建账号personal.newAccount(),创建的第一个账号为默认coinbase账号,挖矿收入将会进入此账号。‘
  • 由于部署合约需要以太坊,使用miner.start()开始挖矿,miner.stop停止挖矿。
  • eth.getBalance(eth.accounts[0])查看余额

创建编译智能合约

  • 安装Solidity编译器solc: apt-get install solc

  • 新建一个 Solidity 智能合约文件,命名为 testContract.sol,该合约包含一个方法 multiply(),将输入的两个数相乘后输出:

    1
    2
    3
    4
    5
    6
    pragma solidity ^0.4.0;
    contract testContract {
    function multiply(uint a) returns(uint d) {
    d = a * 7;
    }
    }
  • 编译智能合约,获得编译后的 EVM 二进制码:

    1
    2
    3
    4
    5
    $ solc --bin testContract.sol

    ======= testContract.sol:TestContract =======
    Binary:
    608060405234801561001057600080fd5b5060bb8061001f6000396000f300608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c6888fa1146044575b600080fd5b348015604f57600080fd5b50606c600480360381019080803590602001909291905050506082565b6040518082815260200191505060405180910390f35b60006007820290509190505600a165627a7a7230582002bc42ae50877423d8703fb9201f4e02d335ff56443e697a4c0d9de0dfe6ad160029
  • 再用 solc 获取智能合约的 JSON ABI(Application Binary Interface),其中指定了合约接口,包括可调用的合约方法、变量、事件等:

    1
    2
    3
    4
    5
    $ solc --abi testContract.sol

    ======= testContract.sol:TestContract =======
    Contract JSON ABI
    [{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]

    1530762830490

  • 回到 Geth 的控制台,用变量 codeabi 记录上面两个值,注意在 code 前加上 0x 前缀:

    1530762753406

部署智能合约

  • 这里使用账户 0 来部署合约,首先解锁账户:

    1
    2
    3
    4
    > personal.unlockAccount(eth.accounts[0])
    Unlock account 0xfb9c00a44223e463016f0b36e1195d2d7a21e0d7
    Passphrase:
    true
  • 发送部署合约的交易:

    1
    2
    3
    4
    > myContract = eth.contract(abi)
    ...
    > contract = myContract.new({from:eth.accounts[0],data:code,gas:1000000})
    ...
  • 此时如果没有挖矿,用 txpool.status 命令可以看到本地交易池中有一个待确认的交易。使用下面的命令查看当前待确认的交易:

    1530762947706

    使用 miner.start() 命令开始挖矿,一段时间后交易会被确认,随新区块进入区块链。

    1530766370261

调用智能合约

使用以下命令发送交易,sendTransaction 方法的前几个参数应该与合约中 multiply 方法的输入参数对应。这种情况下,交易会通过挖矿记录到区块链中:

1
> contract.multiply.sendTransaction(10, {from:eth.accounts[0]})

如果只是本地运行该方法查看返回结果,可以采用如下方式:

1
2
> contract.multiply.call(10)
70

1530766649199

查看节点信息和节点列表

1
2
admin.nodeInfo // 查看节点信息
admin.peers // 查看节点列表

1530694981280

添加节点

如果希望多个节点加入到同一个区块链网络,需要注意以下三点

  • 节点所在的机器,相互之间可以互联互通
  • 它们有相同的创世纪文件
  • 有相同的networkid

第二个节点networkid设置必须与前一致,rpcport 、port不一样。

1530696540314

1530699886655

  • 在节点1使用admin.addPeer(encode)命令添加节点2,节点2enode

“enode://f547fd8925e44fc89c7f71af94ba4d5d8b52e28b4b68cc54fcc5d57be837b24170d1710e884e8be783ac9f07ee35e5c77f2325ba7a5194f53671e7ecd069a365@192.168.213.188:30304”

  • 使用admin.peers查看节点

1530701692797

  • 连接成功后节点2同步区块

1530770536341

  • 节点一中发布交易,看到pending:2

    1530770844338

  • 任一节点miner.start()挖矿,其余节点自动同步新区块,且交易被记录进区块。

1530775904444

1530775911979

控制台操作

进入以太坊 Javascript Console 后,就可以使用里面的内置对象做一些操作,这些内置对象提供的功能很丰富,比如查看区块和交易、创建账户、挖矿、发送交易、部署智能合约等。

常用命令有:

  • personal.newAccount():创建账户;
  • personal.unlockAccount():解锁账户;
  • eth.accounts:枚举系统中的账户;
  • eth.getBalance():查看账户余额,返回值的单位是 Wei(Wei 是以太坊中最小货币面额单位,类似比特币中的,1 ether = 10^18 Wei);
  • eth.blockNumber:列出区块总数;
  • eth.getTransaction():获取交易;
  • eth.getBlock():获取区块;
  • miner.start():开始挖矿;
  • miner.stop():停止挖矿;
  • web3.fromWei():Wei 换算成以太币;
  • web3.toWei():以太币换算成 Wei;
  • txpool.status:交易池中的状态;
  • admin.addPeer():连接到其他节点;
Donate comment here