fabric1.1开发(零-基础知识)

一、Fabric介绍

fabric是一种联盟链,是通过认证后才可以进入,其中MSP(Membership Service Provider)就是会员服务系统,基于PKI规范建立的用户证书和私钥体系。

fabric共识算法也和其他公联不同,fabric支持solo和kafka两种模式:

  • solo:单个节点中完成排序,安全性稳定性差
  • kafka:排序节点从kafka集群获取对应topic分区的数据,避免单点故障

二、Fabric快速入门

fabric的5个模块
fabric分为这5个模块,意思是fabric有这5个个命令关键字,开发前要用下面的方法编译好这些模块,这些关键字才可以使用

  • peer:主节点,存储区块链数据,运行链码
  • orderer:对交易进行排序,将排序好的交易打包
  • cryptogen:组织和证书生成模块
  • configtxgen:区块和交易生成模块
  • configtxlator:区块和交易解析模块

开发时模块生成方法(任选一个):

  • 直接编译源代码:可以将这些模块先编译,再放到系统目录中,就可以在任何路径下运行这些模块;
  • 使用本地源代码生成fabric模块的docker镜像
  • 从docker仓库中直接下载fabric模块的docker镜像文件(e2e_cli就是这种方法)
    • baseos:基础镜像,其他镜像都在该镜像基础之上生成
    • baseimage:包含jdk、golang、nodejs等,用来生成chaincode
    • peer:peer模块镜像,从1.0开始peer不再提交数据,由客户端完成,peer还是会验证和背书
    • orderer:oderer节点库镜像
    • ca:ca模块镜像
    • tools:工具镜像,包含cryptogen、configtxgen、configtxlator等工具 本地客户端镜像
    • couchdb:couchdb数据库镜像
    • kafka:kafka库镜像
    • zookeeper:zookeeper库镜像
    • testenv:测试环境库镜像
    • buildenv:编译环境库镜像
    • javaenv:java链码运行镜像
    • ccenv:go链码运行镜像

docker compose:是使用docker容器分布式部署的工具,只需要定义一个多容器应用的yml文件,定义哪个容器运行哪个应用,然后用一条命令即可部署所有容器

fabric启动步骤

  1. 生成相关证书,cryptogen模块完成,根据yaml配置文件生成证书

  2. 生成创始块

    1. 系统创始块,系统创始块是存配置信息的,configtxgen模块完成,根据configtx.yaml生成创始块文件orderer.genesis.block
      yaml文件1
      yaml文件2

    2. 账本创始块,channel的创始块,configtxgen模块完成,根据configtx.yaml生成roberttestchannel.tx,该文件生成channel,还要生成锚节点文件Org1MSPanchors.tx和Org2MSPanchors.tx

  3. 启动orderer节点,orderer模块完成,根据orderer的yaml文件(还定义了log格式等)启动orderer节点

  4. 启动peer节点,peer模块完成,根据peer的yaml文件(还定义了log格式等)启动peer节点

  5. 创建通道(都是peer节点完成)

    1. 创建通道
    2. 让已经运行的peer的节点加入通道
    3. 更新锚节点
  6. 部署chaincode-实例化chaincode代码-调用chaincode代码

三、模块介绍

若是使用docker运行,尽量使用环境变量的配置方式;
若是使用命令直接启动,使用配置文件参数配置方式

1. cryptogen模块

开发第一步就是要编写cryptogen的配置文件,通过配置文件来生成各种证书


OrdererOrgs:
	- Name: Orderer						// 定义oderer节点的名字
		Domain: example.com				// 定义oderer节点的根域名
		Spacs:
			- Hostname: orderder		// 定义orderer节点的主机名
PeerOrgs:
	- Name: Org1						// 定义组织1的名字
		Domain: org1.example.com		// 定义组织1的根域名
		Template:
			Count: 2					// 定义组织1的节点数目
		Users:
			Count: 1					// 定义组织1的用户数目
	- Name: Org2
		Domain: org2.example.com
		Template:
			Count: 2
		Users:
			Count: 1

