参考fabric官方文档:https://hyperledger-fabric.readthedocs.io/en/latest/test_network.html
一、前言
二、准备
项目 | 版本 | 备注 |
java gradle | jdk 1.8 gradle 6.5 | 如果运行【java版的链码需要java和gradle环境】 |
nodejs和npm | 14.16.0 | 如果运行【js版的链码需要nodejs和npm环境】 参考我的另一个文章:https://blog.csdn.net/knight86/article/details/114454551 |
三、启动网络
上一篇文章启动的网络没有使用ca服务,本次需要启动ca服务
./network.sh down
./network.sh up -ca
四、创建channel
network.sh createChannel [Flags]
-ca <use CAs> - Use Certificate Authorities to generate network crypto material
-c <channel name> - Name of channel to create (defaults to "mychannel")
-s <dbtype> - Peer state database to deploy: goleveldb (default) or couchdb
-r <max retry> - CLI times out after certain number of attempts (defaults to 5)
-d <delay> - CLI delays for a certain number of seconds (defaults to 3)
-i <imagetag> - Docker image tag of Fabric to deploy (defaults to "latest")
-cai <ca_imagetag> - Docker image tag of Fabric CA to deploy (defaults to "latest")
-verbose - Verbose mode
[root@localhost test-network]# ./network.sh createChannel
Creating channel 'mychannel'.
If network is not up, starting nodes with CLI timeout of '5' tries and CLI delay of '3' seconds and using database 'leveldb
Generating channel create transaction 'mychannel.tx'
+ configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/mychannel.tx -channelID mychannel
2021-03-20 06:25:40.507 EDT [common.tools.configtxgen] main -> INFO 001 Loading configuration
2021-03-20 06:25:40.529 EDT [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /home/admin/go/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network/configtx/configtx.yaml
2021-03-20 06:25:40.529 EDT [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 003 Generating new channel configtx
2021-03-20 06:25:40.532 EDT [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 004 Writing new channel tx
+ res=0
Creating channel mychannel
Using organization 1
+ peer channel create -o localhost:7050 -c mychannel --ordererTLSHostnameOverride orderer.example.com -f ./channel-artifacts/mychannel.tx --outputBlock ./channel-artifacts/mychannel.block --tls --cafile /home/admin/go/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
+ res=0
2021-03-20 06:25:43.616 EDT [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-03-20 06:25:43.637 EDT [cli.common] readBlock -> INFO 002 Expect block, but got status: &{NOT_FOUND}
2021-03-20 06:25:43.641 EDT [channelCmd] InitCmdFactory -> INFO 003 Endorser and orderer connections initialized
2021-03-20 06:25:43.844 EDT [cli.common] readBlock -> INFO 004 Expect block, but got status: &{SERVICE_UNAVAILABLE}
2021-03-20 06:25:43.853 EDT [channelCmd] InitCmdFactory -> INFO 005 Endorser and orderer connections initialized
2021-03-20 06:25:44.056 EDT [cli.common] readBlock -> INFO 006 Expect block, but got status: &{SERVICE_UNAVAILABLE}
2021-03-20 06:25:44.065 EDT [channelCmd] InitCmdFactory -> INFO 007 Endorser and orderer connections initialized
2021-03-20 06:25:44.268 EDT [cli.common] readBlock -> INFO 008 Expect block, but got status: &{SERVICE_UNAVAILABLE}
2021-03-20 06:25:44.277 EDT [channelCmd] InitCmdFactory -> INFO 009 Endorser and orderer connections initialized
2021-03-20 06:25:44.480 EDT [cli.common] readBlock -> INFO 00a Expect block, but got status: &{SERVICE_UNAVAILABLE}
2021-03-20 06:25:44.489 EDT [channelCmd] InitCmdFactory -> INFO 00b Endorser and orderer connections initialized
2021-03-20 06:25:44.698 EDT [cli.common] readBlock -> INFO 00c Received block: 0
Channel 'mychannel' created
Joining org1 peer to the channel...
Using organization 1
+ peer channel join -b ./channel-artifacts/mychannel.block
+ res=0
2021-03-20 06:25:47.805 EDT [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-03-20 06:25:47.835 EDT [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
Joining org2 peer to the channel...
Using organization 2
+ peer channel join -b ./channel-artifacts/mychannel.block
+ res=0
2021-03-20 06:25:50.919 EDT [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-03-20 06:25:50.955 EDT [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
Setting anchor peer for org1...
+ peer channel fetch config config_block.pb -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com -c mychannel --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
Using organization 1
Fetching channel config for channel mychannel
Using organization 1
Fetching the most recent configuration block for the channel
2021-03-20 10:25:51.168 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-03-20 10:25:51.170 UTC [cli.common] readBlock -> INFO 002 Received block: 0
2021-03-20 10:25:51.170 UTC [channelCmd] fetch -> INFO 003 Retrieving last config block: 0
2021-03-20 10:25:51.173 UTC [cli.common] readBlock -> INFO 004 Received block: 0
+ configtxlator proto_decode --input config_block.pb --type common.Block
Decoding config block to JSON and isolating config to Org1MSPconfig.json
+ jq '.data.data[0].payload.data.config'
Generating anchor peer update transaction for Org1 on channel mychannel
+ jq '.channel_group.groups.Application.groups.Org1MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org1.example.com","port": 7051}]},"version": "0"}}' Org1MSPconfig.json
+ configtxlator proto_encode --input Org1MSPconfig.json --type common.Config
+ configtxlator proto_encode --input Org1MSPmodified_config.json --type common.Config
+ configtxlator compute_update --channel_id mychannel --original original_config.pb --updated modified_config.pb
+ configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate
+ jq .
++ cat config_update.json
+ echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":{' '"channel_id":' '"mychannel",' '"isolated_data":' '{},' '"read_set":' '{' '"groups":' '{' '"Application":' '{' '"groups":' '{' '"Org1MSP":' '{' '"groups":' '{},' '"mod_policy":' '"",' '"policies":' '{' '"Admins":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Endorsement":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Readers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Writers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '}' '},' '"values":' '{' '"MSP":' '{' '"mod_policy":' '"",' '"value":' null, '"version":' '"0"' '}' '},' '"version":' '"0"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"1"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"0"' '},' '"write_set":' '{' '"groups":' '{' '"Application":' '{' '"groups":' '{' '"Org1MSP":' '{' '"groups":' '{},' '"mod_policy":' '"Admins",' '"policies":' '{' '"Admins":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Endorsement":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Readers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Writers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '}' '},' '"values":' '{' '"AnchorPeers":' '{' '"mod_policy":' '"Admins",' '"value":' '{' '"anchor_peers":' '[' '{' '"host":' '"peer0.org1.example.com",' '"port":' 7051 '}' ']' '},' '"version":' '"0"' '},' '"MSP":' '{' '"mod_policy":' '"",' '"value":' null, '"version":' '"0"' '}' '},' '"version":' '"1"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"1"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"0"' '}' '}}}}'
+ configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope
2021-03-20 10:25:51.449 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-03-20 10:25:51.464 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update
Anchor peer set for org 'Org1MSP' on channel 'mychannel'
Setting anchor peer for org2...
+ peer channel fetch config config_block.pb -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com -c mychannel --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
Using organization 2
Fetching channel config for channel mychannel
Using organization 2
Fetching the most recent configuration block for the channel
2021-03-20 10:25:51.678 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-03-20 10:25:51.681 UTC [cli.common] readBlock -> INFO 002 Received block: 1
2021-03-20 10:25:51.681 UTC [channelCmd] fetch -> INFO 003 Retrieving last config block: 1
2021-03-20 10:25:51.683 UTC [cli.common] readBlock -> INFO 004 Received block: 1
Decoding config block to JSON and isolating config to Org2MSPconfig.json
+ configtxlator proto_decode --input config_block.pb --type common.Block
+ jq '.data.data[0].payload.data.config'
Generating anchor peer update transaction for Org2 on channel mychannel
+ jq '.channel_group.groups.Application.groups.Org2MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org2.example.com","port": 9051}]},"version": "0"}}' Org2MSPconfig.json
+ configtxlator proto_encode --input Org2MSPconfig.json --type common.Config
+ configtxlator proto_encode --input Org2MSPmodified_config.json --type common.Config
+ configtxlator compute_update --channel_id mychannel --original original_config.pb --updated modified_config.pb
+ configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate
+ jq .
++ cat config_update.json
+ echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":{' '"channel_id":' '"mychannel",' '"isolated_data":' '{},' '"read_set":' '{' '"groups":' '{' '"Application":' '{' '"groups":' '{' '"Org2MSP":' '{' '"groups":' '{},' '"mod_policy":' '"",' '"policies":' '{' '"Admins":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Endorsement":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Readers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Writers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '}' '},' '"values":' '{' '"MSP":' '{' '"mod_policy":' '"",' '"value":' null, '"version":' '"0"' '}' '},' '"version":' '"0"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"1"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"0"' '},' '"write_set":' '{' '"groups":' '{' '"Application":' '{' '"groups":' '{' '"Org2MSP":' '{' '"groups":' '{},' '"mod_policy":' '"Admins",' '"policies":' '{' '"Admins":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Endorsement":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Readers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Writers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '}' '},' '"values":' '{' '"AnchorPeers":' '{' '"mod_policy":' '"Admins",' '"value":' '{' '"anchor_peers":' '[' '{' '"host":' '"peer0.org2.example.com",' '"port":' 9051 '}' ']' '},' '"version":' '"0"' '},' '"MSP":' '{' '"mod_policy":' '"",' '"value":' null, '"version":' '"0"' '}' '},' '"version":' '"1"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"1"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"0"' '}' '}}}}'
+ configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope
2021-03-20 10:25:51.945 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-03-20 10:25:51.960 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update
Anchor peer set for org 'Org2MSP' on channel 'mychannel'
Channel 'mychannel' joined
五、部署链码(ChainCode)
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-java/ -ccl java
-c <channel name> - Name of channel to deploy chaincode to
-ccn <name> - Chaincode name.
-ccl <language> - Programming language of the chaincode to deploy: go (default), java, javascript, typescript
-ccv <version> - Chaincode version. 1.0 (default), v2, version3.x, etc
-ccs <sequence> - Chaincode definition sequence. Must be an integer, 1 (default), 2, 3, etc
-ccp <path> - File path to the chaincode.
-ccep <policy> - (Optional) Chaincode endorsement policy using signature policy syntax. The default policy requires an endorsement from Org1 and Org2
-cccg <collection-config> - (Optional) File path to private data collections configuration file
-cci <fcn name> - (Optional) Name of chaincode initialization function.
[root@localhost test-network]# ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-java/ -ccl java
deploying chaincode on channel 'mychannel'
executing with the following
- CHANNEL_NAME: mychannel
- CC_NAME: basic
- CC_SRC_PATH: ../asset-transfer-basic/chaincode-java/
- CC_SRC_LANGUAGE: java
- CC_VERSION: 1.0
- CC_SEQUENCE: 1
- CC_END_POLICY: NA
- CC_COLL_CONFIG: NA
- CC_INIT_FCN: NA
- DELAY: 3
- MAX_RETRY: 5
- VERBOSE: false
# ################################################################################
# ################ 编译java版本的【链码】
Compiling Java code...
/home/admin/go/src/github.com/hyperledger/fabric/scripts/fabric-samples/asset-transfer-basic/chaincode-java /home/admin/go/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network
Downloading file:/opt/gradle-6.5-bin.zip
.................................................................................................
Starting a Gradle Daemon (subsequent builds will be faster)
BUILD SUCCESSFUL in 2m 18s
10 actionable tasks: 10 executed
/home/admin/go/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network
Finished compiling Java code
+ peer lifecycle chaincode package basic.tar.gz --path ../asset-transfer-basic/chaincode-java//build/install/basic --lang java --label basic_1.0
+ res=0
Chaincode is packaged
# ################################################################################
# ################ 部署java版本的【链码】
Installing chaincode on peer0.org1...
Using organization 1
+ peer lifecycle chaincode install basic.tar.gz
+ res=0
2021-03-20 09:01:01.088 EDT [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nJbasic_1.0:b7715fc54c512c989446d3e9a673be200f4bfa975dc10eb209e90f39ed7c72a1\022\tbasic_1.0" >
2021-03-20 09:01:01.091 EDT [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: basic_1.0:b7715fc54c512c989446d3e9a673be200f4bfa975dc10eb209e90f39ed7c72a1
Chaincode is installed on peer0.org1
[root@localhost application-java]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
02dda6554705 dev-peer0.org2.example.com-basic_1.0-b7715fc54c512c989446d3e9a673be200f4bfa975dc10eb209e90f39ed7c72a1-cea2d58f347bb8bbd69c9efea7eec667e4c54945d5923aea62e82cc273e0082e "/root/chaincode-jav…" 21 minutes ago Up 21 minutes dev-peer0.org2.example.com-basic_1.0-b7715fc54c512c989446d3e9a673be200f4bfa975dc10eb209e90f39ed7c72a1
42c131568324 dev-peer0.org1.example.com-basic_1.0-b7715fc54c512c989446d3e9a673be200f4bfa975dc10eb209e90f39ed7c72a1-ccac46b173233a4fda9ed4d628e2277ce63a7e672fa7291a1b1fec8115990da0 "/root/chaincode-jav…" 21 minutes ago Up 21 minutes dev-peer0.org1.example.com-basic_1.0-b7715fc54c512c989446d3e9a673be200f4bfa975dc10eb209e90f39ed7c72a1
4e5371f50458 hyperledger/fabric-tools:latest "/bin/bash" 23 minutes ago Up 23 minutes cli
4f6c61928b1e hyperledger/fabric-peer:latest "peer node start" 23 minutes ago Up 23 minutes 7051/tcp, 0.0.0.0:9051->9051/tcp peer0.org2.example.com
806d33be6e6b hyperledger/fabric-peer:latest "peer node start" 23 minutes ago Up 23 minutes 0.0.0.0:7051->7051/tcp peer0.org1.example.com
a5770f7d13c7 hyperledger/fabric-orderer:latest "orderer" 23 minutes ago Up 23 minutes 0.0.0.0:7050->7050/tcp orderer.example.com
9bb6e6c6d91d hyperledger/fabric-ca:latest "sh -c 'fabric-ca-se…" 23 minutes ago Up 23 minutes 0.0.0.0:7054->7054/tcp ca_org1
8427ae863a60 hyperledger/fabric-ca:latest "sh -c 'fabric-ca-se…" 23 minutes ago Up 23 minutes 7054/tcp, 0.0.0.0:9054->9054/tcp ca_orderer
f535b13fe926 hyperledger/fabric-ca:latest "sh -c 'fabric-ca-se…" 23 minutes ago Up 23 minutes 7054/tcp, 0.0.0.0:8054->8054/tcp ca_org2
b2bbf3c11ff7 hello-world "/hello" 32 hours ago Exited (0) 32 hours ago zen_meninsky
六、运行应用
(1)java应用
cd /home/admin/go/src/github.com/hyperledger/fabric/scripts/fabric-samples/asset-transfer-basic/application-java
gradle run
[root@localhost application-java]# gradle run
> Task :run
An identity for the admin user "admin" already exists in the wallet
An identity for the user "appUser" already exists in the wallet
Submit Transaction: InitLedger creates the initial set of assets on the ledger.
Evaluate Transaction: GetAllAssets, result: [{"appraisedValue":300,"assetID":"asset1","color":"blue","owner":"Tomoko","size":5},{"appraisedValue":400,"assetID":"asset2","color":"red","owner":"Brad","size":5},{"appraisedValue":500,"assetID":"asset3","color":"green","owner":"Jin Soo","size":10},{"appraisedValue":600,"assetID":"asset4","color":"yellow","owner":"Max","size":10},{"appraisedValue":700,"assetID":"asset5","color":"black","owner":"Adrian","size":15},{"appraisedValue":700,"assetID":"asset6","color":"white","owner":"Michel","size":15}]
Submit Transaction: CreateAsset asset13
Evaluate Transaction: ReadAsset asset13
result: {"owner":"Tom","color":"yellow","size":5,"appraisedValue":1300,"assetID":"asset13"}
Evaluate Transaction: AssetExists asset1
result: true
Submit Transaction: UpdateAsset asset1, new AppraisedValue : 350
Evaluate Transaction: ReadAsset asset1
result: {"owner":"Tomoko","color":"blue","size":5,"appraisedValue":350,"assetID":"asset1"}
Submit Transaction: UpdateAsset asset70
No valid proposal responses received. 2 peer error responses: error in simulation: transaction returned with failure: Asset asset70 does not exist; error in simulation: transaction returned with failure: Asset asset70 does not exist
Submit Transaction: TransferAsset asset1 from owner Tomoko > owner Tom
Expected an error on UpdateAsset of non-existing Asset: org.hyperledger.fabric.gateway.ContractException: No valid proposal responses received. 2 peer error responses: error in simulation: transaction returned with failure: Asset asset70 does not exist; error in simulation: transaction returned with failure: Asset asset70 does not exist
Evaluate Transaction: ReadAsset asset1
result: {"owner":"Tom","color":"blue","size":5,"appraisedValue":350,"assetID":"asset1"}
BUILD SUCCESSFUL in 22s
3 actionable tasks: 1 executed, 2 up-to-date
(2)peer客户端
peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'
[root@localhost test-network]# peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'
[{"appraisedValue":350,"assetID":"asset1","color":"blue","owner":"Tom","size":5},{"appraisedValue":1300,"assetID":"asset13","color":"yellow","owner":"Tom","size":5},{"appraisedValue":400,"assetID":"asset2","color":"red","owner":"Brad","size":5},{"appraisedValue":500,"assetID":"asset3","color":"green","owner":"Jin Soo","size":10},{"appraisedValue":600,"assetID":"asset4","color":"yellow","owner":"Max","size":10},{"appraisedValue":700,"assetID":"asset5","color":"black","owner":"Adrian","size":15},{"appraisedValue":700,"assetID":"asset6","color":"white","owner":"Michel","size":15}]