超級賬本hyperledger fabric第七集:智慧合約
阿新 • • 發佈:2018-12-20
智慧合約
- 執行環境:以太坊虛擬智慧合約執行環境EVM,fabric執行環境是docker
- 鏈碼
- 是應用層和區塊鏈底層的中間點
- 每一個鏈碼執行環境是一個獨立的docker
- 使用GRPC協議與背書節點通訊,只有背書節點才能執行智慧合約
- 鏈碼的生命週期
- 打包,智慧合約的編寫和編譯
- 安裝,將打包好的檔案,上傳到背書節點
- 例項化,實際的安裝了,執行Init方法,只執行一次,建構函式
- 升級,升級和修復鏈碼
- 互動,自己定義的方法的呼叫
- 鏈碼的互動流程
- 系統鏈碼(瞭解)
- LSCC:管理鏈碼的生命週期
- CSCC:配置管理鏈碼,管理鏈的配置
- QSCC:查詢賬本儲存,是一個區塊索引的外部服務
- ESCC:交易背書的鏈碼,交易執行後的鏈碼進行封裝簽名,給客戶端返回背書交易結果
- VSCC:交易驗證的鏈碼
- 鏈碼程式設計的介面
- Init():鏈碼初始化,只執行一次
- Invoke():鏈碼的業務邏輯的編寫
- 上面2個方法引數一樣,引數是SDK的介面
- 鏈碼SDK的介面:寫程式碼再看
- 一些注意點:
- 分散式多機多節點執行,鏈碼會執行很多次
- 不寫隨機函式,交易會無效,多次執行不一樣
- 系統時間不寫,多機時間不一定一樣
網路搭建配置的實現
- 建立fabric_asset工程,在裡面建立chaincode資料夾。
- 在badexample.go中
package main import ( "github.com/hyperledger/fabric/core/chaincode/shim" pb "github.com/hyperledger/fabric/protos/peer" "bytes" "strconv" "math/rand" "time" "fmt" ) type BadExampleCC struct { } //每一個鏈碼必須實現2個方法 //鏈碼的初始化 func (c *BadExampleCC) Init(stub shim.ChaincodeStubInterface) pb.Response { //直接返回成功 return shim.Success(nil) } //鏈碼互動的入口 func (c *BadExampleCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response { //直接返回一個隨機數結果 return shim.Success(bytes.NewBufferString(strconv.Itoa(int(rand.Int63n(time.Now().Unix())))).Bytes()) } func main() { err := shim.Start(new(BadExampleCC)) if err != nil { fmt.Printf("Error starting Simple chaincode: %s", err) } }
- crypto-config.yaml:用於配置組織節點的個數,參考first-network去編寫
- 編寫好後,傳到linux對應目錄
- 進入deploy目錄,設定工作目錄為當前目錄
- 指定按照yaml檔案生成配置
- configtx.yaml:用於區塊聯盟中的組織資訊,配置名字和證書等的位置,參考firstnetwork去編寫
--- #聯盟配置 #聯盟內的組織對區塊鏈的操作 Profiles: #系統鏈的配置 #全域性配置 OneOrgsOrdererGenesis: Orderer: <<: *OrdererDefaults Organizations: - *OrdererOrg Consortiums: SampleConsortium: Organizations: - *Org0 - *Org1 #業務相關的配置 TwoOrgsChannel: Consortium: SampleConsortium Application: <<: *ApplicationDefaults Organizations: - *Org0 - *Org1 Organizations: #組織內的配置 - &OrdererOrg #組織名字 Name: OrdererOrg #組織ID ID: OrdererMSP #組織證書的位置 MSPDir: crypto-config/ordererOrganizations/example.com/msp - &Org0 Name: Org0MSP ID: Org0MSP MSPDir: crypto-config/peerOrganizations/org0.example.com/msp #錨節點的配置 AnchorPeers: - Host: peer0.org0.example.com Port: 7051 - &Org1 Name: Org1MSP ID: Org1MSP MSPDir: crypto-config/peerOrganizations/org1.example.com/msp #錨節點 AnchorPeers: - Host: peer0.org1.example.com Port: 7051 #orderer配置 Orderer: &OrdererDefaults #配置共識機制 OrdererType: solo Addresses: - orderer.example.com:7050 #出塊的時間間隔 BatchTimeout: 2s #每個塊的大小資訊 BatchSize: MaxMessageCount: 10 AbsoluteMaxBytes: 99 MB PreferredMaxBytes: 512 KB #kafka的配置 Kafka: Brokers: - 127.0.0.1:9092 Organizations: Application: &ApplicationDefaults Organizations:
- 編寫好後,傳到linux對應目錄
- 建立用於存放配置的目錄
- 生成系統鏈的創世區塊:-profile指定聯盟配置,outputBlock指定存放的位置
- 生成通道的創世交易:profile指定業務聯盟,outputCreateChannelTx存放的路徑,建立的名字叫mychannel
- 生成兩個組織錨節點的交易資訊
- 將docker-compose.yaml拖進deploy目錄
version: '2'
services:
#1.系統一些環境變數的配置
#2.埠的對映關係
#3.檔案的對映關係
orderer.example.com:
container_name: orderer.example.com
#指定使用映象名稱
image: hyperledger/fabric-orderer:x86_64-1.0.0
#環境變數的配置
environment:
#設定日誌級別
- ORDERER_GENERAL_LOGLEVEL=debug
#服務暴露的地址
- ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
#下面2個是注入創世區塊
- ORDERER_GENERAL_GENESISMETHOD=file
- ORDERER_GENERAL_GENESISFILE=/etc/hyperledger/config/genesis.block
#下面2個是證書相關的配置
- ORDERER_GENERAL_LOCALMSPID=OrdererMSP
- ORDERER_GENERAL_LOCALMSPDIR=/etc/hyperledger/orderer/msp
working_dir: /home/go_work/src/github.com/hyperledger/fabric/orderer
command: orderer
ports:
#前面是本機的,埠對映
- 7050:7050
volumes:
- ./config/genesis.block:/etc/hyperledger/config/genesis.block
- ./crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/:/etc/hyperledger/orderer
#peer的基礎設定
peer.base:
image: hyperledger/fabric-peer:x86_64-1.0.0
environment:
#peer節點可能對chaincode做一些操作
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
#日誌級別
- CORE_LOGGING_PEER=debug
#開啟開發者模式
#- CORE_CHAINCODE_MODE=dev
#關於鏈碼的日誌級別
- CORE_CHAINCODE_LOGGING_LEVEL=DEBUG
#msp證書
- CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/peer/msp
#狀態資料庫的儲存引擎,這裡配置使用levledb
- CORE_LEDGER_STATE_STATEDATABASE=goleveldb
#配置chaincode與peer節點使用的網路,同一個網路
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=deploy_default
working_dir: /home/go_work/src/github.com/hyperledger/fabric
command: peer node start
#開啟開發者模式
#command: peer node start --peer-chaincodedev=true
peer0.org0.example.com:
extends:
service: peer.base
container_name: peer0.org0.example.com
environment:
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_PEER_ID=peer0.org0.example.com
- CORE_PEER_LOCALMSPID=Org0MSP
- CORE_PEER_ADDRESS=peer0.org1.example.com:7051
ports:
#grpc的埠
- 7051:7051
#事件監聽的埠
- 7053:7053
volumes:
- /var/run/:/host/var/run/
- ./crypto-config/peerOrganizations/org0.example.com/peers/peer0.org0.example.com:/etc/hyperledger/peer
depends_on:
- orderer.example.com
peer1.org0.example.com:
extends:
service: peer.base
container_name: peer1.org0.example.com
environment:
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_PEER_ID=peer1.org0.example.com
- CORE_PEER_LOCALMSPID=Org0MSP
- CORE_PEER_ADDRESS=peer1.org0.example.com:7051
ports:
#別與上面peer0的埠衝突就可以
- 17051:7051
- 17053:7053
volumes:
- /var/run/:/host/var/run/
- ./crypto-config/peerOrganizations/org0.example.com/peers/peer1.org0.example.com:/etc/hyperledger/peer
depends_on:
- orderer.example.com
peer0.org1.example.com:
extends:
service: peer.base
container_name: peer0.org1.example.com
environment:
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_PEER_ID=peer0.org1.example.com
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_PEER_ADDRESS=peer0.org1.example.com:7051
ports:
#注意埠不衝突就可以
- 27051:7051
- 27053:7053
volumes:
- /var/run/:/host/var/run/
- ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com:/etc/hyperledger/peer
depends_on:
- orderer.example.com
peer1.org1.example.com:
extends:
service: peer.base
container_name: peer1.org1.example.com
environment:
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_PEER_ID=peer1.org1.example.com
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_PEER_ADDRESS=peer1.org1.example.com:7051
ports:
#注意埠不衝突就可以
- 37051:7051
- 37053:7053
volumes:
- /var/run/:/host/var/run/
- ./crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com:/etc/hyperledger/peer
depends_on:
- orderer.example.com
peer2.org1.example.com:
extends:
service: peer.base
container_name: peer2.org1.example.com
environment:
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_PEER_ID=peer2.org1.example.com
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_PEER_ADDRESS=peer2.org1.example.com:7051
ports:
- 47051:7051
- 47053:7053
volumes:
- /var/run/:/host/var/run/
- ./crypto-config/peerOrganizations/org1.example.com/peers/peer2.org1.example.com:/etc/hyperledger/peer
depends_on:
- orderer.example.com
#peer節點客戶端配置
cli:
container_name: cli
image: hyperledger/fabric-tools
tty: true
environment:
- GOPATH=/home/go_work
- CORE_LOGGING_LEVEL=DEBUG
- CORE_PEER_ID=cli
- CORE_PEER_ADDRESS=peer0.org1.example.com:7051
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/peer/users/[email protected]/msp
working_dir: /home/go_work/src/github.com/hyperledger/fabric/
command: /bin/bash
volumes:
#鏈碼路徑的注入
#本地中的相對路徑,對映的容器中的絕對路徑
- ./../chaincode:/home/go_work/src/github.com/chaincode
- ./config:/etc/hyperledger/config
- ./crypto-config/peerOrganizations/org1.example.com/:/etc/hyperledger/peer
啟動網路
- 啟動docker,後臺執行
- 檢視orderer節點的執行日誌
- 與客戶端互動操作
- 建立通道:-o指定與哪個orderer節點通訊,-c指定建立的通道名稱,-f指定使用的檔案
- 加入通道
- 檢視peer加入的通道列表
- 指定主節點
------------------------------------------------------------------基礎網路搞定了----------------------------------------------------------------------------------
- 安裝鏈碼:-n是安裝的名字,-v是version,-l是使用語言
- 克隆一個會話,互動執行peer0,檢視安裝的鏈碼
- 鏈碼例項化
- 鏈碼互動執行
- 多次執行查詢,得到的結果不用,因為invoke()中使用了隨機數,不要這麼做