标签:network ber 操作 排序 min 本地 方式 shell 出现
智能合约在 Hyperledger Fabric 中称为链码(chaincode),是提供分布式账本的状态处理逻辑。链码被部署在fabric 的网络节点中,能够独立运行在具有安全特性的受保护的 Docker 容器中,以 gRPC 协议与相应的 peer 节点进行通信,以操作分布式账本中的数据。
一般链码分为两种:系统链码和用户链码。
负责 Fabric 节点自身的处理逻辑,包括系统配置、背书、校验等工作,在 Peer 节点启动时会自动完成注册和部署。系统链码分为以下五种:
生命周期系统链码(Lifecycle System Chaincode,LSCC):负责对用户链码的生命周期进行管理;
验证系统链码(Validation System Chaincode,VSCC):处理交易的验证,包括检查背书策略以及多版本并发控制。
用户链码不同于系统链码,系统链码是 fabric 的内置链码,而用户链码是由应用程序开发人员根据不同场景需求编写的基于分布式账本的状态的业务处理逻辑代码,运行在链码容器中,通过 Fabric 提供的接口与账本状态进行交互。
用户链码向下可对账本数据进行操作,向上可以给企业级应用程序提供调用接口。
管理 Chaincode 的生命周期共有五个命令:
install:将已编写完成的链码安装在网络节点中;
instantiate:对已安装的链码进行实例化;
upgrade:对已有链码进行升级,链代码可以在安装后根据具体需求的变化进行升级;
package:对指定的链码进行打包的操作。
singnpackage:对已打包的文件进行签名。
我们使用 fabric v1.4.3 版本的 fabric-samples 提供的 first-network 网络进行说明,修改 first-network/scripts/script.sh
脚本中的下列代码:
# 将判断语句中的 true 改为 false,first-network 网络就不会进行链码的安装、实例化等操作
if [ "${NO_CHAINCODE}" != "false" ]; then
## Install chaincode on peer0.org1 and peer0.org2
echo "Installing chaincode on peer0.org1..."
installChaincode 0 1
echo "Install chaincode on peer0.org2..."
installChaincode 0 2
#...
#...
fi
启动 first-network 网络:
$ ./byfn.sh up
进入 CLI 客户端容器,CLI 客户端默认以 Admin.org1 身份连接 peer0.org1 节点:
$ docker exec -it cli bash
检查当前节点(peer0.org1.example.com)以加入哪些通道:
# peer channel list
执行结果返回:
Channels peers has joined:
mychannel
说明当前节点已经加入通道 mychannel。
使用 install 命令安装链码:
# peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
执行结果返回:
[chaincodeCmd] install -> INFO 04c Installed remotely response:<status:200 payload:"OK" >
说明链码成功安装至 peer 节点中。
注意:链码需要根据指定的背书策略安装在需要背书的所有 peer 节点中。未安装链码的节点不能执行链码逻辑,但仍可以验证交易并提交到账本中。
设置通道名称的环境变量:
# export CHANNEL_NAME=mychannel
# echo $CHANNEL_NAME
设置 orderer 节点的证书路径的环境变量:
# export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
# echo $ORDERER_CA
使用 instantiate 命令进行链码的实例化:
# peer chaincode instantiate -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "OR ('Org1MSP.peer','Org2MSP.peer')"
背书策略的背书实体一般表示为:MSP.ROLE
,其中 MSP 是 MSP ID
,ROLE 支持 client、peer、admin 和 member 四种角色。 例如: Org1MSP.admin
表示 Org1 这个 MSP 下的任意管理员; Org1MSP.member
表示 Org1 这个 MSP 下的任意成员。
背书策略语法结构如下:
// 基础表达式形式,EXPR 可以是 AND、OR 和 OutOf 逻辑符,E 是实体或者嵌套的表达式
EXPR(E[, E...])
// 需要三个组织 org1、org2 和 org3 的 member 共同背书签名
AND('Org1MSP.member', 'Org2MSP.member', 'Org3MSP.member')
// 需要 org1 和 org2 其中一个组织的 member 背书签名
OR('Org1MSP.member', 'Org2MSP.member')
// 需要 Org1 的 admin 背书,或者 Org2 和 Org3 下的 member 共同背书签名
OR('Org1MSP.admin', AND('Org2MSP.member', 'Org3MSP.member'))
// 需要 org1、org2、org3 的 member 的至少两个背书签名
OutOf(2, 'Org1MSP.member', 'Org2MSP.member', 'Org3MSP.member')
注意:链码需要安装在多个背书的 Peer 节点中,但实例化只需执行一次。
链码部署成功之后,可以通过特定的命令调用链码,从而发起交易或查询请求,对账本数据进行操作。
使用 query 命令查询链码:
# peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
执行成功后,返回输出结果 100。
客户端发起交易,对账本数据进行更改,需要将背书之后的交易发送给排序节点上链。因此,需要开启 TLS 验证并指定对应的 orderer 证书路径。
需要注意,链码执行查询操作和执行事务(改变账本数据)操作的流程是不同的:
使用 invoke 命令调用链码:
# peer chaincode invoke -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}'
执行返回以下结果,说明交易执行成功:
[chaincodeCmd] chaincodeInvokeOrQuery -> INFO 04c Chaincode invoke successful. result: status:200
再次查询 a 账户的余额,如果执行结果返回 90,说明交易被正确执行了:
# peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
注意:如果交易需要多个背书节点的背书,可以使用 --peerAddresses
标志指定节点。例如:交易需要 peer0.org1 和 peer0.org2 的共同背书:
# peer chaincode invoke -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc --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":["invoke","a","b","10"]}'
链码部署除了正常的安装、实例化操作步骤之外,还有一种部署方式,即先将链码进行打包,然后对已打包的文件进行签名,最后再进行安装与实例的操作。
使用如下的命令进行打包操作:
# peer chaincode package -n exacc -v 1.0 -p github.com/chaincode/chaincode_example02/go/ -s -S -i "AND('Org1MSP.admin')" ccpack.out
参数说明:
打包后的文件可以直接使用 install 命令安装,如:peer chaincode install ccpack.out
,但是一般对打包后的文件签名再进一步安装。
使用如下的命令对打包文件进行签名操作(添加当前 MSP 签名到签名列表中):
# peer chaincode signpackage ccpack.out signedccpack.out
signedccpack.out
包含一个用本地 MSP 对包进行的附加签名。
安装已签名的打包文件:
# peer chaincode install signedccpack.out
对已安装的链码进行实例化操作,指定背书策略:
# peer chaincode instantiate -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n exacc -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "OR ('Org1MSP.peer','Org2MSP.peer')"
测试:
使用如下命令查询链码,输出结果为 100:
# peer chaincode query -C $CHANNEL_NAME -n exacc -c '{"Args":["query","a"]}'
使用如下命令调用链码进行转账操作:
# peer chaincode invoke -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n exacc -c '{"Args":["invoke","a","b","10"]}'
使用如下命令再次查询链码,输出结果为 90:
# peer chaincode query -C $CHANNEL_NAME -n exacc -c '{"Args":["query","a"]}'
首先,先对修改之后的链码进行安装:
# peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go/
然后,使用如下命令对已安装的链码进行升级:
# peer chaincode upgrade -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -v 2.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "OR ('Org1MSP.peer','Org2MSP.peer')"
测试:
使用如下命令查询链码,输出结果为 100:
# peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
使用如下命令调用链码进行转账操作:
# peer chaincode invoke -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}'
使用如下命令再次查询链码,输出结果为 90:
# peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
需要注意的是,升级过程中,chaincode 的 Init 函数会被调用以执行数据相关的操作,或者重新初始化数据;所以需要多加小心,以避免在升级 chaincode 时重设状态信息。
使用 docker ps
命令可以查看到当前网络中有以下三个链码容器启动:
dev-peer0.org1.example.com-mycc-1.0
dev-peer0.org1.example.com-mycc-2.0
dev-peer0.org1.example.com-exacc-1.0
使用 docker logs
命令可以查看链码日志:
$ docker logs dev-peer0.org1.example.com-mycc-1.0
ex02 Init
Aval = 100, Bval = 200
ex02 Invoke
Query Response:{"Name":"a","Amount":"100"}
ex02 Invoke
Aval = 90, Bval = 210
ex02 Invoke
Query Response:{"Name":"a","Amount":"90"}
$ docker logs dev-peer0.org1.example.com-mycc-2.0
ex02 Init
Aval = 100, Bval = 200
ex02 Invoke
Query Response:{"Name":"a","Amount":"100"}
ex02 Invoke
Aval = 90, Bval = 210
ex02 Invoke
Query Response:{"Name":"a","Amount":"90"}
$ docker logs dev-peer0.org1.example.com-exacc-1.0
ex02 Init
Aval = 100, Bval = 200
ex02 Invoke
Query Response:{"Name":"a","Amount":"100"}
ex02 Invoke
Aval = 90, Bval = 210
ex02 Invoke
Query Response:{"Name":"a","Amount":"90"}
上述过程是在 first-network 网络下的链码测试,但是该网络下的链码测试过于复杂,需要指定很多参数,如果只是想测试所编写的链码的正确性,可以使用 dev 开发模式。
进入 chaincode-docker-devmode
目录:
$ cd ./fabric-samples/chaincode-docker-devmode/
该目录下存在如下五个文件:
使用如下命令启动网络:
$ docker-compose -f docker-compose-simple.yaml up -d
Creating network "chaincodedockerdevmode_default" with the default driver
Creating orderer ...
Creating orderer ... done
Creating peer ...
Creating peer ... done
Creating cli ...
Creating chaincode ...
Creating cli
Creating cli ... done
以开发模式开启 peer,还启动了两个容器:chaincode 容器,用于链码环境;CLI 容器,用于与链码进行交互,其中创建和连接通道的命令已经被嵌入 CLI 容器中了,所以可以直接进行链码调用。
使用如下命令进入 chaincode 容器 :
$ docker exec -it chaincode bash
出现如下结果,则运行成功:
root@d32997378218:/opt/gopath/src/chaincode#
查看该 chaincode 容器的定义:
chaincode:
container_name: chaincode
image: hyperledger/fabric-ccenv
tty: true
environment:
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- FABRIC_LOGGING_SPEC=DEBUG
- CORE_PEER_ID=example02
- CORE_PEER_ADDRESS=peer:7051
- CORE_PEER_LOCALMSPID=DEFAULT
- CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp
working_dir: /opt/gopath/src/chaincode
command: /bin/sh -c 'sleep 6000000'
volumes:
- /var/run/:/host/var/run/
- ./msp:/etc/hyperledger/msp
- ./../chaincode:/opt/gopath/src/chaincode
depends_on:
- orderer
- peer
该容器的当前目录 /opt/gopath/src/chaincode
对应本地系统中的 ./../chaincode
,我们使用该目录下的 chaincode_example02 链码进行测试。进入 chaincode_example02/go/
目录编译链码:
# cd chaincode_example02/go/
# go build
使用如下命令启动并运行链码:
# CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=mycc:0 ./go
命令含义:
CORE_PEER_ADDRESS:用于指定 peer,其中 7052 端口是链码的专用监听端口(7051 是 peer 节点监听的网络端口)
开启一个新的终端,使用如下命令进行 CLI 容器:
$ docker exec -it cli bash
进入 CLI 容器后,使用如下命令安装链码:
# peer chaincode install -p chaincodedev/chaincode/chaincode_example02/go -n mycc -v 0
使用如下命令实例化链码:
# peer chaincode instantiate -n mycc -v 0 -c '{"Args":["init","a", "100", "b","200"]}' -C myc
测试:
使用如下命令查询链码,输出结果为 100:
# peer chaincode query -n mycc -c '{"Args":["query","a"]}' -C myc
使用如下命令调用链码进行转账操作:
# peer chaincode invoke -n mycc -c '{"Args":["invoke","a","b","10"]}' -C myc
使用如下命令再次查询链码,输出结果为 90:
# peer chaincode query -n mycc -c '{"Args":["query","a"]}' -C myc
使用如下命令关闭测试网络:
$ docker-compose -f docker-compose-simple.yaml down
- 《Hyperledger Fabric 菜鸟进阶攻略》
标签:network ber 操作 排序 min 本地 方式 shell 出现
原文地址:https://www.cnblogs.com/zongmin/p/11842562.html