1、代码分析

1.1、链码启动

asset-transfer-basic/chaincode-go/assetTransfer.go

func main() {//新建链码assetChaincode, err := contractapi.NewChaincode(&chaincode.SmartContract{})if err != nil {log.Panicf("Error creating asset-transfer-basic chaincode: %v", err)}//启动链码if err := assetChaincode.Start(); err != nil {log.Panicf("Error starting asset-transfer-basic chaincode: %v", err)}
}

1.2、链码结构

asset-transfer-basic/chaincode-go/chaincode/smartcontract.go

type SmartContract struct {contractapi.Contract
}

1.3、数据操作

asset-transfer-basic/chaincode-go/chaincode/smartcontract.go

1.3.1、存放数据

err = ctx.GetStub().PutState(asset.ID, assetJSON)

1.3.2、获取数据

assetJSON, err := ctx.GetStub().GetState(id)

1.3.3、删除数据

ctx.GetStub().DelState(id)

1.3.4、获取数据列表(迭代器)

resultsIterator, err := ctx.GetStub().GetStateByRange("", "")

2、链码部署

2.1、启动测试网络

2.1.1、进入测试网络目录

cd fabric-samples/test-network

[root@localhost hyperledger]# cd fabric-samples/test-network

2.1.2、关闭测试网络

./network.sh down

[root@localhost test-network]# ./network.sh down
Using docker and docker-compose
Stopping network
[+] Running 4/0⠿ Volume compose_peer0.org3.example.com  Removed                                                                                                 0.0s⠿ Volume compose_orderer.example.com     Removed                                                                                                 0.0s⠿ Volume compose_peer0.org1.example.com  Removed                                                                                                 0.0s⠿ Volume compose_peer0.org2.example.com  Removed                                                                                                 0.0s
Error: No such volume: docker_orderer.example.com
Error: No such volume: docker_peer0.org1.example.com
Error: No such volume: docker_peer0.org2.example.com
Removing remaining containers
Removing generated chaincode docker images
"docker kill" requires at least 1 argument.
See 'docker kill --help'.Usage:  docker kill [OPTIONS] CONTAINER [CONTAINER...]Kill one or more running containers

2.1.3、启动测试网络,同时创建一个channel

./network.sh up createChannel -c tracychannel

-c 指定channel名称,不指定时默认为mychannel

