用Geth搭建以太坊私链

Posted by Kaka Blog on June 30, 2021

前言

为了与区块链进行通信,我们必须使用区块链客户端。客户端是能够与其他客户建立p2p通信信道,签署和广播交易,挖掘,部署和与智能合约交互等的软件。客户端通常被称为节点。

安装Geth

安装Geth有多种方式,这里给出两种:系统包管理器(apt-get)安装和源码安装。

一、apt-get

sudo apt-get install software-properties-common
sudo add-apt-respository -y poa:ethereum/ethereum
sudo apt-get update
sudo apt-get install ethereum

二、源码安装

1、获取最新的软件包源,并添加至当前的apt库

add-apt-repository ppa:longsleep/golang-backports

2、更新 apt库

apt-get update

3、安装go

sudo apt-get install golang-go

4、鉴定是否安装成功

go version

5、克隆github仓库

git clone https://github.com/ethereum/go-ethereum.git

6、从源码构建Geth

cd go-ethereum
make geth

可能出现问题:

go: github.com/Azure/azure-pipeline-go@v0.2.2: Get https://proxy.golang.org/github.com/%21azure/azure-pipeline-go/@v/v0.2.2.mod: dial tcp 172.217.24.17:443: connect: connection refused make: *** [geth] Error 1

解决:

go env -w GOPROXY=https://goproxy.cn

查看geth version:

./build/bin/geth version

启动节点同步

./build/bin/geth --datadir ./data

同步模式

同步模式有三种:”fast”, “full”, or “light”

geth --syncmode "fast" --datadir DataDir

搭建自己的私有链

初始化创世块

新建一个文件genesis.json来放置创世块(第0号区块)的配置信息。

