以太坊私有鏈搭建指南

go-ethereum 私有鏈搭建指南

前言

工具
  1. 以太坊客戶端

    以太坊客戶端用於接入以太坊網絡,進行賬戶管理、交易、挖礦、智能合約相關的操作。目前有多種語言實現的客戶端,常用的有 Go 語言實現的 go-ethereum 客戶端 Geth,支持接入以太坊網絡併成爲一個完整節點,也可作爲一個 HTTP-RPC 服務器對外提供 JSON-RPC 接口。

    其他的客戶端有:

    • Parity:Rust 語言實現;
    • cpp-ethereum:C++ 語言實現;
    • ethereumjs-lib:JavaScript 語言實現;
    • Ethereum(J):Java 語言實現;
    • ethereumH:Haskell 語言實現;
    • pyethapp: Python 語言實現;
    • ruby-ethereum:Ruby 語言實現;
  2. 智能合約編譯器
    以太坊支持兩種智能合約的編程語言:Solidity 和 Serpent。Serpent 語言面臨一些安全問題,現在已經不推薦使用了。Solidity 語法類似 JavaScript,它編譯器 solc 可以把智能合約源碼編譯成以太坊虛擬機 EVM 可以執行的二進制碼。
    現在以太坊提供更方便的在線 IDE —— Remix https://remix.ethereum.org 使用 Remix,免去了安裝 solc 和編譯過程,它可以直接提供部署合約所需的二進制碼和 ABI。

  3. 以太坊錢包
    以太坊提供了圖形界面的錢包 Ethereum Wallet 和 Mist Dapp 瀏覽器。錢包的功能是 Mist 的一個子集,可用於管理賬戶和交易;Mist 在錢包基礎上,還能操作智能合約。爲了演示合約部署過程,本文使用了 Geth console 操作,沒有用到 Mist,當然,使用 Mist 會更簡單。

環境說明

操作系統:Ubuntu16.4
Go環境:1.9.2

安裝 ethereum

1、PPA 直接安裝

# 安裝必要的工具包
apt install software-properties-common
# 添加以太坊源
add-apt-repository -y ppa:ethereum/ethereum
apt update
# 安裝 go-ethereum
apt install ethereum

安裝完成可以通過geth version 命令查看是否安裝成功

2、源碼安裝,源碼安裝需要安裝Go環境

參考官方文檔 https://golang.org/doc/install

  • 配置Go環境,版本1.9.2
# 下載最新版本
curl -O https://storage.googleapis.com/golang/go1.9.2.linux-amd64.tar.gz
# 解壓
tar -C /usr/local -xzf go1.9.2.linux-amd64.tar.gz
# 卸載
apt-get purge golang-go
# 查看版本
go version
  • 設置GOPATH和PATH

    1、設置一個去文件夾 mkdir -p ~/go; echo "export GOPATH=$HOME/go" >> ~/.bashrc

    2、更新你的路徑 echo "export PATH=$PATH:$HOME/go/bin:/usr/local/go/bin" >> ~/.bashrc

    3、將環境變量讀入當前會話: source ~/.bashrc

  • 安裝ethereum

  sudo apt-get install software-properties-common
  sudo add-apt-repository -y ppa:ethereum/ethereum
  sudo add-apt-repository -y ppa:ethereum/ethereum-dev
  sudo apt-get update
  sudo apt-get install ethereum
  • 安裝 solc 編譯器
  sudo add-apt-repository ppa:ethereum/ethereum-qt
  sudo add-apt-repository ppa:ethereum/ethereum
  sudo apt-get update
  sudo apt-get install cpp-ethereum

至此環境已經安裝完成

私有鏈搭建

一、配置初始狀態

​ 要運行以太坊私有鏈,需要定義自己的創世區塊,創世區塊信息寫在一個 JSON 格式的配置文件中。首先將下面的內容保存到一個 JSON 文件中,例如 genesis.json

{
   "config": {
        "chainId": 1024,
        "homesteadBlock": 0,
        "eip155Block": 0,
        "eip158Block": 0
    },
  "alloc": {},
  "nonce": "0x0000000000000042",
  "difficulty": "0x020000",
  "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "coinbase": "0x0000000000000000000000000000000000000000",
  "timestamp": "0x00",
  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "extraData": "0x6d6f7475692d32",
  "gasLimit": "0xffffffff"
}

各個參數的含義如下:

  • chainId :指定了獨立的區塊鏈網絡 ID。網絡 ID 在連接到其他節點的時候會用到,以太坊公網的網絡 ID 是 1,爲了不與公有鏈網絡衝突,運行私有鏈節點的時候要指定自己的網絡 ID。不同 ID 網絡的節點無法相互連接。

  • mixhash:與nonce配合用於挖礦,由上一個區塊的一部分生成的hash。注意他和nonce的設置需要滿足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章節所描述的條件。.

  • nonce: nonce就是一個64位隨機數,用於挖礦,注意他和mixhash的設置需要滿足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章節所描述的條件。
  • difficulty: 設置當前區塊的難度,如果難度過大,cpu挖礦就很難,這裏設置較小難度
  • alloc: 用來預置賬號以及賬號的以太幣數量,因爲私有鏈挖礦比較容易,所以我們不需要預置有幣的賬號,需要的時候自己創建即可以。默認爲空即可
  • coinbase: 礦工的賬號,隨便填
  • timestamp: 設置創世塊的時間戳
  • parentHash: 上一個區塊的hash值,因爲是創世塊,所以這個值是0
  • extraData: 附加信息。【注意】新版本該值需要爲16進制數據,以0x 開頭
  • gasLimit: 該值設置對GAS的消耗總量限制,用來限制區塊能包含的交易信息總和,因爲我們是私有鏈,所以填最大。