[root@localhost test-network]# ./network.sh up createChannel -c tracychannel
Using docker and docker-compose
Creating channel 'tracychannel'.
If network is not up, starting nodes with CLI timeout of '5' tries and CLI delay of '3' seconds and using database 'leveldb with crypto from 'cryptogen'
Bringing up network
LOCAL_VERSION=2.4.4
DOCKER_IMAGE_VERSION=2.4.4
/home/gopath/src/github.com/hyperledger/fabric-samples/bin/cryptogen
Generating certificates using cryptogen tool
Creating Org1 Identities
+ cryptogen generate --config=./organizations/cryptogen/crypto-config-org1.yaml --output=organizations
org1.example.com
+ res=0
Creating Org2 Identities
+ cryptogen generate --config=./organizations/cryptogen/crypto-config-org2.yaml --output=organizations
org2.example.com
+ res=0
Creating Orderer Org Identities
+ cryptogen generate --config=./organizations/cryptogen/crypto-config-orderer.yaml --output=organizations
+ res=0
Generating CCP files for Org1 and Org2
[+] Running 8/8⠿ Network fabric_test                      Created                                                                                               0.1s⠿ Volume "compose_orderer.example.com"     Created                                                                                               0.0s⠿ Volume "compose_peer0.org1.example.com"  Created                                                                                               0.0s⠿ Volume "compose_peer0.org2.example.com"  Created                                                                                               0.0s⠿ Container peer0.org1.example.com         Started                                                                                               0.7s⠿ Container peer0.org2.example.com         Started                                                                                               0.6s⠿ Container orderer.example.com            Started                                                                                               1.0s⠿ Container cli                            Started                                                                                               1.2s
CONTAINER ID   IMAGE                               COMMAND             CREATED         STATUS                  PORTS                                                                                                                             NAMES
996db23379fb   hyperledger/fabric-tools:latest     "/bin/bash"         2 seconds ago   Up Less than a second                                                                                                                                     cli
9694d2a81710   hyperledger/fabric-peer:latest      "peer node start"   2 seconds ago   Up Less than a second   0.0.0.0:9051->9051/tcp, :::9051->9051/tcp, 7051/tcp, 0.0.0.0:9445->9445/tcp, :::9445->9445/tcp                                    peer0.org2.example.com
256d3c257a04   hyperledger/fabric-peer:latest      "peer node start"   2 seconds ago   Up Less than a second   0.0.0.0:7051->7051/tcp, :::7051->7051/tcp, 0.0.0.0:9444->9444/tcp, :::9444->9444/tcp                                              peer0.org1.example.com
0c67126f3c75   hyperledger/fabric-orderer:latest   "orderer"           2 seconds ago   Up Less than a second   0.0.0.0:7050->7050/tcp, :::7050->7050/tcp, 0.0.0.0:7053->7053/tcp, :::7053->7053/tcp, 0.0.0.0:9443->9443/tcp, :::9443->9443/tcp   orderer.example.com
Using docker and docker-compose
Generating channel genesis block 'tracychannel.block'
/home/gopath/src/github.com/hyperledger/fabric-samples/bin/configtxgen
+ configtxgen -profile TwoOrgsApplicationGenesis -outputBlock ./channel-artifacts/tracychannel.block -channelID tracychannel
2022-10-08 09:17:04.201 CST 0001 INFO [common.tools.configtxgen] main -> Loading configuration
2022-10-08 09:17:04.208 CST 0002 INFO [common.tools.configtxgen.localconfig] completeInitialization -> orderer type: etcdraft
2022-10-08 09:17:04.208 CST 0003 INFO [common.tools.configtxgen.localconfig] completeInitialization -> Orderer.EtcdRaft.Options unset, setting to tick_interval:"500ms" election_tick:10 heartbeat_tick:1 max_inflight_blocks:5 snapshot_interval_size:16777216
2022-10-08 09:17:04.208 CST 0004 INFO [common.tools.configtxgen.localconfig] Load -> Loaded configuration: /home/gopath/src/github.com/hyperledger/fabric-samples/test-network/configtx/configtx.yaml
2022-10-08 09:17:04.209 CST 0005 INFO [common.tools.configtxgen] doOutputBlock -> Generating genesis block
2022-10-08 09:17:04.209 CST 0006 INFO [common.tools.configtxgen] doOutputBlock -> Creating application channel genesis block
2022-10-08 09:17:04.209 CST 0007 INFO [common.tools.configtxgen] doOutputBlock -> Writing genesis block
+ res=0
Creating channel tracychannel
Using organization 1
+ osnadmin channel join --channelID tracychannel --config-block ./channel-artifacts/tracychannel.block -o localhost:7053 --ca-file /home/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem --client-cert /home/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt --client-key /home/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.key
+ res=0
Status: 201
{"name": "tracychannel","url": "/participation/v1/channels/tracychannel","consensusRelation": "consenter","status": "active","height": 1
}Channel 'tracychannel' created
Joining org1 peer to the channel...
Using organization 1
+ peer channel join -b ./channel-artifacts/tracychannel.block
+ res=0
2022-10-08 09:17:10.273 CST 0001 INFO [channelCmd] InitCmdFactory -> Endorser and orderer connections initialized
2022-10-08 09:17:10.284 CST 0002 INFO [channelCmd] executeJoin -> Successfully submitted proposal to join channel
Joining org2 peer to the channel...
Using organization 2
+ peer channel join -b ./channel-artifacts/tracychannel.block
+ res=0
2022-10-08 09:17:13.322 CST 0001 INFO [channelCmd] InitCmdFactory -> Endorser and orderer connections initialized
2022-10-08 09:17:13.335 CST 0002 INFO [channelCmd] executeJoin -> Successfully submitted proposal to join channel
Setting anchor peer for org1...
Using organization 1
Fetching channel config for channel tracychannel
Using organization 1
Fetching the most recent configuration block for the channel
+ peer channel fetch config config_block.pb -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com -c tracychannel --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem
2022-10-08 01:17:13.467 UTC 0001 INFO [channelCmd] InitCmdFactory -> Endorser and orderer connections initialized
2022-10-08 01:17:13.469 UTC 0002 INFO [cli.common] readBlock -> Received block: 0
2022-10-08 01:17:13.469 UTC 0003 INFO [channelCmd] fetch -> Retrieving last config block: 0
2022-10-08 01:17:13.470 UTC 0004 INFO [cli.common] readBlock -> Received block: 0
Decoding config block to JSON and isolating config to Org1MSPconfig.json
+ configtxlator proto_decode --input config_block.pb --type common.Block --output config_block.json
+ jq '.data.data[0].payload.data.config' config_block.json
Generating anchor peer update transaction for Org1 on channel tracychannel
+ 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 --output original_config.pb
+ configtxlator proto_encode --input Org1MSPmodified_config.json --type common.Config --output modified_config.pb
+ configtxlator compute_update --channel_id tracychannel --original original_config.pb --updated modified_config.pb --output config_update.pb
+ configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json
+ jq .
++ cat config_update.json
+ echo '{"payload":{"header":{"channel_header":{"channel_id":"tracychannel", "type":2}},"data":{"config_update":{' '"channel_id":' '"tracychannel",' '"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":' '"0"' '}' '},' '"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":' '"0"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"0"' '}' '}}}}'
+ configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output Org1MSPanchors.tx
2022-10-08 01:17:13.809 UTC 0001 INFO [channelCmd] InitCmdFactory -> Endorser and orderer connections initialized
2022-10-08 01:17:13.817 UTC 0002 INFO [channelCmd] update -> Successfully submitted channel update
Anchor peer set for org 'Org1MSP' on channel 'tracychannel'
Setting anchor peer for org2...
Using organization 2
Fetching channel config for channel tracychannel
Using organization 2
+ peer channel fetch config config_block.pb -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com -c tracychannel --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem
Fetching the most recent configuration block for the channel
2022-10-08 01:17:13.960 UTC 0001 INFO [channelCmd] InitCmdFactory -> Endorser and orderer connections initialized
2022-10-08 01:17:13.962 UTC 0002 INFO [cli.common] readBlock -> Received block: 1
2022-10-08 01:17:13.962 UTC 0003 INFO [channelCmd] fetch -> Retrieving last config block: 1
2022-10-08 01:17:13.963 UTC 0004 INFO [cli.common] readBlock -> Received block: 1
Decoding config block to JSON and isolating config to Org2MSPconfig.json
+ configtxlator proto_decode --input config_block.pb --type common.Block --output config_block.json
+ jq '.data.data[0].payload.data.config' config_block.json
Generating anchor peer update transaction for Org2 on channel tracychannel
+ 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 --output original_config.pb
+ configtxlator proto_encode --input Org2MSPmodified_config.json --type common.Config --output modified_config.pb
+ configtxlator compute_update --channel_id tracychannel --original original_config.pb --updated modified_config.pb --output config_update.pb
+ configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json
+ jq .
++ cat config_update.json
+ echo '{"payload":{"header":{"channel_header":{"channel_id":"tracychannel", "type":2}},"data":{"config_update":{' '"channel_id":' '"tracychannel",' '"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":' '"0"' '}' '},' '"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":' '"0"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"0"' '}' '}}}}'
+ configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output Org2MSPanchors.tx
2022-10-08 01:17:14.130 UTC 0001 INFO [channelCmd] InitCmdFactory -> Endorser and orderer connections initialized
2022-10-08 01:17:14.137 UTC 0002 INFO [channelCmd] update -> Successfully submitted channel update
Anchor peer set for org 'Org2MSP' on channel 'tracychannel'
Channel 'tracychannel' joined

2.1.4、查看channel

peer channel list

[root@localhost test-network]# peer channel list
-bash: peer: command not found

如果报错“-bash: peer: command not found”,需要设置环境变量(提前操作了步骤2.3.2)

export PATH=${PWD}/../bin:$PATH

export FABRIC_CFG_PATH=$PWD/../config/

[root@localhost test-network]# export PATH=${PWD}/../bin:$PATH
[root@localhost test-network]# export FABRIC_CFG_PATH=$PWD/../config/

查看设置的环境变量

echo $PATH

echo $FABRIC_CFG_PATH

[root@localhost test-network]# echo $PATH
/home/gopath/src/github.com/hyperledger/fabric-samples/test-network/../bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/local/go/bin:/home/gopath/bin:/root/bin
[root@localhost test-network]# echo $FABRIC_CFG_PATH
/home/gopath/src/github.com/hyperledger/fabric-samples/test-network/../config/

再次执行peer channel list

[root@localhost test-network]# peer channel list
2022-10-08 10:04:30.074 CST 0001 ERRO [main] InitCmd -> Cannot run peer because cannot init crypto, specified path "/home/gopath/src/github.com/hyperledger/fabric-samples/config/msp" does not exist or cannot be accessed: stat /home/gopath/src/github.com/hyperledger/fabric-samples/config/msp: no such file or directory

2.1.5、查看启动的节点

docker ps

启动了2个组织,每个组织 有一个peer节点

