Hyperledger Fabric 专题

9. Hyperledger Fabric 专题 - 私有数据

2020-02-24  本文已影响0人  furnace

Hyperledger Fabric 专题 - 私有数据

有可能存在这样一种特殊的需求,对于同属于一个通道的多个组织,其中某些组织构成的子集需要提供额外的数据隐私性,即这些私有数据只能由通道中的子组织查看,而不能被所有组织查看。有一种方法是这些子组织重新定义一个通道,但这样做存在下列缺点:一是有可能创建过多的只包含少数组织的通道;二是通道之间的数据和链码是无法交互的,导致多个通道中的链码实现变得冗余和复杂。因此,Fabric 从 v1.2 开始,可以创建私有数据集合,从而使通道上已定义的组织子集能够背书,提交或查询私有数据,而无需创建单独的通道。

1.1 私有数据特性

1.2 使用私有数据的交易流程

当在链码中引用私有数据集合时,交易流程略有不同,以便在提案,背书并提交到帐本时保护私有数据的机密性。

  1. 客户端应用程序提交提案请求以调用链码功能 (读取或写入私有数据) 给背书的对端节点,这些对端节点是私有数据的授权组织的一部分。私有数据或用于以链码生成私有数据的数据在提案的 transient 字段中发送。
  2. 背书对端节点模拟交易并将私有数据存储在 transient data store (对端节点本地的临时存储) 中。他们根据私有数据策略通过 gossip 协议将私有数据分发给授权的对端节点。
  3. 背书对端节点将提案响应发送回客户端。提案响应包括背书的读/写集,其中包括公共数据,以及任何私有数据键和值的哈希。没有私有数据发送回客户端。
  4. 客户端应用程序将交易 (包括带有私有数据哈希的提案响应) 提交给交易排序器。带有私有数据哈希的交易通常包含在区块中。具有私有数据哈希的区块将分配给所有对端节点。这样,通道上的所有对端节点都可以以一致的方式用私有数据的哈希值验证交易,而无需知道实际的私有数据。
  5. 在区块提交时,授权对端节点使用集合策略来确定他们是否被授权有权访问私有数据。如果这样做,他们将首先检查其本地瞬态数据存储 (transient data store) 以确定在链码背书时是否已经接收到私有数据。如果没有,他们将尝试从另一个授权对端节点获取私有数据。然后,他们将根据公共区块中的哈希来验证私有数据,并提交交易和该区块。验证/提交后,私有数据将移至私有状态数据库和私有写入集存储的副本。然后,将私有数据从瞬态数据存储中删除。

1.3 清除私有数据

私有数据是可以从子组织中清除的,清除之后链码就无法再访问该私有数据,即使子组织也无法再使用该私有数据。

所以在清除之前,需要确保将这些私有数据导出到外部数据库中,并进行独立维护。

清除之后,通道中仍然保持着私有数据的哈希,因此仍然能够对该私有数据进行正常的审计、验证等。

1.4 私有数据的定义

私有数据的简单定义由以下属性组成,更详细的定义请参考官方文档:

这是一个示例集合定义 JSON 文件 collections_config.json,其中包含两个私有数据的定义:

[
 {
    "name": "collectionMarbles",
    "policy": "OR('Org1MSP.member', 'Org2MSP.member')",
    "requiredPeerCount": 0,
    "maxPeerCount": 3,
    "blockToLive":1000000,
    "memberOnlyRead": true
 },
 {
    "name": "collectionMarblePrivateDetails",
    "policy": "OR('Org1MSP.member')",
    "requiredPeerCount": 0,
    "maxPeerCount": 3,
    "blockToLive":3,
    "memberOnlyRead": true
 }
]

本示例使用来自官方 BYFN 示例网络 Org1 和 Org2 的组织。 collectionMarbles 定义中的策略授权两个组织使用私有数据。当链码数据需要对交易排序器节点保持私有时,这是一种典型配置。但是,collectionMarblePrivateDetails 定义中的策略将限制访问通道中的组织子集 (在本例中为 Org1)。在实际情况下,通道中将有许多组织,每个私有数据在两个或多个组织之间共享。

1.5 私有数据的部署

链码实例化 (或升级) 时,私有数据的定义将部署到通道。如果使用对端节点 CLI 实例化链码,则使用 --collections-config 标志将私有数据定义文件传递到链码实例化。如果使用客户端 SDK,请查看 SDK 文档以获取有关提供集合定义的信息。