二、初始化:寫入創世區塊

初始化命令如下。/root/chain 【{dataDir}】目錄存放區塊鏈數據(可爲其他目錄)

geth  --datadir "/root/chain" init genesis.json 

出現如下內容就成功了

Successfully wrote genesis state         database=lightchaindata         hash=84e71d…97246e

初始化成功後,會在數據目錄{dataDir} 中生成 gethkeystore (存儲加密後的賬戶信息)兩個文件夾,目錄結構如下:

.(root)
├── chain
│   ├── geth
│   │   ├── chaindata
│   │   │   ├── 000001.log
│   │   │   ├── CURRENT
│   │   │   ├── LOCK
│   │   │   ├── LOG
│   │   │   └── MANIFEST-000000
│   │   └── lightchaindata
│   │       ├── 000001.log
│   │       ├── CURRENT
│   │       ├── LOCK
│   │       ├── LOG
│   │       └── MANIFEST-000000
│   └── keystore
└── genesis.json

三、啓動私有鏈節點

初始化完成後,就有了一條自己的私有鏈,之後就可以啓動自己的私有鏈節點並做一些操作,在終端中輸入以下命令即可啓動節點:

geth --identity "motui"  --rpc  --rpccorsdomain "*" --datadir "/root/chain" --port "30303"  --rpcapi "db,eth,net,web3" --networkid 89898 console

參數說明如下:

  • identity :指定節點 用於標示目前網絡的名字;
  • rpc :表示開啓 HTTP-RPC 服務;
  • init :指定創世塊文件的位置,並創建初始塊
  • rpcport :指定 HTTP-RPC 服務監聽端口號(默認爲 8545);
  • rpcapi: 設置允許連接的rpc的客戶端,一般爲db,eth,net,web3
  • datadir :指定區塊鏈數據的存儲位置;
  • port :指定和其他節點連接所用的端口號(默認爲 30303);
  • networkid: 設置當前區塊鏈的網絡ID,用於區分不同的網絡,是一個數字
  • nodiscover :關閉節點發現機制,防止加入有同樣初始配置的陌生節點。
  • maxpeers : 如果你不希望其他人連接到你的測試鏈,可以使用maxpeers 0。反之,如果你確切知道希望多少人連接到你的節點,你也可以通過調整數字來實現。
  • rpccorsdomain : 這個可以指示什麼URL能連接到你的節點來執行RPC定製端任務。務必謹慎,輸入一個特定的URL而不是wildcard ( * ),後者會使所有的URL都能連接到你的RPC實例。
  • console:啓動命令行模式,可以在Geth中執行命令

注意:如果想將Ubuntu作爲永久區塊鏈節點使用,當使用nohup命令時,Geth啓動參數console必須去掉,否則Geth會自動停止。

​ 啓動完成之後進入控制檯,這是一個交互式的 JavaScript 執行環境,在這裏面可以執行 JavaScript 代碼,其中 > 是命令提示符。在這個環境裏也內置了一些用來操作以太坊的 JavaScript 對象,可以直接使用這些對象。這些對象主要包括:

  • eth:包含一些跟操作區塊鏈相關的方法;
  • net:包含一些查看p2p網絡狀態的方法;
  • admin:包含一些與管理節點相關的方法;
  • miner:包含啓動&停止挖礦的一些方法;
  • personal:主要包含一些管理賬戶的方法;
  • txpool:包含一些查看交易內存池的方法;
  • web3:包含了以上對象,還包含一些單位換算的方法。
> eth.accounts
["0x6594cc2f72908c0fea54d5c9dd297ce68f735411", "0x442aa25d86f30c3ed1cdee8cb787dccac680abdd"]
> 

3、查看賬戶餘額

> eth.getBalance(eth.accounts[0])
0
> eth.getBalance(eth.accounts[1])
0
> 

查詢餘額有多種方式,可以通過創建時的16進制碼,也可以通過賬戶下標查詢,下標默認從0開始

啓動&停止挖礦

啓動挖礦

> miner.start(1)

其中 start 的參數表示挖礦使用的線程數。第一次啓動挖礦會先生成挖礦所需的 DAG 文件,這個過程有點慢,等進度達到 100% 後,就會開始挖礦,此時屏幕會被挖礦信息刷屏。

停止挖礦

> miner.stop()

