背书策略
背书策略用来定义交易是否合法的判断条件,策略以主体的形式表示。主体格式为'MSP.ROLE', MSP代表所要求的MSPID, ROLE表示角色,一共有四种合法角色:member, admin, client, peer。
背书策略的语法
背书策略的语法如下:
EXPR(E[, E...])
EXPR可以是AND、OR、OutOf,E可以是一个上面示例的主体或者是另一个嵌套的EXPR策略。示例如下:
AND('Org1.member', 'Org2.member', 'Org3.member') :要求三个主体中每一个主体都要签名。
OR('Org1.member', 'Org2.member') :要求三个主体中至少有一个主体签名。
OR('Org1.member', AND('Org2.member', 'Org3.member')):要求同时有主体Org1.member的签名,以及主体Org2.member与Org3.member中至少一个主体的签名。
OutOf(2, 'Org1.member', 'Org2.member', 'Org3.member') :要求三个主体中,至少有两个主体签名。
背书策略的新特性
链码级别的背书策略绑定到相关链码的生命周期中,它只可以在链码初始化时候设置,或者在升级链码时候更新。在fabric1.3版本中,对背书策略进行了优化,增加了背书策略的灵活性。允许针对key设置背书策略,key级别背书策略的设置可以在链码中动态操作。基于key级的背书策略修改会保存在正常交易的读写集中。
如果没有设置基于键级别的背书策略的话,使用的是链码级别的背书策略。设置基于键级的背书策略的请求,需要满足当前的背书策略。
基于键值背书策略的应用
shim包提供了以下的函数设置或者恢复键对应的背书策略。下面的ep代表是“endorsement policy”的缩写。
SetStateValidationParameter(key string, ep []byte) error
GetStateValidationParameter(key string) ([]byte, error)
以上两个函数是设置交易中键级背书策略的函数,针对私有信息中键级别的背书策略用一下两个函数进行设置。
SetPrivateDataValidationParameter(collection, key string, ep []byte) error
GetPrivateDataValidationParameter(collection, key string) ([]byte, error)
为了帮助设置背书策略和将背书策略序列化为有效的字节格式的参数,shim包提供了便利的接口。
type KeyEndorsementPolicy interface {
// Policy returns the endorsement policy as bytes
Policy() ([]byte, error)
// AddOrgs adds the specified orgs to the list of orgs that are required
// to endorse
AddOrgs(roleType RoleType, organizations ...string) error
// DelOrgs delete the specified channel orgs from the existing key-level endorsement
// policy for this KVS key. If any org is not present, an error will be returned.
DelOrgs(organizations ...string) error
// ListOrgs returns an array of channel orgs that are required to endorse changes
ListOrgs() ([]string)
}
基于键级别背书策略的使用示例
此部分主要介绍了如何如何在链码(chaincode)中设置键级别的背书策略。
示例链码主要实现并使用了一下三个接口:
query:查询
endorsement: 设置背书策略
add:账户添加额度
链码的工程代码已经上传到git上,需要测试的话可以去git下载,git地址:https://github.com/suchongming/keylevelep
以下部分是测试的过程,测试环境共运行两个组织Org1和Org2,链码的背书策略AND('Org1.member', 'Org2.member'):
- 开始时候账户a余额为100
root@42ffceeab24e:/opt/gopath/src/github.com/hyperledger/fabric/peer# peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
100
- 账户a向余额添加10,向org1和org2同时背书,a余额为110,交易成功
root@4318321f14d0:/opt/gopath/src/github.com/hyperledger/fabric/peer# peer chaincode invoke -o orderer.example.com:7050 -C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 --peerAddresses peer1.org2.example.com:7051 -c '{"Args":["add","a","10"]}'
2019-06-03 08:50:16.772 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
root@4318321f14d0:/opt/gopath/src/github.com/hyperledger/fabric/peer# peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
110
- 账户a余额添加10,仅向org1背书,a余额为110,交易失败
root@a0b46d997084:/opt/gopath/src/github.com/hyperledger/fabric/peer# peer chaincode invoke -o orderer.example.com:7050 -C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 -c '{"Args":["add","a","10"]}'
2019-06-04 01:24:39.195 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
root@a0b46d997084:/opt/gopath/src/github.com/hyperledger/fabric/peer# peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
110
- 修改账户a的背书策略为AND('Org1.member'),然后账户a余额添加10,仅向org1背书,a余额为120,交易成功
root@a0b46d997084:/opt/gopath/src/github.com/hyperledger/fabric/peer# peer chaincode invoke -o orderer.example.com:7050 -C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 --peerAddresses peer0.org2.example.com:7051 -c '{"Args":["endorsement","a","Org1MSP"]}'
2019-06-04 01:24:27.752 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
root@a0b46d997084:/opt/gopath/src/github.com/hyperledger/fabric/peer# peer chaincode invoke -o orderer.example.com:7050 -C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 -c '{"Args":["add","a","10"]}'
2019-06-04 01:24:39.195 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
root@a0b46d997084:/opt/gopath/src/github.com/hyperledger/fabric/peer# peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
120