1.背书策略的定义
每个链码都有背书策略,背书策略指定了通道上的一组 Peer 节点必须执行链码,并且为执行结果进行背书,以此证明交易是有效的。这些背书策略指定了必须为提案进行背书的组织。
作为Peer节点进行交易验证的一部分,每个 Peer 节点的检查确保了交易保存了合适数量的背书,并且是指定背书节点的背书。这些背书结果的检查,同样确保了它们是有效的(比如,从有效的证书得到的有效签名)。
2.背书策略的分类
根据fabric2.0的官方文档,背书策略共分为三类:链码级别的背书策略、集合级别的背书策略、键级别的背书策略。
3.背书策略的语法
策略是使用主体来表达的(主题是跟角色匹配的)。主体可以描述为'MSP.ROLE'
, MSP 代表了 MSP ID, ROLE 是以下4个其中之一:member, admin, client, and peer。
以下是几个有效的主体示例:
'Org0.admin': Org0 MSP
的任何管理员'Org1.member': Org1 MSP
的任何成员'Org1.client': Org1 MSP
的任何客户端'Org1.peer': Org1 MSP
的任何 Peer
语法是:
EXPR(E[, E...])
EXPR
可以是AND
, OR
, 或者OutOf
, 并且E
是一个以上语法的主体或者另外一个 EXPR
。
比如:AND('Org1.member', 'Org2.member', 'Org3.member')
要求3个组织的都至少一个成员进行签名。OR('Org1.member', 'Org2.member')
要求组织1或者组织2的任一成员进行签名。OR('Org1.member', AND('Org2.member', 'Org3.member'))
要求组织1的任一成员签名,或者组织2和组织3的任一成员,分别进行签名。OutOf(1, 'Org1.member', 'Org2.member')
, 等价于OR(‘Org1.member’, ‘Org2.member’)
。
类似的, OutOf(2, 'Org1.member', 'Org2.member')
等价于 AND('Org1.member', 'Org2.member'), OutOf(2, 'Org1.member', 'Org2.member', 'Org3.member')
等价于 OR(AND('Org1.member', 'Org2.member'), AND('Org1.member', 'Org3.member'), AND('Org2.member', 'Org3.member'))
.
4.设置背书策略
此为前述(修改智能合约)的拓展,所有操作均在修改智能合约后执行。
4.1 链码级别背书策略
链码级别背书策略可以理解为通过简单执行shell指令指定背书。
4.1.1 或逻辑
在pee0.org1和peer0.org2安装链码后,在peer0.org1的环境变量下执行以下指令,使得交易只需任意org1或org2的成员背书。(如不设置,则默认半数以上通道成员进行背书)
- 同意合约
peer lifecycle chaincode approveformyorg --signature-policy "OR('Org1MSP.member','Org2MSP.member')" --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID channel2 --name mycc1 --version 1 --package-id mycc_1:9be809ce61602d4b44000dc1d39dcb3707eb9c132e6cbe8cfe7d7facd26458e3 --sequence 2 –waitForEvent
切换环境变量,重复执行上述指令。
- 提交合约
peer lifecycle chaincode commit -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID channel2 --name mycc1 --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 --version 1 --sequence 2 --signature-policy "OR('Org1MSP.member','Org2MSP.member')"
- 验证背书策略
这里指定背书节点为peer0.org1
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C channel2 -n mycc1 --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 -c '{"Args":["invoke","a","b","10"]}'
查询a的值,如果相较指令执行前,确实减了10,则交易成功。
peer chaincode query -C channel2 -n mycc1 -c '{"Args":["query","a"]}'
4.1.2 与逻辑
- 同意合约
peer lifecycle chaincode approveformyorg --signature-policy "AND('Org1MSP.member','Org2MSP.member')" --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID channel2 --name mycc1 --version 1 --package-id mycc_1:0f82614b848d9f8a3ec49f718c8521709736fe89957c8f1a97918df726f83e51 --sequence 2 --waitForEvent
切换环境变量,重复执行上述指令。
- 提交合约
peer lifecycle chaincode commit -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID channel2 --name mycc1 --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 --version 1 --sequence 2 --signature-policy "AND('Org1MSP.member','Org2MSP.member')"
- 验证背书策略
这里指定背书节点为peer0.org1,测试不满足背书策略时的情况。
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C channel2 -n mycc1 --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 -c '{"Args":["invoke","a","b","10"]}'
查询a的值,相较指令执行前,无变化,交易失败。
peer chaincode query -C channel2 -n mycc1 -c '{"Args":["query","a"]}'
4.2 键级别背书策略
键级别背书策略可以理解为通过编写的链码内部调用SDK来指定背书。
4.2.1 修改链码
- 备份first-network链码源文件
sudo nautilus
通过图形界面备份fabric-samples/chaincode/abstore/go文件,另存为go_origin
- 修改abstore.go文件中的背书策略并保存
4.2.2 下载扩展依赖
- 从图形界面(abstore/go目录)进入到终端,执行如下指令
source ~/.profile #更新环境变量
GO111MODULE=on go mod vendor #更新vendor
- 下载扩展依赖
Go 链码需要 Go 标准库之外的一些依赖包(比如链码 shim)。当链码安装到 peer 的时候,这些报的源码必须被包含在你的链码包中。如果你将你的链码构造为一个模块,最简单的方法就是在打包你的链码之前使用 go mod vendor
来 “vendor” 依赖。
go mod tidy
go mod vendor
这就把你链码的扩展依赖放进了本地的 vendor 目录。
当依赖都引入到你的链码目录后, peer chaincode package
和 peer chaincode install
操作将把这些依赖一起放入链码包中。
- 检验是否获取到相关依赖包
ll vendor/github.com/hyperledger/fabric-chaincode-go/
已获取到pkg和shim包
ll vendor/github.com/hyperledger/fabric-chaincode-go/pkg
已获取到statebased包
- 编译链码
go build
4.2.3 打包链码
peer lifecycle chaincode package mycc_new.tar.gz --path github.com/hyperledger/fabric-samples/chaincode/abstore/go/ --lang golang --label mycc_1
4.2.4 安装链码
peer lifecycle chaincode install mycc_new.tar.gz
4.2.5 同意链码
peer lifecycle chaincode approveformyorg --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID channel2 --name mycc1 --version 1 --package-id mycc_1:1019711c7eebe7f23827321ffc33549708ce2e9e9c95e2983df3ecea5e45de39 --sequence 2 –waitForEvent
切换环境变量,重复4.2.4和4.2.5的操作
4.2.6 提交链码
peer lifecycle chaincode commit -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID channel2 --name mycc1 --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 --version 1 --sequence 2
4.2.7 验证背书策略
- 指定背书策略为Org1 and Org2
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C channel2 -n mycc1 --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":["endorsement","a","Org1MSP","add"]}'
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C channel2 -n mycc1 --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":["endorsement","a","Org2MSP","add"]}'
虽然调用后,会返回Chaincode invoke successful
结果,但交易不一定有效,需要查看peer
容器的日志。
交易成功。
- 检验addTen函数
指定peer0.org1和peer0.org2对a进行加10操作
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C channel2 -n mycc1 --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":["addTen","a"]}'
查询a的状态值
peer chaincode query -C channel2 -n mycc1 -c '{"Args":["query","a"]}'
a值成功加10,表示交易有效。
只指定peer0.org1进行加10操作
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C channel2 -n mycc1 --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 -c '{"Args":["addTen","a"]}'
查询a的状态值
peer chaincode query -C channel2 -n mycc1 -c '{"Args":["query","a"]}'
查看peer日志
a值未发生变化,交易无效。
- 修改背书策略,删除Org2的MSP,检验addTen
只指定Org1
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C channel2 -n mycc1 --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":["endorsement","a","Org2MSP","del"]}'
修改成功也可查看日志,因为每次配置的变化都将记录在账本中。
对a进行加10操作
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C channel2 -n mycc1 --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 -c '{"Args":["addTen","a"]}'
查询a的状态值
peer chaincode query -C channel2 -n mycc1 -c '{"Args":["query","a"]}'
a值成功加10,表示交易有效。