伴着随前段时间 NFT 的大火,Alan结合公司发展阶段计划对区块链进行一定程序的研究,虽然区块链早已不是什么新技术,但对我而言目前仍是研究的初级阶段,因此理解并不深刻,同时这里所说的区块链并不涉及加密货币的应用,所以比特币、狗狗币以及其它以太坊技术延展出来的各类加密货币均不在研究范畴内。
据了解当前国内区块链技术的应用主要有两大阵营:一类是基于以太坊技术,比较有规模的是微众银行所开源的fisco-bcos,其完整性已经非常高,通过 WeBASE几乎可一键部署测试环境,其中以太坊的交易机制如gas以及solidity语言编写智能合约的方式都有保留,并且还结合国情加入了对国密的支持。以太坊的创始人江湖人称V神也是个传奇人物了,Alan 计划会单独写一篇文章进行研究。另一类自然是本文的主角 Hyperledger,包含很多项目(当前共16个),Fabric是其中最为知名的。蚂蚁区块链的底层就是 Hyperledger,而微众银行自然属于腾讯系,很有意思,阿里、腾讯在区块链的应用上选择了不同的路径。
No | Hyperledger Projects | Project Type | Status* | |||
---|---|---|---|---|---|---|
Distributed Ledger | Libraries | Tools | Domain Specific | |||
1 | Hyperledger Indy | X | Active | |||
2 | Hyperledger Fabric | X | Active | |||
3 | Hyperledger Aries | X | Active | |||
4 | Hyperledger Iroha | X | Active | |||
5 | Hyperledger Sawtooth | X | Active | |||
6 | Hyperledger Besu | X | Active | |||
7 | Hyperledger Quilt | X | Incubation | |||
8 | Hyperledger Ursa | X | Incubation | |||
9 | Hyperledger Transact | X | Incubation | |||
10 | Hyperledger Cactus | X | Incubation | |||
11 | Hyperledger Caliper | X | Incubation | |||
12 | Hyperledger Cello | X | Incubation | |||
13 | Hyperledger Explorer | X | Incubation | |||
14 | Hyperledger Grid | X | Incubation | |||
15 | Hyperledger Burrow | X | Incubation | |||
16 | Hyperledger Avalon | X | Incubation |
在技术上不论是Fabric还是fisco-bcos 都支持主流语言,Fabric采用Go语言进行开发,不过不涉及底层区别应该不大,而 fisco-bcos 基于 JAVA 语言,对JAVA的支持应该是更为完备的。
区块链的4代划分
采译自Hands-On Smart Contract Development with Hyperledger Fabric V2一书
区块链1.0
初代区块链伴随着比特币类的加密货币出现在大众的视野。区块链技术扮演的角色是通过允许人们依靠加密技术来代替银行发送交易,从而改善已有货币体系。在这代区块链里,网络是端到端、去中心化、匿名并且透明的。但主要的缺点是它使用的工作量证明(PoW)需要进行大量的挖矿。
区块链2.0
区块链技术在2015年出现了一次拐点,这时技术创新者开始探索其货币交易之外的去信任化(trustless)特性。此时以太坊(Ethereum)平台的创建带来了两大创新:
- 加密货币之外其它数字资产的应用,成为其它去中心化项目的基石
- 智能合约的出现,自动化链上所有成员的交易处理时,通过自动化控制所有成员所有条件的执行,增加了安全性。
区块链3.0
第三代区块链在其前辈的基础上,聚焦于改善它们的缺陷和不足,而又扩展了它们的使用场景。例如,工作量证明共识机制换成了权益证明(Proof-of-Stake)。增了其它特性和功能来提升区块链的性能并让其在不同的产业中可实施。例如,发明了联盟链或跨链交易处理这样的区块链架构。类似地,也引入了其它的变化,有法规的遵守和治理,隐私和智能合约。
区块链4.0
当前对第四化区块链技术的具体特性或方向上专家们尚未达成一致。有些人认为会加入一些新兴的技术,如 IoT或AI,另一部分人认为只需紧随前几代的步伐,提升其功能并让其更高效、可扩展及对更贴近大众即可。
Hyperledger9大区块链组件
- 共识层Consensus Layer:Raft
- 智能合约层Smart Contract Layer
- 通讯层Communication Layer
- 数据存储抽象层Data Store Abstraction:CouchDB(支持更多功能)、LevelDB(默认)
- 加密抽象层Crypto Abstraction
- 身份服务Identity Service
- 政策服务Policy Service
- API
- 跨链操作Interoperation
安装
环境准备
1 2 3 4 5 6 7 8 |
# Go 语言(暂不建议安装1.16) wget https://golang.google.cn/dl/go1.15.11.linux-amd64.tar.gz sudo tar -C /usr/local -xzf go1.15.11.linux-amd64.tar.gz # 环境变量 export PATH=$PATH:/usr/local/go/bin # 国内加速 go env -w GO111MODULE=on go env -w GOPROXY=https://goproxy.cn,direct |
安装Fabric(v2)
使用Fabric测试网络
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# curl -sSL https://bit.ly/2ysbOFE | bash -s curl -sSL https://raw.githubusercontent.com/hyperledger/fabric/master/scripts/bootstrap.sh | bash -s export PATH=<下载路径>/bin:$PATH # 也可 cp bin/* /usr/local/bin/ # 启动测试网络 docker pull hyperledger/fabric-tools:2.3 docker tag hyperledger/fabric-tools:2.3 hyperledger/fabric-tools:latest cd fabric-samples/test-network/ ./network.sh up # ./network.sh up -ca # 创建通道,-c可指定名称 ./network.sh createChannel # 部署链码 cd ../asset-transfer-basic/chaincode-go/ go mod vendor cd ../../test-network/ ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go # 与测试网络交互 # 添加环境变量 export PATH=${PWD}/../bin:$PATH export FABRIC_CFG_PATH=$PWD/../config/ # org1的环境变量 export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp export CORE_PEER_ADDRESS=localhost:7051 # 初始化账本 peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls \ --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \ -C mychannel -n basic --peerAddresses localhost:7051 \ --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \ --peerAddresses localhost:9051 \ --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \ -c '{"function":"InitLedger","Args":[]}' # 查询 peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}' # 链码调用 peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls \ --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \ -C mychannel -n basic --peerAddresses localhost:7051 \ --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \ --peerAddresses localhost:9051 \ --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \ -c '{"function":"TransferAsset","Args":["asset6","Christopher"]}' # Org2的环境变量 export CORE_PEER_TLS_ENABLED=true export CORE_PEER_LOCALMSPID="Org2MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp export CORE_PEER_ADDRESS=localhost:9051 # 在Org2上查询链码 peer chaincode query -C mychannel -n basic -c '{"Args":["ReadAsset","asset6"]}' |
部署生产网络
部分文件地址:https://github.com/alanhou/blockchain
1 2 3 4 5 6 7 8 9 10 |
# 生成模板文件 cryptogen showtemplate > crypto-config.yaml sed -i 's/EnableNodeOUs: false/EnableNodeOUs: true/g' crypto-config.yaml # 生成组织结构和证书文件 cryptogen generate --config=crypto-config.yaml cp xxx/fabric-samples/test-network/configtx/configtx.yaml ./ # 修改其中的MSPDir为前述命令生成的路径,如crypto-config/ordererOrganizations/example.com/msp # ClientTLSCert和ServerTLSCert路径也需要进行同样的修改 # 如此前创建时保持默认名称则可直接使用 sed -i 's/..\/organizations/.\/crypto-config/g' configtx.yaml |
2.3较2.2中有一个较大的变化,即 Profiles 部分,可对比 configtx.yaml 与官方文档 Profiles 部分。我们先替换为原2.2中的内容进行部署,即
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
Profiles: TwoOrgsOrdererGenesis: <<: *ChannelDefaults Orderer: <<: *OrdererDefaults Organizations: - *OrdererOrg Capabilities: <<: *OrdererCapabilities Consortiums: SampleConsortium: Organizations: - *Org1 - *Org2 TwoOrgsChannel: Consortium: SampleConsortium <<: *ChannelDefaults Application: <<: *ApplicationDefaults Organizations: - *Org1 - *Org2 Capabilities: <<: *ApplicationCapabilities |
准备工作
1 2 3 4 5 6 7 |
# 生成创世块文件,通道ID 需要与后面的不同 configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block -channelID fabric-channel # 生成通道文件 configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel # 创建 Org1和 Org2的锚节点文件 configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP |
通过配置文件启动节点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
cp xxx/fabric-samples/test-network/docker/docker-compose-test-net.yaml ./docker-compose.yaml # 修改 network 名称后需修改CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE对应的值 sed -i 's/..\/system-genesis-block/.\/channel-artifacts/g' docker-compose.yaml sed -i 's/..\/organizations/crypto-config/g' docker-compose.yaml # 将 cli 改成 cli1和 cli2两个终端,参考修改: cli1: container_name: cli1 ... environment: - GOPATH=/opt/gopath - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock - FABRIC_LOGGING_SPEC=INFO - CORE_PEER_ID=cli1 - CORE_PEER_ADDRESS=peer0.org1.example.com:7051 - CORE_PEER_LOCALMSPID=Org1MSP - CORE_PEER_TLS_ENABLED=true - CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt - CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/key.crt - CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp ... volumes: - /var/run/:/host/var/run/ - ./chaincode/go/:/opt/gopath/src/github.com/hyperledger/fabric-cluster/chaincode/go - ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ - ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts networks: - test # 将- ORDERER_GENERAL_BOOTSTRAPMETHOD=none替换为 - ORDERER_GENERAL_METHOD=file - ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block # 启动命令 docker-compose up -d # 清理命令 docker-compose down docker-compose down -v |
关于cli 也可仅配置一个,通过修改环境变量来操作不同的 peer 节点:
1 2 3 4 5 6 7 8 |
export CORE_PEER_ID=xxx export CORE_PEER_ADDRESS=xxx export CORE_PEER_LISTENADDRESS=0.0.0.0:7051 export CORE_PEER_CHAINCODEADDRESS=xxx export CORE_PEER_CHAINCODELISTENADDRESS=xxx export CORE_PEER_GOSSIP_BOOTSTRAP=xxx export CORE_PEER_GOSSIP_EXTERNALENDPOINT=xxx export CORE_PEER_LOCALMSPID=xxx |
通道&链码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# 创建通道文件 docker exec -it cli1 peer channel create -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/channel.tx --tls true \ --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/msp/tlscacerts/tlsca.example.com-cert.pem # 拷贝至 cli2 docker cp cli1:/opt/gopath/src/github.com/hyperledger/fabric/peer/mychannel.block ./ docker cp mychannel.block cli2:/opt/gopath/src/github.com/hyperledger/fabric/peer/mychannel.block # 加入通道 docker exec -it cli1 peer channel join -b mychannel.block docker exec -it cli2 peer channel join -b mychannel.block # 更新通道 docker exec -it cli1 peer channel update -o orderer.example.com:7050 -c mychannel \ -f ./channel-artifacts/Org1MSPanchors.tx --tls \ --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem docker exec -it cli2 peer channel update -o orderer.example.com:7050 -c mychannel \ -f ./channel-artifacts/Org2MSPanchors.tx --tls \ --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem # 拷贝测试链码文件 sudo cp ../fabric-samples/chaincode/sacc/sacc.go chaincode/go/ # 打包链码 docker exec -it cli1 bash cd /opt/gopath/src/github.com/hyperledger/fabric-cluster/chaincode/go/ go env -w GOPROXY=https://goproxy.cn,direct go mod init go mod vendor cd /opt/gopath/src/github.com/hyperledger/fabric/peer/ peer lifecycle chaincode package sacc.tar.gz --path github.com/hyperledger/fabric-cluster/chaincode/go/ --label sacc_1 # 退出 cli1 exit # 拷贝打包文件至 cli2 docker cp cli1:/opt/gopath/src/github.com/hyperledger/fabric/peer/sacc.tar.gz ./ docker cp sacc.tar.gz cli2:/opt/gopath/src/github.com/hyperledger/fabric/peer # 安装链码 docker exec -it cli1 peer lifecycle chaincode install sacc.tar.gz docker exec -it cli2 peer lifecycle chaincode install sacc.tar.gz # 记录下Chaincode code package identifier后的内容供下面的命令使用,也可使用peer lifecycle chaincode queryinstalled进行查询 # 在组织中进行确定 docker exec -it cli1 peer lifecycle chaincode approveformyorg --channelID mychannel \ --name sacc --version 1.0 --init-required --package-id <Chaincode code package identifier:后的内容> --sequence 1 --tls true \ --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem docker exec -it cli2 peer lifecycle chaincode approveformyorg --channelID mychannel \ --name sacc --version 1.0 --init-required --package-id <Chaincode code package identifier:后的内容> --sequence 1 --tls true \ --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem # 查看 docker exec -it cli1 peer lifecycle chaincode checkcommitreadiness --channelID mychannel \ --name sacc --version 1.0 --init-required --sequence 1 --tls true \ --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --output json |
此时输出如下内容表示配置正常,如有 false 则表示安装有问题:
1 2 3 4 5 6 |
{ "approvals": { "Org1MSP": true, "Org2MSP": true } } |
任意一个节点执行
1 2 3 4 5 6 7 |
peer lifecycle chaincode commit -o orderer.example.com:7050 --channelID mychannel --name sacc \ --version 1.0 --sequence 1 --init-required --tls true \ --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/msp/tlscacerts/tlsca.example.com-cert.pem \ --peerAddresses peer0.org1.example.com:7051 \ --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \ --peerAddresses peer0.org2.example.com:9051 \ --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt |
开始调用测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# 设置 peer chaincode invoke -o orderer.example.com:7050 --isInit --ordererTLSHostnameOverride orderer.example.com --tls true \ --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/msp/tlscacerts/tlsca.example.com-cert.pem \ -C mychannel -n sacc --peerAddresses peer0.org1.example.com:7051 \ --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \ --peerAddresses peer0.org2.example.com:9051 \ --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \ -c '{"Args":["hello", "world"]}' # 查询 peer chaincode query -C mychannel -n sacc -c '{"Args":["query", "hello"]}' # 修改 peer chaincode invoke -o orderer.example.com:7050 --tls true \ --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/msp/tlscacerts/tlsca.example.com-cert.pem \ -C mychannel -n sacc --peerAddresses peer0.org1.example.com:7051 \ --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \ --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \ -c '{"Args":["set", "hello", "block chain"]}' # 查询 peer chaincode query -C mychannel -n sacc -c '{"Args":["query", "hello"]}' |
区块链浏览器
https://github.com/hyperledger/blockchain-explorer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
mkdir ~/explorer && cd ~/explorer # 从GitHub拉取相关文件 wget https://raw.githubusercontent.com/hyperledger/blockchain-explorer/main/examples/net1/config.json wget https://raw.githubusercontent.com/hyperledger/blockchain-explorer/main/examples/net1/connection-profile/test-network.json -P connection-profile wget https://raw.githubusercontent.com/hyperledger/blockchain-explorer/main/docker-compose.yaml # 将前面生成的证书文件拷贝至当前目录 cp -R xxx/crypto-config ./organizations # 修改网络文件并编辑 docker-compose.yaml services: explorer.mynetwork.com: ... volumes: - ./config.json:/opt/explorer/app/platform/fabric/config.json - ./connection-profile:/opt/explorer/app/platform/fabric/connection-profile - ./organizations:/tmp/crypto - walletstore:/opt/explorer/wallet |
Fabric 核心模块
- peer:系统模块,peer 节点用于存储区块链数据,维护链码
- order:系统模块,排序、交易打包,提交给 peer 节点
- cryptogen:工具模块,组织和证书生成模块
- configtxgen:工具模块,区块和交易生成模块
- confgtxlator:工具模块,区块和交易解析模块
1 2 3 4 5 6 7 |
# 生成模板文件 cryptogen showtemplate > conf.yaml # 修改配置文件,然后生成证书 cryptogen generate --config conf.yaml # configtx.yam路径:fabric-samples/config/configtx.yaml # 测试网络:fabric-samples/test-network/configtx/configtx.yaml |
configtx.yaml中Organizations内的 ID 应与orderer.yaml内的LocalMSPID保持一致。
常见问题
1、Failed connect to raw.githubusercontent.com:443; Connection refused
https://githubusercontent.com.ipaddress.com/raw.githubusercontent.com获取到 IP 地址(如http://185.199.108.133/),然后在 host 文件中加入:
1 2 3 4 5 6 7 8 |
185.199.108.133 raw.githubusercontent.com 185.199.108.133 user-images.githubusercontent.com 185.199.108.133 avatars2.githubusercontent.com 185.199.108.133 avatars1.githubusercontent.com # 同理,在https://www.ipaddress.com/查询其它域名解析的IP 地址,进行GitHub的加速 140.82.112.4 github.com 185.199.108.153 assets-cdn.github.com 199.232.69.194 github.global.ssl.fastly.net |
2、Error response from daemon: manifest for hyperledger/fabric-tools:latest not found: manifest unknown: manifest unknown
1 2 |
docker pull hyperledger/fabric-tools:2.3 docker tag hyperledger/fabric-tools:2.3 hyperledger/fabric-tools:latest |
3、Chaincode packaging has failed Deploying chaincode failed
1 2 |
go env -w GO111MODULE=on go env -w GOPROXY=https://goproxy.cn,direct |
4、Cannot run peer because cannot init crypto, specified path “fabric-samples/config/msp” does not exist or cannot be accessed
1 |
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp |
5、Error on inspectChannelCreateTx: org ‘Org1MSP’ does not have any anchor peers defined
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
- &Org1 ... Policies: .... AnchorPeers: - Host: peer0.org1.example.com Port: 7051 - &Org2 ... Policies: .... AnchorPeers: - Host: peer0.org2.example.com Port: 9051 |
Credit:
- Hands-On Smart Contract Development with Hyperledger Fabric V2
- https://space.bilibili.com/373566326