github:https://github.com/ethereum/go-ethereum
go-ethereum客户端通常被称为geth,是目前用户最多,使用最广泛的客户端。通过Geth客户端与以太坊网络进行连接和交互可以实现账户管理、合约部署、挖矿等功能。
参照github上README.md下载编译即可
安装完成之后配置下环境变量后使用geth version查看版本,我安装的为1.9.10稳定版
[Muyi@ai-research MineChain]$ geth version
Geth
Version: 1.9.10-unstable
Git Commit: 6ae9dc15cc51310f33a011dcafab5739a6ceea93
Git Commit Date: 20191218
Architecture: amd64
Protocol Versions: [64 63]
Go Version: go1.13
Operating System: linux
GOPATH=/home/Muyi/Go/gopath
GOROOT=/home/Muyi/Go/go
二、私链搭建
2.1、准备创世区块配置文件
{
"config": {
"chainId": 10,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0
},
"coinbase" : "0x0000000000000000000000000000000000000000",
"difficulty" : "0x20000",
"extraData" : "",
"gasLimit" : "0xffffffff",
"nonce" : "0x0000000000000042",
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00",
"alloc" : {}
}
初始化命令 | 作用 |
---|---|
mixhash | 与nonce配合用于挖矿,由上一个区块的一部分生成的hash |
nonce | nonce就是一个64位随机数,用于挖矿 |
difficulty | 设置当前区块的难度,如果难度过大,cpu挖矿就很难,这里设置较小难度 |
alloc | 用来预置账号以及账号的以太币数量,因为私有链挖矿比较容易,所以我们不需要预置有币的账号,需要的时候自己创建即可以 |
coinbase | 矿工的账号,随便填 |
timestamp | 设置创世块的时间戳 |
parentHash | 上一个区块的hash值,因为是创世块,所以这个值是0 |
extraData | 附加信息,随便填,可以填你的个性信息 |
gasLimit | 该值设置对GAS的消耗总量限制,用来限制区块能包含的交易信息总和,因为我们是私有链,所以填最大 |
准备好创世区块配置文件后,需要初始化区块链,将上面的创世区块信息写入区块链。首先新建初始化存储目录MineChain/data。新建创世区块配置文件genesis.json并写入上面的信息。接下来在MineChain目录下执行初始化命令:
[Muyi@ai-research MineChain]geth --datadir data init genesis.json
上面的主体命令是geth init,表示初始化区块链。初始化成功后可以看到如下信息:
Successfully wrote genesis state...
data目录结构如下:
[Muyi@ai-research data]$ ls
geth history keystore
其中geth中存放的是区块数据,keystore中存储的是账户数据。
初始化命令包含的参数项可参见下表:
初始化命令 | 作用 |
---|---|
identity | 区块链的标示,随便填写,用于标示目前网络的名字 |
init | 指定创世块文件的位置,并创建初始块 |
datadir | 设置当前区块链网络数据存放的位置 |
rpc | 启动rpc通信,可以进行智能合约的部署和调试 |
rpcport | HTTP-RPC服务器监听端口(default: 8545) |
rpcapi | 设置允许连接的rpc的客户端,默认只有eth,net,web3 |
networkid | 设置当前区块链的网络ID,用于区分不同的网络,是一个数字 |
console | 启动命令行模式,可以在Geth中执行命令 |
rpccorsdomain | 指定一个可以接收请求来源的以逗号间隔的域名列表(浏览器访问的话,要强制指定该选项) |
启动私有链节点命令如下:
[Muyi@ai-research MineChain]$ geth --datadir ./data --networkid 666 console
Welcome to the Geth JavaScript console!
instance: Geth/v1.9.10-unstable-6ae9dc15-20191218/linux-amd64/go1.13
coinbase: 0xfb7ce62560a198415434d191b371b79b7579402b
at block: 46 (Mon, 23 Dec 2019 21:36:27 CST)
datadir: /home/yangchen/BlockChain/MineChain/data
modules: admin:1.0 debug:1.0 eth:1.0 ethash:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
>
上面命令的主体是geth console,表示启动节点并进入交互式控制台,–datadir选项指定使用data0作为数据目录,–networkid选项后面跟一个数字,这里是1108,表示指定这个私有链的网络id为1108。网络id在连接到其他节点的时候会用到,以太坊公网的网络id是1,为了不与公有链网络冲突,运行私有链节点的时候要指定自己的网络id。 注意:单独运行geth命令也是连接公网!
运行上面的命令后,就启动了区块链节点并进入了Javascript Console交互式控制台。
dev模式这里多说两句:如果只是自己测试开发使用,建议使用dev环境,在需要在启动时增加–dev参数即可,在dev模式下会监听交易,一旦有交易发送就会打包然后挖矿确认,且默认的account[0]开发者账户初始有lot of以太币。
这是一个交互式的Javascript执行环境,在这里面可以执行Javascript代码,其中>是命令提示符。在这个环境里也内置了一些用来操作以太坊的Javascript对象,可以直接使用这些对象。这些对象其实为一个大的web3对象,其中又主要包括:
进入以太坊Javascript Console后,就可以使用里面的内置对象做一些操作,这些内置对象提供的功能很丰富,比如查看区块和交易、创建账户、挖矿、发送交易、部署智能合约等。 接下来介绍几个常用功能,下面的操作中,前面带>的表示在Javascript Console中执行的命令。
3.1、attach:连接到控制台可以将geth放置在后台启动,nohup geth --datadir … &,然后通过geth attach命令进行连接,attach支持三种协议:ipc、http、websocket。在Linux中可以使用ipc/ws方式,如
geth attach ipc:yourdatadir/geth.ipc
geth attach ws://191.168.1.1:8546
如果启动节点时使用了–rpc选项,也可以使用http方式,如:
geth attach http://localhost:8545
以下为我通过rpc方式进行连接:
[Muyi@ai-research MineChain]$ geth attach http://10.5.12.19:8545
Welcome to the Geth JavaScript console!
instance: Geth/v1.9.10-unstable-6ae9dc15-20191218/linux-amd64/go1.13
coinbase: 0xb59477dd2ea62fe2ba54bd4599acad6645ac0b42
at block: 34 (Mon, 30 Dec 2019 10:15:39 CST)
datadir: /home/Muyi/MineChain/data
modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
>
3.2、账户
查看全部账户eth.accounts,查看特定账户eth.accounts[index]
> eth.accounts
["0xb59477dd2ea62fe2ba54bd4599acad6645ac0b42", "0xa4eba67cadfbeabb095b270032ae6228e2a0df88"]
> eth.accounts[0]
"0xb59477dd2ea62fe2ba54bd4599acad6645ac0b42"
查看账户余额eth.getBalance(eth.accounts[1])
> eth.getBalance(eth.accounts[1])
0
新建账户personal.newAccount()
> personal.newAccount()
Password:
Repeat password:
"0xffc8b660f09920e5b966ed4358995afb8b6d13b1"
> eth.accounts
["0xb59477dd2ea62fe2ba54bd4599acad6645ac0b42", "0xa4eba67cadfbeabb095b270032ae6228e2a0df88", "0xffc8b660f09920e5b966ed4358995afb8b6d13b1"]
>
解锁账户,在交易发送之前需要先解锁账户,personal.unlockAccount()
> personal.unlockAccount(eth.accounts[0])
Unlock account 0xb59477dd2ea62fe2ba54bd4599acad6645ac0b42
Password:
true
>
3.3、挖矿
通过miner.start()来启动挖矿
通过miner.stop()来停止挖矿> web3.fromWei(eth.getBalance(eth.accounts[0]),'ether')
60
3.4、交易
可以通过发送一笔交易,从A账户转移N个以太币到B账户;
注意:
> amount = web3.toWei(10,'ether')
"10000000000000000000"
账户默认是锁住的,想要发送交易,必须先解锁账户,由于我们要从账户0发送交易,所以要解锁账户0:
> personal.unlockAccount(eth.accounts[0])
Unlock account 0xb59477dd2ea62fe2ba54bd4599acad6645ac0b42
Password:
true
>
发送交易,设置下发送者from,接收者to和发送的以太数量value即可,
> eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[1],value:web3.toWei(10,'ether')})
"0xfde58d47b1066905a1cf15b1d6e24dcb79a924f64d0ecb952e38947c68610d66"
此时交易已经提交到区块链,返回了交易的hash,但还未被处理,这可以通过查看txpool来验证:
> txpool.status
{
pending: 1,
queued: 0
}
其中有一条pending的交易,pending表示已提交但还未被处理的交易。
要使交易被处理,必须要挖矿。这里我们启动挖矿,然后等待挖到一个区块之后就停止挖矿:
> miner.start(1);admin.sleepBlocks(1);miner.stop();
当miner.stop()返回true后,txpool中pending的交易数量应该为0了,说明交易已经被处理了:
> txpool.status
{
pending: 0,
queued: 0
}
此时,交易已经生效,账户一应该已经收到了10个以太币了:
> web3.fromWei(eth.getBalance(eth.accounts[1]),'ether')
10
3.5、查看交易和区块
eth对象封装了查看交易和区块信息的方法。
大家可以通过eth+tab键来查看eth下都有哪些方法。
查看当前区块总数:
> eth.blockNumber
35
通过区块号(高度)查看区块信息,通过交易hash查看交易:
> eth.getBlock(35)
{
difficulty: 2,
extraData: "0xd68301090a846765746886676f312e3133856c696e7578000000000000000000fbb60823e3d15161cd50781d48366d743d12cd0a22d696367facd28dde0b9d5a1d3ba7671ecd8d2dce07b2532565d90dc8c719ce49f5b05c8ebb0a505abae6aa01",
gasLimit: 6501491,
gasUsed: 21000,
hash: "0x19876ca7838b5c1d0cc68c26b1a867ded5990d7b5287d418e258535e8f558fdd",
logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
miner: "0x0000000000000000000000000000000000000000",
mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
nonce: "0x0000000000000000",
number: 35,
parentHash: "0x5e30aa2e6026086929014391028cea452bd904fdfc4c87769a2822a5eee8f64f",
receiptsRoot: "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
size: 720,
stateRoot: "0x25408f038d715972c1b0b5f00e687551459a4842417facf139109a24fa745f76",
timestamp: 1577785600,
totalDifficulty: 71,
transactions: ["0xfde58d47b1066905a1cf15b1d6e24dcb79a924f64d0ecb952e38947c68610d66"],
transactionsRoot: "0xc3c4e8497f735e18c9924e2af0bc2f43bc167f977b27d874030754ee42833803",
uncles: []
}
可以看到就是我们刚才转10个以太币的交易
> eth.getTransaction('0xfde58d47b1066905a1cf15b1d6e24dcb79a924f64d0ecb952e38947c68610d66')
{
blockHash: "0x19876ca7838b5c1d0cc68c26b1a867ded5990d7b5287d418e258535e8f558fdd",
blockNumber: 35,
from: "0xb59477dd2ea62fe2ba54bd4599acad6645ac0b42",
gas: 21000,
gasPrice: 1000000000,
hash: "0xfde58d47b1066905a1cf15b1d6e24dcb79a924f64d0ecb952e38947c68610d66",
input: "0x",
nonce: 9,
r: "0x398b74e8fdd0b626560f374ca8dabcc1d270e24a16cde17dea7ad2ef2e26324a",
s: "0x47cb58ee002f8a7a37cf807ae45424550af3fd560cd5a1f0e1dc6ca801fd11c0",
to: "0xa4eba67cadfbeabb095b270032ae6228e2a0df88",
transactionIndex: 0,
v: "0xa96",
value: 10000000000000000000
}