建立本地以太坊网络
本文介绍如何在本地搭建以太坊测试网络,以及创建账户、挖矿和交易
按照上一篇的介绍,本来打算开始写p2p网络的部分,但是那部分有点复杂,先写点简单的吧。 工欲善其事,必先利其器。 学习以太坊,首先要有本地的测试环境。
环境准备
本次测试环境在单机上完成,节点以不同的端口号区分。 使用go client geth,版本为Version: 1.6.7-unstable。 源地址:. geth和bootnode的编译是自己完成的。 工作目录结构如下:
➜ ethereum tree -L 2
.
├── bootnode.key
├── bootnode.log
├── bootnode.sh
├── data
│ ├── 00
│ ├── 01
│ ├── 02
│ └── genesis
└── start.sh
启动引导节点
以太坊在启动时需要通知至少一个对等节点,这样它才能访问整个以太坊网络。 Bootnode相当于一个第三方中介。 Node在启动时会将自己的信息注册到bootnode的路由中,并会从bootnode获取其他节点的路由信息。 获得对等节点信息后,您无需连接到引导节点。 公链的节点硬编码了一些bootnode节点地址。
创建脚本bootnode.sh
#如果没有bootnode.key文件,先生成一个
if [ ! -f bootnode.key ];then
bootnode -genkey bootnode.key
fi
pkill bootnode
## 后台启动bootnode,将输出重定向至bootnode.log文件
nohup bootnode -nodekey=bootnode.key > bootnode.log&
查看bootnode.log的内容:
INFO [10-25|14:48:33] UDP listener up self=enode://e9132e9df0fab001c9fa0c20094a413970c8d05b52f78efc483b4c7e935be6cc67b8d448881cda24b824d5eb82084343a6c6def4be1c1d9f7a0f1280d31f83d8@[::]:30301
启动geth节点时以太坊9月15日停止挖矿,需要从上面的内容中解析出bootnode的id。
起始节点
为了方便启动节点,我写了如下脚本start.sh:
# 启动之前需要手工启动bootnode
if [ ! -f bootnode.log ];then
echo "please run bootnode.sh first"
exit
fi
# 解析本机的ip地址
ip=$(ifconfig|grep inet|grep -v inet6|grep broadcast|awk '{print $2}')
# 解析bootnode地址
bootnode_addr=enode://"$(grep enode bootnode.log|tail -n 1|awk -F '://' '{print $2}'|awk -F '@' '{print $1}')""@$ip:30301"
if [ "$1" == "" ];then
echo "node id is empty, please use: start.sh
" ;
exit
fi
no=$1
datadir=data
mkdir -p $datadir
# 如果启动前需要使用创世块初始化
if [ ! -d "$DIRECTORY" ]; then
if [ ! -f $datadir/genesis ];then
echo '{"config": {"chainId": 15, "homesteadBlock": 0, "eip155Block": 0, "eip158Block": 0 }, "coinbase" : "0x0000000000000000000000000000000000000000", "difficulty" : "0x40000", "extraData" : "", "gasLimit" : "0xffffffff", "nonce" : "0x0000000000000042", "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "timestamp" : "0x00", "alloc": { } }' > $datadir/genesis
fi
geth --datadir $datadir/$no init ./data/genesis
fi
# 运行geth,启动console
geth --datadir ./data/$no --networkid 11100 --ipcdisable --port 619$no --rpc --rpccorsdomain "*" --rpcport 81$no --bootnodes $bootnode_addr console
上面的脚本会先判断bootnode是否启动,然后创建创世块配置,然后用它来初始化节点以太坊9月15日停止挖矿,最后启动它,并打开RPC接口,这样就可以使用一些图形浏览器插件来调用接口,注意需要设置跨域header。
分别在三个终端启动三个节点,参数格式为两个数字:
./start.sh 00
./start.sh 01
./start.sh 02
如果参数为00,则工作目录为data/00,p2p端口为61900,rpc端口为8100。
创建一个帐户,我的
start.sh脚本在启动geth的时候会打开控制台,我们可以在里面输入命令来操作以太坊界面。 首先我们创建一个账户:
在00节点端创建账户并查看余额:
# 创建帐户,参数是密码
> personal.newAccount("abc123")
"0xf9ab190a9c56fd0d945eac9659c0c9519b13c64e"
> eth.getBalance("0xf9ab190a9c56fd0d945eac9659c0c9519b13c64e")
0
由于是新用户,余额为0,没问题。接下来我们挖矿,但是在挖矿之前,我们需要解锁账户
> personal.unlockAccount("0xf9ab190a9c56fd0d945eac9659c0c9519b13c64e")
Passphrase:
开始挖矿:
> miner.start()
Successfully sealed new block
# ps. 输入停止挖矿指令时,输入会被打乱,不过不影响。
> miner.stop()
只需要几秒,就会出现Successfully sealed new block,说明矿场已经挖完了,接下来我们看一下账户余额:
> eth.getBalance("0xf9ab190a9c56fd0d945eac9659c0c9519b13c64e")
65000000000000000000
在这个例子中,总共开采了 65 个以太币。
贸易
现在我们在节点 01 上创建另一个帐户:
> personal.newAccount("abc123")
"0x22aa2aa9af7b4ebbf88f3abd394f4948cde5cb6c"
回到00号节点,转10个ETH到这个新账户:
> eth.sendTransaction({from:"0xf9ab190a9c56fd0d945eac9659c0c9519b13c64e", to:"0x22aa2aa9af7b4ebbf88f3abd394f4948cde5cb6c", value: web3.toWei(10, "ether")})
INFO [10-30|13:46:53] Submitted transaction fullhash=0x2ff6f675fcdecff9d5fa03c73eec068c3aabe885beb122533e533b227d08cc64 recipient=0x22aa2aa9af7b4ebbf88f3abd394f4948cde5cb6c
"0x2ff6f675fcdecff9d5fa03c73eec068c3aabe885beb122533e533b227d08cc64"
然后去01节点查看to的账户余额,发现还是0,这是因为我们还没有挖到,交易还没有确认。 接下来,我们在节点02上新建一个账户,解锁并开始挖矿,等待交易确认。
我们看00号和01号节点的账户余额变化:01号节点的余额是10000000000000000000,也就是10个以太币。 交易前00节点的余额是65个ether,现在只有549996220000000000000,少的部分其实是矿工费,由02矿工节点收取。
文章中的账户地址和余额为参考值,在不同环境下会不一致。 另外geth是用CPU挖矿的,在公链上用它挖矿是完全不可能的。