[root@localhost test-network]# docker ps
CONTAINER ID   IMAGE                               COMMAND             CREATED          STATUS          PORTS                                                                                                                             NAMES
996db23379fb   hyperledger/fabric-tools:latest     "/bin/bash"         57 minutes ago   Up 57 minutes                                                                                                                                     cli
9694d2a81710   hyperledger/fabric-peer:latest      "peer node start"   57 minutes ago   Up 57 minutes   0.0.0.0:9051->9051/tcp, :::9051->9051/tcp, 7051/tcp, 0.0.0.0:9445->9445/tcp, :::9445->9445/tcp                                    peer0.org2.example.com
256d3c257a04   hyperledger/fabric-peer:latest      "peer node start"   57 minutes ago   Up 57 minutes   0.0.0.0:7051->7051/tcp, :::7051->7051/tcp, 0.0.0.0:9444->9444/tcp, :::9444->9444/tcp                                              peer0.org1.example.com
0c67126f3c75   hyperledger/fabric-orderer:latest   "orderer"           57 minutes ago   Up 57 minutes   0.0.0.0:7050->7050/tcp, :::7050->7050/tcp, 0.0.0.0:7053->7053/tcp, :::7053->7053/tcp, 0.0.0.0:9443->9443/tcp, :::9443->9443/tcp   orderer.example.com

2.2、生成项目依赖

GO111MODULE=on go mod vendor

进入项目目录,生成依赖

[root@localhost test-network]# cd ..
[root@localhost fabric-samples]# cd asset-transfer-basic/chaincode-go/
[root@localhost chaincode-go]# GO111MODULE=on go mod vendor

生成vendor目录如下:

2.3、打包链码

2.3.1、进入到test-network目录

cd ../../test-network

[root@localhost chaincode-go]# cd ../../test-network

2.3.2、设置环境变量

如果上面操作了步骤2.1.4,则不用再执行此步

注:此处环境变量设置必须在test-network目录中执行

export PATH=${PWD}/../bin:$PATH

export FABRIC_CFG_PATH=$PWD/../config/

[root@localhost test-network]# export PATH=${PWD}/../bin:$PATH
[root@localhost test-network]# export FABRIC_CFG_PATH=$PWD/../config/

2.3.3、打包链码

peer lifecycle chaincode package basic.tar.gz --path ../asset-transfer-basic/chaincode-go/ --lang golang --label basic_1.0

[root@localhost test-network]# peer lifecycle chaincode package basic.tar.gz --path ../asset-transfer-basic/chaincode-go/ --lang golang --label basic_1.0

在当前目录中生链码包basic.tar.gz,如下图所示:

2.4、安装链码

在2个组织中(组织1 与 组织2)安装链码。

2.4.1、设置环境变量(组织1 - 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

[root@localhost test-network]# export CORE_PEER_TLS_ENABLED=true
[root@localhost test-network]# export CORE_PEER_LOCALMSPID="Org1MSP"
[root@localhost test-network]# export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
[root@localhost test-network]# export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
[root@localhost test-network]# export CORE_PEER_ADDRESS=localhost:7051

2.4.2、安装链码(组织1 - Org1)

peer lifecycle chaincode install basic.tar.gz

[root@localhost test-network]# peer lifecycle chaincode install basic.tar.gz
2022-10-08 10:44:16.265 CST 0001 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Installed remotely: response:<status:200 payload:"\nJbasic_1.0:2e20ce421c8037420718c8a3918a1eea76343b7361fffdac454181c54e5736c7\022\tbasic_1.0" >
2022-10-08 10:44:16.265 CST 0002 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Chaincode code package identifier: basic_1.0:2e20ce421c8037420718c8a3918a1eea76343b7361fffdac454181c54e5736c7

2.4.3、设置环境变量(组织2 - 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

[root@localhost test-network]# export CORE_PEER_TLS_ENABLED=true
[root@localhost test-network]# export CORE_PEER_LOCALMSPID="Org2MSP"
[root@localhost test-network]# export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
[root@localhost test-network]# export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
[root@localhost test-network]# export CORE_PEER_ADDRESS=localhost:9051

2.4.4、安装链码(组织2 - Org2)

peer lifecycle chaincode install basic.tar.gz

root@localhost test-network]# peer lifecycle chaincode install basic.tar.gz
2022-10-08 10:50:00.193 CST 0001 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Installed remotely: response:<status:200 payload:"\nJbasic_1.0:2e20ce421c8037420718c8a3918a1eea76343b7361fffdac454181c54e5736c7\022\tbasic_1.0" >
2022-10-08 10:50:00.193 CST 0002 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Chaincode code package identifier: basic_1.0:2e20ce421c8037420718c8a3918a1eea76343b7361fffdac454181c54e5736c7

2.5、授权链码

2.5.1、查看链码安装状态(组织2 - Org2)

因上面步骤2.4.4执行时环境变量配置的是组织2的,因此此处环境变量也是组织2的。

peer lifecycle chaincode queryinstalled

[root@localhost test-network]# peer lifecycle chaincode queryinstalled
Installed chaincodes on peer:
Package ID: basic_1.0:2e20ce421c8037420718c8a3918a1eea76343b7361fffdac454181c54e5736c7, Label: basic_1.0

2.5.2、设置链码包环境变量(组织2 - Org2)

链码包ID为上面查到的Package ID

export CC_PACKAGE_ID=basic_1.0:2e20ce421c8037420718c8a3918a1eea76343b7361fffdac454181c54e5736c7

[root@localhost test-network]# export CC_PACKAGE_ID=basic_1.0:2e20ce421c8037420718c8a3918a1eea76343b7361fffdac454181c54e5736c7

2.5.3、授权链码(组织2 - Org2)

注:channel名称为启动网络时创建的channel名

peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID tracychannel --name basic --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"

[root@localhost test-network]# peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID tracychannel --name basic --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
2022-10-08 11:00:18.110 CST 0001 INFO [chaincodeCmd] ClientWait -> txid [d68bed6e512945ffbd85430acd0f19c2486ba796c4e2a718be1b4ce743d7ba36] committed with status (VALID) at localhost:9051

2.5.4、切换到组织1

export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:7051

[root@localhost test-network]# export CORE_PEER_LOCALMSPID="Org1MSP"
[root@localhost test-network]# export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
[root@localhost test-network]# export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
[root@localhost test-network]# export CORE_PEER_ADDRESS=localhost:7051

2.5.5、查看链码安装状态(组织1 - Org1)

peer lifecycle chaincode queryinstalled

[root@localhost test-network]# peer lifecycle chaincode queryinstalled
Installed chaincodes on peer:
Package ID: basic_1.0:2e20ce421c8037420718c8a3918a1eea76343b7361fffdac454181c54e5736c7, Label: basic_1.0

可以看到,此处链码包ID与在组织2中查询到甸链码包ID是一样的。

2.5.6、设置链码包环境变量(组织1 - Org1)

链码包ID为上面查到的Package ID

export CC_PACKAGE_ID=basic_1.0:2e20ce421c8037420718c8a3918a1eea76343b7361fffdac454181c54e5736c7

[root@localhost test-network]# export CC_PACKAGE_ID=basic_1.0:2e20ce421c8037420718c8a3918a1eea76343b7361fffdac454181c54e5736c7

2.5.7、授权链码(组织1 - Org1)

注:channel名称为启动网络时创建的channel名

peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID tracychannel --name basic --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"

[root@localhost test-network]# peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID tracychannel --name basic --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
2022-10-08 11:09:44.671 CST 0001 INFO [chaincodeCmd] ClientWait -> txid [7dae727d6a3312039fe40c4893244e316e0bd71ab6e9977787f4f1251bea8757] committed with status (VALID) at localhost:7051

2.5.8、查看授权结果

注:channel名称为启动网络时创建的channel名

peer lifecycle chaincode checkcommitreadiness --channelID tracychannel --name basic --version 1.0 --sequence 1 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" --output json

2022-10-08 11:09:44.671 CST 0001 INFO [chaincodeCmd] ClientWait -> txid [7dae727d6a3312039fe40c4893244e316e0bd71ab6e9977787f4f1251bea8757] committed with status (VALID) at localhost:7051
[root@localhost test-network]# peer lifecycle chaincode checkcommitreadiness --channelID tracychannel --name basic --version 1.0 --sequence 1 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" --output json
{"approvals": {"Org1MSP": true,"Org2MSP": true}
}

2.6、提交链码

授权后,可以提交链码了,只有授权链码的组织才能提交链码(任一一个授权链码的组织提交即可),在上面步骤2.5.8可以查看组织授权结果。

2.6.1、提交链码

注:channel名称为启动网络时创建的channel名

peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID tracychannel --name basic --version 1.0 --sequence 1 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" --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"

[root@localhost test-network]# peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID tracychannel --name basic --version 1.0 --sequence 1 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" --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"
2022-10-08 11:19:06.266 CST 0001 INFO [chaincodeCmd] ClientWait -> txid [1129f4b4285403e8660ef674f0f07726865bc720d08f8ebae224ae255f75f67f] committed with status (VALID) at localhost:7051
2022-10-08 11:19:06.274 CST 0002 INFO [chaincodeCmd] ClientWait -> txid [1129f4b4285403e8660ef674f0f07726865bc720d08f8ebae224ae255f75f67f] committed with status (VALID) at localhost:9051

2.6.2、查看提交结果

注:channel名称为启动网络时创建的channel名

peer lifecycle chaincode querycommitted --channelID tracychannel --name basic --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"  --output json

[root@localhost test-network]# peer lifecycle chaincode querycommitted --channelID tracychannel --name basic --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"  --output json
{"sequence": 1,"version": "1.0","endorsement_plugin": "escc","validation_plugin": "vscc","validation_parameter": "EiAvQ2hhbm5lbC9BcHBsaWNhdGlvbi9FbmRvcnNlbWVudA==","collections": {},"approvals": {"Org1MSP": true,"Org2MSP": true}
}

2.7、调用链码

注:调用链码执行的命令中,注意channel名称为启动网络时创建的channel名,命令中channel名使用加粗字体标识。

2.7.1、调用初始化数据函数

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 tracychannel -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":[]}'

-c '{"function":"InitLedger","Args":[]}'

function: 表示要调用函数

InitLedger: 函数名称

Args: 参数,当前参数数组为空,,即没有参数

[root@localhost test-network]# 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 tracychannel -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":[]}'
2022-10-08 11:41:16.406 CST 0001 INFO [chaincodeCmd] chaincodeInvokeOrQuery -> Chaincode invoke successful. result: status:200 

2.7.2、查询全部资产数据

peer chaincode query -C tracychannel -n basic -c '{"Args":["GetAllAssets"]}'

[root@localhost test-network]# peer chaincode query -C tracychannel -n basic -c '{"Args":["GetAllAssets"]}'
[{"AppraisedValue":300,"Color":"blue","ID":"asset1","Owner":"Tomoko","Size":5},{"AppraisedValue":400,"Color":"red","ID":"asset2","Owner":"Brad","Size":5},{"AppraisedValue":500,"Color":"green","ID":"asset3","Owner":"Jin Soo","Size":10},{"AppraisedValue":600,"Color":"yellow","ID":"asset4","Owner":"Max","Size":10},{"AppraisedValue":700,"Color":"black","ID":"asset5","Owner":"Adriana","Size":15},{"AppraisedValue":800,"Color":"white","ID":"asset6","Owner":"Michel","Size":15}]

2.7.3、调用创建资产函数

查看代码中的创建资产函数名称及参数

func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface, id string, color string, size int, owner string, appraisedValue int) error {exists, err := s.AssetExists(ctx, id)if err != nil {return err}if exists {return fmt.Errorf("the asset %s already exists", id)}asset := Asset{ID:             id,Color:          color,Size:           size,Owner:          owner,AppraisedValue: appraisedValue,}assetJSON, err := json.Marshal(asset)if err != nil {return err}return ctx.GetStub().PutState(id, assetJSON)
}

