ethereum开发笔记(一):以太坊私链demo,实现第一笔交易

最近要做一个区块链的项目,前面几周调研区块链相关的资料,也搭了各种区块链的框架做实验,以太坊作为比较成熟的开源项目,学习资料也相对多一些,所以项目框架初步选用go-ethereum。一切从零开始,开发也是个不断摸索的过程,所以开个新坑,记录一下ethereum开发学习的过程。

demo的主要目标

初始化ethereum私链环境、实现多个节点之间交易的产生,挖矿记录交易,最后读取交易信息。

Geth:geth相当于go-ethereum项目中运行区块链节点的命令行客户端,可以下载独立客户端或编译go-ethereum运行build/bin/geth启动节点。
创世块:创世块genesis在以太坊区块链中是第0个块,初始化整个区块链,在私链网络中,其他的参与者必须是同样的创世块才会和你在同一个链上。

初始化私链
以太坊私链环境中,可以认为是以创世块和networkid作标识,使用同样的创世块、newworkid相同,就相当于在同一个私链当中。

首先按照官方的文档搞定安装好客户端环境

准备创世块:

新建文件testgenesis.json,文件内容如下:
1
2
3
4
5
6
7
8
9
10
11
{
"nonce": "0x0000000000000042",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"difficulty": "0x400",
"alloc": { },
"coinbase": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "Custem Ethereum Genesis Block",
"gasLimit": "0xffffffff"
}

创世块目前可能主要需要修改的就是difficulty,我机器性能一般,因此demo的难度设的比较低。

准备好创世块以后,就可以使用创世块来初始化区块链了,通过如下命令初始化:
1
geth --datadir chain init testgenesis.json

这个命令使用创世块初始化了区块链的数据(–datadir后面的参数是生成的区块链目录,这个地址可以根据自己的目录修改)
打印如下信息表明初始化成功:
img
接着可以启动节点了:
1
geth --identity "testetherum" --rpc --rpcport "7999" --rpcapi "db,eth,net,web3" --rpccorsdomain "*" --datadir chain --port "30305" --networkid 555 --maxpeers 5 --minerthreads 1 console 2>>output

执行上述命令,geth会启动节点,并启动控制台,将控制台的数据打印到output中,启动成功就可以看到“Welcome to the Geth JavaScript console”的提示,同时可以在控制台中输入相应的命令。
关于上面这条命令的参数说明:
1
2
3
4
5
6
7
--identity "testetherum" ,标识名称,随意
--rpc --rpcport "7999" --rpcapi "db,eth,net,web3",启用rpc通信,通信端口为7999,rpcapi声明了可以连接rpc的客户端。
--rpccorsdomain "\*",这个应该是运行连接rpc的域名,\*应该就是允许任何人连接了
--datadir chain,数据块的目录,我们这里当然是使用之前初始化好的数据目录
--port "30305",这个端口是监听网络请求的端口
--networkid 555,当前的区块链的网络id,必须是同一个id才会在一个区块链内
--maxpeers 5 --minerthreads 1,maxpeers指定了允许连接的最多节点数,minerthreads指定挖矿线程数


启动完节点以后,其实已经等于一个只有一个节点的私链了。安装上述方法,再启动另外一个节点。
我本地是在windows上启用的虚拟机建了一个节点,虚拟机性能太差尝试挖矿半天没动静,因此我在windows上开启了另外一个节点挖矿,和虚拟机上的节点组成链,互相交易。
发送一笔交易

在控制台中,我们可以执行交易、挖矿等操作,项目命令参考https://github.com/ethereum/go-ethereum/wiki/Management-APIs
本次所用到的命令如下:
admin //查看当前信息
eth.accounts //查看当前账户
personal.newAccount(‘pwd’) //创建账户
userxxx=eth.accounts[n] //把账户赋值给变量,方便操作
eth.getBalance(userxxx) //查看账户的余额
personal.unlockAccount(userxxx,’pwd’) //解锁账户,账户解锁以后才能交易
eth.sendTransaction({form:,to:,value:}) //发出交易,参数后面会讲
miner.start() miner.stop() //开始挖矿,停止挖矿
admin.addPeer() //连接节点

连接节点(经过测试,如果没有连接账户,交易执行不会报错,但是接收方没有拿到交易的以太币)

首先使用admin获取当前节点信息:
img
其中,encode就是连接的地址,使用当前ip替换掉[::],在另外一个节点中,使用admin.addPeer()连接节点(也可以使用static-nodes.json静态的添加连接节点,后面的参考文章中有给出方法)
连接成功以后,在admin中可以看到peers的信息,证明连接没有问题
img
在两个节点上都创建好账户,然后其中一个节点先挖一会矿(第一次会生成dag比较慢),这样有一个账户就会获得以太以便交易
初始余额:
img
img
执行交易

1
2
var tx = {"from": "0xfcbbac1e74a354eb1ba54b5dda562c7133dc7bf2", "to": "0xb633eb86f6e7b32a54d7adce4f3beb0ecd6911d5", "gas": "0x76c0", "gasPrice": "0x9184e72a000","value": "0x9184e72a", "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"}
eth.sendTransaction(tx)

img
发送交易后返回transactionhash,但是并不会马上确认,需要有矿工在进行挖矿,交易记录到block中以后,交易就执行成功。这时可以看到接收者账户中的金额变多了,第一笔交易完成。
不得不吐槽一下…挖矿真是完全在烧cpu…启动挖矿电脑完全卡死- -
查看输出日志可以看到交易被记录在了第35个block中
img
可以看到交易完成后第二个节点中的接收账户余额增加
img
img

通过rpcapi,我们可以根据transactionhash获取到之前的交易信息(实际上,上述控制台中的操作,应该都可以通过rpcapi完成):
rpcapi可以通过上面我们启动命令中的–rpcport “7999”这个端口号来访问,我们通过eth_getTransactionByHash这个接口得到交易信息
img
img
rpcapi参考https://github.com/ethereum/wiki/wiki/JSON-RPC

参考文章:
http://blog.csdn.net/sportshark/article/details/51855007
https://souptacular.gitbooks.io/ethereum-tutorials-and-tips-by-hudson/content/private-chain.html

待续………