挖到一個區塊會獎勵n個以太幣,挖礦所得的獎勵會進入礦工的賬戶,這個賬戶叫做 coinbase,默認情況下 coinbase 是本地賬戶中的第一個賬戶,可以通過 miner.setEtherbase() 將其他賬戶設置成 coinbase。

交易

假如0賬戶向1賬戶轉賬,需要先把0賬戶鎖定,然後才能進行交易

> personal.unlockAccount(eth.accounts[0])
Unlock account 0x6594cc2f72908c0fea54d5c9dd297ce68f735411
Passphrase: 
true
> 

轉賬 賬戶0 –> 賬戶1

> amount = web3.toWei(5,'ether')
"5000000000000000000"
> eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[1],value:amount})
INFO [01-18|17:56:14] Submitted transaction                    fullhash=0x065c698cceaf996ab9ab06c6eddc8b035704defbcff0d65227d32c06a5b17637 recipient=0x4BD9F7b3c365D35C50757AF4CC7Bdb1307A083C0
"0x065c698cceaf996ab9ab06c6eddc8b035704defbcff0d65227d32c06a5b17637
>

此時如果沒有挖礦,用 txpool.status 命令可以看到本地交易池中有一個待確認的交易,可以使用 eth.getBlock("pending", true).transactions 查看當前待確認交易。

查交易和區塊

> eth.blockNumber
200

通過交易 Hash 查看交易(Hash 值包含在上面交易返回值中):

> eth.getTransaction("0x65a8278d571d7cf3f2ca36ce721900d61e9d6eadd1ed5f24f39b646c2b194427")
{
  blockHash: "0x0101b5f9e9c50ee45156f0631df18a97176aef5215bde40b3e167195d367ed80",
  blockNumber: 342,
  from: "0x16671cdabbc9b3f0f1b31380d972dcd9725f7d8a",
  gas: 90000,
  gasPrice: 18000000000,
  hash: "0x65a8278d571d7cf3f2ca36ce721900d61e9d6eadd1ed5f24f39b646c2b194427",
  input: "0x",
  nonce: 1,
  r: "0x52b7fce530ebd67527d4fe684cb3b5a4b96909154aeedcc5f371ab27e9e7f1ba",
  s: "0x141268e8fef639b79773f6ab7fb778b958be77bd05944f305dc4f1ec68f21962",
  to: "0x4bd9f7b3c365d35c50757af4cc7bdb1307a083c0",
  transactionIndex: 0,
  v: "0x823",
  value: 5000000000000000000
}
> 

通過區塊號查看區塊:

> eth.getBlock(0)
{
  difficulty: 131072,
  extraData: "0x6d6f7475692d32",
  gasLimit: 4294967295,
  gasUsed: 0,
  hash: "0x5117726df3040cb5cbd6e8d59cdaacaaa1cd8df4a20072d0e8242e96ea5c893f",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0x0000000000000000000000000000000000000000",
  mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  nonce: "0x0000000000000042",
  number: 0,
  parentHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 515,
  stateRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  timestamp: 0,
  totalDifficulty: 131072,
  transactions: [],
  transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  uncles: []
}
> 

連接到其他節點

所有的節點創建都是一樣的。

可以通過 admin.addPeer() 方法連接到其他節點,兩個節點要要指定相同的 chainID。

假設有兩個節點:節點一和節點二,chainID 都是 1024,通過下面的步驟就可以從節點一連接到節點二。

首先要知道節點二的 enode 信息,在節點二的 JavaScript console 中執行下面的命令查看 enode 信息:

> admin.nodeInfo.enode
"enode://8db747ce768cb5e6ea3dc00bd16fe2bdf56dbeda0b1abfcd2ddcbb5a5cf0fe6bb0123ca341935c2c4348a34c89b0a73e2fac72e8b4fac414006760aa9ab1f613@[::]:30303"
> 

然後在節點一的 JavaScript console 中執行 admin.addPeer(),就可以連接到節點二:

> admin.addPeer("enode://8db747ce768cb5e6ea3dc00bd16fe2bdf56dbeda0b1abfcd2ddcbb5a5cf0fe6bb0123ca341935c2c4348a34c89b0a73e2fac72e8b4fac414006760aa9ab1f613@127.0.0.1:30303")
true
>

addPeer() 的參數就是節點二的 enode 信息,注意要把 enode 中的 [::] 替換成節點二的 IP 地址。連接成功後,節點二就會開始同步節點一的區塊,同步完成後,任意一個節點開始挖礦,另一個節點會自動同步區塊,向任意一個節點發送交易,另一個節點也會收到該筆交易。

通過 admin.peers 可以查看連接到的其他節點信息,通過 net.peerCount 可以查看已連接到的節點數量。

除了上面的方法,也可以在啓動節點的時候指定 --bootnodes 選項連接到其他節點。

注意:

​ 1、對於操作過程中存在的問題網上基本上都有解決方法,可以參考錯誤信息自己解決

​ 2、如果使用的服務器或者虛擬機需要注意防火牆和端口的配置

參考內容

以太坊

以太坊私有鏈搭建指南

碼農的區塊鏈:搭建一個私有區塊鏈環境

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章