以太坊私有链搭建及常用操作


写在前面

使用系统版本:Ubuntu 18.04

go 版本: go1.17.3

go-ethereum 版本:1.10.18-unstable

一、安装以太坊

1. 下载 Go Ethereum

注1:先安装 Go 和 C 编译器,C 编译器一般 Linux 系统自带,Go 安装比 go-ethereum 版本要求版本更高版本即可。

git clone https://github.com/ethereum/go-ethereum.git
cd go-ethereum
make geth # or make all (构建全套实用程序)

# 查看版本以验证是否安装成功
./build/bin/geth version

# 打印如下即为成功
# Geth
# Version: 1.10.18-unstable
# Git Commit: bb5633c5ee3975ce016636066ec790054ec469e4
# Git Commit Date: 20220417
# Architecture: amd64
# Go Version: go1.17.3
# Operating System: linux
# GOPATH=/home/jie/goproject
# GOROOT=/usr/local/go1.17.3

2. 配置环境

第一步结束后已经可以使用以太坊客户端 geth 了,但每次必须使用去 go-ethereum//build/bin/ 下运行 geth,可以把它配个环境,这个直接使用 geth 命令即可运行。

# 配置在 .bashrc 或者 /etc/profile 下均可,看个人习惯
sudo vim ~/.bashrc

# 在其中添加以下环境
export PATH=$PATH:$HOME/path/go-ethereum/build/bin # path 是具体安装的路径,$HOME 表示首页,即 ~

# 令环境立即生效
source ~/.bashrc

# 查看版本以验证是否安装成功
geth version

二、初始化创世区块

1. 创建 genesis.json

注2:建议使用 Go Ethereum 官方给的你安装版本对应的 genesis.json,直接使用网上的脚本可以后续会有错误。

注3:可以自己新建一个文件夹进行以下操作,最好不要直接在 go-ethereum 文件夹中直接操作。

{
  "config": {
  	# 这里输入链的网络 ID,建议设置大一点的数,如 22
    "chainId": 22, 
    "homesteadBlock": 0,
    "eip150Block": 0,
    "eip155Block": 0,
    "eip158Block": 0,
    "byzantiumBlock": 0,
    "constantinopleBlock": 0,
    "petersburgBlock": 0,
    "istanbulBlock": 0,
    "berlinBlock": 0,
    "londonBlock": 0
  },
  # alloc 包含初始化的账户信息以及以太币,这里为空,也可添加。
  "alloc": {},
  "coinbase": "0x0000000000000000000000000000000000000000",
  # difficulty 代表挖矿难度,数值越小难度反而越大,所以为了挖矿更加简单,可以把这个值设置大一点。
  "difficulty": "0x20000",
  "extraData": "",
  "gasLimit": "0x2fefd8",
  "nonce": "0x0000000000000042",
  "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "timestamp": "0x00"
}

2. 初始化传世区块

# ./ 代表当前目录,init genesis.json 表示使用这个文件初始化创世区块
geth --datadir ./ init genesis.json

执行后会在 genesis.json的当前目录下初始化,然后执行完后会生成两个文件夹,geth 以及 keystore,分别存放该链数据以及用户密钥。也可以将 ./ 替换成你想放的目录下。

# 如果成功最后一句会是 Succsessfully,不使用官方给的就有可能会失败
# Successfully wrote genesis state         database=lightchaindata hash=d9f9b7..32048b

三、启动私有链

1. 启动私有链

geth --datadir ./ console 2>>geth.log

# 如果 exit 退出后想要重新进入该链,执行以下命令
geth --datadir --networkid 22 ./ console 2>>geth.log

2>>geth.log 命令是指将日志输出到 geth.log 文件上,如果不加这个参数日志将会在控制台输出,会看起来很乱,建议加上。

networkid 后为在创世区块中设置的 chainId

2. (可选)查看实时日志输出

# 可以打开一个新的终端查看输出的日志
# 进入私有链所在目录
taif -f geth.log

