1. 程式人生 > >超級賬本hyperledger fabric第七集:智慧合約

超級賬本hyperledger fabric第七集:智慧合約

智慧合約

  • 執行環境:以太坊虛擬智慧合約執行環境EVM,fabric執行環境是docker
  • 鏈碼
    1. 是應用層和區塊鏈底層的中間點
    2. 每一個鏈碼執行環境是一個獨立的docker
    3. 使用GRPC協議與背書節點通訊,只有背書節點才能執行智慧合約
  • 鏈碼的生命週期
    1. 打包,智慧合約的編寫和編譯
    2. 安裝,將打包好的檔案,上傳到背書節點
    3. 例項化,實際的安裝了,執行Init方法,只執行一次,建構函式
    4. 升級,升級和修復鏈碼
    5. 互動,自己定義的方法的呼叫
  • 鏈碼的互動流程

  • 系統鏈碼(瞭解)
    1. LSCC:管理鏈碼的生命週期
    2. CSCC:配置管理鏈碼,管理鏈的配置
    3. QSCC:查詢賬本儲存,是一個區塊索引的外部服務
    4. ESCC:交易背書的鏈碼,交易執行後的鏈碼進行封裝簽名,給客戶端返回背書交易結果
    5. VSCC:交易驗證的鏈碼
  • 鏈碼程式設計的介面
    1. Init():鏈碼初始化,只執行一次
    2. Invoke():鏈碼的業務邏輯的編寫
    3. 上面2個方法引數一樣,引數是SDK的介面
  • 鏈碼SDK的介面:寫程式碼再看
  • 一些注意點:
    1. 分散式多機多節點執行,鏈碼會執行很多次
    2. 不寫隨機函式,交易會無效,多次執行不一樣
    3. 系統時間不寫,多機時間不一定一樣

網路搭建配置的實現

  • 建立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()中使用了隨機數,不要這麼做