orderer节点的域名一般也是整个系统,测试环境中域名可以随意定义,正式生产环境中,域名选择已备案或放到白名单里
用下面命令生成证书

cryptogen generate --config=yaml文件位置 --output 存放证书的文件夹位置

生成的证书结构如下图:
证书文件

2. configtxgen模块

configtxgen模块用来生成orderer初始化文件和channel初始化文件,更新锚节点

configtxgen -profile TestTwoOrdererGenesis -outputBlock ./orderer.genesis.block
configtxgen -profile TestTwoOrgsChannel -outputCreateChannelTx ./roberttestchannel.tx -channelID roberttestchannel
configtxgen -profile TestTwoOrgsChannel -outputAnchorPeersUpdate  ./Org1MSPanchors.tx -channelID roberttestchannel -asOrg Org1MSP

3. configtxlator模块

configtxlator模块可以把区块链的二进制文件转为json文件格式
configtxlator的rest服务提供了解码、编码、计算配置更新、交易打包四个功能

在这里插入代码片

4. orderer模块

orderer模块负责对交易进行排序,并将排好序的交易打包成区块

orderer模块的配置文件

  • General节点配置
  • FileLedger节点配置
  • RAMLedger节点配置
  • Kafka节点配置
  • Debug节点配置

工作原理

  1. 客户端向orderer模块发送交易
  2. orderer节点对交易进行检查,符合条件就发送到排序队列
  3. orderer节点从队列中取出交易并打包,打包后将相关消息存储到本地
  4. orderer节点根据客户端请求将区块链发送给客户端

5. peer模块

主节点模块,负责存储区块链数据、运行维护链码、提供对外服务接口

peer模块的配置文件

  • logging相关配置
  • peer节点配置
  • vm节点配置:定义peer与orderer的交互
  • chaincode节点配置

每个组织的peer节点有四种角色:

  • 提交节点(committer):维护区块链账本,客户端发起交易时要指定一个提交节点(不能配置),作为接入区块链的入口来发起交易,提交节点还会定期从orderer节点获取包含交易的区块,并对区块校验、加入区块链
  • 背书节点(Endorse)负责对交易校验,校验后会将结果发送给客户端,也是由客户端发起交易时指定的(不能配置)
  • leader节点:代表组织从Orderer节点获取区块信息,一个组织只有一个,在peer模块的配置文件中配置,是自主选举还是强制指定
  • 锚节点(Anchor):负责代表组织和其他组织进行信息交换,通过configtxgen模块的配置文件配置host和port

这四种角色可以放在一个或多个peer节点上
在这里插入图片描述

6. TLS

TLS是为了保证数据传输的安全性,不是必选项,可以通过相关配置(orderer模块和peer模块的配置文件)激活或关闭

四、Fabric账号体系

cryptogen模块生成的账号结构:

msp
	admincerts ## 管理员证书
	cacerts	   ## 根CA服务器证书
	keystore   ## 节点或账号的私钥
	signcerts  ## 符合X.509的节点或者用户证书文件
	tlscacerts ## TLS根CA的证书
tls
	ca.crt
	server,crt
	server.key

Fabric中,每个动作创建通道、部署链码、调用链码都需要账号
启动Orderer节点时需要通过环境变量或配置文件设置账号,设置的是Orderer账号
启动Peer节点时需要通过环境变量或配置文件设置账号,设置的是Peer账号
创建channel时需要用到账号,用到的是用户账号

但是cryptogen模块生成账号具有局限性,只能刚开始通过配置文件生成相应数量的账号,但是无法动态的增加用户账号(peer账号可以通过配置start属性添加)。可以使用fabric-ca项目

五、Fabric智能合约

chaincode是客户端程序和Fabric之间的桥梁,客户端通过chaincode发起、查询交易,chaincode运行在docker容器中,chaincode支持多种语言开发。chaincode的管理在peer模块。

编写chaincode

  1. 编写链码的代码
package main
import(
	"fmt"
	"github.com/hyperledger/fabric/core/chaincode/shim"  // fabric上下文
	pb "github.com/hyperledger/fabric/protos/peer"		 // 主要负责和客户端通信
)

