使用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ì)心檢查