1.6 示例

一个简单的使用私有数据的示例包括下列步骤。

Step 1. 定义私有数据的配置文件

请参考章节 1.4 的配置文件 collections_config.json

需要说明的是,这一步将配置哪些组织和对端节点能够访问和存储私有数据。

Step 2. 启动 Fabric 网络

这里假设已经启动 Fabric 网络,如官方示例中的 BYFN 网络。

到这一步,假设已经创建了通道,并且各组织及其对端节点都已经加入通道。特别需要注意是关于锚定节点的配置要正确。

Step 3. 安装链码

这一步已普通的链码安装并无不同。假设已经启动 BYFN 网络。

先进入 cli 工具:

$ sudo docker exec -it cli bash
# 

在 peer0.org1 上安装:

peer chaincode install -n marblesp -v 1.0 -p github.com/chaincode/marbles02_private/go/

在 peer1.org1 上安装:

export CORE_PEER_ADDRESS=peer1.org1.example.com:8051
peer chaincode install -n marblesp -v 1.0 -p github.com/chaincode/marbles02_private/go/

先切换到 org2 环境变量:

export CORE_PEER_LOCALMSPID=Org2MSP
export PEER0_ORG2_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG2_CA
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp

在 peer0.org2 上安装:

export CORE_PEER_ADDRESS=peer0.org2.example.com:9051
peer chaincode install -n marblesp -v 1.0 -p github.com/chaincode/marbles02_private/go/

在 peer1.org2 上安装:

export CORE_PEER_ADDRESS=peer1.org2.example.com:10051
peer chaincode install -n marblesp -v 1.0 -p github.com/chaincode/marbles02_private/go/

Step 4. 实例化链码 & 部署私有数据

私有数据的部署发生在链码实例化阶段。命令如下:

# 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
# peer chaincode instantiate -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C mychannel -n marblesp -v 1.0 -c '{"Args":["init"]}' -P "OR('Org1MSP.member','Org2MSP.member')" --collections-config  $GOPATH/src/github.com/chaincode/marbles02_private/collections_config.json

Step 5. 链码

链码主要是通过两个接口 PutPrivateData()GetPrivateData() 进行查询、新增或更新。

官方示例的链码实现请参考 大理石私有数据示例

Step 6. 应用程序

应用程序需要通过特殊的字段 transient 来传递私有数据的 Key & Value,同时需要在链码部分通过接口 getTransient() 获取应用程序传入的私有数据的 Key & Value。

由于,私有数据只有 Org1 有操作权限,所以需要先切换回 Org1 的环境变量:

export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
export CORE_PEER_LOCALMSPID=Org1MSP
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export PEER0_ORG1_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
更新操作

通过下面的命令行来调用链码接口,注意私有数据的 Key & Value 是如何传递给链码接口的,同时还需要注意 Value 需要采用 Base64 编码,并且在 Linux 环境中还需要去掉编码后多出的换行符:

export MARBLE=$(echo -n "{\"name\":\"marble1\",\"color\":\"blue\",\"size\":35,\"owner\":\"tom\",\"price\":99}" | base64 | tr -d \\n)
peer chaincode invoke -o orderer.example.com:7050 --tls --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 mychannel -n marblesp -c '{"Args":["initMarble"]}'  --transient "{\"marble\":\"$MARBLE\"}"

需要考虑,如果通过 SDK 来实现上面的操作,该如何实现。可以参考示例 marbles02_private 中 javascript 版本的实现。

查询操作

上面的是存储私有数据命令,下面是私有数据的查询命令:

# peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarble","marble1"]}'

或者

# peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}'

1.7 私有数据相关的实现细节

私有数据相关的实现细节包含:私有数据的定义、私有数据的部署、私有数据的链码编写以及客户端交互等部分。

私有数据的定义请参考章节 1.4 的相关内容。

私有数据的部署请参考章节 1.5 和 1.6 的相关内容。

私有数据的链码编写以及客户端交互请参考章节 1.6 的相关内容。

需要说明的是,私有数据开发相关的工作量主要还是体现在链码编写及客户端交互这部分。

1.8 技术风险

参考文献

项目源代码

项目源代码会逐步上传到 Github,地址为 https://github.com/windstamp

Contributor

  1. Windstamp, https://github.com/windstamp
上一篇下一篇

猜你喜欢

热点阅读