區塊鏈系列教程——建立屬於自己的區塊鏈
區塊鏈系列教程以以太坊區塊鏈為基礎,主要包括若干以太坊區塊鏈的建立使用等,還包括部分原理說明,後期還會加入對其的改進。
本文是區塊鏈系列教程的第一章,主要內容是使用以太坊區塊鏈建立私鏈,並使用控制檯進行一些基本操作。
1. 區塊鏈簡介
在正文之前,先簡單介紹一下區塊鏈的基本概念。
區塊鏈,顧名思義,其儲存形式是若干個區塊組成,區塊之間通過某種方式聯絡在一起。如圖所示:

區塊鏈示意圖
實際上,除了區塊(區塊頭)結構,區塊鏈可以抽象出更多的技術,比如共識機制、密碼學機制、P2P網路、Hash樹、智慧合約等,這些可以統稱為區塊鏈技術,後續教程會涉及到其中部分的原理。
以太坊區塊鏈的區塊結構較為複雜,遠遠不止示意圖中的結構,有興趣的讀者可以去其 github上檢視詳細原始碼,這是go語言實現版本,也是官方主推的版本。此處大概說明以太坊區塊鏈的區塊結構,以太坊的區塊結構主要定義在go-ethereum/core/types/block.go檔案中,其區塊結構為:
type Block struct { header*Header uncles[]*Header transactions Transactions // caches hash atomic.Value size atomic.Value // Td is used by package core to store the total difficulty // of the chain up to and including the block. td *big.Int // These fields are used by package eth to track // inter-peer block relay. ReceivedAttime.Time ReceivedFrom interface{} }
區塊結構中,header表示區塊頭,是非常重要的引數,其具體結構後面會說明 ;uncles表示該區塊的叔塊,也就是父區塊的兄弟區塊(因為以太坊的區塊發行時間只有10秒左右,所以礦工之間會存在競爭,兩個同時發行的區塊將成為兄弟區塊);transactions表示區塊中裝載的交易資訊,這也是一個非常重要的引數,在區塊鏈中交易是最為重要的功能。
以太坊區塊頭格式為:
type Header struct { ParentHashcommon.Hash`json:"parentHash"gencodec:"required"` UncleHashcommon.Hash`json:"sha3Uncles"gencodec:"required"` Coinbasecommon.Address `json:"miner"gencodec:"required"` Rootcommon.Hash`json:"stateRoot"gencodec:"required"` TxHashcommon.Hash`json:"transactionsRoot" gencodec:"required"` ReceiptHash common.Hash`json:"receiptsRoot"gencodec:"required"` BloomBloom`json:"logsBloom"gencodec:"required"` Difficulty*big.Int`json:"difficulty"gencodec:"required"` Number*big.Int`json:"number"gencodec:"required"` GasLimituint64`json:"gasLimit"gencodec:"required"` GasUseduint64`json:"gasUsed"gencodec:"required"` Timeuint64`json:"timestamp"gencodec:"required"` Extra[]byte`json:"extraData"gencodec:"required"` MixDigestcommon.Hash`json:"mixHash"` NonceBlockNonce`json:"nonce"` }
- ParentHash表示父區塊的Hash值,該值實際上就是所謂的鏈,用於實現區塊鏈資料不可逆的特性。
- UncleHash是區塊結構中uncles經過hash運算得到的結果,用於驗證區塊資料的正確性。
- Coinbase用於記錄該區塊的發行者,其可獲得區塊獎勵和礦工費獎勵。
- Root用於驗證當前區塊鏈的狀態,其中狀態使用MPT(Merkle-Patricia-Tree)結構儲存。
- TxHash用於驗證當前區塊的交易資訊,所有交易使用
MPT結構組織儲存。 - ReceiptHash用於驗證當前區塊的交易收據資訊,對於一個交易執行完成後會有相應的收據,其組織形式也是MPT。
- Bloom是當前區塊交易執行日誌的布隆過濾器,用於快速確定某交易是否存在。
- Difficulty是當前區塊鏈POW的難度值,這與共識機制有關,後文會詳細介紹。
- Number是當前區塊高度,即區塊id,創世區塊為0,逐一遞增。
- GasLimit是當前區塊大小,以太坊使用gas機制來控制區塊大小,每個交易(包括轉賬交易和智慧合約交易)都會消耗相應的gas,特別是智慧合約交易,消耗的gas大小與其執行步驟和儲存消耗有關,因為以太坊是圖靈完備的,所以需要此措施來防止出現死迴圈。
- GasUsed是當前區塊所消耗的總的gas大小。
- Time是區塊打包時間。
- Extra是額外附加資訊。
- MixDigest和Nonce是POW共識機制的結果證明。
2. 開始實踐
本文主要使用以太坊geth客戶端來建立私鏈,並基於console進行部分簡單操作,讓讀者可以對區塊鏈有一個大概的直觀的感覺。
1.1 安裝geth客戶端
方法1
可以直接去官網下載對應作業系統的客戶端。
方法2
Ubuntu的讀者可以通過命令來安裝:
sudo add-apt-repository -y ppa:ethereum/ethereum sudo apt-get update sudo apt-get install ethereum
macOS的讀者可以通過brew進行安裝:
brew tap ethereum/ethereum brew install ethereum
1.2 創世塊檔案
在建立私鏈時,由於我們是從創世塊開始,其他區塊的內容和創世塊會有很大的關係,而創世塊是需要我們來設定其中的欄位資訊的。此處,設定genesis.json檔案:
{ "config": { "chainId": 10, "homesteadBlock": 0, "eip155Block": 0, "eip158Block": 0 }, "alloc": {}, "coinbase": "0x0000000000000000000000000000000000000000", "difficulty" : "0x2000000", "extraData": "", "gasLimit": "0x33450", "nonce": "0x0000000000000042", "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "timestamp": "0x00" 17 }
1.3 建立資料資料夾
使用命令建立資料資料夾test:

建立資料資料夾
1.4 初始化區塊鏈
使用命令初始化區塊鏈:
geth --datadir test/ init genesis.json
得到結果:
INFO [05-01|21:27:32.575] Maximum peer countETH=25 LES=0 total=25 INFO [05-01|21:27:32.576] Allocated cache and file handlesdatabase=/home/hadoop/blockchain/test/geth/chaindata cache=16 handles=16 INFO [05-01|21:27:32.581] Writing custom genesis block INFO [05-01|21:27:32.581] Persisted trie from memory databasenodes=0 size=0.00B time=3.104µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B INFO [05-01|21:27:32.581] Successfully wrote genesis statedatabase=chaindatahash=b123b8…4077eb INFO [05-01|21:27:32.581] Allocated cache and file handlesdatabase=/home/hadoop/blockchain/test/geth/lightchaindata cache=16 handles=16 INFO [05-01|21:27:32.584] Writing custom genesis block INFO [05-01|21:27:32.584] Persisted trie from memory databasenodes=0 size=0.00B time=2.105µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B INFO [05-01|21:27:32.585] Successfully wrote genesis statedatabase=lightchaindatahash=b123b8…4077eb
1.5 建立區塊鏈私鏈
使用命令建立區塊鏈私鏈:
geth --datadir test/ --networkid 10 console
得到結果:
INFO [05-01|21:29:06.015] Maximum peer countETH=25 LES=0 total=25 INFO [05-01|21:29:06.016] Starting peer-to-peer nodeinstance=Geth/v1.8.17-stable-8bbe7207/linux-amd64/go1.10 INFO [05-01|21:29:06.016] Allocated cache and file handlesdatabase=/home/hadoop/blockchain/test/geth/chaindata cache=768 handles=512 INFO [05-01|21:29:06.024] Initialised chain configurationconfig="{ChainID: 10 Homestead: 0 DAO: <nil> DAOSupport: false EIP150: <nil> EIP155: 0 EIP158: 0 Byzantium: <nil> Constantinople: <nil> Engine: unknown}" INFO [05-01|21:29:06.024] Disk storage enabled for ethash cachesdir=/home/hadoop/blockchain/test/geth/ethash count=3 INFO [05-01|21:29:06.024] Disk storage enabled for ethash DAGsdir=/home/hadoop/.ethashcount=2 INFO [05-01|21:29:06.024] Initialising Ethereum protocolversions="[63 62]" network=10 INFO [05-01|21:29:06.025] Loaded most recent local headernumber=0 hash=b123b8…4077eb td=33554432 age=50y2w3d INFO [05-01|21:29:06.025] Loaded most recent local full blocknumber=0 hash=b123b8…4077eb td=33554432 age=50y2w3d INFO [05-01|21:29:06.025] Loaded most recent local fast blocknumber=0 hash=b123b8…4077eb td=33554432 age=50y2w3d INFO [05-01|21:29:06.025] Regenerated local transaction journaltransactions=0 accounts=0 INFO [05-01|21:29:06.025] Starting P2P networking INFO [05-01|21:29:08.150] UDP listener upself=enode://21d2a8209dc9aeadd15d94c2df30128dd7bd4b772f34e61e8f76afb893a2f7735a77c9061b64076ca61b5635b5d434fa32600af0e56f833fd7e582bff94e679d@222.201.145.179:30303 INFO [05-01|21:29:08.151] RLPx listener upself=enode://21d2a8209dc9aeadd15d94c2df30128dd7bd4b772f34e61e8f76afb893a2f7735a77c9061b64076ca61b5635b5d434fa32600af0e56f833fd7e582bff94e679d@222.201.145.179:30303 INFO [05-01|21:29:08.155] IPC endpoint openedurl=/home/hadoop/blockchain/test/geth.ipc INFO [05-01|21:29:08.169] Mapped network portproto=udp extport=30303 intport=30303 interface="UPNP IGDv1-IP1" INFO [05-01|21:29:08.189] Mapped network portproto=tcp extport=30303 intport=30303 interface="UPNP IGDv1-IP1" Welcome to the Geth JavaScript console! instance: Geth/v1.8.17-stable-8bbe7207/linux-amd64/go1.10 modules: admin:1.0 debug:1.0 eth:1.0 ethash:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0 >
1.6 使用區塊鏈
完成步驟1.5後,區塊鏈已經可以使用,1.5中的console命令是指開啟控制檯用於與區塊鏈進行互動——具體的geth命令後面教程將會詳細說明。此處,我們可以控制當前區塊鏈節點做一些操作了。
- 建立一個賬戶
> personal.newAccount() Passphrase: Repeat passphrase: "0x6393bb737b95465ccd9e4597df0647cdcd09775f"
- 挖礦
> miner.start() INFO [05-01|21:34:33.568] Updated mining threadsthreads=8 INFO [05-01|21:34:33.568] Transaction pool price threshold updated price=1000000000 INFO [05-01|21:34:33.568] Etherbase automatically configuredaddress=0x6393Bb737b95465cCD9E4597dF0647CdcD09775f null > INFO [05-01|21:34:33.569] Commit new mining worknumber=1 sealhash=0fcb98…71f1eb uncles=0 txs=0 gas=0 fees=0 elapsed=299.471µs
- 檢視餘額
> eth.getBalance(eth.coinbase) 5000000000000000000
- 解鎖賬戶
> personal.unlockAccount(eth.coinbase) Unlock account 0x6393bb737b95465ccd9e4597df0647cdcd09775f Passphrase: true
-
轉賬
需要注意的是,轉賬操作前需要將賬戶解鎖,在轉賬操作發起成功後,需要等待一段時間,礦工將該轉賬交易打包進入新的發行區塊後才會生效。
> eth.sendTransaction({from:eth.coinbase, to:personal.listAccounts[1], value:100}) INFO [05-01|21:37:28.223] Setting new local accountaddress=0x6393Bb737b95465cCD9E4597dF0647CdcD09775f INFO [05-01|21:37:28.223] Submitted transactionfullhash=0xc2479ec79713c9a7bd638146fabf5175eeaad8df87939af83be91ce4218a7c6c recipient=0x5eDcF2B2eFa9500C9F056f58E9C032B375b877E0 "0xc2479ec79713c9a7bd638146fabf5175eeaad8df87939af83be91ce4218a7c6c" > INFO [05-01|21:37:29.194] Commit new mining worknumber=6 sealhash=47fb15…84b362 uncles=0 txs=1 gas=21000 fees=2.1e-05 elapsed=601.799µs
隨後,檢查兩者的餘額,發現已經轉賬成功:
> eth.getBalance(eth.coinbase) 29999999999999999900 > eth.getBalance(personal.listAccounts[1]) 100
聯絡與交流
歡迎小夥伴與我討論哦~
本文歡迎轉載,請註明本文地址: https://www.jianshu.com/p/d1ec1cc10355