执行命令:

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 tracychannel -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":"CreateAsset","Args":["asset7","pink","27","Tracy","900"]}'

[root@localhost test-network]# 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 tracychannel -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":"CreateAsset","Args":["asset7","pink","27","Tracy","900"]}'
2022-10-08 11:58:40.493 CST 0001 INFO [chaincodeCmd] chaincodeInvokeOrQuery -> Chaincode invoke successful. result: status:200

注:参数是int类型时,也使用双引号,否则将报错如下:

Error: chaincode argument error: json: cannot unmarshal number into Go struct field .Args of type string

[root@localhost test-network]# 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 tracychannel -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":"CreateAsset","Args":["asset7","pink","27","Tracy",900]}'
Error: chaincode argument error: json: cannot unmarshal number into Go struct field .Args of type string

3、链码升级

3.1、重新生成项目依赖

进入到项目目录,重新生成项目依赖

go mod vendor

[root@localhost test-network]# cd ../asset-transfer-basic/chaincode-go/
[root@localhost chaincode]# go mod vendor

3.2、 重新打包链码

链码包tag由1.0升为2.0

peer lifecycle chaincode package basic.tar.gz --path ../asset-transfer-basic/chaincode-go/ --lang golang --label basic_2.0

[root@localhost test-network]# ​peer lifecycle chaincode package basic.tar.gz --path ../asset-transfer-basic/chaincode-go/ --lang golang --label basic_2.0

3.3、安装链码

以下操作打开2个终端,一个环境变量设置为组织1,另一个环境变量设置为组织2

3.3.1、设置环境变量

# 终端1 - 环境变量设置为组织1

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

# 终端2 - 环境变量设置为组织2

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

3.3.2、安装链码(2个组织)

组织1与组织2 都执行安装链码命令:

peer lifecycle chaincode install basic.tar.gz

[root@localhost test-network]# peer lifecycle chaincode install basic.tar.gz
2022-10-11 17:28:13.880 CST 0001 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Installed remotely: response:<status:200 payload:"\nJbasic_2.0:f7ee6e4bff33e4ad7e28060f5d6528550489f1409d0acbd44236974a699ef6a7\022\014marriage_2.0" >
2022-10-11 17:28:13.880 CST 0002 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Chaincode code package identifier: basic_2.0:f7ee6e4bff33e4ad7e28060f5d6528550489f1409d0acbd44236974a699ef6a7

3.4、授权链码

3.4.1、查看链码安装状态