{
  "config": {
    "chainId": 666,
    "homesteadBlock": 0,
    "eip150Block": 0,
    "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "eip155Block": 0,
    "eip158Block": 0,
    "byzantiumBlock": 0,
    "constantinopleBlock": 0,
    "petersburgBlock": 0,
    "istanbulBlock": 0,
    "ethash": {}
  },
  "nonce": "0x0",
  "timestamp": "0x5ddf8f3e",
  "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "gasLimit": "0x47b760",
  "difficulty": "0x00002",
  "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "coinbase": "0x0000000000000000000000000000000000000000",
  "alloc": {
    "0x1e82968C4624880FD1E8e818421841E6DB8D1Fa4" : {"balance" : "30000000000000000000"}
  },
  "number": "0x0",
  "gasUsed": "0x0",
  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
  • chainId 用于标记一条以太链的ID,它必须和你的代码中交易时的chainId一致。
  • alloc 用来预置账号以及账上的币的数量,因为私有链开启挖矿后很简单地就能获得测试所需要的币,所以不需要预置有币的账号
  • difficulty 设置挖矿难度,私有链在测试时可将该值设置小点,使得区块容易被挖出来,测试效率更高
  • gasLimit GAS 的消耗量限制,用来限制区块能包含的交易信息总和

使用以下命令初始化创世块:

./build/bin/geth --datadir datadir init genesis.json

输出:

bigdata@master:~/geth/go-ethereum$ ./build/bin/geth --datadir ../data init ../genesis.json 
INFO [06-30|16:56:22.680] Maximum peer count                       ETH=50 LES=0 total=50
INFO [06-30|16:56:22.680] Smartcard socket not found, disabling    err="stat /run/pcscd/pcscd.comm: no such file or directory"
INFO [06-30|16:56:22.681] Set global gas cap                       cap=25,000,000
INFO [06-30|16:56:22.681] Allocated cache and file handles         database=/home/bigdata/geth/data/geth/chaindata cache=16.00MiB handles=16
INFO [06-30|16:56:22.841] Writing custom genesis block 
INFO [06-30|16:56:22.841] Persisted trie from memory database      nodes=0 size=0.00B time="3.146µs" gcnodes=0 gcsize=0.00B gctime=0s livenode
s=1 livesize=0.00BINFO [06-30|16:56:22.841] Successfully wrote genesis state         database=chaindata                              hash=2615eb..374a30
INFO [06-30|16:56:22.841] Allocated cache and file handles         database=/home/bigdata/geth/data/geth/lightchaindata cache=16.00MiB handles
=16INFO [06-30|16:56:22.936] Writing custom genesis block 
INFO [06-30|16:56:22.936] Persisted trie from memory database      nodes=0 size=0.00B time="2.612µs" gcnodes=0 gcsize=0.00B gctime=0s livenode
s=1 livesize=0.00BINFO [06-30|16:56:22.936] Successfully wrote genesis state         database=lightchaindata                         hash=2615eb..374a30

启动私链

使用以下命令启动私链:

geth --data datadir --networkid 15

注意networdid要与创世块配置里的chainId一致。

输出:

bigdata@master:~/geth/go-ethereum$ ./build/bin/geth --datadir ../data --networkid 15
INFO [06-30|16:59:44.815] Maximum peer count                       ETH=50 LES=0 total=50
INFO [06-30|16:59:44.815] Smartcard socket not found, disabling    err="stat /run/pcscd/pcscd.comm: no such file or directory"
INFO [06-30|16:59:44.815] Set global gas cap                       cap=25,000,000
INFO [06-30|16:59:44.815] Allocated trie memory caches             clean=154.00MiB dirty=256.00MiB
INFO [06-30|16:59:44.815] Allocated cache and file handles         database=/home/bigdata/geth/data/geth/chaindata cache=512.00MiB handles=524
,288INFO [06-30|16:59:45.135] Opened ancient database                  database=/home/bigdata/geth/data/geth/chaindata/ancient readonly=false
INFO [06-30|16:59:45.135] Initialised chain configuration          config="{ChainID: 15 Homestead: <nil> DAO: <nil> DAOSupport: false EIP150: 
<nil> EIP155: <nil> EIP158: <nil> Byzantium: <nil> Constantinople: <nil> Petersburg: <nil> Istanbul: <nil>, Muir Glacier: <nil>, Berlin: <nil>, London: <nil>, Engine: unknown}"INFO [06-30|16:59:45.135] Disk storage enabled for ethash caches   dir=/home/bigdata/geth/data/geth/ethash count=3
INFO [06-30|16:59:45.135] Disk storage enabled for ethash DAGs     dir=/home/bigdata/.ethash               count=2
INFO [06-30|16:59:45.135] Initialising Ethereum protocol           network=15 dbversion=<nil>
INFO [06-30|16:59:45.136] Loaded most recent local header          number=0 hash=2615eb..374a30 td=2000 age=52y2mo4w
INFO [06-30|16:59:45.136] Loaded most recent local full block      number=0 hash=2615eb..374a30 td=2000 age=52y2mo4w
INFO [06-30|16:59:45.136] Loaded most recent local fast block      number=0 hash=2615eb..374a30 td=2000 age=52y2mo4w
WARN [06-30|16:59:45.136] Failed to load snapshot, regenerating    err="missing or corrupted snapshot"
INFO [06-30|16:59:45.136] Rebuilding state snapshot 
INFO [06-30|16:59:45.136] Regenerated local transaction journal    transactions=0 accounts=0
INFO [06-30|16:59:45.143] Allocated fast sync bloom                size=512.00MiB
INFO [06-30|16:59:45.144] Initialized state bloom                  items=0 errorrate=0.000 elapsed="16.762µs"
INFO [06-30|16:59:45.144] Gasprice oracle is ignoring threshold set threshold=2
WARN [06-30|16:59:45.144] Error reading unclean shutdown markers   error="leveldb: not found"
INFO [06-30|16:59:45.144] Starting peer-to-peer node               instance=Geth/v1.10.4-unstable-c73652da-20210526/linux-amd64/go1.13.8
INFO [06-30|16:59:45.144] Resuming state snapshot generation       root=56e81f..63b421 accounts=0 slots=0 storage=0.00B elapsed=8.271ms
INFO [06-30|16:59:45.144] Generated state snapshot                 accounts=0 slots=0 storage=0.00B elapsed=8.437ms
INFO [06-30|16:59:45.268] New local node record                    seq=1 id=e7b4862fffc81615 ip=127.0.0.1 udp=30303 tcp=30303
INFO [06-30|16:59:45.269] Started P2P networking                   self=enode://793dee3e84c5f083e28b02648c51d0ea13d1fe9dc66bc341c18c9c9f94276a
c0860743c6bceb621e0d62627b967e71bae43d160b7d3de64abb7d97a24a5704d4@127.0.0.1:30303INFO [06-30|16:59:45.271] IPC endpoint opened                      url=/home/bigdata/geth/data/geth.ipc
INFO [06-30|16:59:47.211] New local node record                    seq=2 id=e7b4862fffc81615 ip=183.233.224.164 udp=30303 tcp=30303

