一。数据存储对多链的支持
这个目录下面有两个目录:businesschannel和pocchannel。它们代表的是两个通道,也就是两个链的数据,每个链现在只有一个区块文件,blockfile_是文件名中固定的前缀,000000是固定的6位占位符,下一个文件名会依次递增。从这个目录结构可以看到,记账节点在底层账本数据存储的时候就对不同链的数据进行了隔离。
排序节点会存储所有链的账本数据,排序节点除了可以选择序列化区块文件的格式外,还支持JSON文件格式和内存数据结构的账本数据,后面两种都只在测试环境下使用。序列化区块文件和JSON文件格式区块文件的存储目录一般是/var/hyperledger/production/orderer/chains。其中,orderer/chain是固定的目录后缀。同样地,不同链的账本数据存储在以通道名称为目录名称的目录中,以实现不同链账本数据的物理隔离。内存数据的账本数据没有持久化的存储,不同链的账本数据存储在不同的数据结构中。
7.1.2索引数据
记账节点和排序节点都会给账本数据建立索引,不同的是排序节点只会建立以BlockNum为属性的索引。
索引文件存储的目录是/var/hyperledger/production/ledgersData/chains/index,其中,ldegersData/chains/index是记账节点上固定的目录后缀,排序节点上的目录后缀是orderer/index。
下面是一个记账节点上的索引数据的目录:
root@peer0:/var/hyperledger/production/ledgersData/chains/index# tree
|--000002.1db
|--000007.log
|--CURRENT
|--LOCK
|--LOG
--MANIFEST-000008
0 directories,6 files
索引数据是存储在LevelDB数据库里的,数据库的类型目前是不可选的。LevelDB是持久化的K-V数据库,在保存索引的时候会加上ledgerid作为前缀,当然生成的组合键在构造的时候是要先转换成[]byte数组的。由于索引数据存储在同一个数据库中,所以对于不同链的数据,索引数据的实现是逻辑隔离的,并非是物理隔离的。
7.1.3状态数据
排序节点不需要查询具体的交易信息和状态数据,也不会存储状态数据及其历史数据。
peer节点上状态数据存储的目录是/var/hyperleder/production/ledgersData/stateLeveldb,其中,ledgesData/stateLeveldb是固定的后缀:
root@peer0:/var/hyperleder/production/ledgersData/stateLeveldb# tree
.
|--000002.ldb
|--000007.log
|--CURRENT
|--LOCK
|--LOG
--MANIFEST--000008
0 directories, 6 file
状态数据也是基于K-V存储的,同一个节点的状态存储在同一个数据库中,没有进行物理隔离。和索引数据不同的是,状态数据是和chaincodeID相关的,不同chaincodeID的数据是逻辑隔离的,而chaincodeID同样是以chainID为前缀进行了逻辑隔离。
7.1.4历史数据
历史数据存储的目录是/var/hyperleder/production/ledgersData/historyLeveldb,其中,ledgersData/historyLeveldb是固定的后缀:
root@peer0:/var/hyperleder/production/ledgersData/historyLeveldb# tree
.
|--000002.ldb
|--000010.ldb
|--000012.log
|--CURRENT
|--LOCK
|--LOG
|--LOG.old
--MANIFEST--000013
`--level-party.sock
0 directories, 9 file
历史数据目前内置的数据库是levelDB,也是不可替换的。记录的是状态数据的历史记录。同状态数据一样,通过在构建chaincodeID的时候增加ChainID前缀来逻辑隔离不同链的数据。
二。链码对多链的支持
链码是Hyperledger Fabric1.0提供的智能合约方案,实现了交易的模拟执行。链码从多个纬度对多链提供了支持。比如链码的生命周期管理、链码和背书节点的通信、链码的部署方法等。
1。链码的生命周期管理
【1】智能合约在Hyperledger Fabric1.0上称为“链码(chaincode)”,是独立运行的应用程序,只接收启支它的“背书节点”的指令,执行指定的业务逻辑。
【2】多链情况,同一个智能合约可能会在不同的链上运行。
【3】为重用智能合约代码,智能合约的部署拆分成“安装”和“实例化”两个步骤
安装:只是将链码的源代码序列化后和链码名称、版本等封装成ChaincodeDeploymentSpec保存到peer节点上,
链码安装跟具体的链没有关系,也不需要ChainID参数。
不同链的链码是没有隔离的,即在一个链安装的链码可能和另一个链的链码产生冲突。
链码安装时会检查是否存在相同名称和版本的链码,若不同的上层应用同时都部署了相同的链码和版本,可能存在一个链码安装成功,另一个链的链码安装失败。
实例化和链码升级是在指定链上操作的,实际过程分两步:
(1)。调用系统链码LSCC的部署操作,通过LSCC把链码计算哈希后生成的chaincodeData存放到状态数据库中。
(2)。从文件系统中读取保存的链码源码,生成镜像后执行初始化操作。
链码操作包括:初始化和调用。它们都是在具体链上操作的,链码镜像命名规则:
NetworkID-PeerID-ChaincodeName-ChaincodeVersion-SHA256(ChainID)
链码镜像名称最后一部分是对ChainID计算SHA256哈希后再转换成十六制的字符串,逻辑上不同链的链码会有不同的镜像名称。
启动的链码容器命名和镜像一样,只会把“:”替换成“_”。这样,不同链的链码执行是可以在不同的环境中隔离的。
实际在启动链码容器时并未指定ChainID参数,即目前不同链上相同链码是运行在同一个容器中的。但即使运行在相同的链码容器中,也会通过ChainID进行逻辑隔离。
2。链码和背书节点的通信
http://keliu.me/2018/03/07/FabricChaincode/
链码容器启动后,会和启动它的“背书节点” 建立gPRC连接。
应用程序/命令行通过gRPC连接给背书节点发送请求,背书节点校验通过,通过链码和背书节点建立gRPC连接将请求发送给链码去执行。
链码执行本身和具体链无关,链码容器也不会在本地保存任何数据,是一个无状态的执行环境。
需要访问或写入状态数据时,通过建立好的gRPC连接发送请求给背书节点,再进行后续的业务逻辑处理。即在链码这一端,是不区分链的,所以不同链才可以共用相同的链码容器。
3。链码的部署和调用
三。多通道对多链的支持
四。命令行和SDK对多链的支持
可指定-C在指定的通道上操作,在入口处提供了对多链的支持。
五。关于系统链
系统链是一个特殊的链,含有系统层而全局配置区块链网络的联盟及组织信息、MSP信息和策略信息等,只存在于排序服务中。
涉及一些信息修改,如增加一个组织,增加排序服务节点,这些都会在系统链上增加一个配置区块,
整个系统有且只有一个系统链,系统链通过创世区块配置,排序服务启动时通过ORDER_GENERAL_GENESISFILE环境变量指定创世区块文件并创建系统链。
系统链的名称可以在创建创世区块的时候通过工具configtxgen的channelID参数指定,默认的系统链名称是testchainid,
是否是系统链的判断方法就配置区块信息里是否有联盟信息配置项。