在fabric中,共识过程意味着多个节点对于某一批交易的发生顺序、合法性以及它们对账本状态的更新结构达成一致的观点。满足共识则意味着多个节点可以始终保证相同的状态,对于以同样顺序到达的交易可以进行一致的处理。
具体来看,fabric中的共识包括背书、排序和验证三个环节的保障。
我们先来研究下背书策略。
一.什么是背书策略
chaincode在实例化的时候,需要指定背书策略。这里的背书策略就是需要什么节点背书交易才能生效。
发起交易的时候,发起端(一般是SDK),需要指定交易发给哪些节点进行背书验证(fabric不会自动发送),而是由sdk发送。发送后等待背书节点的返回,收集到足够的背书后将交易发送给orderer(排序节点或称共识节点)进行排序打包分发。最后,当每个Peer接受到block数据后,会对其中的交易进行验证,如果交易不符合背书策略,就不会在本地生效,所以真正验证背书是在这一步。
二.Endorsement policy 设计
背书策略有两个主要组成部分:
主体(principal):P定义了期望的签名来源实体
门槛(thshold gate):T有两个参数:整数t(阈值)和n个主体,表示从这n个主体中获取t个签名
例如:
T(2, 'A', 'B', 'C')表示需要A、B、C中任意2个主体的签名背书
T(1, 'A', T(2, 'B', 'C'))表示需要来自主体A的签名或者来自B和C两者的签名背书
三.在CLI中实行背书策略
3.1CLI endorsement policy语法
在CLI中,使用一种简单的语言来表示相对于Principal的布尔表达式的策略。
principal通过MSP进行描述,MSP的任务是验证签名者的身份和签名者在该MSP内的角色。目前,支持两个角色:成员和管理员。
principal被描述为 MSP.ROLE 其中 MSP 是所需的MSP ID,
和 ROLE 是 member 或者 admin 。
有效principle的示例是 ‘Org0.admin’( MSP Org0的任何管理员)或
‘Org1.member’ (Org1 MSP的任何成员)。
语言的语法是:
EXPR(E[, E…])
其中 EXPR 是 AND 或
OR 表示两个布尔表达式,并且 E 是principle(
具有上述语法)或另一个嵌套调用 EXPR 。
例如:
- AND(‘Org1.member’, ‘Org2.member’, ‘Org3.member’) ,请求3个principle的签名。
- OR(‘Org1.member’, ‘Org2.member’) 请求两个中的一个的签名。
- OR(‘Org1.member’, AND(‘Org2.member’, ‘Org3.member’)) ,请求一个来自MSP=red >
Org1 的签名,或者来自MSP=red > org2 的成员和来自=red > Org3 的成员的签名。
3.2为chaincode指定Endorsement policy
通过使用这种语言,chaincode的开发者可以为一个chaincode指定特定的endorsement策略。
注意 - 默认策略需要 DEFAULTMSP 成员的一个签名 )。如果在CLI中未指定策略,则使用此选项。
该策略可以在部署时通过键 -P 来指定。
例如: peer chaincode deploy -C testchainid -n mycc
-p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
-c ‘{“Args”:[“init”,”a”,”100”,”b”,”200”]}’ -P “AND(‘Org1.member’, ‘Org2.member’)”
该命令使用 AND(‘Org1.member’, ‘Org2.member’) 策略,将chaincode
mycc 部署到链testchain上。
四.Node SDK中实行背书
官方实例balance-transfer使用fabric node sdk构建了一个完整的客户端,实现了CLI的完整功能(包括注册用户、创建channel、加入channel、安装链码、实例化链码),并且提供了REST API。但是在balance-transfer在实例化时并未指定背书策略。但是我们可以在实例化请求的Request对象中加入背书策略。
我们可以构建一个endorsement对象。先看两个例子:
4.1 example
背书策略: "由其中一个组织的任何成员签名"
{
identities: [
{ role: { name: "member", mspId: "org1" }},
{ role: { name: "member", mspId: "org2" }}
],
policy: {
"1-of": [{ "signed-by": 0 }, { "signed-by": 1 }]
}
}
背书策略: "ordererOrg的管理员和一个peer组织的成员签名"
{
identities: [
{ role: { name: "member", mspId: "peerOrg1" }},
{ role: { name: "member", mspId: "peerOrg2" }},
{ role: { name: "admin", mspId: "ordererOrg" }}
],
policy: {
"2-of": [
{ "signed-by": 2},
{ "1-of": [{ "signed-by": 0 }, { "signed-by": 1 }]}
]
}
}
4.2 endorsement对象分析
它有两个高级属性:indentities和policy。
Indentities:在policy中引用的身份列表。
Policy:使用“signed-by”和“n-f”结构组合的策略规范。policy可以是对于单个indentities签名的“signed-by”或是“n-of”。如果类型属性是“sign-by”,则该值是策略中指定的indentities数组的数字索引。如果类型属性是“n-of”,则该值是policy对象的数组。正如所看到的,这个结构允许复杂策略的递归定义。
policy是可选的。如果不指定,那么就将采用默认的背书策略:被来自MSPs内任何组织的任何成员签名。不推荐使用默认策略投入实际生产,因为这允许应用绕过请求背书将一个手动构建的具有任意输出的交易直接发送给orderer。应用程序自己的签名将会允许交易成功验证并提交到账本。