控制台操作

启动控制台:

geth --data datadir --networkid 15 console

一直显示looking for peer,可以在启动命令加上--nodiscover,禁止寻找节点

退出:Ctrl+D

查看基本对象:

> web3

常用命令:

# 查看有哪些账户
> eth.acounts
# 查询账户余额
> web3.fromWei(eth.getBalance(""), 'ether')
# 查询区块
> eth.blockNumber
# 创建账户
> personal.newAccount()
Passphrase: 
Repeat passphrase: 
INFO [06-30|17:29:03.295] Your new key was generated               address=0x085ED72FFC866da7913bD3a32630349626487d08
WARN [06-30|17:29:03.295] Please backup your key file!             path=/home/bigdata/geth/data/keystore/UTC--2021-06-30T09-29-01.734622396Z--
085ed72ffc866da7913bd3a32630349626487d08WARN [06-30|17:29:03.295] Please remember your password! 
"0x085ed72ffc866da7913bd3a32630349626487d08"
# 转账,交易信息需要被挖矿才算成功
> eth.sendTransaction({from: XX, to: XX ,value: XX})
# 账户默认是锁住的,想要发送交易,必须先解锁账户
> personal.unlockAccount(XX)
# 查看交易池的状态
> txpool.status
# 其中start的参数表示挖矿使用的线程数。第一次启动挖矿会先生成挖矿所需的DAG文件,这个过程有点慢,等进度达到100%后,就会开始挖矿,此时屏幕会被挖矿信息刷屏。
> miner.start(1)
# 停止挖矿
> miner.stop()
# 查看挖到的以太币
> web3.fromWei(eth.getBalance(eth.coinbase))
# 查看区块信息
> eth.getBlock(16)
# 查看交易信息
> eth.getTransaction("0xc6a74142d2b20d48df2c61ce55d06677ea891e3f0bb4231547d21b8799a01701")
# 查看区块有多少个交易
> eth.getBlockTransactionCount(60)

在后台启动geth后,可以通过以下命令进入控制台:

nohup geth --datadir datadir --networkid 15 2>output.log &
geth attach http://localhost:8545

dev模式

使用POA共识网络,默认预分配一个开发者账户并且会自动开启挖矿。

使用以下命令启动开发者模式:

geth --datadir datadir --networkid 15 --dev console 2>output.log

JSON-RPC

以太坊客户端提供了API和一组远程调用(RPC)命令,这些命令被编码为JSON,称为JSON-RPC API。本质上就是一个接口。通常RPC接口作为一个HTTP服务,端口设定为8545。出于安全原因,默认情况下,仅限于接受来自localhost的连接。可通过JavaScript的web3.js或者构建HTTP请求访问JSON-RPC API。

启动RPC:

./build/bin/geth --datadir ../data --nodiscover --networkid 15 --rpc console

输出:

...
INFO [07-01|10:57:37.916] HTTP server started                      endpoint=127.0.0.1:8545 prefix= cors= vhosts=localhost
...

访问RPC:

curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "web3_clientVersion", "params": [], "id": 1}' http://localhost:8545

输出:

{"jsonrpc":"2.0","id":1,"result":"Geth/v1.10.4-unstable-c73652da-20210526/linux-amd64/go1.13.8"}

当执行personal.unlockAccount()或在程序中调用personal_unlockAccount接口时,会出现:account unlock with HTTP access is forbidden异常。

解决:可通启动命令中添加参数:

--allow-insecure-unlock

请求对象:

  • jsonrpc:指定JSON-RPC协议版本的字符串,必须准确写为“2.0”
  • method:包含所要调用方法名称的字符串,以rpc开头的方法名,用英文句号(U+002E or ASCII 46)连接的为预留给rpc内部的方法名及扩展名,且不能在其他地方使用。
  • params:调用方法所需要的结构化参数值,该成员参数可以被省略。
  • id:已建立客户端的唯一标识id,值必须包含一个字符串、数值或NULL空值。如果不包含该成员则被认定为是一个通知。该值一般不为NULL,若为数值则不应该包含小数。

开启远程调用

./build/bin/geth --datadir ../data --nodiscover --networkid 15 --rpc --rpcaddr X.X.X.X --rpccorsdomain "*" console
  • –rpccorsdomain:解决跨域问题
  • rpcaddr:指定IP地址访问

参考