peer lifecycle chaincode queryinstalled

[root@localhost test-network]# peer lifecycle chaincode queryinstalled
Installed chaincodes on peer:
Package ID: basic_2.0:f7ee6e4bff33e4ad7e28060f5d6528550489f1409d0acbd44236974a699ef6a7, Label: marriage_2.0
Package ID: basic_1.0:2e20ce421c8037420718c8a3918a1eea76343b7361fffdac454181c54e5736c7, Label: basic_1.0

3.4.2、设置链码包环境变量(2个组织)

组织1与组织2 都执行

export CC_PACKAGE_ID=basic_2.0:f7ee6e4bff33e4ad7e28060f5d6528550489f1409d0acbd44236974a699ef6a7

[root@localhost test-network]# export CC_PACKAGE_ID=basic_2.0:f7ee6e4bff33e4ad7e28060f5d6528550489f1409d0acbd44236974a699ef6a7

3.4.3、授权链码(2个组织)

组织1与组织2 都执行,注意:标签为2.0,序号为2

peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID tracychannel --name basic --version 2.0 --package-id $CC_PACKAGE_ID --sequence 2 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"

[root@localhost test-network]# peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID tracychannel --name basic --version 2.0 --package-id $CC_PACKAGE_ID --sequence 2 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
2022-10-11 18:09:07.883 CST 0001 INFO [chaincodeCmd] ClientWait -> txid [e259a06ab844af518d87ddd264c0f1db7d2cb050a7cdb79d7ad3406808431e07] committed with status (VALID) at localhost:9051

3.5、提交链码

3.5.1、提交链码

使用组织1 或 组织2提交链码即可,注意:标签为2.0,序号为2

peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID tracychannel --name basic --version 2.0 --sequence 2 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" --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"

[root@localhost test-network]# peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID tracychannel --name basic --version 2.0 --sequence 2 --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" --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"
2022-10-11 19:02:18.990 CST 0001 INFO [chaincodeCmd] ClientWait -> txid [3ae48a1b16c8295e3fbf44289447581b66828c1ddfd1ea1761219c5baca0206c] committed with status (VALID) at localhost:9051
2022-10-11 19:02:19.025 CST 0002 INFO [chaincodeCmd] ClientWait -> txid [3ae48a1b16c8295e3fbf44289447581b66828c1ddfd1ea1761219c5baca0206c] committed with status (VALID) at localhost:7051

3.5.2、 查看提交结果

peer lifecycle chaincode querycommitted --channelID tracychannel --name basic --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"  --output json

4、使用deployCC部署链码

可直接使用network.sh脚本提供的deployCC部署或升级链码,直接代替部署(第3步骤 - 打包、安装、授权及提交操作)或升级(第4步骤)中所有执行的命令

4.1、查看帮助

./network.sh deployCC -h

[root@localhost test-network]# ./network.sh deployCC -h
Using docker and docker-compose
Usage: network.sh deployCC [Flags]Flags:-c <channel name> - Name of channel to deploy chaincode to-ccn <name> - Chaincode name.-ccl <language> - Programming language of chaincode to deploy: go, 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. When a function is provided, the execution of init will be requested and the function will be invoked.-h - Print this messagePossible Mode and flag combinationsdeployCC -ccn -ccl -ccv -ccs -ccp -cci -r -d -verboseExamples:network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-javascript/ ./ -ccl javascriptnetwork.sh deployCC -ccn mychaincode -ccp ./user/mychaincode -ccv 1 -ccl javascript

4.2、使用deployCC部署链码

./network.sh deployCC -c tracychannel -ccn basic -ccl go -ccv 2 -ccs 2 -ccp ../asset-transfer-basic/chaincode-go/

