fabric-sdk-go的簡單使用

使用fabric-sdk-go之前,需要安裝好go環(huán)境,docker以及docker compose環(huán)境,還有 hyperledger fabric 環(huán)境.

一. 創(chuàng)建crypto-config.yaml

使用fabric提供的cryptogen工具生成文件模板
$ cryptogen showtemplate > crypto-config.yaml
進(jìn)行修改,添加一個組織,一個orderer節(jié)點.

OrdererOrgs:

  - Name: Orderer
    Domain: xq.com
    Specs:
      - Hostname: orderer

PeerOrgs:

  - Name: Travle
    Domain: travle.xq.com
    EnableNodeOUs: false

    Template:
      Count: 2

    Users:
      Count: 2

根據(jù)crypto-config.yaml文件生成證書文件:
$ cryptogen generate --config=crypto-config.yaml

查看生成的證書文件夾結(jié)構(gòu):

.
├── ordererOrganizations
│   └── xq.com
│       ├── ca
│       │   ├── 1d8deec1977f7abf81692e72c06861e811c00b34278b48c9fe44dc51238d8621_sk
│       │   └── ca.xq.com-cert.pem
│       ├── msp
│       │   ├── admincerts
│       │   ├── cacerts
│       │   └── tlscacerts
│       ├── orderers
│       │   └── orderer.xq.com
│       ├── tlsca
│       │   ├── 5b189397d9390ae07146a411f0e7b6c5bf1fdb809d4b4d51b6f25b739a7cc127_sk
│       │   └── tlsca.xq.com-cert.pem
│       └── users
│           └── Admin@xq.com
└── peerOrganizations
    └── travle.xq.com
        ├── ca
        │   ├── 8ae1b694ae88d19d07fd698b0990b8d4f3bc46782fbfb3620e3e6e3fb0263e1c_sk
        │   └── ca.travle.xq.com-cert.pem
        ├── msp
        │   ├── admincerts
        │   ├── cacerts
        │   └── tlscacerts
        ├── peers
        │   ├── peer0.travle.xq.com
        │   └── peer1.travle.xq.com
        ├── tlsca
        │   ├── d6e2633fe6f35345eca10bc0231a2b34f127c2b9ebc8a86b582b412e875e513c_sk
        │   └── tlsca.travle.xq.com-cert.pem
        └── users
            ├── Admin@travle.xq.com
            ├── User1@travle.xq.com
            └── User2@travle.xq.com

二. 生成創(chuàng)世區(qū)塊文件和 通道

需要從fabric的源碼案例中拷貝configtx.yaml文件
$ cp $GOPATH/src/github.com/hyperledger/fabric-samples/first-network/configtx.yaml ./
對configtx.yaml文件進(jìn)行修改.
修改之前,創(chuàng)建一個文件夾,來保存即將創(chuàng)建的創(chuàng)世區(qū)塊文件

$ mkdir channel-artifacts

將創(chuàng)建區(qū)塊文件和通道的命令寫到一個腳本中! generate.sh