3. 重新进入该链

geth --datadir --networkid 22 ./ console 2>>geth.log

四、一些基本命令

1. 查看账户

# 返回一个空数组说明当前并无账户
eth.accounts

# 输出:
# []

2. 创建账户

# 创建两个账户,回车后会要求输入两次密码,该密码即为该账户的私钥
# 同时会返回账户哈希,并将账户信息存储到 keystore 文件中
personal.newAccount()
personal.newAccount()

# 查看账户,会返回创建的两个账户,返回为数组类型,可通过下标查看对应账户,如 eth.accounts[0]
eth.accounts
eth.accounts[0]

# 输出
# ["0x3113384d0968f6e1adafa677c7b8b5007f827e83", "0xa0b65c2f4130676eb5cccef52fbaf3b03cb7684f"]

3. 查看账户余额

# 查看第一个账户余额
eth.getBalance(eth.accounts[0])
# or
eth.getBalance("0x3113384d0968f6e1adafa677c7b8b5007f827e83") # 后面为所创建的账户地址

4. 查看当前区块总数

eth.blockNumber

5. 启动&停止挖矿

  • 通过 miner.start() 来启动挖矿
  • 通过 miner.stop() 来停止挖矿

其中 start 的参数表示挖矿使用的线程数,如使用一个线程:miner.start(1)

# 启动挖矿(这里使用一个线程,反正挖的太快)
miner.start(1)

# 停止挖矿
miner.stop()

# 当前区块总数
eth.blockNumber

# 查看账户余额
eth.getBalance(eth.accounts[0])
eth.getBalance(eth.accounts[1])

# 挖出一个区块后后停止挖矿
miner.start(1);admin.sleepBlocks(1);miner.stop()

注4:挖到一个区块会奖励以太币,挖矿所得的奖励会进入矿工的账户,这个账户叫做 coinbase,默认情况下 coinbase 是本地账户中的第一个账户,通过 miner.setEtherbase() 可将其他账户设置成 coinbase

注5: getBalance() 返回值的单位是 weiwei 是以太币的最小单位,$1 eth = 10^{18} wei$。要查看有多少个以太币,可以用 web3.fromWei() 将返回值换算成以太币

web3.fromWei(eth.getBalance(eth.accounts[0]),'ether')
# 以下命令与以上命令等效
web3.fromWei(eth.getBalance(eth.accounts[0]))

6. 发送交易

可以通过发送一笔交易,从 A 账户转移 x weiB 账户

注6:以太坊区块链中,交易过程转移金额的默认单位为 wei,可以通过 web3.toWei(5,'ether') 命令来转移以 eth 为单位的金额,这里即为 5 eth

注7:账户默认是锁住的,想要发送交易,必须先解锁账户。

# 由于我们要从账户0 发送交易,所以要解锁账户0
# 执行以下命令,会要求输入创建账户时设置的密码,输入后即可成功解锁账户。然后再发送交易
personal.unlockAccount(eth.accounts[0])

# 账户0 向账户1 转账 5以太
# 这里如果在创建创世区块时没有使用官方给的 genesis.json,就很可能会报 invalid sender 错误
# 如果没有解锁账户直接执行以下命令,可能会报 authentication needed: password or unlock 错误
eth.sendTransaction({from:eth.accounts[0], to:eth.accounts[1], value:web3.toWei(5,'ether')})

# 输出,即交易哈希
# "0x3b446dd1241a0caaac0c33c66770205fa01368b2772ab391f9526436817402a8"

注8:发送交易命令执行后会返回一串交易哈希,即交易 ID,证明可以转账,但还未被处理,这可以通过查看 txpool 或查看账户1 和 2 的余额来验证。

# 查看 txpool
txpool.status

# 输出:
#{
#  pending: 1,
#  queued: 0
#}

# 查看账户 1 和 2 的余额,余额并未变化
web3.fromWei(eth.getBalance(eth.accounts[0]))
web3.fromWei(eth.getBalance(eth.accounts[1]))