[root@localhost test-network]# ./network.sh deployCC -c tracychannel -ccn basic -ccl go -ccv 2 -ccs 2 -ccp ../asset-transfer-basic/chaincode-go/
Using docker and docker-compose
deploying chaincode on channel 'tracychannel'
executing with the following
- CHANNEL_NAME: tracychannel
- CC_NAME: basic
- CC_SRC_PATH: ../asset-transfer-basic/chaincode-go/
- CC_SRC_LANGUAGE: go
- CC_VERSION: 2
- CC_SEQUENCE: 2
- CC_END_POLICY: NA
- CC_COLL_CONFIG: NA
- CC_INIT_FCN: NA
- DELAY: 3
- MAX_RETRY: 5
- VERBOSE: false
Vendoring Go dependencies at ../asset-transfer-basic/chaincode-go/
/home/gopath/src/github.com/hyperledger/fabric-samples/asset-transfer-basic/chaincode-go /home/gopath/src/github.com/hyperledger/fabric-samples/test-network
/home/gopath/src/github.com/hyperledger/fabric-samples/test-network
Finished vendoring Go dependencies
+ peer lifecycle chaincode package basic.tar.gz --path ../asset-transfer-basic/chaincode-go/ --lang golang --label basic_2
+ res=0
Chaincode is packaged
Installing chaincode on peer0.org1...
Using organization 1
+ peer lifecycle chaincode install basic.tar.gz
+ res=0
2022-10-12 02:07:22.101 CST 0001 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Installed remotely: response:<status:200 payload:"\nHbasic_2:228a0fc53601ffa1a02c38684534133de993c5e980077edc3e6d0141a9fca4a2\022\007basic_2" >
2022-10-12 02:07:22.101 CST 0002 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Chaincode code package identifier: basic_2:228a0fc53601ffa1a02c38684534133de993c5e980077edc3e6d0141a9fca4a2
Chaincode is installed on peer0.org1
Install chaincode on peer0.org2...
Using organization 2
+ peer lifecycle chaincode install basic.tar.gz
+ res=0
2022-10-12 02:07:31.538 CST 0001 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Installed remotely: response:<status:200 payload:"\nHbasic_2:228a0fc53601ffa1a02c38684534133de993c5e980077edc3e6d0141a9fca4a2\022\007basic_2" >
2022-10-12 02:07:31.538 CST 0002 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Chaincode code package identifier: basic_2:228a0fc53601ffa1a02c38684534133de993c5e980077edc3e6d0141a9fca4a2
Chaincode is installed on peer0.org2
Using organization 1
+ peer lifecycle chaincode queryinstalled
+ res=0
Installed chaincodes on peer:
Package ID: marriage_5.0:5b1643320e134816113b2b56344dc62eb4f3c03ccf0922f203f5a435f089a27a, Label: marriage_5.0
Package ID: marriage_6.0:ed4871dd8ea92ada34a86177246a2b09a7f95459d4e9d693997bd55e6e946417, Label: marriage_6.0
Package ID: marriage_7.0:ae39c2a9ec16e025fb0cb202245fb90a95cc78df66c290c10c79dd903d889998, Label: marriage_7.0
Package ID: basic_2:228a0fc53601ffa1a02c38684534133de993c5e980077edc3e6d0141a9fca4a2, Label: basic_2
Package ID: marriage_1.0:925646ffd9f02e51a860a94366685ebd78dbbd1416839f505fbe81c660c66266, Label: marriage_1.0
Package ID: marriage_3.0:a3479c2dabe5451cdbe7851aefa3de52c19f882ef9898a194cf88b292056e08a, Label: marriage_3.0
Package ID: marriage_4.0:4bb04c3808309e75d226c0450595b602bbc78f1dbc7edb7cc02dd8ea426d380b, Label: marriage_4.0
Package ID: marriage_8:e0f08bb9c7447f2da1efb9481ed0998278a7913993feda42981a3980153e6b9e, Label: marriage_8
Package ID: basic_1:edf534ff779c873877e0552c894053a1f02263fc7213ac8b91425ec014bef426, Label: basic_1
Package ID: marriage_2.0:f7ee6e4bff33e4ad7e28060f5d6528550489f1409d0acbd44236974a699ef6a7, Label: marriage_2.0
Query installed successful on peer0.org1 on channel
Using organization 1
+ peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /home/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem --channelID tracychannel --name basic --version 2 --package-id basic_2:228a0fc53601ffa1a02c38684534133de993c5e980077edc3e6d0141a9fca4a2 --sequence 2
+ res=0
2022-10-12 02:07:33.638 CST 0001 INFO [chaincodeCmd] ClientWait -> txid [f43136a5bc8ec1100d201931c4fec26084c5aed67f30c006fe1b6e0e945ebf8c] committed with status (VALID) at localhost:7051
Chaincode definition approved on peer0.org1 on channel 'tracychannel'
Using organization 1
Checking the commit readiness of the chaincode definition on peer0.org1 on channel 'tracychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org1, Retry after 3 seconds.
+ peer lifecycle chaincode checkcommitreadiness --channelID tracychannel --name basic --version 2 --sequence 2 --output json
+ res=0
{"approvals": {"Org1MSP": true,"Org2MSP": false}
}
Checking the commit readiness of the chaincode definition successful on peer0.org1 on channel 'tracychannel'
Using organization 2
Checking the commit readiness of the chaincode definition on peer0.org2 on channel 'tracychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org2, Retry after 3 seconds.
+ peer lifecycle chaincode checkcommitreadiness --channelID tracychannel --name basic --version 2 --sequence 2 --output json
+ res=0
{"approvals": {"Org1MSP": true,"Org2MSP": false}
}
Checking the commit readiness of the chaincode definition successful on peer0.org2 on channel 'tracychannel'
Using organization 2
+ peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /home/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem --channelID tracychannel --name basic --version 2 --package-id basic_2:228a0fc53601ffa1a02c38684534133de993c5e980077edc3e6d0141a9fca4a2 --sequence 2
+ res=0
2022-10-12 02:07:41.780 CST 0001 INFO [chaincodeCmd] ClientWait -> txid [b2354d11c5a12acdc209e4d6cb36409ed1a6ee6de075d1fa274ebcb567965ea0] committed with status (VALID) at localhost:9051
Chaincode definition approved on peer0.org2 on channel 'tracychannel'
Using organization 1
Checking the commit readiness of the chaincode definition on peer0.org1 on channel 'tracychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org1, Retry after 3 seconds.
+ peer lifecycle chaincode checkcommitreadiness --channelID tracychannel --name basic --version 2 --sequence 2 --output json
+ res=0
{"approvals": {"Org1MSP": true,"Org2MSP": true}
}
Checking the commit readiness of the chaincode definition successful on peer0.org1 on channel 'tracychannel'
Using organization 2
Checking the commit readiness of the chaincode definition on peer0.org2 on channel 'tracychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org2, Retry after 3 seconds.
+ peer lifecycle chaincode checkcommitreadiness --channelID tracychannel --name basic --version 2 --sequence 2 --output json
+ res=0
{"approvals": {"Org1MSP": true,"Org2MSP": true}
}
Checking the commit readiness of the chaincode definition successful on peer0.org2 on channel 'tracychannel'
Using organization 1
Using organization 2
+ peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /home/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem --channelID tracychannel --name basic --peerAddresses localhost:7051 --tlsRootCertFiles /home/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem --peerAddresses localhost:9051 --tlsRootCertFiles /home/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem --version 2 --sequence 2
+ res=0
2022-10-12 02:07:50.017 CST 0001 INFO [chaincodeCmd] ClientWait -> txid [46253162c9f92d8c5adbec13805139658a335e27c5d7f85396bf2753b165db6a] committed with status (VALID) at localhost:9051
2022-10-12 02:07:50.050 CST 0002 INFO [chaincodeCmd] ClientWait -> txid [46253162c9f92d8c5adbec13805139658a335e27c5d7f85396bf2753b165db6a] committed with status (VALID) at localhost:7051
Chaincode definition committed on channel 'tracychannel'
Using organization 1
Querying chaincode definition on peer0.org1 on channel 'tracychannel'...
Attempting to Query committed status on peer0.org1, Retry after 3 seconds.
+ peer lifecycle chaincode querycommitted --channelID tracychannel --name basic
+ res=0
Committed chaincode definition for chaincode 'basic' on channel 'tracychannel':
Version: 2, Sequence: 2, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]
Query chaincode definition successful on peer0.org1 on channel 'tracychannel'
Using organization 2
Querying chaincode definition on peer0.org2 on channel 'tracychannel'...
Attempting to Query committed status on peer0.org2, Retry after 3 seconds.
+ peer lifecycle chaincode querycommitted --channelID tracychannel --name basic
+ res=0
Committed chaincode definition for chaincode 'basic' on channel 'tracychannel':
Version: 2, Sequence: 2, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]
Query chaincode definition successful on peer0.org2 on channel 'tracychannel'
Chaincode initialization is not required

4.3、编译部署脚本

4.3.1、创建脚本文件

vi install-cc.sh

[root@localhost test-network]# vi install-cc.sh

4.3.2、编译脚本文件

