自 bitcoin 開始,blockchain被視為是下一代新的技術革新,因為本質為去中心化的一個資料庫,也就是用了 P2P 的技術,來解決原本集中式的網路架構,所造成的網路互信問題。
一般認為 blockchain 會是一項改變世界的創新技術,但也由於這樣分散式的架構,所有參與這個 blockchain 的網路節點,都會是一個參與驗證的獨立個體,每一個節點的運算速度跟網路頻寬,也間接影響了 blockchain 所能提供的每秒最大交易數量(tps transaction per second)的速度。
因此 blockchain 由 bitcoin 時代的 public blockchain,演進出現了 federated blockchain 以及 private blockchain,速度最快的 private blockchain 也是最貼近企業應用的一種 blockchain。
事實上也有人認為私有鏈並不是 blockchain,就像是傳統的資料庫一樣,只是換了一個 blockchain 的包裝,這就像是一種既有的分散式帳本技術而已,可以參閱這篇文章的討論:全面認識區塊鏈:公有鏈vs私有鏈,關於 blockchain 的企業應用目前並沒有很明確的答案。
Hyperledger
Hyperledger 是 2015 年 12 月由 Linux 基金會聯合了三十家公司,合作的一個 private blockchain 專案,它可說是繼 bitcoin,ethereum 之後,最受關注的一個 blockchain 專案。
在超級賬本聯盟成立之前,IBM公司就已經開源了一個 Open Blockchain,OBC 專案。在聯盟成立之後,IBM把OBC項目約 44000 行代碼貢獻給了Linux基金會,這部分代碼成為了Fabric的代碼的主要組成部分。在2016年3月的一次黑客松編程活動中,Blockstream和數字資產兩個成員公司把各自的區塊鏈功能代碼融合到OBC中,最終建立了Fabric的雛形,也就是Fabric項目進入孵化階段的基礎代碼。
目前有三個帳本平台項目
- fabric:包括 fabric 和 fabric-api、fabric-sdk-node、fabric-sdk-py 等,目標是區塊鏈的基礎核心平台,支持 pbft 等新的 consensus 機制,支持權限管理,最早由 IBM 和 DAH 發起;
- sawtooth Lake:包括 arcade、core、dev-tools、validator、mktplace 等。是 Intel 主要發起和貢獻的區塊鏈平台,支持全新的基於硬體晶片的共識機制 Proof of Elapsed Time(PoET)。
- Iroha:賬本平台項目,主要由 Soramitsu 發起和貢獻。
測試 hyperledger smartcontract
ref: 從零開始,5分鐘創建並玩轉屬於自己的區塊鏈(圖文攻略)
IBM中國研究院開發的 SuperVessel 平臺提供了給區塊鏈愛好者、開發者的區塊鏈開發測試環境。通過該平臺,用戶能夠免費、超快速創建基於Hyperledger Fabric的多節點區塊鏈。
到 SuperVessel 區塊鏈 申請帳號
點中間的 MY DASHBOARD
點擊 Chain -> Apply a new chain,產生一個 blockchain,我們選擇 pbft 演算法,4 個 nodes
主畫面是剛剛建立的 test pbft blockchain
Smart Contract 裡面已經有兩個 sample: map 跟 chaincode_example02
回到 test pbft,點右下角的 deploy,選擇 chaincode_example02,任意一個 instance name,init a 與 b 分別有 100 及 200 元
點 invoke,function: transfer 就是轉帳,由 a 帳戶轉給 b 50 元
可以 Query a 或 b 帳戶目前的餘額
帳戶異動的動作都會產生一個新的 block
如果在同一個 blockchain 部署兩個 smart contact,blocks 上的區塊是會累積起來的。
以 docker 測試 hyperledger
ref: 區塊鏈技術指南
用 dokcer 下載 hyperledger images
$ docker pull hyperledger/fabric-peer:x86_64-0.6.1-preview \
&& docker pull hyperledger/fabric-membersrvc:x86_64-0.6.1-preview \
&& docker pull yeasy/blockchain-explorer:latest \
&& docker tag hyperledger/fabric-peer:x86_64-0.6.1-preview hyperledger/fabric-peer \
&& docker tag hyperledger/fabric-peer:x86_64-0.6.1-preview hyperledger/fabric-baseimage \
&& docker tag hyperledger/fabric-membersrvc:x86_64-0.6.1-preview hyperledger/fabric-membersrvc
可使用 noops 或是 PBFT 兩種不同的一致性演算法
如果使用 noops 可以只開一個節點
$ docker run --name=vp0 \
--restart=unless-stopped \
-it \
-p 7050:7050 \
-p 7051:7051 \
-v /var/run/docker.sock:/var/run/docker.sock \
-e CORE_PEER_ID=vp0 \
-e CORE_PEER_ADDRESSAUTODETECT=true \
-e CORE_NOOPS_BLOCK_WAIT=10 \
hyperledger/fabric-peer:latest peer node start
PBFT 是比較常用的一致性演算法,只少需要四個節點
在 yeasy/docker-compose-files 有幾個 template,可以用 git 下載
git clone https://github.com/yeasy/docker-compose-files
在 docker-compose-files/hyperledger/0.6/pbft 目錄中有以下這些 templates
- 4-peers.yml: 啟動四個 PBFT peer 節點
- 4-peers-with-membersrvc.yml: 啟動 4 個 PBFT peer 節點 + 1 個 CA 節點,並啟用 CA 功能。
- 4-peers-with-explorer.yml: 啟動 4 個 PBFT peer 節點 + 1 個 Blockchain-explorer,可以通過 Web 界面監控集群狀態。
- 4-peers-with-membersrvc-explorer.yml: 啟動 4 個 PBFT peer 節點 + 1 個 CA 節點 + 1 個 Blockchain-explorer,並啟用 CA 功能。
可用 docker-compose 快速啟動一個 4 個 PBFT 節點的集群
$ docker-compose -f 4-peers.yml up
如果要自己一個一個慢慢建立節點
# vp0 初始的探測節點 (10.0.0.1)
$docker run --name=vp0 \
--net="host" \
--restart=unless-stopped \
-it --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-e CORE_PEER_ID=vp0 \
-e CORE_PBFT_GENERAL_N=4 \
-e CORE_LOGGING_LEVEL=debug \
-e CORE_PEER_ADDRESSAUTODETECT=true \
-e CORE_PEER_NETWORKID=dev \
-e CORE_PEER_VALIDATOR_CONSENSUS_PLUGIN=pbft \
-e CORE_PBFT_GENERAL_MODE=batch \
-e CORE_PBFT_GENERAL_TIMEOUT_REQUEST=10s \
hyperledger/fabric-peer:latest peer node start
# vp1 ~ vp3
$ NAME=vp1
$ ROOT_NODE=10.0.0.1
$ docker run --name=${NAME} \
--net="host" \
--restart=unless-stopped \
-it --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-e CORE_PEER_ID=${NAME} \
-e CORE_PBFT_GENERAL_N=4 \
-e CORE_LOGGING_LEVEL=debug \
-e CORE_PEER_ADDRESSAUTODETECT=true \
-e CORE_PEER_NETWORKID=dev \
-e CORE_PEER_VALIDATOR_CONSENSUS_PLUGIN=pbft \
-e CORE_PBFT_GENERAL_MODE=batch \
-e CORE_PBFT_GENERAL_TIMEOUT_REQUEST=10s \
-e CORE_PEER_DISCOVERY_ROOTNODE=${ROOT_NODE}:7051 \
hyperledger/fabric-peer:latest peer node start
測試 example02 smart contract
使用 docker-compose 快速啟動一個 4 個 PBFT 節點的集群,如果剛剛有啟動過,就先把舊的 containers 刪除
$ docker-compose -f 4-peers.yml up
進入 pbftvp01
$ docker exec -it pbft_vp0_1 bash
部署 example02 chain code,就是 init a 100 元 b 200 元兩個帳戶
# peer chaincode deploy -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -c '{"Function":"init", "Args": ["a","100", "b", "200"]}'
03:42:46.851 [chaincodeCmd] chaincodeDeploy -> INFO 001 Deploy result: type:GOLANG chaincodeID:<path:"github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02" name:"ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539" > ctorMsg:<args:"init" args:"a" args:"100" args:"b" args:"200" >
Deploy chaincode: ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539
03:42:46.852 [main] main -> INFO 002 Exiting.....
得到的 codecode id,放在環境變數中
$ CC_ID=ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539
查詢 a 帳戶的餘額
$ peer chaincode query -n ${CC_ID} -c '{"Function": "query", "Args": ["a"]}'
03:45:54.865 [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Successfully queried transaction: chaincodeSpec:<type:GOLANG chaincodeID:<name:"ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539" > ctorMsg:<args:"query" args:"a" > >
Query Result: 100
03:45:54.865 [main] main -> INFO 002 Exiting.....
a 轉帳 50 元給 b
$ peer chaincode invoke -n ${CC_ID} -c '{"Function": "invoke", "Args": ["a", "b", "50"]}'
03:46:58.806 [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Successfully invoked transaction: chaincodeSpec:<type:GOLANG chaincodeID:<name:"ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539" > ctorMsg:<args:"invoke" args:"a" args:"b" args:"50" > > (b63aead7-154c-42bb-8ae5-3a880f305f9e)
03:46:58.806 [main] main -> INFO 002 Exiting.....
查詢 a 帳戶的餘額
$ peer chaincode query -n ${CC_ID} -c '{"Function": "query", "Args": ["a"]}'
03:47:25.763 [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Successfully queried transaction: chaincodeSpec:<type:GOLANG chaincodeID:<name:"ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539" > ctorMsg:<args:"query" args:"a" > >
Query Result: 50
03:47:25.763 [main] main -> INFO 002 Exiting.....
測試 權限管理
啟動帶成員管理的 PBFT 集群,包含 4 個 PBFT peer 節點 + 1 個 CA 節點 + 1 個 Blockchain-explorer,並啟用 CA 功能。
docker-compose -f 4-peers-with-membersrvc.yml up
連線到 pbftvp01
docker exec -it pbft_vp0_1 bash
以內建帳號 jim (密碼為: 6avZQLwcUe9b)登錄到系統
# peer network login jim
08:09:30.235 [networkCmd] networkLogin -> INFO 001 CLI client login...
08:09:30.236 [networkCmd] networkLogin -> INFO 002 Local data store for client loginToken: /var/hyperledger/production/client/
Enter password for user 'jim': 6avZQLwcUe9b
08:11:18.446 [networkCmd] networkLogin -> INFO 003 Logging in user 'jim' on CLI interface...
08:11:18.881 [networkCmd] networkLogin -> INFO 004 Storing login token for user 'jim'.
08:11:18.882 [networkCmd] networkLogin -> INFO 005 Login successful for user 'jim'.
08:11:18.882 [main] main -> INFO 006 Exiting.....
先安裝 curl
apt-get update
apt-get install curl
用 POST 的方式呼叫 register
$ curl -X POST -H 'Content-Type: application/json' -d '{"enrollId": "jim","enrollSecret": "6avZQLwcUe9b"}' http://localhost:7050/registrar
{"OK":"User jim is already logged in."}
接下來 chaincode 的部屬跟呼叫都需要再加上 -u 指定帳號。
# peer chaincode deploy -u jim -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -c '{"Function":"init", "Args": ["a","100", "b", "200"]}'
08:20:35.263 [chaincodeCmd] getChaincodeSpecification -> INFO 001 Local user 'jim' is already logged in. Retrieving login token.
08:20:38.338 [chaincodeCmd] chaincodeDeploy -> INFO 002 Deploy result: type:GOLANG chaincodeID:<path:"github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02" name:"ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539" > ctorMsg:<args:"init" args:"a" args:"100" args:"b" args:"200" >
Deploy chaincode: ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539
08:20:38.338 [main] main -> INFO 003 Exiting.....
紀錄 chaincode ID
$ CC_ID=ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539
查詢帳戶 a 的餘額為 100
$ peer chaincode query -u jim -n ${CC_ID} -c '{"Function": "query", "Args": ["a"]}'
08:22:25.600 [chaincodeCmd] getChaincodeSpecification -> INFO 001 Local user 'jim' is already logged in. Retrieving login token.
08:22:25.876 [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 002 Successfully queried transaction: chaincodeSpec:<type:GOLANG chaincodeID:<name:"ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539" > ctorMsg:<args:"query" args:"a" > secureContext:"jim" >
Query Result: 100
08:22:25.876 [main] main -> INFO 003 Exiting.....
用 REST 方式進行 query
$ curl -X POST -H 'Content-Type: application/json' -d '
{
"jsonrpc": "2.0",
"method": "invoke",
"params": {
"type": 1,
"chaincodeID":{
"name":"ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539"
},
"ctorMsg": {
"function":"query",
"args":["a"]
},
"secureContext": "jim"
},
"id": 3
}
' http://localhost:7050/chaincode
{"jsonrpc":"2.0","result":{"status":"OK","message":"c62697b9-5ade-41ff-99ef-0733cf99c05d"},"id":3}
查詢 block 資訊
$ curl -X GET http://localhost:7050/chain/blocks/2
{"stateHash":"QkIbllrDhpZ1+ZGCTwbu83CEnR9oA8/fECHDCvYNz6wjdpxvCS/aTsG24NbDAhMtHQmhq12yhoCYmSLgGvLm+A==","previousBlockHash":"DnwB438SiFir+5AoeUPLup8l1qEZN1ddPdgOPr2BnbBQT4W0ENOPym1o4c0IkAHC+xuQiw68cXkcSjcrZi1CJg==","consensusMetadata":"CAI=","nonHashData":{"localLedgerCommitTimestamp":{"seconds":1482913592,"nanos":719911090},"chaincodeEvents":[{}]}}
References
區塊鏈科技趨勢與應用
專訪R3聯盟高層:分散式分類帳和區塊鏈有何不同?
中国区块链技术和应用发展白皮书 2016
五個問答讓你秒懂區塊鏈原理及應用
最具商用價值的開源區塊鏈項目:超級賬本
hyperledger 官方網站
hyperledger fabric doc
區塊鏈組織-超級賬本(Hyperledger)的簡介
區塊鏈在中國:IBM HyperLedger
Hyperledger智能合约Hello World示例程序
學習鏈碼
在开发环境下编写,运行,测试chaincode
hyperledger fabric本地開發環境mac部署
Hyperledger fabric 開發環境搭建