fabric-sdk-go
项目地址:https://github.com/sxguan/fabric-go-sdk
一、fabric-sdk-go概述
软件开发工具包(外语首字母缩写:SDK、外语全称:Software Development Kit)一般都是一些软件工程师为特定的软件包、软件框架、硬件平台、操作系统等建立应用软件时的开发工具的集合。软件开发工具包括广义上指辅助开发某一类软件的相关文档、范例和工具的集合。软件开发工具包是一些被软件工程师用于为特定的软件包、软件框架、硬件平台、操作系统等创建应用软件的开发工具的集合,一般而言SDK即开发 Windows 平台下的应用程序所使用的 SDK。它可以简单的为某个程序设计语言提供应用程序接口 API 的一些文件,但也可能包括能与某种嵌入式系统通讯的复杂的硬件。一般的工具包括用于调试和其他用途的实用工具。SDK 还经常包括示例代码、支持性的技术注解或者其他的为基本参考资料澄清疑点的支持文档。为了鼓励开发者使用其系统或者语言,许多 SDK 是免费提供的。
Fabric的Peer节点和Orderer节点都提供了基于GRPC协议(Google开发的远程过程调用RPC)的接口,通过这些接口可以和Peer节点与Orderer节点进行命令/数据交互,为了简化开发,官方提供了多语言版本的SDK。目前主流支持的已经有Go版本了,列出主流的三个:
Fabric Nodejs SDK
Fabric Java SDK
Fabric Go SDK
Golang是Fabric原生的开发语言,Fabric,Fabric-ca,Chaincode都是采用Golang开发的,所以我们围绕Golang版本的Fabric SDK来介绍。
fabric-go-sdk官方网址为https://github.com/hyperledger/fabric-sdk-go,其目录结构如下:
其中pkg目录是fabric-go-sdk的主要实现,internel目录和third_party目录包含了fabric-go-sdk依赖的一些代码。
pkg目录包含了以下这些软件包:
pkg/fabsdk:Fabric SDK的主软件包。此程序包使您可以基于配置创建上下文。这些上下文由下面列出的客户端软件包使用。参考:https://pkg.go.dev/github.com/hyperledger/fabric-sdk-go/pkg/fabsdkpkg/client/channel:提供通道交易功能。参考:https://pkg.go.dev/github.com/hyperledger/fabric-sdk-go/pkg/client/channelpkg/client/event:提供通道事件功能参考:https://pkg.go.dev/github.com/hyperledger/fabric-sdk-go/pkg/client/eventpkg/client/ledger:启用对渠道基础分类账的查询。参考:https://pkg.go.dev/github.com/hyperledger/fabric-sdk-go/pkg/client/ledgerpkg/client/resmgmt:提供资源管理功能,例如安装链码。参考:https://pkg.go.dev/github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmtpkg/client/msp:启用身份管理功能。参考:https://pkg.go.dev/github.com/hyperledger/fabric-sdk-go/pkg/client/msp
基本工作流程:
使用配置实例化
fabsdk实例。 注意:fabsdk维护高速缓存,因此您应最小化fabsdk本身的实例。使用
fabsdk实例基于用户和组织创建上下文。 注意:通道上下文还需要通道ID。使用其New函数创建一个客户端实例,并传递上下文。 注意:您需要为每个上下文创建一个新的客户端实例。
使用每个客户提供的功能来创建解决方案。
调用
fabsdk.Close()释放资源和缓存。
二、准备网络环境
在这个项目中我们构建一个有一个排序节点以及两个组织每个组织有一个节点的超级账本网络。
1. 准备证书文件
在$GOPATH/src目录下创建一个名为fabric-sdk-go的文件夹做为项目根目录,在此目录下创建名为fixtures的文件夹存放我们网络相关配置文件,在文件夹中创建一个名为crypto-config.yaml的文件并编辑如下:
使用以下命令生成证书文件:
2. 准备通道文件
在fixtures路径下创建一个名为configtx.yaml的文件并编辑如下:
生成创始块文件,使用以下命令在当前目录下的channel-artifacts目录下得到一个文件genesis.block。
生成通道文件,使用以下命令在当前目录下的channel-artifacts目录下得到一个文件channel.tx。
生成组织一锚节点更新文件,使用以下命令在当前目录下的channel-artifacts目录下得到一个文件Org1MSPanchors.tx。
生成组织二锚节点更新文件,使用以下命令在当前目录下的channel-artifacts目录下得到一个文件Org2MSPanchors.tx。
使用ls命令查看刚刚生成的文件。
3. 准备docker-compose文件
在fixtures路径下创建一个名为docker-compose.yaml的文件并编辑如下:
三、配置文件config.yaml
客户端使用sdk与fabric网络交互,需要告诉sdk两类信息:
我是谁:即当前客户端的信息,包含所属组织、密钥和证书文件的路径等, 这是每个客户端专用的信息。
对方是谁:即fabric网络结构的信息,channel、org、orderer和peer等 的怎么组合起当前fabric网络的,这些结构信息应当与
configytx.yaml中是一致的。这是通用配置,每个客户端都可以拿来使用。另外,这部分信息并不需要是完整fabric网络信息,如果当前客户端只和部分节点交互,那配置文件中只需要包含所使用到的网络信息。
下面是详细的配置文件用法:
1. 声明
2. 客户端部分
3. 通道部分
4. 组织部分
5. 排序节点部分
6. 对等节点部分
7. CA部分
8. EntityMatchers部分
9. operations部分
10. Metrics部分
11. 改写一个配置文件
现在我们来改写一个适用于我们网络的配置文件。在fabric-sdk-go路径下新建一个名为config.yaml的配置文件并编辑。我们将官方的config_e2e_multiorg_bootstrap.yaml文件进行改写,相关文件可在官方githubhttps://github.com/hyperledger/fabric-sdk-go/blob/main/test/fixtures/config/config_e2e_multiorg_bootstrap.yaml上找到。我们只将所有的证书路径改成我们项目的对应路径,以及将端口号改为在基础网络中对应的端口号。改好的配置文件如下:
四、初始化及加入通道
1. 定义所需结构体
在项目路径下新建名为sdkInit的文件夹,此文件夹用于存放实现sdk的代码。在sdkInit路径下新建sdkInfo.go并编辑如下:
导入所需包
mspclient "github.com/hyperledger/fabric-sdk-go/pkg/client/msp"msp包允许在Fabric网络上创建和更新用户。msp客户端支持以下操作:注册、重注册、登记和获取身份签名。基本工作流为:准备客户端上下文
创建msp客户端
登记用户
注册用户
"github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt"resmgmt包用于在Fabric网络中创建和更新资源。它允许管理员创建和/或更新通道,并允许对等节点加入通道。管理员还可以在对等节点上执行链码相关操作,如安装、实例化、升级链码等。基本工作流为:准备客户端上下文
创建资源管理器客户端
创建新通道
节点加入通道
查询对等节点的通道,安装/实例化的链代码等。
contextAPI "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context"提供所需上下文接口
2.初始化
在sdkInit路径下新建sdkSetting.go并编辑如下:
导入所需包
"github.com/hyperledger/fabric-sdk-go/pkg/core/config":获取所需配置文件"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk":fabsdk包允许客户端使用Hyperledger Fabric网络。
3. 创建及加入通道
继续在sdkSetting.go文件中编辑如下:
导入所需包
调用创建通道函数及加入通道
创建通道
五、链码生命周期
链码运行在一个隔离于背书peer节点进程的安全的Docker容器中。链码通过应用提交的交易来初始化以及管理账本状态。从hyperledger fabric v2.0版本开始启用了新的链码生命周期,Fabric 链码生命周期是一个过程,它允许多个组织在使用一个链码之前就如何操作达成一致。Fabric链码生命周期需要组织同意定义一个链码的参数,比如说名称、版本以及链码背书策略。通道成员通过以下四步达成共识。不是通道上的每一个组织都需要完成每一步。
打包链码:这一步可以被一个或者每一个组织完成。
安装链码在你的 peer 节点上:每一个用链码的组织需要完成这一步。
为你的组织批准链码定义:使用链码的每一个组织需要完成这一步。链码能够在通道上运行之前,链码定义需要被足够多的组织批准来满足通道的生命周期背书(LifecycleEndorsement)策略(默认为大多数组织)。
提交链码定义到链上:一旦通道上所需数量的组织已经同意,提交交易需要被提交。提交者首先从已同意组织中的足够的peer节点中收集背书,然后通过提交交易来提交链码声明。
1. 添加DiscoverLocalPeers方法
DiscoverLocalPeers方法可以自动查找的所有节点
在sdkInit路径下新建一个名为intergration.go的文件。编辑如下:
2. 链码自动化生命周期
继续在sdkSetting.go文件中编辑如下:
导入所需包
打包链码
在被安装到
peer节点之前,链码需要被打包进一个tar文件。当你创建一个链码包的时候,你需要提交一个用来创建简明易读的包描述的链码包标签。使用
fabric-go-sdk将会自动以这个格式来创建文件。链码需要被打包进一个以
.tar.gz文件扩展名结尾的tar文件。tar文件需要包含两个文件(没有目录):metadata.json和另一个包含了链码文件的 tar 文件code.tar.gz。metadata.json包含了指定链码语言、代码路径、以及包标签的 JSON 文件。
安装链码
你需要在每个要执行和背书交易的peer节点上安装链码包。使用SDK时,你需要以
Peer Administrator(peer所在组织的管理员) 的身份来完成这步。链码安装后,你的 peer 节点会构建链码,并且如果你的链码有问题,会返回一个构建错误。建议每个组织只打包链码一次,然后安装相同的包在属于他们组织的每一个peer节点上。如果某个通道希望确保每个组织都运行同样的链码,某一个组织可以打包链码并通过带外数据(不通过链上)把它发送给其他通道成员.通过指令成功安装链码后会返回链码包标识符,它是包标签和包哈希值的结合。这个包标识符用来关联安装在你的peer节点上的链码包已被批准的链码。为下一步的操作保存这个标识符。你也可以查询安装在peer节点上的包来查看包标识符。
获取已安装链码包
查询安装
各组织批准链码
通过 链码定义来管理链码。当通道成员批准一个链码定义,这个批准便作为一个组织在接受链码参数方面的投票。这些同意的组织定义允许通道成员在链码可以在通道上使用之前达成一致意见(同意链码运行在此通道上)。链码定义包含了以下需要持续在组织之间保持一致的参数:
名称:应用调用链码时使用的名称。
版本:一个版本号或者和给定链码包关联的值。如果你升级链码二进制文件(译者注:打包后的链码文件),你也需要改变你的链码版本。
序列号:链码被定义的次数。这个值是一个整数,并且被用来追踪链码的更新次数。例如当你第一次安装并且同意一个链码定义,这个序列号会是1。当你下一次更新链码,序列号会是2。
背书策略:哪些组织需要执行并且验证交易输出。背书策略可以表达为传递给 CLI 工具的字符串或者它能参考通道配置中的一个策略。默认情况下,背书策略设置为
Channel/Application/Endorsement,默认通道中大多数组织为一笔交易背书。集合配置(私有数据集合配置):和你链码相关的私有数据集合定义文件的路径。了解更多关于私有数据集合的信息。
ESCC/VSCC插件:这个链码使用的定制的背书或者验证插件名称。初始化: 如果你使用 Fabric Chaincode Shim API 提供的低级别的 API,你的链码需要包含用来初始化链码的
Init方法。链码接口需要这个方法,但不必要被你的应用调用。 当你批准一个链码定义时,你可以指定是否Init方法必须在调用(调用非 init 方法)之前被执行。如果你指定需要Init,Fabric 会确保Init方法在链码中的其他方法之前被调用,并且只会被调用一次。 请求执行Init方法允许你实现链码初始化时运行的逻辑,例如设置一些初始状态。每次你的链码版本更新,你都需要调用Init来初始化链码,假定链码定义增加了版本号意味着Init是需要的。
查询已批准的链码
检查智能合约是否就绪
提交智能合约定义
一旦足够多的通道成员同意一个链码定义,某个组织能够提交定义到通道。你可以用上述
checkcommitreadiness方法在将链码定义提交到通道之前,基于哪个通道成员已经批准了该定义,来检查提交链码定义是否应该成功。(根据通道成员同意的状况,来判断提交是否可能成功)。提交交易请求首先发送给通道成员的 peer节点,peer节点会查询链码定义被他们组织同意的状况,并且为定义背书如果所在组织已经同意了。交易然后提交给排序服务,排序服务会把链码定义提交给通道。提交定义交易需要以 Organization Administrator 身份来提交。链码在被成功提交到通道之前,需要被同意的组织的数量是通过
Channel/Application/LifecycleEndorsement策略来管理的。默认情况下,这个策略需要通道中大多数的组织来给交易背书。生命周期背书策略不同于链码背书策略。例如,尽管一个链码背书策略只需要一个或两个组织的签名,根据默认策略大多数的通道成员仍然需要批准链码定义。当提交一个通道定义,你需要面向足够多的 peer 组织,以确保你的生命周期背书策略被满足。你也可以设置
Channel/Application/LifecycleEndorsement策略为一个签名策略并且明确指明通道上可以批准链码定义的组织集合。这允许你创建一个其中大多数组织作为链码管理者并且治理通道业务逻辑的通道。如果你的通道有大量的Idemix(身份混合,实现零知识证明)组织,你也可以用一个签名策略(策略只需要一个签名),因为这些组织不能批准链码定义或者为链码背书并且可能阻碍通道达成大多数成员同意的结果。一个组织在不安装链码包的条件下能够批准链码定义。如果一个组织不需要使用链码,他们可以在没有包身份的情况下批准一个链码定义来确保生命周期背书策略被满足。
在链码定义已经提交到通道上后,链码容器会在所有的链码安装到的 peer 节点上启动,来允许通道成员开始使用链码。可能会花费几分钟的时间来启动链码容器。你可以用链码定义来要求调用
Init方法初始化链码。如果Init方法调用是需要的,链码的第一个调用必须是调用Init方法。Init方法的调用服从于链码的背书策略。
查询已提交的智能合约定义
智能合约初始化
智能合约完整生命周期(即整合调用上述方法)
六、项目启动
1. main方法
在项目的根目录下新建一个名为main.go的文件,为项目的主函数。在这里我们实现将组织通道等相关信息实例化,以及调用前面的函数实现创建通道加入通道将链码实例化。
2. 添加链码文件
在项目根目录下新建一个名为chaincode的文件夹,在chaincode目录下添加一个名为sacc.go的智能合约(此智能合约为官方测试网络中的示例链码),编辑如下:
3. 启动项目
在命令行中进入chaincode路径,并使用以下命令为链码添加依赖包。
在命令行中进入项目根目录,并使用以下命令为项目添加依赖包。
在命令行中进入fixture路径,并使用以下命令启动网络。
在命令行中进入项目根目录,并使用以下命令build整个项目。
接着使用以下命令运行项目。
运行成功后输出:
Last updated