#!/bin/bash# 验证参数个数
if [ $# != 4 ]; then echo "the count of paramter is not 4";exit;
ficc_name=$1        #链码名称
cc_version=$2     #版本号
cc_sequence=$3    #序号
cc_path=$4        #源码路径./network.sh deployCC -c tracychannel -ccn $cc_name -ccl go -ccv $cc_version -ccs $cc_sequence -ccp $cc_path

按Esc退出编译, 输入:wq 保存文件并退出

4.3.3、执行脚本文件

./install-cc.sh basic 1 1 ../asset-transfer-basic/chaincode-go/

以下可以看到,与4.2执行结果相同(版本号与序号不一样)

[root@localhost test-network]# ./install-cc.sh basic 1 1 ../asset-transfer-basic/chaincode-go/
Using docker and docker-compose
deploying chaincode on channel 'tracychannel'
executing with the following
- CHANNEL_NAME: tracychannel
- CC_NAME: basic
- CC_SRC_PATH: ../asset-transfer-basic/chaincode-go/
- CC_SRC_LANGUAGE: go
- CC_VERSION: 1
- CC_SEQUENCE: 1
- CC_END_POLICY: NA
- CC_COLL_CONFIG: NA
- CC_INIT_FCN: NA
- DELAY: 3
- MAX_RETRY: 5
- VERBOSE: false
Vendoring Go dependencies at ../asset-transfer-basic/chaincode-go/
/home/gopath/src/github.com/hyperledger/fabric-samples/asset-transfer-basic/chaincode-go /home/gopath/src/github.com/hyperledger/fabric-samples/test-network
/home/gopath/src/github.com/hyperledger/fabric-samples/test-network
Finished vendoring Go dependencies
+ peer lifecycle chaincode package basic.tar.gz --path ../asset-transfer-basic/chaincode-go/ --lang golang --label basic_1
+ res=0
Chaincode is packaged
Installing chaincode on peer0.org1...
Using organization 1
+ peer lifecycle chaincode install basic.tar.gz
+ res=0
2022-10-12 02:02:24.752 CST 0001 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Installed remotely: response:<status:200 payload:"\nHbasic_1:edf534ff779c873877e0552c894053a1f02263fc7213ac8b91425ec014bef426\022\007basic_1" >
2022-10-12 02:02:24.753 CST 0002 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Chaincode code package identifier: basic_1:edf534ff779c873877e0552c894053a1f02263fc7213ac8b91425ec014bef426
Chaincode is installed on peer0.org1
Install chaincode on peer0.org2...
Using organization 2
+ peer lifecycle chaincode install basic.tar.gz
+ res=0
2022-10-12 02:02:34.474 CST 0001 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Installed remotely: response:<status:200 payload:"\nHbasic_1:edf534ff779c873877e0552c894053a1f02263fc7213ac8b91425ec014bef426\022\007basic_1" >
2022-10-12 02:02:34.474 CST 0002 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Chaincode code package identifier: basic_1:edf534ff779c873877e0552c894053a1f02263fc7213ac8b91425ec014bef426
Chaincode is installed on peer0.org2
Using organization 1
+ peer lifecycle chaincode queryinstalled
+ res=0
Installed chaincodes on peer:
Package ID: marriage_1.0:925646ffd9f02e51a860a94366685ebd78dbbd1416839f505fbe81c660c66266, Label: marriage_1.0
Package ID: marriage_5.0:5b1643320e134816113b2b56344dc62eb4f3c03ccf0922f203f5a435f089a27a, Label: marriage_5.0
Package ID: marriage_6.0:ed4871dd8ea92ada34a86177246a2b09a7f95459d4e9d693997bd55e6e946417, Label: marriage_6.0
Package ID: marriage_7.0:ae39c2a9ec16e025fb0cb202245fb90a95cc78df66c290c10c79dd903d889998, Label: marriage_7.0
Package ID: basic_1:edf534ff779c873877e0552c894053a1f02263fc7213ac8b91425ec014bef426, Label: basic_1
Package ID: marriage_2.0:f7ee6e4bff33e4ad7e28060f5d6528550489f1409d0acbd44236974a699ef6a7, Label: marriage_2.0
Package ID: marriage_3.0:a3479c2dabe5451cdbe7851aefa3de52c19f882ef9898a194cf88b292056e08a, Label: marriage_3.0
Package ID: marriage_4.0:4bb04c3808309e75d226c0450595b602bbc78f1dbc7edb7cc02dd8ea426d380b, Label: marriage_4.0
Package ID: marriage_8:e0f08bb9c7447f2da1efb9481ed0998278a7913993feda42981a3980153e6b9e, Label: marriage_8
Query installed successful on peer0.org1 on channel
Using organization 1
+ peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /home/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem --channelID tracychannel --name basic --version 1 --package-id basic_1:edf534ff779c873877e0552c894053a1f02263fc7213ac8b91425ec014bef426 --sequence 1
+ res=0
2022-10-12 02:02:36.576 CST 0001 INFO [chaincodeCmd] ClientWait -> txid [df1759d59ddfb01450b6fa11f75410f36fa826020d716b7fe17537b1aea09b05] committed with status (VALID) at localhost:7051
Chaincode definition approved on peer0.org1 on channel 'tracychannel'
Using organization 1
Checking the commit readiness of the chaincode definition on peer0.org1 on channel 'tracychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org1, Retry after 3 seconds.
+ peer lifecycle chaincode checkcommitreadiness --channelID tracychannel --name basic --version 1 --sequence 1 --output json
+ res=0
{"approvals": {"Org1MSP": true,"Org2MSP": false}
}
Checking the commit readiness of the chaincode definition successful on peer0.org1 on channel 'tracychannel'
Using organization 2
Checking the commit readiness of the chaincode definition on peer0.org2 on channel 'tracychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org2, Retry after 3 seconds.
+ peer lifecycle chaincode checkcommitreadiness --channelID tracychannel --name basic --version 1 --sequence 1 --output json
+ res=0
{"approvals": {"Org1MSP": true,"Org2MSP": false}
}
Checking the commit readiness of the chaincode definition successful on peer0.org2 on channel 'tracychannel'
Using organization 2
+ peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /home/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem --channelID tracychannel --name basic --version 1 --package-id basic_1:edf534ff779c873877e0552c894053a1f02263fc7213ac8b91425ec014bef426 --sequence 1
+ res=0
2022-10-12 02:02:44.715 CST 0001 INFO [chaincodeCmd] ClientWait -> txid [b52d52b514da29cb6a6234f5fe1e2e05f8fb181da8f46e7548efcccbd593dd47] committed with status (VALID) at localhost:9051
Chaincode definition approved on peer0.org2 on channel 'tracychannel'
Using organization 1
Checking the commit readiness of the chaincode definition on peer0.org1 on channel 'tracychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org1, Retry after 3 seconds.
+ peer lifecycle chaincode checkcommitreadiness --channelID tracychannel --name basic --version 1 --sequence 1 --output json
+ res=0
{"approvals": {"Org1MSP": true,"Org2MSP": true}
}
Checking the commit readiness of the chaincode definition successful on peer0.org1 on channel 'tracychannel'
Using organization 2
Checking the commit readiness of the chaincode definition on peer0.org2 on channel 'tracychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org2, Retry after 3 seconds.
+ peer lifecycle chaincode checkcommitreadiness --channelID tracychannel --name basic --version 1 --sequence 1 --output json
+ res=0
{"approvals": {"Org1MSP": true,"Org2MSP": true}
}
Checking the commit readiness of the chaincode definition successful on peer0.org2 on channel 'tracychannel'
Using organization 1
Using organization 2
+ peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /home/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem --channelID tracychannel --name basic --peerAddresses localhost:7051 --tlsRootCertFiles /home/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem --peerAddresses localhost:9051 --tlsRootCertFiles /home/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem --version 1 --sequence 1
+ res=0
2022-10-12 02:02:52.972 CST 0001 INFO [chaincodeCmd] ClientWait -> txid [ee426616c430d4e75f901cae0f59c8942b016beaf2c0e8f1808a0e22b45b3643] committed with status (VALID) at localhost:7051
2022-10-12 02:02:52.982 CST 0002 INFO [chaincodeCmd] ClientWait -> txid [ee426616c430d4e75f901cae0f59c8942b016beaf2c0e8f1808a0e22b45b3643] committed with status (VALID) at localhost:9051
Chaincode definition committed on channel 'tracychannel'
Using organization 1
Querying chaincode definition on peer0.org1 on channel 'tracychannel'...
Attempting to Query committed status on peer0.org1, Retry after 3 seconds.
+ peer lifecycle chaincode querycommitted --channelID tracychannel --name basic
+ res=0
Committed chaincode definition for chaincode 'basic' on channel 'tracychannel':
Version: 1, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]
Query chaincode definition successful on peer0.org1 on channel 'tracychannel'
Using organization 2
Querying chaincode definition on peer0.org2 on channel 'tracychannel'...
Attempting to Query committed status on peer0.org2, Retry after 3 seconds.
+ peer lifecycle chaincode querycommitted --channelID tracychannel --name basic
+ res=0
Committed chaincode definition for chaincode 'basic' on channel 'tracychannel':
Version: 1, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]
Query chaincode definition successful on peer0.org2 on channel 'tracychannel'
Chaincode initialization is not required