注9:其中有一条 pending 交易,pending 表示已提交但还未被处理的交易。要使交易被处理,必须要挖矿。

# 启动挖矿,挖一个区块停止
miner.start(1);admin.sleepBlocks(1);miner.stop()

# 查看 txpool
txpool.status

# 输出
#{
#  pending: 0,
#  queued: 0
#}

# 查看账户 1 和 2 的余额,余额并未变化
web3.fromWei(eth.getBalance(eth.accounts[0]))
web3.fromWei(eth.getBalance(eth.accounts[1]))

# 当前区块总数
eth.blockNumber

7. 通过区块号(高度)查看区块信息

eth.getBlock(6)

输出:

> eth.getBlock(6)
{
  baseFeePerGas: 448795319,
  difficulty: 131072,
  extraData: "0xd883010a12846765746888676f312e31372e33856c696e7578",
  gasLimit: 3160033,
  gasUsed: 21000,
  hash: "0xc1c0e97720536c772968f7e5c23d3404cb66041ae7253ff9646f2d98d67970e6",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  # miner 即为账户0,也就是 coinbase
  miner: "0x3113384d0968f6e1adafa677c7b8b5007f827e83",
  mixHash: "0x434d61662f34a84f9dc3eaa0d93fec0a2d3118c8a0fcc8f7688e13dad0abdecf",
  nonce: "0x5dfb34e08749f62c",
  number: 6,
  parentHash: "0x55f65d8c3834d9e413371cf9141da3b872d3306cf22b116fb8b982300a83bb60",
  receiptsRoot: "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
  sha3Uncles: "0x70636c369d8297576b3e53a072d9deb3c28fcdcaa9496a8a4f9b2d634eaf0eb8",
  size: 663,
  stateRoot: "0xc4f5adf03bb3b1202d66b2492f7c4c361bc253a1f1528ecd4f28e5362dbaa38c",
  timestamp: 1650461496,
  totalDifficulty: 918144,
  # transactions 中即为前面发送交易的交易哈希
  transactions: ["0x3b446dd1241a0caaac0c33c66770205fa01368b2772ab391f9526436817402a8"],
  transactionsRoot: "0x6b1e64b5e6957fab09c03a8a3e49eda3a50e642d1d4177e43cc0c03b4b73f639",
  uncles: []
}

8. 通过交易 hash 查看交易

eth.getTransaction("0x3b446dd1241a0caaac0c33c66770205fa01368b2772ab391f9526436817402a8")

输出:

{
  accessList: [],
  blockHash: "0xc1c0e97720536c772968f7e5c23d3404cb66041ae7253ff9646f2d98d67970e6",
  # 该交易位于块高为 6 的区块上
  blockNumber: 6,
  # chainId 0x16 即为 22
  chainId: "0x16",
  # from: 账户 1
  from: "0x3113384d0968f6e1adafa677c7b8b5007f827e83",
  gas: 21000,
  gasPrice: 1448795319,
  # 交易哈希
  hash: "0x3b446dd1241a0caaac0c33c66770205fa01368b2772ab391f9526436817402a8",
  input: "0x",
  maxFeePerGas: 2025817872,
  maxPriorityFeePerGas: 1000000000,
  nonce: 0,
  r: "0x8f06eeb98ed23ccbf9d1cd3e8a73e900189c42caa5c9ea50500f95cf4dbeda2c",
  s: "0x402728e7af7d11166fa0813a1febcaff1f7a217d2e3a646284633c85f313a1f2",
  # to: 账户 2
  to: "0xa0b65c2f4130676eb5cccef52fbaf3b03cb7684f",
  transactionIndex: 0,
  type: "0x2",
  v: "0x1",
  # 发送 5 以太币
  value: 5000000000000000000
}

参考文章

  1. Go Ethereum 官方文档
  2. 以太坊安装以及私有链的基本操作
  3. geth搭建以太坊私链及常用操作


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM