基本名词解释

ledger

账本上一系列由事务驱动的状态迁移的记录。状态迁移是链码调用(调用即事务)的结果。这些记录是不可修改顺序的,因此也上抗篡改的。

每个channel有一个账本,但恐怕不只一个账本。

理论上账本是由产生它的链码的命名空间隔离开来的,不能直接被其他链码访问到。

chain

由包含一系列 transaction 的 block 通过hash-link(由散列值作为前驱指针的一种连接方式)组成的数据结构。

state database

记录各种 key 的 latest value。可以被认为上chain的indexed view,可以随时被从链上重建出来。

所以 Fabric 自己就有双层数据结构。

读写集语义

读集和写集搞不好是同一个事务里的数据结构(待查)。

1
2
3
4
5
6
7
8
9
10
11
12
13
<TxReadWriteSet>
<NsReadWriteSet name="chaincode1">
<read-set>
<read key="K1", version="1">
<read key="K2", version="1">
</read-set>
<write-set>
<write key="K1", value="V1"
<write key="K3", value="V2"
<write key="K4", isDelete="true"
</write-set>
</NsReadWriteSet>
<TxReadWriteSet>

锚节点

一个 peer 节点,全 channel 里所有的其他节点都可以跟它交谈。每个组织(Member)都有一个锚节点,Member 里 的所有节点通过它来发现频道中的所有其他节点,通过锚节点和其他组织交换数据

特别像以太坊中的 bootnode。

leader 节点

这个节点代表组织跟 orderer 通信,拉取最新到达的节点以后,通过 gossip 协议向其他节点做同步。

Member

法律上分离的实体,拥有独立的网络根证书。

Membership Service Provider

一个抽象的插件化组件,可以切换实现。主要用意是提供 credentials 甚至 peers 给 client,让它跟网络交流。理论上每个 Member 应该有个 MSP。

MSP 的本质是一系列证书、私钥和验证算法,实际上就是一堆文件夹。

Membership Services

每个 peer 和 orderer 都可能实现 MSP,也就是说 MS 其实是它们的一个服务组件。

BCCSP

Blockchain Crypto Service Provider

和MSP一样,是加密服务的提供者。

bin 文件夹下的内容

configtxlator
get-byfn.sh
get-docker-images.sh
orderer
peer

其中 orderer、peer 都会被映射到镜像之内。

初始化的步骤

  1. cryptogen 这个工具根据配置文件生成指定拓扑的 x.509证书材料。
  2. 用 configtxgen 工具生成 orderer 创世区块,给 orderer 用。
  3. 生成频道配置事务-算是元事务的一种吧,给 channel 用。
  4. 生成相关组织的锚节点。

启动脚本的作用

1
./byfn.sh -m up -l node

默认的 chaincode 开发语言是 Golang,但也可以切换到 node 上面。

1
./byfn.sh -m down

这里的-m是 mode 的意思。

这个命令会消灭掉 docker 网络残余文件,包括密码学文件和链码镜像。

这个大脚本会大量依赖父文件夹的../bin脚本。

transaction 的流程

  1. client 根据 endorsement policy 发送 transaction proposal 到各个 peer。
  2. 各个 peer 通过合约容器试算,生成 read-write-set。
  3. client 再根据读写集语义签真正的 transaction,如果不是查询的试算,会把 transaction 发给 orderer。
  4. orderer只负责收集所有的 transaction 打包成区块。
  5. 区块发送给 peer,如果 read-write-set 语义还依然满足,则 transaction validate 通过,把区块添加到区块链上。

CA 问题

CA 是可选组件。

但如果 CA server 跑起来,我们可以向它发送 REST 请求给组织的 CA 来完成用户注册和登记。

CA 是 PKI 的实现。PKI 可以抗女巫攻击。

CA 可以像 cryptogen 一样,先生成组织里的节点证书和私钥(组织里一定会有 root-ca),然后生成成员(admin 和普通成员)的证书和私钥。

常见端口号

这些端口号有先后顺序,适合在同一个 host 编排一系列容器。

orderer:7050
peer:7051
peer event:7053
ca:7054

SDK 问题

区块链天然可以用gRPC来通信。

因为各种语言都支持 Protocol Buffers,基于Protocol Buffers over gRPC,我们可以制造各种语言的SDK。

所以理论上我们可以直接通过 gRPC 跟区块链通信。

读写集语义

实际上读集(read set)和写集(write set)是分开的。
它们共同组成了事务。

configuration block

有configtx,就有configuration block,这不奇怪。两者都要经过orderer。

可以通过命令行来获取configuration(peer channel fetch)。peer channel fetch 可以用来获取任意序号的区块。

packaging

1
peer chaincode package -n mycc -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -v 0 -s -S -i "AND('OrgA.admin')" ccpack.out

这一行命令生成了一个 signedCDS。

-s(signing的意思)应该有-S,否则再也没有机会让 owner 来签署这个 package 了。-S指出了需要本地 MSP 来 sign 这个 package。

-i是 intantiate policy,指的是只有 OrgA 的 admin 可以初始化这个 package。

实际上不用 package 和 sign 最好了,反正每个peer默认可以初始化链码也只有本 Member 的 admin(这种 admin 在默认的情况下是大多数需要产生变化的 wrtier)。

可见这个初始化策略是针对 package 而不是针对 channel 的。我们只可以组织一个 package 被初始化,不能阻止别人在一个 channel 上安装任意的 chaincode。

这个初始化策略还会进一步限制 upgrade。只有符合策略的 MSP 才能 upgrade 整个lian ma

停止链码

目前只能通过停止和删除容器,并删除 peer 上 CDS的方式来做到,对其他组织的机器是个考验呢。

1
2
docker rm -f <container id>
rm /var/hyperledger/production/chaincodes/<ccname>:<ccversion>

系统链码

逻辑上和普通链码是一样的(应该也是通过各种事务驱动的),但只跑在 peer 进程内。

系统链码的目的是为了减少 peer 和 chaincode 容器之间的 gRPC。

要 upgrade 链码只有 upgrade peer 二进制文件(实际上就是跟着 Fabric 版本走)。

架构流程图