本教程是基於CentOS7.5系統進行的。
區塊鏈是由若干個區塊組成的。因此我們首先需要爲私有鏈創建第一個區塊(即創世區塊),類似於數據結構中鏈表的頭節點。
創建創世區塊
首先,你需要創建一個創世區塊,這個區塊的創建應該讓所有節點都知道,並且都同意。
創建創世區塊的配置主要存儲於一個JSON文件中,這裏我們存在一個叫genesis.json的文件中。
爲了使結構更加清晰,先創建一個文件夾,專門存放私有鏈相關數據。
mkdir private_eth
cd private_eth
touch genesis.json
把下面的具體配置拷貝到genesis.json中,並保存
{
"config": {
"chainId": 10001,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0
},
"alloc": {},
"coinbase": "0x0000000000000000000000000000000000000000",
"difficulty": "0x20000",
"extraData": "",
"gasLimit": "0x2fefd8",
"nonce": "0x0000000000000042",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp": "0x00"
}
如果你想爲一些賬戶預先分配一些資金便於測試,那麼可以在配置中創建賬戶並分配一些資金。這時候,你只需要用下面的配置替換掉上面的"alloc":{ }即可:
"alloc": {
"0x0000000000000000000000000000000000000001": {
"balance": "111111111"
},
"0x0000000000000000000000000000000000000002": {
"balance": "222222222"
}
}
初始化區塊鏈
啓動之前,先進行初始化:
geth init genesis.json --datadir test
test目錄表示保存區塊鏈相關數據的目錄,這裏的test 與 genesis.json 文件在同一個目錄下。
test目錄是之前不存在的,執行後會自動生成。
test目錄下有兩個子目錄:
- geth:存儲同步區塊鏈以及相關的數據;
- keystore:保存了賬戶文件。由於私鏈剛創建,此時keystore目錄爲空。
注意:
如果直接執行
geth init genesis.json
可能會出現如下錯誤:
Fatal: Failed to write genesis block: database contains incompatible genesis (have d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3, new a3c5c170988f516e00ea3078b2461a149bcd4d0422c8c894923c6cfa22d6926b)
因此記得通過--datadir 設置相應的存儲區塊鏈相關數據的目錄。
啓動以太坊客戶端
geth --rpc --rpccorsdomain="*" --nodiscover --allow-insecure-unlock --datadir './test' console
執行成功之後,如下圖所示:
一些常用相關參數總結:
// Ethereum參數
--config value:表示TOML配置文件的目錄;
--datadir value:存儲區塊鏈相關數據的文件目錄,包含geth和keystore兩個文件夾(默認爲 "/home/ligi/.ethereum"),geth目錄存儲同步區塊鏈以及相關的數據,keystore存儲賬戶相關數據;
--datadir.ancient value Data directory for ancient chain segments (default = inside chaindata)
--keystore value 賬戶祕鑰的存儲目錄 (默認在datadir裏面)
--networkid value 網絡標識符 (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby) (default: 1)
--testnet Ropsten network: pre-configured proof-of-work test network
--rinkeby Rinkeby network: pre-configured proof-of-authority test network
--syncmode value 區塊鏈同步模式 ("fast", "full", or "light") (default: fast)
--exitwhensynced 塊同步完成後退出
--identity value 自定義節點名稱
//DEVELOPER CHAIN OPTIONS:
--dev 擁有一些預先設置了資金的開發者賬戶的臨時權威證明網絡,並且可以直接挖礦
--dev.period value 在開發者模式中使用塊(出塊)的時間,0表示只有在交易掛起的時候纔會挖礦,1表示不用等有了交易才挖礦 (default: 0)
//ACCOUNT OPTIONS:
--unlock value 要解鎖的賬戶列表(多個賬戶用逗號分隔)
--password value 用於非交互式密碼輸入的密碼文件
//API AND CONSOLE OPTIONS:
--ipcdisable 禁用(關閉)IPC-RPC服務器
--ipcpath value Filename for IPC socket/pipe within the datadir (explicit paths escape it)
--rpc 啓用HTTP-RPC服務器
--rpcaddr value HTTP-RPC服務器監聽的IP地址 (default: "localhost")
--rpcport value HTTP-RPC 服務器監聽端口(default: 8545)
--port:指定和其他節點連接所用的端口號(默認爲 30303);
--rpcapi value 通過HTTP-RPC接口提供的API
--rpc.gascap value 設置可以在eth_call/estimateGas中使用的gas上限(默認值:0) (default: 0)
--rpccorsdomain value 哪些域名允許訪問跨域請求(多個域名用逗號分隔)(瀏覽器執行),"*"表示允許通過任意域名進行訪問
--rpcvhosts value 允許哪些虛擬主機名接受請求(多個的時候用逗號分開)(服務器執行). 接受 '*' 通配符. (default: "localhost")
--ws 啓用WS-RPC服務器
--wsaddr value WS-RPC服務器監聽的地址 (default: "localhost")
--wsport value WS-RPC服務器監聽的端口號 (default: 8546)
--wsapi value WS-RPC接口提供的API
--wsorigins value 接受websockets請求的源
//NETWORKING OPTIONS:
--nodiscover 禁用節點發現機制,防止加入有同樣初始配置的的陌生節點
--verbosity: 表示設置日誌等級,0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=detail (default:
更多具體的參數解析請看:[Command Line Options](https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options)
開始挖礦
(1)使用之前genesis.json中配置的賬戶進行挖礦
挖礦之前,先將賬戶和礦工進行綁定。miner是JavaScript控制檯中內置的礦工對象,在控制檯中可以使用如下的命令將genesis.json文件中的“alloc”中的某個地址與miner對象進行綁定,綁定的目的之一就是爲了明確挖礦得到的獎勵存到哪個賬戶去;
miner.setEtherbase("0x0000000000000000000000000000000000000001")
開始挖礦之前,我們可以查看一下兩個臨時賬戶的餘額
eth.getBalance("0x0000000000000000000000000000000000000001")
eth.getBalance("0x0000000000000000000000000000000000000002")
結果如下:
開始挖礦
miner.start()
查看當前區塊鏈中的區塊數
eth.blockNumber
再次查詢兩個臨時賬戶的餘額
eth.getBalance("0x0000000000000000000000000000000000000001")
eth.getBalance("0x0000000000000000000000000000000000000002")
由於礦工挖礦得到了一些挖礦的獎勵(以太幣),所以我們可以發現與礦工綁定的賬戶的餘額變多了。
(2)創建一個新的賬戶用於挖礦
進入JavaScript控制檯之後,然後先創建一個新賬戶,執行下面的命令輸入兩次密碼即可完成新賬戶的創建:
personal.newAccount()
創建完之後可以查看現有的賬戶
personal.listAccounts
結果如下圖所示,第二個賬戶就是我們創建的新賬戶:
將新賬戶與礦工進行綁定
miner.setEtherbase("0x7a3f4c28a85ec58f3c8bd862ab201b8a03dfff5f")
查看新賬戶的餘額
web3.fromWei(eth.getBalance(eth.coinbase), "ether") //剛開始餘額爲0
//eth.coinbase直接使用賬戶的具體地址也可以實現上面一樣的效果,比如
web3.fromWei(eth.getBalance("0x7a3f4c28a85ec58f3c8bd862ab201b8a03dfff5f"), "ether")
開啓挖礦
miner.start()
停止挖礦
miner.stop()
查詢賬戶餘額,此時賬戶餘額有所增加,因爲礦工挖礦得到了相應的獎勵
web3.fromWei(eth.getBalance(eth.coinbase), "ether")
// or
web3.fromWei(eth.getBalance("0x7a3f4c28a85ec58f3c8bd862ab201b8a03dfff5f"), "ether")
轉賬
我們可以將A賬戶的以太幣轉賬給B賬戶,這裏我們用兩個賬戶進行轉賬操作的展示。
personal.listAccounts
可以發現我們這裏有兩個賬戶:
- 第一個是"0xf157aa0bc8350484171eb0c18e739db03a2f23ce";
- 第二個是"0x7a3f4c28a85ec58f3c8bd862ab201b8a03dfff5f"(這個是和礦工進行綁定了的);
現在我們用第二個賬戶向第一個賬戶轉賬3個Ether。
- (1)首先我們查看轉賬之前,兩個賬戶的餘額是多少
web3.fromWei(eth.getBalance("0x7a3f4c28a85ec58f3c8bd862ab201b8a03dfff5f"), "ether") // 22 Ether
web3.fromWei(eth.getBalance("0xf157aa0bc8350484171eb0c18e739db03a2f23ce"), "ether") // 542 Ether
- (2)在轉賬之前,我們需要先把賬戶解鎖(類似我們在銀行轉賬,要先輸密碼一樣)
personal.unlockAccount("0x7a3f4c28a85ec58f3c8bd862ab201b8a03dfff5f", "123456", 300) //"123456"表示該賬戶的密碼
如果轉賬之前沒有解鎖賬戶,會出現如下錯誤:
WARN [11-11|16:11:04.940] Served eth_sendTransaction reqid=35 t=13.912431ms err="authentication needed: password or unlock"
Error: authentication needed: password or unlock
at web3.js:3143:20
at web3.js:6347:15
at web3.js:5081:36
at <anonymous>:1:1
- (3)從第二個賬戶向第一個賬戶轉賬3個Ether
eth.sendTransaction({from: '0x7a3f4c28a85ec58f3c8bd862ab201b8a03dfff5f', to: '0xf157aa0bc8350484171eb0c18e739db03a2f23ce', value: web3.toWei(3, "ether")})
執行完成之後,會有如下顯示:
INFO [11-11|16:12:35.946] Setting new local account address=0x7a3F4c28A85eC58F3c8bD862ab201B8a03Dfff5F
INFO [11-11|16:12:35.946] Submitted transaction fullhash=0x0fb7355356dc901976c9d996e59bfed1315bdd0546a5dbf9abca2fdabffff35c recipient=0xF157Aa0BC8350484171eb0C18e739DB03A2F2
"0x0fb7355356dc901976c9d996e59bfed1315bdd0546a5dbf9abca2fdabffff35c"
address 表示從哪個賬戶轉出;
fullhash 表示交易hash值;
recipient 表示轉入哪個賬戶;
這個時候我們再次查詢兩個賬戶的餘額,可以發現這兩個賬戶的餘額依然不變。
這是因爲交易在挖礦之後才能記入到區塊中並上鏈,所以我們需要進行挖礦。
miner.start(1)
然後再停止挖礦
miner.stop()
最後,查詢兩個賬戶的餘額
web3.fromWei(eth.getBalance("0x7a3f4c28a85ec58f3c8bd862ab201b8a03dfff5f"), "ether")
web3.fromWei(eth.getBalance("0xf157aa0bc8350484171eb0c18e739db03a2f23ce"), "ether")
我們可以發現第一個賬戶(0xf157aa0bc8350484171eb0c18e739db03a2f23ce)增加了 3 Ether,第二個賬戶(0x7a3f4c28a85ec58f3c8bd862ab201b8a03dfff5f)之前是22 Ether,現在也增加到了 29 Ether,這是因爲第二個賬戶挖礦得到了 10 Ether的獎勵,所以減去轉出的 3 Ether,還有29 Ether。
參考: