文章目录
摘要
比特币和以太坊都是公链,链中存储的数据任何人都可查询,不适合用来做对隐私有较高要求的企业开发,且其都用了工作量证明机制,能耗成本很高,数据存储效率低(尤其是比特币,大约每10分钟生成一个新块)。Fabric引入了证书颁发机构和通道的概念,使得不被授权的用户无法访问链中数据,保证了数据的隐私性。Fabric还采用背书策略代替了工作量证明机制,在保证数据安全的同时,消除了”挖矿”的能耗,提高了存储效率。本文基于Fabric进行区块链的系统开发,详述了在linux操作系统(Unbuntu)上Fabric环境的搭建、Fabric的基本概念、用Fabric开发区块链系统(未完)。
在总结处细述了Fabric的一个交易提案是如何一步步部署到区块链上的。
一、Fabric环境搭建
1.1 安装docker
1. 官方帮助文档:https://hyperledger-fabric.readthedocs.io/en/release-1.2/
2. 安装 cURL( https://curl.haxx.se/download.html ), curl --version 查询版本
3. 安装docker, docker --version 查询版本
4. 安装docker-compose, docker-compose --version 查询版本
5. 安装 go 语言环境, go version 查询版本
6. 安装node.js, node -v 查询版本
7. Python 版本要求为 2.7, python --version 查询版本
- yum包更新到最新
yum update
- 安装需要的软件包,yum-util提供yum-config-manager功能,另外两个是devicemapper驱动的依赖
yum install -y yum-utils device-mapper-persistent-data lvm2
- 设置yum安装源
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
- 安装docker,出现界面都按y
yum install -y docker-ce
- 安装docker-compose
sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
- 给docker-compose添加可执行权限
sudo chmod +x /usr/local/bin/docker-compose
1.2 安装go
下载地址:
https://golang.org/dl/ – 翻墙 https://studygolang.com/dl – 国内镜像源
如果没有进行安装包下载, 可直接使用如下命令(目前最新版本):
# 1. 使用wget工具下载安装包
$ wget https://dl.google.com/go/go1.11.linux-amd64.tar.gz
# 2. 解压tar包到/usr/local
$ sudo tar zxvf go1.11.linux-amd64.tar.gz -C /usr/local
# 3. 创建Go目录
$ mkdir $HOME/go
# 4. 用vi打开~./bashrc,配置环境变量
$ vim ~/.bashrc
# 5. 增加下面的环境变量,保存退出
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
# 6. 使环境变量立即生效, 一些命令二选一
$ source ~/.bashrc $ . ~/.bashrc
# 7. 检测go是否安装好
$ go version
1.3 安装Node.js
#1. 安装包
wget https://nodejs.org/dist/v16.13.1/node-v16.13.1-linux-x64.tar.xz
#2. 解压包到/opt下
sudo tar xvf node-v16.13.1-linux-x64.tar.xz -C /opt
#3.配置环境变量
#进入系统级别的配置文件
sudo vim /etc/profile
#文件末尾输入
export NODEJS_HOME=/opt/node-v16.13.1-linux-x64
export PATH=$PATH:$NODEJS_HOME/bin
#加载配置文件
. /etc/profile
#4. 测试
node -v
1.4 部署hyperledger Fabric
- 下载并执行fabric的引导脚本bootstrap.sh
# 创建放置的目录,然后进入该目录,用curl下载脚本。
$ cd ~ # 这里在家目录下创建放置目录
$ mkdir hyperledger-fabric
# 创建放置目录
$ cd hyperledger-fabric
#不翻墙的安装命令
$ curl -sSL https://raw.githubusercontent.com/hyperledger/fabric/master/scripts/bootstrap.sh | bash -s 1.2.0 1.2.0 0.4.10
二、Fabric的概念
2.1 逻辑架构
身份管理
(
Fabric中的“账户”体系
.)
-
成员服务
-
注册登录和属性证书:首先用户填写信息(身份信息等)生成证书明文F发送注册请求,证书颁发机构CA对明文进行摘要(进行一次hash运算)得到h1,CA用自己的私钥对h1进行加密得到密文F ‘。验证证书时,用CA公钥对F ‘解密得到h2,比较h2是否等于h1。(
Hyperledger Fabric注册及CA证书颁发
.)
-
注册登录和属性证书:首先用户填写信息(身份信息等)生成证书明文F发送注册请求,证书颁发机构CA对明文进行摘要(进行一次hash运算)得到h1,CA用自己的私钥对h1进行加密得到密文F ‘。验证证书时,用CA公钥对F ‘解密得到h2,比较h2是否等于h1。(
账本管理
- 区块链:区块链中存储着所有的交易记录。
- 世界状态:根据区块链中的交易记录得到的数据状态,每当有一个新区块生成时,世界状态也随之更新,每个节点的世界状态都存在其节点的数据库中。
交易管理
-
客户端发送某一类型提案,根据提案类型对应的背书测略,指定对应的背书节点peer,背书节点peer执行链码,如果成功则生成实际账本。当一定数量的背书节点认可该提案后,该提案通过排序节点广播给所有节点,每个节点验证并执行该提案,从而更新账本。(
深入理解Fabric的交易背书
)
智能合约
-
智能合约是用来进行业务逻辑操作的代码,在docker容器中运行,和以太坊相比,Fabric的智能合约和底层账本是分开的,升级链码并不需要将账本迁移到新的区块链上,真正实现了逻辑与数据的分离。
(Fabric的智能合约详解
)
2.2 Fabric基础概念
(
Fabric基本概念—很好的文章
)
组织
- fabric系统是通过组织来划分的,每个组织内都有承担不同功能的peer节点,同时每个组织都有自己对应的fabric-ca服务器,fabric系统中所有的组织共用一个orderer集群。fabric中的组织在现实世界中可以是一个公司、一个企业,或者一个协会。在fabric中,组织是承担着数据信用责任的区块链系统参与方。在设计一个fabric系统时,第一步就是要确定系统的参与方,然后从这些参与者中选出组织(生成对应的组织编号、域名、证书等),然后再确认组织的管理方式。组织的管理方式是指组织在遇到问题时的协作方式(如新组织的加入)。
通道(Channel)
-
fabric的数据存储结构被设计成多账本体系,每个账本在fabric中被称为channel。每个channel中都有一个完全独立的账本。同一个channel中的所有peer节点都保存一份相同的数据。
通道由成员(组织)、每个成员的锚节点、账本、链码应用程序和排序服务节点定义。网络上的每个交易都是在一个通道上执行的,在该通道上,每一方都必须经过身份验证和授权才能在该通道上进行交易。加入通道的每一个peer都有其自己的身份,由成员服务提供者(MSP)提供。
账本
-
Fabric有一个账本子系统包含两个组件:世界状态和交易日志。世界状态是代表当前数据的状态,交易日志组件存放在数据库中,它记录了所有的交易记录,世界状态是根据交易日志得到的。
世界状态中有一个属性——版本号,版本号从0开始,每当状态更新时版本号就递增。状态更新时会首先检查版本号,以确保当前状态的版本与背书时的版本一致(避免并发更新)。
节点(peer)
是区块链的通信实体,是一个逻辑概念,不同类型的多个节点可以运行在同一个物理服务器上。节点主要有以下四种:
-
客户端节点:客户端必须连接到某一个peer节点或排序服务节点上才能与区块链网络进行通信。客户端向背书节点(endorser)提交交易提案(transaction proposal),当收集到足够背书后,向排序服务节点广播交易提案,进行排序,生成区块。
-
普通节点peer:peer节点根据所承担的角色又可以分为记账节点(committer)、背书节点(endorser)、主节点(leader)和锚节点(anchor)。
- 记账节点:所有的peer节点都是记账节点(committer),负责验证排序服务节点区块里的交易,维护状态和总账(Ledger)的副本。该节点会定期从orderer节点获取包含交易的区块,在对这些区块进行核发验证之后,会把这些区块加入到区块链中。committer节点无法通过配置文件配置,需要在当前客户端或者命令行发起交易请求的时候手动指定相关的committer节点。记账节点可以有多个。
- 背书节点:部分节点还会执行交易并对结果进行签名背书,充当背书节点(endorser)的角色。背书节点是动态的角色,是与具体链码绑定的。每个链码在实例化的时候都会设置背书策略,指定哪些节点对交易背书后交易才是有效的。并且只有应用程序向它发起交易背书请求的时候才是背书节点,其他时候都是普通的记账节点,只负责验证交易并记账。背书节点也无法通过配置文件指定,而是由发起交易请求的客户端指定。背书节点可以有多个。
- 锚节点:peer节点还可以是锚节点(anchor peer),锚节点主要负责代表组织和其他组织进行信息交换。每个组织都有一个锚节点,锚节点对于组织来说非常重要,如果锚节点出现问题,当前组织就会与其他组织失去联系。锚节点的配置信息是在configtxgen模块的配置文件configtx.yaml中配置的。锚节点只能有一个。
- 主节点:peer节点还可以是主节点(leader peer),能与排序服务节点通信,负责从排序服务节点获取最新的区块并在组织内部同步。主节点在整个组织中只能有一个。
-
排序服务节点orderer:接收包含背书签名的交易,对未打包的交易进行排序生成区块,广播给peer节点。排序服务提供的是原子广播,保证同一个链上的节点接收到相同的信息,并且有相同的逻辑顺序。
-
CA节点:fabric1.0的证书颁发机构,由服务器和客户端组成。CA节点接收客户端的注册申请,返回注册密码用于用户登录,以便获取身份证书。区块链上的所有操作都需要验证用户身份。
区块结构
- 由三个部分组成,分别是区块头、区块数据和区块元数据。
- 区块头包含三个属性(区块号、当前区块哈希、前一个区块的哈希),当一个区块被创建时写入。
- 区块数据包含的是排序后的交易列表。当区块被ordering service创建时写入。
- 区块元数据包括区块的写入时间,以及区块写入者的证书、公钥和签名。
2.3 Fabric交易流程
前提假设是各节点已经提前颁发好证书,且已正常启动,并加入已经创建好的通道。此流程介绍的是在已经实例化了的链码通道上从发起一个调用交易到最终结账的全过程。
-
提交交易提案
应用程序(客户端节点)构造好交易提案(交易提案中包含本次交易要调用的合约标识、合约方法和参数信息以及客户端签名等)请求后,根据背书策略选择背书节点执行交易提案并进行背书签名。背书节点是链代码中背书策略指定的节点。正常情况下背书节点执行后的结果是一致的,只有背书节点对结果的签名不一样。 -
模拟执行提案并进行背书
背书节点在收到交易提案后会进行一些验证,验证通过后,背书节点会根据当前账本数据模拟执行链码中的业务逻辑并生成读写集(RwSet)。模拟执行时不会更新账本数据。然后背书节点对这些读写集进行签名生成提案响应(proposal response),然后返回给应用程序。 -
收集交易的背书(返回模拟执行结果)
应用程序收到proposal response后会对背书节点的签名进行验证(所有节点接收到任何消息时都需要先验证消息的合法性)。如果链码只进行账本查询操作,应用程序只需要检查查询响应,并不会将交易提交给排序服务节点。如果链码对账本进行了invoke操作,则需要提交交易给排序服务进行账本更新(提交前会判断背书策略是否满足)。 -
构造交易请求并发送给排序服务节点
应用程序接收到所有背书节点的签名后,根据背书签名调用SDK生成交易,并广播给排序服务节点。其中生成交易的过程很简单,只需要确认所有背书节点的执行结果完全一致,再将交易提案、提案响应和背书签名打包生成交易即可。 -
排序服务节点对交易进行排序并生成区块
排序服务节点接收到网络中所有通道发出的交易信息,读取交易信封获取通道名称,按各个通道上交易的接收时间顺序对交易信息进行排序(多通道隔离),生成区块。(在这个过程中,排序服务节点不会关心交易是否正确,只是负责排序和打包。交易的有效性在第7步进行验证)
-
排序服务节点广播区块给主节点
排序服务节点生成区块后会广播给通道上不同组织的主节点。
-
记账节点验证区块内容并写入到账本
所有的peer节点都是记账节点,记录的是节点已加入通道的账本数据。记账节点接收到的排序服务节点生成的区块后,会验证区块交易的有效性,然后提交到本地账本并产生一个生成区块的事件,监听区块事件的应用程序会进行后续的处理。(如果接收的是配置区块,则会更新缓存的配置信息)
-
主节点在组织内部同步最新的区块
如果交易是无效的,也会更新区块,但不会更新世界状态。(区块存储的是操作语句,而世界状态存储的是被处理的数据。
三、基于Fabric的区块链系统开发(未完)
目前开发是准备先做一个简单的系统,在该系统中有一个排序节点,2个组织,每个组织中分别有3个Peer节点和2个用户,系统还未完成。
3.1 证书配置文件(crypto-config.yaml)
#排序组织
OrdererOrgs:
Name: Orderer #组织名称
Domain: itcast.com #域名
specs:
orderer #生成一个叫orderer的排序子节点
#节点组织
PeerOrgs:
#组织OrgGo
Name: OrgGo
Domain: OrgGo.itcast.com
Template:
Cout: 2 #按模板生成2个peer节点,节点名称格式Peer0、Peer1...
User:
Cout: 3 #生成3个用户,默认创建一个管理员
#组织OrgCpp
Name: OrgCpp
Domain: OrgGo.itcast.com
Template:
Cout: 2
User:
Cout: 3
创建好文件后,使用cryptogen generate –config=crypto-config.yaml,即可生成证书文件crypto-config。
3.2 创世块及通道的配置文件
Organizations: #排序组织,固定的不能改
- &OrdererOrg #排序节点组织,用作后面引用的
Name: OrdererOrg #排序节点的组织名
ID: OrdrerMSP #排序节点组织的ID(证书)
MSPDir: /home/py/itcast/crypto-config/ordererOrganizations/itcast.com/msp #证书文件地址
- &OrgCpp
Name: orgcpp
ID: OrgcppMSP
MSPDir: /home/py/itcast/crypto-config/peerOrganizations/orgcpp.itcast.com/msp
AnchorPeers: #设置锚节点
- Host: peer0.orgcpp.itcast.com #用orgcpp中的peer0作为锚节点
port: 7051
- &OrgGo
Name: orggo
ID: orggoMSP
MSPDir: /home/py/itcast/crypto-config/peerOrganizations/orggo.itcast.com/msp
AnchorPeers:
- Host: peer0.orggo.itcast.com
port: 7051
#*******************************************
Orderer: &OrdererDefaults
OrdererType: solo
Addresses:
- orderer.smartforce.io:7050
BatchTimeout: 2s
BatchSize:
MaxMessageCount: 10
AbsoluteMaxBytes: 99 MB
PreferredMaxBytes: 512 KB
Organizations:
Application: &ApplicationDefaults
Organizations:
Profiles:
TwoOrgsOrdererGenesis:
Orderer:
<<: *OrdererDefaults
Organizations:
- *Smartforce
Consortiums:
SampleConsortium:
Organizations:
- *OrgCpp
- *OrgGo
TwoOrgsChannel:
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
Organizations:
- *OrgCpp
- *OrgGo
总结
客户端节点发送交易提案(proposal),根据该类型提案对应的背书策略,指定对应的背书节点,背书节点收到提案请求后,会根据当前账本数据,模拟执行链码中的业务逻辑,生成一个读写集(RwSet),然后背书节点对读写集进行签名生成提案响应(proposal response)并返回给客户端节点,客户端收到一定数量正的提案响应后,便会将该交易发送给排序节点,排序节点收到所有通道发出的交易信息,按其发送时间对其进行排序(多通道隔离),生成区块,将其广播给各个通道的主节点,节点再对生成的区块中的数据进行校验,然后将其提交到本地账本,更新区块链账本和世界状态。