5、总结

  • 分析代码,链码的创建、启动与存储
  • 启动测试网络,同时创建一个channel,在channel中进行链码部署 ./network.sh up createChannel
  • 生成项目依赖  GO111MODULE=on go mod vendor
  • 打包链码 peer lifecycle chaincode package
  • 安装链码 peer lifecycle chaincode install (不同的组织分别安装)
  • 查看链码安装结果: peer lifecycle chaincode queryinstalled
  • 授权链码 peer lifecycle chaincode approveformyorg (不同的组织分别授权)
  • 查看链码授权结果:peer lifecycle chaincode checkcommitreadiness
  • 提交链码 peer lifecycle chaincode commit
  • 查看链码提交结果:peer lifecycle chaincode querycommitted
  • 调用链码写入数据:peer chaincode invoke
  • 查看链码读取数据:peer chaincode query
  • 链码升级:注意更新版本号vesion及序号sequence
  • 使用deployCC部署链码:./network.sh deployCC

Fabric-samples asset-transfer-basic 链码部署与升级(Fabric 2.4.4)相关推荐

  1. (Fabric 学习二)测试fabric2.0 test-network使用basic链码

    这是更新,上一次写的错误很多,这次来更新一下! 以下是参考: Hyperledger 学习(二):超级账本链码部署及调用(上:官方示例测试)_王三三的博客-CSDN博客 尝试链码编写及部署测试_rou ...

  2. Python—自动化部署工具:Fabric

    Fabric是python编写的一款自动化部署工具 Fabric依赖paramiko进行SSH交互,某种意义上Fabric是对paramiko的封装,封装完成后,不需要像使用paramiko一样处理S ...

  3. Hyperledger Fabric 1.4 Kafka集群部署教程

    Hyperledger Fabric 1.4 Kafka集群部署教程 作者:区块链教程 时间:2019/12/08 10:36 标签:Docker ComposeDockerYMLHyperledge ...

  4. 基于本地部署的hyperledger fabric升级chaincode

    上个版本的chaincode有很多功能不完备,所以要部署新版本的chaincode.Fabric支持在保留现有状态的前提对chaincode进行升级. 一.新版chaincode 新版本的chainc ...

  5. 用Kubernetes部署超级账本Fabric的区块链即服务(1)

    用Kubernetes部署超级账本Fabric的区块链即服务(1) 2017年08月13日 00:00:00 阅读数:937 题图摄于旧金山市区:云海中的 Twin Peaks 不久前,我们发表了如何 ...

  6. 用Kubernetes部署超级账本Fabric的区块链即服务

    关注微信公众号 区块链大本营,学习更多区块链技术及应用知识. 区块链行业投稿,请邮件联系 jiawd@csdn.net 本文将探讨如何把 Fabric v1.0自动化部署在现今最流行的 Kuberne ...

  7. 【Fabric】简单测试:链码单元测试+fabric-go-sdk

    纯粹记录一下,也不知道干了啥~ 链码单元测试 在Ubuntu中安装VScode 下载安装包 打开Ubuntu的火狐,访问网址:https://code.visualstudio.com/docs=&g ...

  8. 多个 vCenter Server 实例部署的升级或迁移顺序以及混合版本转换行为

    多个 vCenter Server 实例部署的升级或迁移顺序以及混合版本转换行为 VMware vSphere 6.5 https://docs.vmware.com/cn/VMware-vSpher ...

  9. java war包更新 部署_关于Linux系统下基于Tomcat部署和升级war包的详细过程

    1.首先Linux先安装java,Tomcat 中间件规范要求: 1)         软件必须下载到/services/download_soft_v        --------(用xftp上传 ...

最新文章

  1. 【分析函数】Oracle分析函数之LAG和LEAD
  2. AI:几张图理清人工智能与机器学习、知识发现、数据挖掘、统计学、模式识别、神经计算学、数据库之间的暧昧关系
  3. matlab eeg信号处理,EEG数据信号的Matlab滤波仿真设计分析研究
  4. TP5 上传文件 中文乱码问题
  5. java实现三个数字的随机组合_JAVA编程实现随机生成指定长度的密码功能【大小写和数字组合】...
  6. 从最大似然估计到最小二乘法
  7. Spring Data JPA 从入门到精通~方法的查询策略的属性表达式
  8. Build String(CF-237E)
  9. python pip有什么用_pip的介绍和使用
  10. Java:输出“水仙花数”
  11. NO3 cat-xargs-cp-mv-rm-find命令
  12. django文件——django + jquery-file-upload上传篇(二)-- 插件实现文件上传+进度条显示 +拖入文件上传...
  13. Go gorilla websocket 小试牛刀
  14. Mismatch between array dtype (‘<U40‘) and format specifier (‘%.18e‘)
  15. Word 2007 目录生成技巧
  16. 高校校园网络设计与实现
  17. UE4遇到的各种奇葩问题
  18. 怎么给视频添加水印?几个简单的步骤就搞定
  19. web自动化测试-第五讲: 三大切换
  20. 丘比特之箭——知乎多场景内容匹配项目:实现各种不同类型的文本之间的准确匹配 |百万人学AI评选

热门文章

  1. Happy 1024!
  2. 2020疫情经济盘点:二手经济化身新消费风口
  3. 优思学院:初学者应如何自学ISO9001质量管理体系?
  4. 看好股市的新人说港股投资
  5. DP和HDMI有什么区别?DP1.4和DP1.2线材怎么选?显示器视频带宽如何计算?
  6. 常用图像数据集:标注、检索
  7. Android rom ram sd卡 区别
  8. MacBook M1苹果电脑安装 brew
  9. Dota2锁区steam下载国际服办法
  10. 软件通用自动更新系统