rm -rf ./channel-artifacts/*
rm -rf ./crypto-config/*

#根據(jù)crypto-config.yaml文件生成證書
cryptogen generate --config=./crypto-config.yaml

# 生成創(chuàng)始塊文件
echo "---------------- Create genesis.block file BEGIN --------------------"
configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
echo "---------------- Create genesis.block file END --------------------"

# 生成 travlechannel 文件
echo "---------------- Create travlechannel.tx file BEGIN -------------------"
configtxgen -profile TravleOrgsChannel -outputCreateChannelTx ./channel-artifacts/travlechannel.tx -channelID travlechannel
echo "---------------- Create travlechannel.tx file END -------------------"

# 生成更新錨節(jié)點文件
echo "---------------- Create TravleMSPanchors.tx file BEGIN -------------------"
configtxgen -profile TravleOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/TravleMSPanchors.tx -channelID travlechannel -asOrg TravleMSP
echo "---------------- Create TravleMSPanchors.tx file END -------------------"

腳本文件和配置文件的目錄結(jié)構(gòu):

├── channel-artifacts
├── configtx.yaml
├── crypto-config
│   ├── ordererOrganizations
│   └── peerOrganizations
├── crypto-config.yaml
└── generate.sh

執(zhí)行g(shù)enerate.sh文件生成創(chuàng)世區(qū)塊文件和通道,其實只有一個組織,也沒必要生成錨節(jié)點更新文件..
$ ./generate.sh

三. 通過 docker-compose 啟動容器

配置docker-compose文件:

version: '2'

networks:
  xq_travle:

services:
  orderer.xq.com:
    image: hyperledger/fabric-orderer:latest
    container_name: orderer.xq.com
    environment:
      - ORDERER_GENERAL_LOGLEVEL=debug
      - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
      - ORDERER_GENERAL_LISTENPORT=7050
      - ORDERER_GENERAL_GENESISPROFILE=Orderer
      - ORDERER_GENERAL_GENESISMETHOD=file
      - ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block
      - ORDERER_GENERAL_LOCALMSPID=xq.com
      - ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
      - ORDERER_GENERAL_TLS_ENABLED=true
      - ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
      - ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt
      - ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]

    working_dir: /opt/gopath/src/github.com/hyperledger/fabric
    command: orderer
    volumes:
      - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
      - ./crypto-config/ordererOrganizations/xq.com/orderers/orderer.xq.com/msp:/var/hyperledger/orderer/msp
      - ./crypto-config/ordererOrganizations/xq.com/orderers/orderer.xq.com/tls:/var/hyperledger/orderer/tls
    ports:
      - 7050:7050
    networks:
      - xq_travle

  peer0.travle.xq.com:
    image: hyperledger/fabric-peer:latest
    container_name: peer0.travle.xq.com
    environment:
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - CORE_VM_DOCKER_ATTACHSTDOUT=true
      - CORE_LOGGING_LEVEL=DEBUG
      - CORE_PEER_PROFILE_ENABLED=true
      - CORE_PEER_TLS_ENABLED=true
      - CORE_PEER_TLS_CERT_FILE=/var/hyperledger/tls/server.crt
      - CORE_PEER_TLS_KEY_FILE=/var/hyperledger/tls/server.key
      - CORE_PEER_TLS_ROOTCERT_FILE=/var/hyperledger/tls/ca.crt
      - CORE_PEER_ID=peer0.travle.xq.com
      - CORE_PEER_ADDRESSAUTODETECT=true
      - CORE_PEER_ADDRESS=peer0.travle.xq.com:7051
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.travle.xq.com:7051
      - CORE_PEER_GOSSIP_USELEADERELECTION=true
      - CORE_PEER_GOSSIP_ORGLEADER=false
      - CORE_PEER_GOSSIP_SKIPHANDSHAKE=true
      - CORE_PEER_LOCALMSPID=travle.xq.com
      - CORE_PEER_MSPCONFIGPATH=/var/hyperledger/msp
      - CORE_PEER_TLS_SERVERHOSTOVERRIDE=peer0.travle.xq.com
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    command: peer node start
    volumes:
      - /var/run/:/host/var/run/
      - ./crypto-config/peerOrganizations/travle.xq.com/peers/peer0.travle.xq.com/msp:/var/hyperledger/msp
      - ./crypto-config/peerOrganizations/travle.xq.com/peers/peer0.travle.xq.com/tls:/var/hyperledger/tls
    ports:
      - 7051:7051
      - 7053:7053
    depends_on:
      - orderer.xq.com
    links:
      - orderer.xq.com
    networks:
      - xq_travle

  peer1.travle.xq.com:
    image: hyperledger/fabric-peer:latest
    container_name: peer1.travle.xq.com
    environment:
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - CORE_VM_DOCKER_ATTACHSTDOUT=true
      - CORE_LOGGING_LEVEL=DEBUG
      - CORE_PEER_PROFILE_ENABLED=true
      - CORE_PEER_TLS_ENABLED=true
      - CORE_PEER_TLS_CERT_FILE=/var/hyperledger/tls/server.crt
      - CORE_PEER_TLS_KEY_FILE=/var/hyperledger/tls/server.key
      - CORE_PEER_TLS_ROOTCERT_FILE=/var/hyperledger/tls/ca.crt
      - CORE_PEER_ID=peer1.travle.xq.com
      - CORE_PEER_ADDRESSAUTODETECT=true
      - CORE_PEER_ADDRESS=peer1.travle.xq.com:7051
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.travle.xq.com:7051
      - CORE_PEER_GOSSIP_USELEADERELECTION=true
      - CORE_PEER_GOSSIP_ORGLEADER=false
      - CORE_PEER_GOSSIP_SKIPHANDSHAKE=true
      - CORE_PEER_LOCALMSPID=travle.xq.com
      - CORE_PEER_MSPCONFIGPATH=/var/hyperledger/msp
      - CORE_PEER_TLS_SERVERHOSTOVERRIDE=peer1.travle.xq.com
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    command: peer node start
    volumes:
      - /var/run/:/host/var/run/
      - ./crypto-config/peerOrganizations/travle.xq.com/peers/peer1.travle.xq.com/msp:/var/hyperledger/msp
      - ./crypto-config/peerOrganizations/travle.xq.com/peers/peer1.travle.xq.com/tls:/var/hyperledger/tls
    ports:
      - 8051:7051
      - 8053:7053
    depends_on:
      - orderer.xq.com
    links:
      - orderer.xq.com
    networks:
      - xq_travle

啟動容器, 啟動后查看容器運行情況
$ docker-compose up -d
$ docker-compose ps

       Name               Command       State                       Ports                     
----------------------------------------------------------------------------------------------
orderer.xq.com        orderer           Up      0.0.0.0:7050->7050/tcp                        
peer0.travle.xq.com   peer node start   Up      0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcp
peer1.travle.xq.com   peer node start   Up      0.0.0.0:8051->7051/tcp, 0.0.0.0:8053->7053/tcp

在這里,創(chuàng)建兩個腳本文件,用于docker容器的管理
clear_docker.sh 文件:

sudo docker rm -f $(sudo docker ps -aq) # 清除容器們
sudo docker network prune # 來清理沒有再被任何容器引用的networks
sudo docker volume prune  # 清理掛載卷

restart.sh 文件:

./clear_docker.sh    # 執(zhí)行clear_docker.sh腳本文件
docker-compose up -d

四. 創(chuàng)建sdk配置文件

創(chuàng)建配置文件的時候,有兩個文件可以進(jìn)行參考...

$GOPATH/src/github.com/hyperledger/fabric-sdk-go/test/fixtures/config/config_test.yaml
$GOPATH/src/github.com/hyperledger/fabric-sdk-go/pkg/core/config/testdata/template/config.yaml

修改后的sdk配置文件:

name: "driver-service-network"

version: 1.1.0

client:
  organization: Travle
  logging:
    level: info
  cryptoconfig:
    path: /Users/xq_mac/Go/src/driverFabricDemo/conf/crypto-config
  credentialStore:
    path: /tmp/driverStore

  BCCSP:
    security:
      enabled: true
      default:
        provider: "SW"
      hashAlgorithm: "SHA2"
      softVerify: true
      level: 256

  tlsCerts:
    systemCertPool: true
    client:
      keyfile: /Users/xq_mac/Go/src/driverFabricDemo/conf/crypto-config/peerOrganizations/travle.xq.com/users/User1@travle.xq.com/tls/client.key
      certfile: /Users/xq_mac/Go/src/driverFabricDemo/conf/crypto-config/peerOrganizations/travle.xq.com/users/User1@travle.xq.com/tls/client.crt

channels:
  travlechannel:
    orderers:
      - orderer.xq.com

    peers:
      peer0.travle.xq.com:
        endorsingPeer: true
        chaincodeQuery: true
        ledgerQuery: true
        eventSource: true

      peer1.travle.xq.com:
        endorsingPeer: true
        chaincodeQuery: true
        ledgerQuery: true
        eventSource: true

    policies:
      queryChannelConfig:
        minResponses: 1
        maxTargets: 1
        retryOpts:
          attempts: 5
          initialBackoff: 500ms
          maxBackoff: 5s
          backoffFactor: 2.0

organizations:
  travle:
    # configtx.yaml organizations -> ID
    mspid: travle.xq.com

    cryptoPath: /Users/xq_mac/Go/src/driverFabricDemo/conf/crypto-config/peerOrganizations/travle.xq.com/users/{username}@travle.xq.com/msp
    peers:
    - peer0.travle.xq.com
    - peer1.travle.xq.com

  ordererorg:
    mspID: xq.com
    cryptoPath: /Users/xq_mac/Go/src/driverFabricDemo/conf/crypto-config/ordererOrganizations/xq.com/users/Admin@xq.com/msp

orderers:
  orderer.xq.com:
    url: localhost:7050
    grpcOptions:
      ssl-target-name-override: orderer.xq.com
      keep-alive-time: 0s
      keep-alive-timeout: 20s
      keep-alive-permit: false
      fail-fast: false
      allow-insecure: false

    tlsCACerts:
      path: /Users/xq_mac/Go/src/driverFabricDemo/conf/crypto-config/ordererOrganizations/xq.com/tlsca/tlsca.xq.com-cert.pem
peers:
  peer0.travle.xq.com:
    url: grpcs://localhost:7051
    eventUrl: localhost:7053
    grpcOptions:
      ssl-target-name-override: peer0.travle.xq.com
      keep-alive-time: 0s
      keep-alive-timeout: 20s
      keep-alive-permit: false
      fail-fast: false
      allow-insecure: false
    tlsCACerts:
      path: /Users/xq_mac/Go/src/driverFabricDemo/conf/crypto-config/peerOrganizations/travle.xq.com/tlsca/tlsca.travle.xq.com-cert.pem

  peer1.travle.xq.com:
    url: grpcs://localhost:8051
    eventUrl: localhost:8053
    grpcOptions:
      ssl-target-name-override: peer1.travle.xq.com
      keep-alive-time: 0s
      keep-alive-timeout: 20s
      keep-alive-permit: false
      fail-fast: false
      allow-insecure: false
    tlsCACerts:
      path: /Users/xq_mac/Go/src/driverFabricDemo/conf/crypto-config/peerOrganizations/travle.xq.com/tlsca/tlsca.travle.xq.com-cert.pem

五. 實例化sdk

  • 5.1 在工程中定義一個模型,來維護(hù)實例化sdk所需要的變量
type FabricModel struct {
    ConfigFile  string //sdk的配置文件路徑
    ChainCodeID string // 鏈碼名稱
    ChaincodePath string  // 鏈碼在工程中的存放目錄
    ChaincodeGoPath string  // GOPATH
    OrgAdmin string // 組織的管理員用戶
    OrgName  string // config.yaml ---> organizations ---> travle
    OrgID    string // 組織id
    UserName string // 組織的普通用戶
    ChannelID string // 通道id
    ChannelConfigPath string //組織的通道文件路徑
    OrdererName string  // config.yaml ---> orderers ---> orderer.xq.com // 將組織添加到通道時候使用!
    Sdk        *fabsdk.FabricSDK // 保存實例化后的sdk
    ResMgmtCli *resmgmt.Client // 資源管理客戶端,也需要在安裝鏈碼時候的使用
    Channelclient     *channel.Client // 通道客戶端
    HasInit  bool // 是否已經(jīng)初始化了sdk
}

創(chuàng)建出一個模型對象,給其賦值,并開始初始化sdk

func init() {
    fs := FabricModel{
        OrdererName: "orderer.xq.com",
        ChannelID:     "travlechannel",
        ChannelConfigPath: os.Getenv("GOPATH") + "/src/driverFabricDemo/conf/channel-artifacts/travlechannel.tx",
        ChainCodeID:     "mycc",
        ChaincodeGoPath: os.Getenv("GOPATH"),
        ChaincodePath:   "driverFabricDemo/chaincode",
        OrgAdmin:        "Admin",
        OrgName:         "travle",
        ConfigFile:      "conf/config.yaml",
        UserName: "User1",
    }
    // 實例化SDK  創(chuàng)建通道, 將組織節(jié)點加入到通道
    fs.Initialization()
}

使用 pkg/fabsdk/fabsdk.go中的New()方法進(jìn)行實例化

sdk, err := fabsdk.New(config.FromFile(this.ConfigFile))

  • 5.2 根據(jù)實例創(chuàng)建資源管理客戶端
resCliProvider := sdk.Context(fabsdk.WithUser(this.OrgAdmin),fabsdk.WithOrg(this.OrgName))
resClient, err := resmgmt.New(resCliProvider)
  • 5.3 創(chuàng)建channel. 得到一個操作鏈代碼的客戶端
    使用pkg/client/resmgmt/resmgmt.go文件中的方法
// 先創(chuàng)建一個 創(chuàng)建channel的請求
chanReq := resmgmt.SaveChannelRequest{
        ChannelID: this.ChannelID,
        ChannelConfigPath: this.ChannelConfigPath,
}
// 利用 resClient 創(chuàng)建 channel
chanRsp, err := resClient.SaveChannel(chanReq)
  • 5.4 把組織添加到 channel 中, 一般制定一些重試的策略,和指定 orderer節(jié)點的網(wǎng)絡(luò)位置
err = resClient.JoinChannel(
        this.ChannelID,
        resmgmt.WithRetry(retry.DefaultResMgmtOpts),
        resmgmt.WithOrdererEndpoint(this.OrdererName),
)

六. 安裝鏈碼,實例化鏈碼

  • 6.1 在工程中創(chuàng)建一個chaincode文件夾,用來存在鏈碼,寫一個最簡單的鏈碼,實現(xiàn)寫入數(shù)據(jù)和讀取數(shù)據(jù)的功能
package main

import (
    "github.com/hyperledger/fabric/core/chaincode/shim"
    pb "github.com/hyperledger/fabric/protos/peer"
    "fmt"
)

type ChaincodeXQ struct {

}

func (this * ChaincodeXQ)Init(stub shim.ChaincodeStubInterface) pb.Response  {

    return shim.Success([]byte("初始化成功"))
}

func (this * ChaincodeXQ)Invoke(stub shim.ChaincodeStubInterface) pb.Response  {

    // 獲取方法和參數(shù)
    fname, params := stub.GetFunctionAndParameters()
    if fname == "set" { // 插入操作
        return set(stub,params[0],params[1])
    }else if fname == "get" { //獲取操作

        return get(stub,params[0])
    }
    return shim.Error("Invoke 操作失敗!!")
}

func set(stub shim.ChaincodeStubInterface, key string, value string) pb.Response {

    err := stub.PutState(key,[]byte(value))
    if err != nil {
        return shim.Error("PutState 操作失敗!!")
    }
    return shim.Success([]byte("PutState 操作成功!!"))
}

func get(stub shim.ChaincodeStubInterface, key string) pb.Response {

    data, err := stub.GetState(key)
    if err != nil {
        return shim.Error("GetState 操作失敗!!")
    }
    // If the key does not exist in the state database, (nil, nil) is returned.
    if data == nil {
        return shim.Error("GetState 操作失敗!!, data == nil")
    }
    return shim.Success(data)
}

func main()  {

    err := shim.Start(new(ChaincodeXQ))
    if err != nil {
        fmt.Println("開啟鏈碼失敗,err:",err)
        return
    }
    fmt.Println("開啟鏈碼成功")
}
  • 6.2 安裝鏈碼
    安裝鏈碼之前需要創(chuàng)建請求
InstallCCRequest := resmgmt.InstallCCRequest{
        Name:this.ChainCodeID, // 鏈碼名稱
        Path:this.ChaincodePath, //鏈碼在工程中的路徑
        Version:"0",
        Package:ccp,
}

創(chuàng)建請求之前,需要使用 gopackager.NewCCPackage 方法生成一個resource.CCPackage 對象,傳遞兩個參數(shù),一個是鏈碼的路徑(相對于工程的路徑), 一個是GOPATH的路徑.

ccp, err := gopackager.NewCCPackage(this.ChaincodePath,this.ChaincodeGoPath)

安裝鏈碼,使用pkg/client/resmgmt/resmgmt.go文件中的方法

req2Arr, err := this.ResMgmtCli.InstallCC(InstallCCRequest)
  • 6.3 實例化鏈碼
    實例化鏈碼之前需要創(chuàng)建請求
rsp1 := resmgmt.InstantiateCCRequest{
        Name:this.ChainCodeID,// 鏈碼名稱
        Path:this.ChaincodeGoPath,//鏈碼在工程中的路徑
        Version:"0",
        Args:nil,
        Policy:ccpolity,
}

創(chuàng)建請求之前,需要生成一個*cb.SignaturePolicyEnvelope類型的對象,使用 third_party/github.com/hyperledger/fabric/common/cauthdsl/cauthdsl_builder.go 文件中的方法即可,提供了好幾個方法, 使用任意一個即可.這里使用 SignedByAnyMember 方法: 需要傳入所屬組織ID

ccpolity := cauthdsl.SignedByAnyMember([]string{this.OrgID})

實例化鏈碼

txID,err := this.ResMgmtCli.InstantiateCC(this.ChannelID,rsp1)
  • 6.4 再創(chuàng)建一個通道的客戶端,后面的調(diào)用鏈碼需要使用這個客戶端
    使用的是 pkg/client/channel/chclient.go 中的方法
// 創(chuàng)建上下文
clientContext := this.Sdk.ChannelContext(this.ChannelID, fabsdk.WithUser(this.UserName))
// 創(chuàng)建channel客戶端
channelclient, err := channel.New(clientContext)

七. 調(diào)用鏈碼

使用 pkg/client/channel/chclient.go 中的 Execute()方法,來進(jìn)行數(shù)據(jù)寫入的操作:
rsp, err := model.Channelclient.Execute(req)
寫入之前,要創(chuàng)建請求:

req := channel.Request{
        ChaincodeID:model.ChainCodeID, // 鏈碼名稱
        Fcn:args[0], // 方法名:  get
        Args:tempArgs, // 傳遞的參數(shù),是一個二維字符切片  [[49] [49 49 49 49]]  
}

tempArgs是要傳給鏈碼的參數(shù),可以做下封裝,就不受參數(shù)個數(shù)的限制了

var tempArgs [][]byte
    for i := 1; i < len(args); i++ {
        tempArgs = append(tempArgs, []byte(args[i]))
}

使用 pkg/client/channel/chclient.go 中的 Query()方法,來進(jìn)行數(shù)據(jù)查詢的操作: 查詢之前,同樣需要創(chuàng)建請求.

req := channel.Request{
        ChaincodeID: model.ChainCodeID, 
        Fcn: args[0], 
        Args: tempArgs,
    }
rsp, err := model.Channelclient.Query(req)

遇到的問題

1 鏈碼路徑錯誤

Chaincode status Code: (500) UNKNOWN. Description: error starting container: error starting container: Failed to generate platform-specific docker build: Error returned from build: 1 "can't load package: package chaincode: cannot find package "chaincode" in any of:
        /opt/go/src/chaincode (from $GOROOT)
        /chaincode/input/src/chaincode (from $GOPATH)
        /opt/gopath/src/chaincode

鏈碼在工程中的路徑應(yīng)該是 工程名/chaincode文件夾
比如:
driverFabricDemo/chaincode
而不應(yīng)該省略掉工程名這樣寫:chaincode

2 go版本的問題

Failed to build the application: # github.com/cloudflare/cfssl/csr
../github.com/cloudflare/cfssl/csr/csr.go:272:26: cert.URIs undefined (type *x509.Certificate has no field or method URIs)
../github.com/cloudflare/cfssl/csr/csr.go:387:7: tpl.URIs undefined (type x509.CertificateRequest has no field or method URIs)

錯誤原因:cert.URIs 和 tpl.URIs 這兩個字段沒有被定義.
進(jìn)入tpl對象中,/usr/local/go/src/crypto/x509/x509.go 是個結(jié)構(gòu)體,并沒有發(fā)現(xiàn)URIs字段

對go版本進(jìn)行升級,從1.9.3升級到1.11.3, 再次進(jìn)入 /usr/local/go/src/crypto/x509/x509.go 文件中,查看結(jié)構(gòu)體內(nèi)容:

 // Subject Alternate Name values.
   DNSNames       []string
   EmailAddresses []string
   IPAddresses    []net.IP
   URIs           []*url.URL

3 寫入數(shù)據(jù)到區(qū)塊鏈時錯誤

Transaction processing for endorser [localhost:7051]: Chaincode status Code: (500) UNKNOWN. 
Description: Received unknow function invocatio

在執(zhí)行sdk的Excute()方法時報錯.
方法不存在,一般是由于鏈碼的Invoke方法中的方法名和Excute()方法傳入的方法名不一樣.
但是可以肯定的是,鏈碼的Invoke方法中的方法名和,項目中執(zhí)行Excute()方法時傳入的方法名是完全一樣的! 但是很奇怪了,為什么會出現(xiàn)這個錯誤呢? 使用docker rmi 刪除掉dev-peerx.travle.xq.com 的鏡像,再重新運行即可.

4 Cannot use str (type *cb.SignaturePolicyEnvelope) as type *common.SignaturePolicyEnvelope

在創(chuàng)建實例化鏈碼請求的時候

ccpolity := cauthdsl.SignedByAnyMember([]string{this.OrgID})
rsp1 := resmgmt.InstantiateCCRequest{
   Name:this.ChainCodeID,
   Path:this.ChaincodeGoPath,
   Version:"1.0",
   Args:nil,
   Policy:ccpolity,
}

總是提示
Cannot use str (type *cb.SignaturePolicyEnvelope) as type *common.SignaturePolicyEnvelope less... (?F1) Inspection info: Reports composite literals with incompatible types and values
明明是相同的類型,卻總是報錯,應(yīng)該是IDE的問題.把vendor文件夾刪除后,就不會有提示了. 再使用vendor對工程進(jìn)行init 和 add +external 就好了!!

5 CONNECTION_ Description: dialing connection timed out

出現(xiàn)這個錯誤,一般都是配置文件哪個地方寫錯了,需要細(xì)心檢查

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蕉鸳,更是在濱河造成了極大的恐慌鲸沮,老刑警劉巖窖维,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啦吧,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)拖吼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進(jìn)店門鳞上,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人绿贞,你說我怎么就攤上這事因块。” “怎么了籍铁?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵涡上,是天一觀的道長。 經(jīng)常有香客問我拒名,道長吩愧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任增显,我火速辦了婚禮雁佳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘同云。我一直安慰自己糖权,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布炸站。 她就那樣靜靜地躺著星澳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪旱易。 梳的紋絲不亂的頭發(fā)上禁偎,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天,我揣著相機(jī)與錄音阀坏,去河邊找鬼如暖。 笑死,一個胖子當(dāng)著我的面吹牛忌堂,可吹牛的內(nèi)容都是我干的盒至。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼士修,長吁一口氣:“原來是場噩夢啊……” “哼妄迁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起李命,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎箫老,沒想到半個月后封字,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年阔籽,在試婚紗的時候發(fā)現(xiàn)自己被綠了流妻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡笆制,死狀恐怖绅这,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情在辆,我是刑警寧澤证薇,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站匆篓,受9級特大地震影響浑度,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鸦概,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一箩张、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧窗市,春花似錦先慷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扎拣,卻和暖如春赴肚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背二蓝。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工誉券, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人刊愚。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓踊跟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鸥诽。 傳聞我的和親對象是個殘疾皇子商玫,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容