寫在前面
使用系統版本: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()
返回值的單位是 wei
,wei
是以太幣的最小單位,$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 wei
到 B
賬戶
注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
}