// 定义结构体作为chaincode的主对象
type simplechaincode struct{
}

// 结构体必须要实现Init方法
func(t *simplechaincode) Init(stub shim.ChaincodesStubInterface) pb.Response {
	fmt.Println("<< ======= success init it is view in docker ======== >>")
	return shim.Sucess([]byte("success init "))
}

// 结构体必须要实现Invoke方法
func(t *simplechaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
	fmt.Println("<< ======= 1. success it is view in docker ======== >>")
	_, args := stub.GetFunctionAndParameters()
	var a_parm = args[0]	// 按照下面的调用 set
	var a_parm = args[1]	// 按照下面的调用 akeym
	var a_parm = args[2]	// 按照下面的调用 11234343
	return shim.Success([]byte("success invoke "))
}

func main() {
	err := shim.Start(new(simplechaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}
  1. 部署、实例化、调用chaincode
## 部署
peer chaincode install -n qlkszzncc -v 1.1 -p chaincode所在目录
## 实例化 指明链码发起的交易需要Org1MSP或Org2MSP中任何一个用户背书即可 只有写操作需要背书 背书策略还有AND
peer chaincode instantiate -o orderer.qklszzn.com:7050 -C qklszzlchannel -n qlkszzncc -v 1.1 -c '{"Args":["init", "a", "100", "b", "200"]}' -P "OR {'Org1MSP.member', 'Org2MSP.member'}"
## 调用
peer chaincode invoke -o orderer.qklszzn.com:7050 -C qklszzlchannel -n qlkszzncc -c '{"Args": ["invoke", "set", "akeym", "11234343"]}'

chaincode实例化后会多出来一个运行chaincode的容器,容器名包含chaincode。如果这个容器启动后,peer容器重启是不影响chaincode容器的,chaincode容器不需要重启,如果chaincode执行出错导致容器关闭,客户端再请求的话,系统会自动启动chaincode容器。
一个通道内,如果在多个peer上安装了相同chaincode,只需要在一个peer节点上实例化就可以了

  1. ChaincodeStubInterface接口方法
方法功能
PutState(key string, value []byte) error存储数据到账本
GetState(key string) ([]byte, error)从账本中获取指定的数据
GetStateByRange(startKey, endKey string) (StateQueryIteratorInterface, error)查询指定key指定范围的数据
GetHistoryForKey(key string) (HistoryQueryIteratorInterface, error)获取指定key的历史记录
DelState(key string) error删除账本的数据
CreateCompositeKey(objectType string, attributes []string)创建复合键
GetStateByPartialCompositeKey(objectType string, attributes []string)通过复合键取值
SplitCompositeKey(compositeKey string) (string, []string, error)拆分复合键
GetTxID() string获取交易编号
GetTxTimestamp() (*timestamp.Timestamp, error)获取交易的时间
GetCreator获取交易的创建者
InvokeChainCode(chaincodeName string, args [][]byte, channel string) pb.Response调用其他Chaincode
  1. chaincode命令
peer chaincode insatll...
peer chaincode instantiate...
peer chaincode invoke...
peer chaincode list...
peer chaincode package...
peer chaincode query...
peer chaincode signpackage...
peer chaincode upgrade...

五、Fabric Java SDK

上面讲述的都是区块链内部节点的开发,下面讲如何通过客户端访问peer节点和orderer节点,下面是客户端开发的demo

<dependencies>
	<dependency>
		<groupId>org.hyperledger.fabric-sdk-java</groupId>
		<artifactId>fabric-sdk-java</artifactId>
		<version>1.1.0-SNAPSHOT</version>
	</dependency>
<dependencies>

待补充

六、CouchDB

fabric网络实际上有三种类型的数据存储,一种是账本本身,也就是区块链数据,是以文件形式存储;第二种是区块数据和历史数据的索引数据库;第三种是状态数据库,即存储我们在chaincode中执行的业务数据。其中第一和第二种是不能更换,第三个状态数据库默认是采用的levelDB,也支持couchdb


版权声明:本文为weixin_42787605原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。