搭建一个3orderer节点、4个组织,其中每个组织各2个peer节点的fabric区块链网络,前期已完成网络测试和链码调用测试(使用的官方sacc)均能成功。于是我想试试能不能将基于hyperledger fabric v2.x 的学历征信系统 的项目改为多组织架构,目前只对fixtures文件夹以及sdkInit文件夹和main.go函数里涉及到网络架构的部分进行了修改。
在配置完config.yaml,sdk部分和main.go后,go build 通过,但go启动时报错
>> 开始创建通道......
>> Create channel and join error: Create channel error: Channel management client create error: failed to create resmgmt client due to context error: invalid options to create identity, invalid org name
目录
①根据https://github.com/akkagao/citizens 提到的相同错误
1.版本
docker镜像
root@model:~/go# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hyperledger/fabric-tools latest 545af418d284 4 months ago 489MB
hyperledger/fabric-peer latest d77dd7cfbcd7 4 months ago 64.2MB
hyperledger/fabric-orderer latest 77c489caa81b 4 months ago 36.7MB
hyperledger/fabric-ccenv latest 4eb7ee7f4af5 4 months ago 520MB
hyperledger/fabric-baseos latest b20d2dde6941 4 months ago 6.82MB
hyperledger/fabric-ca latest 93f19fa873cb 8 months ago 76.5MB
portainer/portainer-ce latest 0df02179156a 15 months ago 273MB
其中fabric是2.4.7,fabric-ca是1.5.5
git
root@model:~/go# git --version
git version 2.17.1
go
root@model:~/go# go version
go version go1.18.6 linux/amd64
docker
root@model:~/go# docker version
Client: Docker Engine - Community
Version: 23.0.1
API version: 1.42
Go version: go1.19.5
Git commit: a5ee5b1
Built: Thu Feb 9 19:46:49 2023
OS/Arch: linux/amd64
Context: default
Server: Docker Engine - Community
Engine:
Version: 23.0.1
API version: 1.42 (minimum version 1.12)
Go version: go1.19.5
Git commit: bc3805a
Built: Thu Feb 9 19:46:49 2023
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.18
GitCommit: 2456e983eb9e37e47538f59ea18f2043c9a73640
runc:
Version: 1.1.4
GitCommit: v1.1.4-0-g5fd4c4d
docker-init:
Version: 0.19.0
GitCommit: de40ad0
docker-compose
root@model:~/go# docker-compose -v
docker-compose version 1.29.2, build 5becea4c
2. 解决思路
①根据https://github.com/akkagao/citizens 提到的相同错误
指的应该是下图OrgName部分
但我看我main.go的配置信息和configtx.yaml中好像是一致的,如果将main函数的orgname改成org1msp,则会报错
>> SDK setup error: non-existent organization: 'Org1MSP'
所以填org1应该是没问题的。
依据sdkSetting.go,出错位置可能在
②setup函数
中后方根据指定的资源管理客户端Context创建通道管理客户端失败
(但报的错是英文所以不一定是在这里,但我也没有在其他地方找到这句错误)
传入的是orgContext,这就是org.OrgAdminUser或者org.OrgName有错误
③ createChannel函数
依据函数内容,就是OrdererClientContext有问题,它也出现在setup函数末尾
所以应该是和↓(main.go文件的main函数)传入的OrdererAdminUser、OrdererOrgName有关
但我对照了我自己的配置文件,应该没有问题。
又或许是多组织时main函数部分获取的不只一个org,或者我的config.yaml 中client部分配置不对?
因为我之前没有完整地学过fabric,网上并不能找到完整的讲解多组织网络下sdk应用的案例,搜索错误信息也只有上面那一个例子还比较模糊,卡了好久就是一个不知所措==
3. 项目目录和代码片
我的项目目录如下
configtx.yaml文件如下
Organizations:
# SampleOrg defines an MSP using the sampleconfig. It should never be used
# in production but may be used as a template for other definitions
- &OrdererOrg
# DefaultOrg defines the organization which is used in the sampleconfig
# of the fabric.git development environment
Name: OrdererOrg
# ID to load the MSP definition as
ID: OrdererMSP
# MSPDir is the filesystem path which contains the MSP configuration
MSPDir: crypto-config/ordererOrganizations/example.com/msp
# Policies defines the set of policies at this level of the config tree
# For organization policies, their canonical path is usually
# /Channel/<Application|Orderer>/<OrgName>/<PolicyName>
Policies:
Readers:
Type: Signature
Rule: "OR('OrdererMSP.member')"
Writers:
Type: Signature
Rule: "OR('OrdererMSP.member')"
Admins:
Type: Signature
Rule: "OR('OrdererMSP.admin')"
OrdererEndpoints:
- orderer0.example.com:7050
- orderer1.example.com:8050
- orderer2.example.com:9050
- &Org1
# DefaultOrg defines the organization which is used in the sampleconfig
# of the fabric.git development environment
Name: Org1MSP
# ID to load the MSP definition as
ID: Org1MSP
MSPDir: crypto-config/peerOrganizations/org1.supervisor.com/msp
# Policies defines the set of policies at this level of the config tree
# For organization policies, their canonical path is usually
# /Channel/<Application|Orderer>/<OrgName>/<PolicyName>
Policies:
Readers:
Type: Signature
Rule: "OR('Org1MSP.admin', 'Org1MSP.peer', 'Org1MSP.client')"
Writers:
Type: Signature
Rule: "OR('Org1MSP.admin', 'Org1MSP.client')"
Admins:
Type: Signature
Rule: "OR('Org1MSP.admin')"
Endorsement:
Type: Signature
Rule: "OR('Org1MSP.peer')"
# leave this flag set to true.
AnchorPeers:
# AnchorPeers defines the location of peers which can be used
# for cross org gossip communication. Note, this value is only
# encoded in the genesis block in the Application section context
- Host: peer0.org1.supervisor.com
Port: 7051
- &Org2
# DefaultOrg defines the organization which is used in the sampleconfig
# of the fabric.git development environment
Name: Org2MSP
# ID to load the MSP definition as
ID: Org2MSP
MSPDir: crypto-config/peerOrganizations/org2.build.com/msp
# Policies defines the set of policies at this level of the config tree
# For organization policies, their canonical path is usually
# /Channel/<Application|Orderer>/<OrgName>/<PolicyName>
Policies:
Readers:
Type: Signature
Rule: "OR('Org2MSP.admin', 'Org2MSP.peer', 'Org2MSP.client')"
Writers:
Type: Signature
Rule: "OR('Org2MSP.admin', 'Org2MSP.client')"
Admins:
Type: Signature
Rule: "OR('Org2MSP.admin')"
Endorsement:
Type: Signature
Rule: "OR('Org2MSP.peer')"
AnchorPeers:
# AnchorPeers defines the location of peers which can be used
# for cross org gossip communication. Note, this value is only
# encoded in the genesis block in the Application section context
- Host: peer0.org2.build.com
Port: 9051
- &Org3
# DefaultOrg defines the organization which is used in the sampleconfig
# of the fabric.git development environment
Name: Org3MSP
# ID to load the MSP definition as
ID: Org3MSP
MSPDir: crypto-config/peerOrganizations/org3.supplier.com/msp
# Policies defines the set of policies at this level of the config tree
# For organization policies, their canonical path is usually
# /Channel/<Application|Orderer>/<OrgName>/<PolicyName>
Policies:
Readers:
Type: Signature
Rule: "OR('Org3MSP.admin', 'Org3MSP.peer', 'Org3MSP.client')"
Writers:
Type: Signature
Rule: "OR('Org3MSP.admin', 'Org3MSP.client')"
Admins:
Type: Signature
Rule: "OR('Org3MSP.admin')"
Endorsement:
Type: Signature
Rule: "OR('Org3MSP.peer')"
AnchorPeers:
# AnchorPeers defines the location of peers which can be used
# for cross org gossip communication. Note, this value is only
# encoded in the genesis block in the Application section context
- Host: peer0.org3.supplier.com
Port: 11051
- &Org4
# DefaultOrg defines the organization which is used in the sampleconfig
# of the fabric.git development environment
Name: Org4MSP
# ID to load the MSP definition as
ID: Org4MSP
MSPDir: crypto-config/peerOrganizations/org4.logistics.com/msp
# Policies defines the set of policies at this level of the config tree
# For organization policies, their canonical path is usually
# /Channel/<Application|Orderer>/<OrgName>/<PolicyName>
Policies:
Readers:
Type: Signature
Rule: "OR('Org4MSP.admin', 'Org4MSP.peer', 'Org4MSP.client')"
Writers:
Type: Signature
Rule: "OR('Org4MSP.admin', 'Org4MSP.client')"
Admins:
Type: Signature
Rule: "OR('Org4MSP.admin')"
Endorsement:
Type: Signature
Rule: "OR('Org4MSP.peer')"
AnchorPeers:
# AnchorPeers defines the location of peers which can be used
# for cross org gossip communication. Note, this value is only
# encoded in the genesis block in the Application section context
- Host: peer0.org4.logistics.com
Port: 13051
################################################################################
#
# SECTION: Capabilities
#
# - This section defines the capabilities of fabric network. This is a new
# concept as of v1.1.0 and should not be utilized in mixed networks with
# v1.0.x peers and orderers. Capabilities define features which must be
# present in a fabric binary for that binary to safely participate in the
# fabric network. For instance, if a new MSP type is added, newer binaries
# might recognize and validate the signatures from this type, while older
# binaries without this support would be unable to validate those
# transactions. This could lead to different versions of the fabric binaries
# having different world states. Instead, defining a capability for a channel
# informs those binaries without this capability that they must cease
# processing transactions until they have been upgraded. For v1.0.x if any
# capabilities are defined (including a map with all capabilities turned off)
# then the v1.0.x peer will deliberately crash.
#
################################################################################
Capabilities:
# Channel capabilities apply to both the orderers and the peers and must be
# supported by both.
# Set the value of the capability to true to require it.
Channel: &ChannelCapabilities
# V2_0 capability ensures that orderers and peers behave according
# to v2.0 channel capabilities. Orderers and peers from
# prior releases would behave in an incompatible way, and are therefore
# not able to participate in channels at v2.0 capability.
# Prior to enabling V2.0 channel capabilities, ensure that all
# orderers and peers on a channel are at v2.0.0 or later.
V2_0: true
# Orderer capabilities apply only to the orderers, and may be safely
# used with prior release peers.
# Set the value of the capability to true to require it.
Orderer: &OrdererCapabilities
# V2_0 orderer capability ensures that orderers behave according
# to v2.0 orderer capabilities. Orderers from
# prior releases would behave in an incompatible way, and are therefore
# not able to participate in channels at v2.0 orderer capability.
# Prior to enabling V2.0 orderer capabilities, ensure that all
# orderers on channel are at v2.0.0 or later.
V2_0: true
# Application capabilities apply only to the peer network, and may be safely
# used with prior release orderers.
# Set the value of the capability to true to require it.
Application: &ApplicationCapabilities
# V2_0 application capability ensures that peers behave according
# to v2.0 application capabilities. Peers from
# prior releases would behave in an incompatible way, and are therefore
# not able to participate in channels at v2.0 application capability.
# Prior to enabling V2.0 application capabilities, ensure that all
# peers on channel are at v2.0.0 or later.
V2_0: true
################################################################################
#
# SECTION: Application
#
# - This section defines the values to encode into a config transaction or
# genesis block for application related parameters
#
################################################################################
Application: &ApplicationDefaults
# Organizations is the list of orgs which are defined as participants on
# the application side of the network
Organizations:
# Policies defines the set of policies at this level of the config tree
# For Application policies, their canonical path is
# /Channel/Application/<PolicyName>
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
LifecycleEndorsement:
Type: ImplicitMeta
Rule: "MAJORITY Endorsement"
Endorsement:
Type: ImplicitMeta
Rule: "MAJORITY Endorsement"
Capabilities:
<<: *ApplicationCapabilities
################################################################################
#
# SECTION: Orderer
#
# - This section defines the values to encode into a config transaction or
# genesis block for orderer related parameters
#
################################################################################
Orderer: &OrdererDefaults
# Orderer Type: The orderer implementation to start
OrdererType: etcdraft
# Addresses used to be the list of orderer addresses that clients and peers
# could connect to. However, this does not allow clients to associate orderer
# addresses and orderer organizations which can be useful for things such
# as TLS validation. The preferred way to specify orderer addresses is now
# to include the OrdererEndpoints item in your org definition
Addresses:
- orderer0.example.com:7050
- orderer1.example.com:8050
- orderer2.example.com:9050
EtcdRaft:
Consenters:
- Host: orderer0.example.com
Port: 7050
ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
# Batch Timeout: The amount of time to wait before creating a batch
BatchTimeout: 2s
# Batch Size: Controls the number of messages batched into a block
BatchSize:
# Max Message Count: The maximum number of messages to permit in a batch
MaxMessageCount: 10
# Absolute Max Bytes: The absolute maximum number of bytes allowed for
# the serialized messages in a batch.
AbsoluteMaxBytes: 99 MB
# Preferred Max Bytes: The preferred maximum number of bytes allowed for
# the serialized messages in a batch. A message larger than the preferred
# max bytes will result in a batch larger than preferred max bytes.
PreferredMaxBytes: 512 KB
# Organizations is the list of orgs which are defined as participants on
# the orderer side of the network
Organizations:
# Policies defines the set of policies at this level of the config tree
# For Orderer policies, their canonical path is
# /Channel/Orderer/<PolicyName>
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
# BlockValidation specifies what signatures must be included in the block
# from the orderer for the peer to validate it.
BlockValidation:
Type: ImplicitMeta
Rule: "ANY Writers"
################################################################################
#
# CHANNEL
#
# This section defines the values to encode into a config transaction or
# genesis block for channel related parameters.
#
################################################################################
Channel: &ChannelDefaults
# Policies defines the set of policies at this level of the config tree
# For Channel policies, their canonical path is
# /Channel/<PolicyName>
Policies:
# Who may invoke the 'Deliver' API
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
# Who may invoke the 'Broadcast' API
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
# By default, who may modify elements at this config level
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
# Capabilities describes the channel level capabilities, see the
# dedicated Capabilities section elsewhere in this file for a full
# description
Capabilities:
<<: *ChannelCapabilities
################################################################################
#
# Profile
#
# - Different configuration profiles may be encoded here to be specified
# as parameters to the configtxgen tool
#
################################################################################
Profiles:
FourOrgsOrdererGenesis:
<<: *ChannelDefaults
Orderer:
<<: *OrdererDefaults
OrdererType: etcdraft
EtcdRaft:
Consenters:
- Host: orderer0.example.com
Port: 7050
ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/server.crt
ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/server.crt
- Host: orderer1.example.com
Port: 8050
ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/server.crt
ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/server.crt
- Host: orderer2.example.com
Port: 9050
ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt
ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt
Addresses:
- orderer0.example.com:7050
- orderer1.example.com:8050
- orderer2.example.com:9050
Organizations:
- *OrdererOrg
Capabilities:
<<: *OrdererCapabilities
Consortiums:
SampleConsortium:
Organizations:
- *Org1
- *Org2
- *Org3
- *Org4
FourOrgsChannel:
Consortium: SampleConsortium
<<: *ChannelDefaults
Application:
<<: *ApplicationDefaults
Organizations:
- *Org1
- *Org2
- *Org3
- *Org4
Capabilities:
<<: *ApplicationCapabilities
config.yaml 文件如下
name: "my-network"
version: 1.0.0
client:
organization: Org1
logging:
level: info
cryptoconfig:
path: ${GOPATH}/src/raft-test/fixtures/crypto-config
credentialStore:
path:
cryptoStore:
path:
BCCSP:
security:
enabled: true
default:
provider: "SW"
hashAlgorithm: "SHA2"
softVerify: true
level: 256
tlsCerts:
systemCertPool: false
client:
key:
path:
cert:
path:
channels:
mychannel:
peers:
peer0.org1.supervisor.com:
endorsingPeer: true
chaincodeQuery: true
ledgerQuery: true
eventSource: true
peer1.org1.supervisor.com:
endorsingPeer: true
chaincodeQuery: true
ledgerQuery: true
eventSource: true
peer0.org2.build.com:
endorsingPeer: true
chaincodeQuery: true
ledgerQuery: true
eventSource: true
peer1.org2.build.com:
endorsingPeer: true
chaincodeQuery: true
ledgerQuery: true
eventSource: true
peer0.org3.supplier.com:
endorsingPeer: true
chaincodeQuery: true
ledgerQuery: true
eventSource: true
peer1.org3.supplier.com:
endorsingPeer: true
chaincodeQuery: true
ledgerQuery: true
eventSource: true
peer0.org4.logistics.com:
endorsingPeer: true
chaincodeQuery: true
ledgerQuery: true
eventSource: true
peer1.org4.logistics.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
discovery:
maxTargets: 2
retryOpts:
attempts: 4
initialBackoff: 500ms
maxBackoff: 5s
backoffFactor: 2.0
eventService:
resolverStrategy: PreferOrg
balancer: Random
blockHeightLagThreshold: 5
reconnectBlockHeightLagThreshold: 10
peerMonitorPeriod: 5s
organizations:
Org1:
mspid: org1.supervisor.com
cryptoPath: peerOrganizations/org1.supervisor.com/users/[email protected]/msp
peers:
- peer0.org1.supervisor.com
- peer1.org1.supervisor.com
# certificateAuthorities:
# - ca.org1.supervisor.com
#因为报错SDK setup error: 根据指定的资源管理客户端Context创建通道管理客户端失败: failed to create resmgmt client due to context error: user not found
users:
Admin:
cert:
path: /root/go/src/raft-test/fixtures/crypto-config/peerOrganizations/org1.supervisor.com/users/[email protected]/msp/signcerts/A[email protected]
key:
path: /root/go/src/raft-test/fixtures/crypto-config/peerOrganizations/org1.supervisor.com/users/[email protected]/msp/keystore/priv_sk
Org2:
mspid: org2.build.com
cryptoPath: peerOrganizations/org2.build.com/users/[email protected]/msp
peers:
- peer0.org2.build.com
- peer1.org2.build.com
# certificateAuthorities:
# - ca.org2.build.com
#同上
users:
Admin:
cert:
path: /root/go/src/raft-test/fixtures/crypto-config/peerOrganizations/org2.build.com/users/[email protected]/msp/signcerts/[email protected]
key:
path: /root/go/src/raft-test/fixtures/crypto-config/peerOrganizations/org2.build.com/users/[email protected]/msp/keystore/priv_sk
Org3:
mspid: org3.supplier.com
cryptoPath: peerOrganizations/org3.supplier.com/users/[email protected]/msp
peers:
- peer0.org3.supplier.com
- peer1.org3.supplier.com
# certificateAuthorities:
# - ca.org3.supplier.com
#同上
users:
Admin:
cert:
path: /root/go/src/raft-test/fixtures/crypto-config/peerOrganizations/org3.supplier.com/users/[email protected]/msp/signcerts/[email protected]
key:
path: /root/go/src/raft-test/fixtures/crypto-config/peerOrganizations/org3.supplier.com/users/[email protected]/msp/keystore/priv_sk
Org4:
mspid: org4.logistics.com
cryptoPath: peerOrganizations/org4.logistics.com/users/[email protected]/msp
peers:
- peer0.org4.logistics.com
- peer1.org4.logistics.com
# certificateAuthorities:
# - ca.org4.logistics.com
#同上
users:
Admin:
cert:
path: /root/go/src/raft-test/fixtures/crypto-config/peerOrganizations/org4.logistics.com/users/[email protected]/msp/signcerts/[email protected]
key:
path: /root/go/src/raft-test/fixtures/crypto-config/peerOrganizations/org4.logistics.com/users/[email protected]/msp/keystore/priv_sk
orderers:
orderer0.example.com:
url: localhost:7050
grpcOptions:
ssl-target-name-override: orderer0.example.com
keep-alive-time: 0s
keep-alive-timeout: 20s
keep-alive-permit: false
fail-fast: false
allow-insecure: false
tlsCACerts:
path: ${GOPATH}/src/raft-test/fixtures/crypto-config/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem
orderer1.example.com:
url: localhost:8050
grpcOptions:
ssl-target-name-override: orderer1.example.com
keep-alive-time: 0s
keep-alive-timeout: 20s
keep-alive-permit: false
fail-fast: false
allow-insecure: false
tlsCACerts:
path: ${GOPATH}/src/raft-test/fixtures/crypto-config/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem
orderer2.example.com:
url: localhost:9050
grpcOptions:
ssl-target-name-override: orderer2.example.com
keep-alive-time: 0s
keep-alive-timeout: 20s
keep-alive-permit: false
fail-fast: false
allow-insecure: false
tlsCACerts:
path: ${GOPATH}/src/raft-test/fixtures/crypto-config/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem
peers:
#org1
peer0.org1.supervisor.com:
url: localhost:7051
eventUrl: localhost:7051
grpcOptions:
ssl-target-name-override: peer0.org1.supervisor.com
keep-alive-time: 0s
keep-alive-timeout: 20s
keep-alive-permit: false
fail-fast: false
allow-insecure: false
tlsCACerts:
path: ${GOPATH}/src/raft-test/fixtures/crypto-config/peerOrganizations/org1.supervisor.com/tlsca/tlsca.org1.supervisor.com-cert.pem
peer1.org1.supervisor.com:
url: localhost:8051
eventUrl: localhost:8051
grpcOptions:
ssl-target-name-override: peer1.org1.supervisor.com
keep-alive-time: 0s
keep-alive-timeout: 20s
keep-alive-permit: false
fail-fast: false
allow-insecure: false
tlsCACerts:
path: ${GOPATH}/src/raft-test/fixtures/crypto-config/peerOrganizations/org1.supervisor.com/tlsca/tlsca.org1.supervisor.com-cert.pem
#org2
peer0.org1.supervisor.com:
url: localhost:9051
eventUrl: localhost:9051
grpcOptions:
ssl-target-name-override: peer0.org2.build.com
keep-alive-time: 0s
keep-alive-timeout: 20s
keep-alive-permit: false
fail-fast: false
allow-insecure: false
tlsCACerts:
path: ${GOPATH}/src/raft-test/fixtures/crypto-config/peerOrganizations/org2.build.com/tlsca/tlsca.org2.build.com-cert.pem
peer1.org1.supervisor.com:
url: localhost:10051
eventUrl: localhost:10051
grpcOptions:
ssl-target-name-override: peer1.org2.build.com
keep-alive-time: 0s
keep-alive-timeout: 20s
keep-alive-permit: false
fail-fast: false
allow-insecure: false
tlsCACerts:
path: ${GOPATH}/src/raft-test/fixtures/crypto-config/peerOrganizations/org2.build.com/tlsca/tlsca.org2.build.com-cert.pem
#org3
peer0.org1.supervisor.com:
url: localhost:11051
eventUrl: localhost:11051
grpcOptions:
ssl-target-name-override: peer0.org3.supplier.com
keep-alive-time: 0s
keep-alive-timeout: 20s
keep-alive-permit: false
fail-fast: false
allow-insecure: false
tlsCACerts:
path: ${GOPATH}/src/raft-test/fixtures/crypto-config/peerOrganizations/org3.supplier.com/tlsca/tlsca.org3.supplier.com-cert.pem
peer1.org1.supervisor.com:
url: localhost:12051
eventUrl: localhost:12051
grpcOptions:
ssl-target-name-override: peer1.org3.supplier.com
keep-alive-time: 0s
keep-alive-timeout: 20s
keep-alive-permit: false
fail-fast: false
allow-insecure: false
tlsCACerts:
path: ${GOPATH}/src/raft-test/fixtures/crypto-config/peerOrganizations/org3.supplier.com/tlsca/tlsca.org3.supplier.com-cert.pem
#org4
peer0.org1.supervisor.com:
url: localhost:13051
eventUrl: localhost:13051
grpcOptions:
ssl-target-name-override: peer0.org4.logistics.com
keep-alive-time: 0s
keep-alive-timeout: 20s
keep-alive-permit: false
fail-fast: false
allow-insecure: false
tlsCACerts:
path: ${GOPATH}/src/raft-test/fixtures/crypto-config/peerOrganizations/org4.logistics.com/tlsca/tlsca.org4.logistics.com-cert.pem
peer1.org1.supervisor.com:
url: localhost:14051
eventUrl: localhost:14051
grpcOptions:
ssl-target-name-override: peer1.org4.logistics.com
keep-alive-time: 0s
keep-alive-timeout: 20s
keep-alive-permit: false
fail-fast: false
allow-insecure: false
tlsCACerts:
path: ${GOPATH}/src/raft-test/fixtures/crypto-config/peerOrganizations/org4.logistics.com/tlsca/tlsca.org4.logistics.com-cert.pem
# certificateAuthorities:
# ca.org1.kevin.kongyixueyuan.com:
# url: http://localhost:7054
# tlsCACerts:
# path: ${GOPATH}/src/github.com/kongyixueyuan.com/education/fixtures/crypto-config/peerOrganizations/org1.kevin.kongyixueyuan.com/ca/ca.org1.kevin.kongyixueyuan.com-cert.pem
# registrar:
# enrollId: admin
# enrollSecret: adminpw
# caName: ca.org1.kevin.kongyixueyuan.com
entityMatchers:
peer:
#org1
- pattern: (\w*)peer0.org1.supervisor.com(\w*)
urlSubstitutionExp: localhost:7051
eventUrlSubstitutionExp: localhost:7051
sslTargetOverrideUrlSubstitutionExp: peer0.org1.supervisor.com
mappedHost: peer0.org1.supervisor.com
- pattern: (\w*)peer1.org1.supervisor.com(\w*)
urlSubstitutionExp: localhost:8051
eventUrlSubstitutionExp: localhost:8051
sslTargetOverrideUrlSubstitutionExp: peer1.org1.supervisor.com
mappedHost: peer1.org1.supervisor.com
#org2
- pattern: (\w*)peer0.org2.build.com(\w*)
urlSubstitutionExp: localhost:9051
eventUrlSubstitutionExp: localhost:9051
sslTargetOverrideUrlSubstitutionExp: peer0.org2.build.com
mappedHost: peer0.org2.build.com
- pattern: (\w*)peer1.org2.build.com(\w*)
urlSubstitutionExp: localhost:10051
eventUrlSubstitutionExp: localhost:10051
sslTargetOverrideUrlSubstitutionExp: peer1.org2.build.com
mappedHost: peer1.org2.build.com
#org3
- pattern: (\w*)peer0.org3.supplier.com(\w*)
urlSubstitutionExp: localhost:11051
eventUrlSubstitutionExp: localhost:11051
sslTargetOverrideUrlSubstitutionExp: peer0.org3.supplier.com
mappedHost: peer0.org3.supplier.com
- pattern: (\w*)peer1.org3.supplier.com(\w*)
urlSubstitutionExp: localhost:12051
eventUrlSubstitutionExp: localhost:12051
sslTargetOverrideUrlSubstitutionExp: peer1.org3.supplier.com
mappedHost: peer1.org3.supplier.com
#org4
- pattern: (\w*)peer0.org4.logistics.com(\w*)
urlSubstitutionExp: localhost:13051
eventUrlSubstitutionExp: localhost:13051
sslTargetOverrideUrlSubstitutionExp: peer0.org4.logistics.com
mappedHost: peer0.org4.logistics.com
- pattern: (\w*)peer1.org4.logistics.com(\w*)
urlSubstitutionExp: localhost:14051
eventUrlSubstitutionExp: localhost:14051
sslTargetOverrideUrlSubstitutionExp: peer1.org4.logistics.com
mappedHost: peer1.org4.logistics.com
orderer:
- pattern: (\w*)orderer0.example.com(\w*)
urlSubstitutionExp: localhost:7050
sslTargetOverrideUrlSubstitutionExp: orderer0.example.com
mappedHost: orderer0.example.com
- pattern: (\w*)orderer1.example.com(\w*)
urlSubstitutionExp: localhost:8050
sslTargetOverrideUrlSubstitutionExp: orderer1.example.com
mappedHost: orderer1.example.com
- pattern: (\w*)orderer2.example.com(\w*)
urlSubstitutionExp: localhost:9050
sslTargetOverrideUrlSubstitutionExp: orderer2.example.com
mappedHost: orderer2.example.com
sdkInfo.go 文件如下
package sdkInit
import (
mspclient "github.com/hyperledger/fabric-sdk-go/pkg/client/msp"
"github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt"
contextAPI "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context"
)
type OrgInfo struct {
OrgAdminUser string // like "Admin"
OrgName string // like "Org1"
OrgMspId string // like "Org1MSP"
OrgUser string // like "User1"
orgMspClient *mspclient.Client
OrgAdminClientContext *contextAPI.ClientProvider
OrgResMgmt *resmgmt.Client
OrgPeerNum int
//Peers []*fab.Peer
OrgAnchorFile string // like ./channel-artifacts/Org2MSPanchors.tx
}
type SdkEnvInfo struct {
// 通道信息
ChannelID string // like "simplecc"
ChannelConfig string // like os.Getenv("GOPATH") + "/src/github.com/hyperledger/fabric-samples/test-network/channel-artifacts/testchannel.tx"
// 组织信息
Orgs []*OrgInfo
// 排序服务节点信息
OrdererAdminUser string // like "Admin"
OrdererOrgName string // like "OrdererOrg"
OrdererEndpoint string
OrdererClientContext *contextAPI.ClientProvider
// 链码信息
ChaincodeID string
ChaincodeGoPath string
ChaincodePath string
ChaincodeVersion string
}
sdkSetting.go文件如下
package sdkInit
import (
"fmt"
mb "github.com/hyperledger/fabric-protos-go/msp"
pb "github.com/hyperledger/fabric-protos-go/peer"
"github.com/hyperledger/fabric-sdk-go/pkg/client/channel"
mspclient "github.com/hyperledger/fabric-sdk-go/pkg/client/msp"
"github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt"
"github.com/hyperledger/fabric-sdk-go/pkg/common/errors/retry"
"github.com/hyperledger/fabric-sdk-go/pkg/common/errors/status"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp"
"github.com/hyperledger/fabric-sdk-go/pkg/core/config"
lcpackager "github.com/hyperledger/fabric-sdk-go/pkg/fab/ccpackager/lifecycle"
"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/common/policydsl"
"strings"
)
func Setup(configFile string, info *SdkEnvInfo) (*fabsdk.FabricSDK, error) {
// Create SDK setup for the integration tests
var err error
sdk, err := fabsdk.New(config.FromFile(configFile))
if err != nil {
return nil, err
}
// 为组织获得Client句柄和Context信息
for _, org := range info.Orgs {
org.orgMspClient, err = mspclient.New(sdk.Context(), mspclient.WithOrg(org.OrgName))
if err != nil {
return nil, err
}
orgContext := sdk.Context(fabsdk.WithUser(org.OrgAdminUser), fabsdk.WithOrg(org.OrgName))
org.OrgAdminClientContext = &orgContext
// New returns a resource management client instance.
resMgmtClient, err := resmgmt.New(orgContext)
if err != nil {
return nil, fmt.Errorf("根据指定的资源管理客户端Context创建通道管理客户端失败: %v", err)
}
org.OrgResMgmt = resMgmtClient
}
// 为Orderer获得Context信息
ordererClientContext := sdk.Context(fabsdk.WithUser(info.OrdererAdminUser), fabsdk.WithOrg(info.OrdererOrgName))
info.OrdererClientContext = &ordererClientContext
return sdk, nil
}
func CreateAndJoinChannel(info *SdkEnvInfo) error {
fmt.Println(">> 开始创建通道......")
if len(info.Orgs) == 0 {
return fmt.Errorf("通道组织不能为空,请提供组织信息")
}
// 获得所有组织的签名信息
signIds := []msp.SigningIdentity{}
for _, org := range info.Orgs {
// Get signing identity that is used to sign create channel request
orgSignId, err := org.orgMspClient.GetSigningIdentity(org.OrgAdminUser)
if err != nil {
return fmt.Errorf("GetSigningIdentity error: %v", err)
}
signIds = append(signIds, orgSignId)
}
// 创建通道
if err := createChannel(signIds, info); err != nil {
return fmt.Errorf("Create channel error: %v", err)
}
fmt.Println(">> 创建通道成功")
fmt.Println(">> 加入通道......")
for _, org := range info.Orgs {
// 加入通道
// Org peers join channel
if err := org.OrgResMgmt.JoinChannel(info.ChannelID, resmgmt.WithRetry(retry.DefaultResMgmtOpts), resmgmt.WithOrdererEndpoint("orderer.example.com")); err != nil {
return fmt.Errorf("%s peers failed to JoinChannel: %v", org.OrgName, err)
}
}
fmt.Println(">> 加入通道成功")
return nil
}
func createChannel(signIDs []msp.SigningIdentity, info *SdkEnvInfo) error {
// Channel management client is responsible for managing channels (create/update channel)
chMgmtClient, err := resmgmt.New(*info.OrdererClientContext)
if err != nil {
return fmt.Errorf("Channel management client create error: %v", err)
}
// create a channel for orgchannel.tx
req := resmgmt.SaveChannelRequest{ChannelID: info.ChannelID,
ChannelConfigPath: info.ChannelConfig,
SigningIdentities: signIDs}
if _, err := chMgmtClient.SaveChannel(req, resmgmt.WithRetry(retry.DefaultResMgmtOpts), resmgmt.WithOrdererEndpoint("orderer.example.com")); err != nil {
return fmt.Errorf("error should be nil for SaveChannel of orgchannel: %v", err)
}
fmt.Println(">>>> 使用每个org的管理员身份更新锚节点配置...")
//do the same get ch client and create channel for each anchor peer as well (first for Org1MSP)
for i, org := range info.Orgs {
req = resmgmt.SaveChannelRequest{ChannelID: info.ChannelID,
ChannelConfigPath: org.OrgAnchorFile,
SigningIdentities: []msp.SigningIdentity{signIDs[i]}}
if _, err = org.OrgResMgmt.SaveChannel(req, resmgmt.WithRetry(retry.DefaultResMgmtOpts), resmgmt.WithOrdererEndpoint("orderer.example.com")); err != nil {
return fmt.Errorf("SaveChannel for anchor org %s error: %v", org.OrgName, err)
}
}
fmt.Println(">>>> 使用每个org的管理员身份更新锚节点配置完成")
//integration.WaitForOrdererConfigUpdate(t, configQueryClient, mc.channelID, false, lastConfigBlock)
return nil
}
func CreateCCLifecycle(info *SdkEnvInfo, sequence int64, upgrade bool, sdk *fabsdk.FabricSDK) error {
if len(info.Orgs) == 0 {
return fmt.Errorf("the number of organization should not be zero.")
}
// Package cc
fmt.Println(">> 开始打包链码......")
label, ccPkg, err := packageCC(info.ChaincodeID, info.ChaincodeVersion, info.ChaincodePath)
if err != nil {
return fmt.Errorf("pakcagecc error: %v", err)
}
packageID := lcpackager.ComputePackageID(label, ccPkg)
fmt.Println(">> 打包链码成功")
// Install cc
fmt.Println(">> 开始安装链码......")
if err := installCC(label, ccPkg, info.Orgs); err != nil {
return fmt.Errorf("installCC error: %v", err)
}
// Get installed cc package
if err := getInstalledCCPackage(packageID, info.Orgs[0]); err != nil {
return fmt.Errorf("getInstalledCCPackage error: %v", err)
}
// Query installed cc
if err := queryInstalled(packageID, info.Orgs[0]); err != nil {
return fmt.Errorf("queryInstalled error: %v", err)
}
fmt.Println(">> 安装链码成功")
// Approve cc
fmt.Println(">> 组织认可智能合约定义......")
if err := approveCC(packageID, info.ChaincodeID, info.ChaincodeVersion, sequence, info.ChannelID, info.Orgs, info.OrdererEndpoint); err != nil {
return fmt.Errorf("approveCC error: %v", err)
}
// Query approve cc
if err:=queryApprovedCC(info.ChaincodeID, sequence, info.ChannelID, info.Orgs);err!=nil{
return fmt.Errorf("queryApprovedCC error: %v", err)
}
fmt.Println(">> 组织认可智能合约定义完成")
// Check commit readiness
fmt.Println(">> 检查智能合约是否就绪......")
if err:=checkCCCommitReadiness(packageID, info.ChaincodeID, info.ChaincodeVersion, sequence, info.ChannelID, info.Orgs); err!=nil{
return fmt.Errorf("checkCCCommitReadiness error: %v", err)
}
fmt.Println(">> 智能合约已经就绪")
// Commit cc
fmt.Println(">> 提交智能合约定义......")
if err:=commitCC(info.ChaincodeID, info.ChaincodeVersion, sequence, info.ChannelID, info.Orgs, info.OrdererEndpoint);err!=nil{
return fmt.Errorf("commitCC error: %v", err)
}
// Query committed cc
if err:=queryCommittedCC(info.ChaincodeID, info.ChannelID, sequence, info.Orgs); err!=nil{
return fmt.Errorf("queryCommittedCC error: %v", err)
}
fmt.Println(">> 智能合约定义提交完成")
// Init cc
fmt.Println(">> 调用智能合约初始化方法......")
if err:=initCC(info.ChaincodeID, upgrade, info.ChannelID, info.Orgs[0], sdk); err!=nil{
return fmt.Errorf("initCC error: %v", err)
}
fmt.Println(">> 完成智能合约初始化")
return nil
}
func packageCC(ccName, ccVersion, ccpath string) (string, []byte, error) {
label := ccName + "_" + ccVersion
desc := &lcpackager.Descriptor{
Path: ccpath,
Type: pb.ChaincodeSpec_GOLANG,
Label: label,
}
ccPkg, err := lcpackager.NewCCPackage(desc)
if err != nil {
return "", nil, fmt.Errorf("Package chaincode source error: %v", err)
}
return desc.Label, ccPkg, nil
}
func installCC(label string, ccPkg []byte, orgs []*OrgInfo) error {
installCCReq := resmgmt.LifecycleInstallCCRequest{
Label: label,
Package: ccPkg,
}
packageID := lcpackager.ComputePackageID(installCCReq.Label, installCCReq.Package)
for _, org := range orgs {
orgPeers, err := DiscoverLocalPeers(*org.OrgAdminClientContext, org.OrgPeerNum)
if err != nil {
fmt.Errorf("DiscoverLocalPeers error: %v", err)
}
if flag, _ := checkInstalled(packageID, orgPeers[0], org.OrgResMgmt); flag == false {
if _, err := org.OrgResMgmt.LifecycleInstallCC(installCCReq, resmgmt.WithTargets(orgPeers...), resmgmt.WithRetry(retry.DefaultResMgmtOpts)); err != nil {
return fmt.Errorf("LifecycleInstallCC error: %v", err)
}
}
}
return nil
}
func getInstalledCCPackage(packageID string, org *OrgInfo) error {
// use org1
orgPeers, err := DiscoverLocalPeers(*org.OrgAdminClientContext, 1)
if err != nil {
return fmt.Errorf("DiscoverLocalPeers error: %v", err)
}
if _, err := org.OrgResMgmt.LifecycleGetInstalledCCPackage(packageID, resmgmt.WithTargets([]fab.Peer{orgPeers[0]}...)); err != nil {
return fmt.Errorf("LifecycleGetInstalledCCPackage error: %v", err)
}
return nil
}
func queryInstalled(packageID string, org *OrgInfo) error {
orgPeers, err := DiscoverLocalPeers(*org.OrgAdminClientContext, 1)
if err != nil {
return fmt.Errorf("DiscoverLocalPeers error: %v", err)
}
resp1, err := org.OrgResMgmt.LifecycleQueryInstalledCC(resmgmt.WithTargets([]fab.Peer{orgPeers[0]}...))
if err != nil {
return fmt.Errorf("LifecycleQueryInstalledCC error: %v", err)
}
packageID1 := ""
for _, t := range resp1 {
if t.PackageID == packageID {
packageID1 = t.PackageID
}
}
if !strings.EqualFold(packageID, packageID1) {
return fmt.Errorf("check package id error")
}
return nil
}
func checkInstalled(packageID string, peer fab.Peer, client *resmgmt.Client) (bool, error) {
flag := false
resp1, err := client.LifecycleQueryInstalledCC(resmgmt.WithTargets(peer))
if err != nil {
return flag, fmt.Errorf("LifecycleQueryInstalledCC error: %v", err)
}
for _, t := range resp1 {
if t.PackageID == packageID {
flag = true
}
}
return flag, nil
}
func approveCC(packageID string, ccName, ccVersion string, sequence int64, channelID string, orgs []*OrgInfo, ordererEndpoint string) error {
mspIDs := []string{}
for _, org := range orgs {
mspIDs = append(mspIDs, org.OrgMspId)
}
ccPolicy := policydsl.SignedByNOutOfGivenRole(int32(len(mspIDs)), mb.MSPRole_MEMBER, mspIDs)
approveCCReq := resmgmt.LifecycleApproveCCRequest{
Name: ccName,
Version: ccVersion,
PackageID: packageID,
Sequence: sequence,
EndorsementPlugin: "escc",
ValidationPlugin: "vscc",
SignaturePolicy: ccPolicy,
InitRequired: true,
}
for _, org := range orgs{
orgPeers, err := DiscoverLocalPeers(*org.OrgAdminClientContext, org.OrgPeerNum)
fmt.Printf(">>> chaincode approved by %s peers:\n", org.OrgName)
for _, p := range orgPeers {
fmt.Printf(" %s\n", p.URL())
}
if err!=nil{
return fmt.Errorf("DiscoverLocalPeers error: %v", err)
}
if _, err := org.OrgResMgmt.LifecycleApproveCC(channelID, approveCCReq, resmgmt.WithTargets(orgPeers...), resmgmt.WithOrdererEndpoint(ordererEndpoint), resmgmt.WithRetry(retry.DefaultResMgmtOpts));err != nil {
fmt.Errorf("LifecycleApproveCC error: %v", err)
}
}
return nil
}
func queryApprovedCC(ccName string, sequence int64, channelID string, orgs []*OrgInfo) error {
queryApprovedCCReq := resmgmt.LifecycleQueryApprovedCCRequest{
Name: ccName,
Sequence: sequence,
}
for _, org := range orgs{
orgPeers, err := DiscoverLocalPeers(*org.OrgAdminClientContext, org.OrgPeerNum)
if err!=nil{
return fmt.Errorf("DiscoverLocalPeers error: %v", err)
}
// Query approve cc
for _, p := range orgPeers {
resp, err := retry.NewInvoker(retry.New(retry.TestRetryOpts)).Invoke(
func() (interface{}, error) {
resp1, err := org.OrgResMgmt.LifecycleQueryApprovedCC(channelID, queryApprovedCCReq, resmgmt.WithTargets(p))
if err != nil {
return nil, status.New(status.TestStatus, status.GenericTransient.ToInt32(), fmt.Sprintf("LifecycleQueryApprovedCC returned error: %v", err), nil)
}
return resp1, err
},
)
if err != nil {
return fmt.Errorf("Org %s Peer %s NewInvoker error: %v", org.OrgName, p.URL(), err)
}
if resp==nil{
return fmt.Errorf("Org %s Peer %s Got nil invoker", org.OrgName, p.URL())
}
}
}
return nil
}
func checkCCCommitReadiness(packageID string, ccName, ccVersion string, sequence int64, channelID string, orgs []*OrgInfo) error {
mspIds := []string{}
for _, org := range orgs {
mspIds = append(mspIds, org.OrgMspId)
}
ccPolicy := policydsl.SignedByNOutOfGivenRole(int32(len(mspIds)), mb.MSPRole_MEMBER, mspIds)
req := resmgmt.LifecycleCheckCCCommitReadinessRequest{
Name: ccName,
Version: ccVersion,
//PackageID: packageID,
EndorsementPlugin: "escc",
ValidationPlugin: "vscc",
SignaturePolicy: ccPolicy,
Sequence: sequence,
InitRequired: true,
}
for _, org := range orgs{
orgPeers, err := DiscoverLocalPeers(*org.OrgAdminClientContext, org.OrgPeerNum)
if err!=nil{
fmt.Errorf("DiscoverLocalPeers error: %v", err)
}
for _, p := range orgPeers {
resp, err := retry.NewInvoker(retry.New(retry.TestRetryOpts)).Invoke(
func() (interface{}, error) {
resp1, err := org.OrgResMgmt.LifecycleCheckCCCommitReadiness(channelID, req, resmgmt.WithTargets(p))
fmt.Printf("LifecycleCheckCCCommitReadiness cc = %v, = %v\n", ccName, resp1)
if err != nil {
return nil, status.New(status.TestStatus, status.GenericTransient.ToInt32(), fmt.Sprintf("LifecycleCheckCCCommitReadiness returned error: %v", err), nil)
}
flag := true
for _, r := range resp1.Approvals {
flag = flag && r
}
if !flag {
return nil, status.New(status.TestStatus, status.GenericTransient.ToInt32(), fmt.Sprintf("LifecycleCheckCCCommitReadiness returned : %v", resp1), nil)
}
return resp1, err
},
)
if err != nil {
return fmt.Errorf("NewInvoker error: %v", err)
}
if resp==nil{
return fmt.Errorf("Got nill invoker response")
}
}
}
return nil
}
func commitCC(ccName, ccVersion string, sequence int64, channelID string, orgs []*OrgInfo, ordererEndpoint string) error{
mspIDs := []string{}
for _, org := range orgs {
mspIDs = append(mspIDs, org.OrgMspId)
}
ccPolicy := policydsl.SignedByNOutOfGivenRole(int32(len(mspIDs)), mb.MSPRole_MEMBER, mspIDs)
req := resmgmt.LifecycleCommitCCRequest{
Name: ccName,
Version: ccVersion,
Sequence: sequence,
EndorsementPlugin: "escc",
ValidationPlugin: "vscc",
SignaturePolicy: ccPolicy,
InitRequired: true,
}
_, err := orgs[0].OrgResMgmt.LifecycleCommitCC(channelID, req, resmgmt.WithOrdererEndpoint(ordererEndpoint), resmgmt.WithRetry(retry.DefaultResMgmtOpts))
if err != nil {
return fmt.Errorf("LifecycleCommitCC error: %v", err)
}
return nil
}
func queryCommittedCC( ccName string, channelID string, sequence int64, orgs []*OrgInfo) error {
req := resmgmt.LifecycleQueryCommittedCCRequest{
Name: ccName,
}
for _, org := range orgs {
orgPeers, err := DiscoverLocalPeers(*org.OrgAdminClientContext, org.OrgPeerNum)
if err!=nil{
return fmt.Errorf("DiscoverLocalPeers error: %v", err)
}
for _, p := range orgPeers {
resp, err := retry.NewInvoker(retry.New(retry.TestRetryOpts)).Invoke(
func() (interface{}, error) {
resp1, err := org.OrgResMgmt.LifecycleQueryCommittedCC(channelID, req, resmgmt.WithTargets(p))
if err != nil {
return nil, status.New(status.TestStatus, status.GenericTransient.ToInt32(), fmt.Sprintf("LifecycleQueryCommittedCC returned error: %v", err), nil)
}
flag := false
for _, r := range resp1 {
if r.Name == ccName && r.Sequence == sequence {
flag = true
break
}
}
if !flag {
return nil, status.New(status.TestStatus, status.GenericTransient.ToInt32(), fmt.Sprintf("LifecycleQueryCommittedCC returned : %v", resp1), nil)
}
return resp1, err
},
)
if err != nil {
return fmt.Errorf("NewInvoker error: %v", err)
}
if resp==nil{
return fmt.Errorf("Got nil invoker response")
}
}
}
return nil
}
func initCC(ccName string, upgrade bool, channelID string, org *OrgInfo, sdk *fabsdk.FabricSDK) error {
//prepare channel client context using client context
clientChannelContext := sdk.ChannelContext(channelID, fabsdk.WithUser(org.OrgUser), fabsdk.WithOrg(org.OrgName))
// Channel client is used to query and execute transactions (Org1 is default org)
client, err := channel.New(clientChannelContext)
if err != nil {
return fmt.Errorf("Failed to create new channel client: %s", err)
}
// init
_, err = client.Execute(channel.Request{ChaincodeID: ccName, Fcn: "init", Args: nil, IsInit: true},
channel.WithRetry(retry.DefaultChannelOpts))
if err != nil {
return fmt.Errorf("Failed to init: %s", err)
}
return nil
}