一、简介

Fabric Gateway是Hyperledger Fabric v2.4 Peer节点中引入的一项服务,它提供了一个简化的、最小的API,用于向Fabric网络提交事务。以前对客户端SDK提出的要求,例如从各个组织的Peer节点收集交易背书,现在被委托给在Peer节点中运行的Fabric Gateway服务,以便简化v2.4中的客户端应用程序开发过程中的事务提交和处理。归纳起来,具有以下优点:


  • 简化客户端应用程序和SDK——您的客户端应用程序可以简单地将事务提交委托给受信任的Peer节点。您的应用程序不需要打开到Peer节点的连接,也不需要从其他组织订购服务节点。
  • Fabric Gateway代表(代替)客户端应用程序——实现管理来自其他组织的交易背书的收集以及向订购服务的提交。
  • Fabric Gateway具有智能功能——可以确定给定交易需要哪些背书,即使您的解决方案结合了链码级别的背书策略、私人数据收集背书策略和基于状态的背书策略。

该新的轻量级网关SDK(v1.0.0)可适用于Node、Java和Go语言开发。这些SDK支持下面一些灵活的应用程序开发模式:


  • 您可以继续使用类似于早期SDK版本的高级编程模型;但是,现在,您的应用程序只需调用一个SubmitTransaction()函数
  • 更高级的应用程序可以利用网关单独的背书、提交和提交状态服务(Endorse、Submit和CommitStatus)进行事务提交,并利用评估服务进行查询。
  • 您可以将事务背书完全委托给网关(Gateway);或者如果需要,指定背书组织,由网关来使用每个组织的Peer节点。

二、编写客户端应用程序

从Fabric v2.4开始,客户端应用程序编程时应该使用其中一个网关SDK(Go、Node或Java),这些SDK已经经过优化处理以便与Fabric网关进行交互。简言之,这些SDK公开了最初在Fabric v1.4中引入的那种高级编程模型。

Fabric网关(简称网关)管理以下事务步骤:


  • 评估交易方案。这将在单个Peer节点上调用智能合约(chaincode)函数,并将结果返回给客户端。这通常用于查询分类帐的当前状态,而不进行任何分类帐更新。网关将优选地选择与网关Peer节点在同一组织中的Peer节点,并选择具有最高分类账块高度的Peer节点。如果网关的组织中没有可用的Peer节点,则它将从另一个组织中选择一个Peer节点。
  • 认可交易方案。这将收集足够的背书响应,以满足组合签名策略(见下文),并将准备好的交易信封返回给客户进行签名。
  • 提交交易。这将向排序(Orderer)服务发送一个签名的交易信封,以提交到分类账。
  • 等待提交状态事件。这允许客户端等待交易提交到分类账,并获得提交(验证/无效)状态代码。
  • 接收链代码事件。这将允许客户端应用程序在将交易提交到分类账时响应智能合约功能发出的事件。

网关SDK将背书/提交/提交状态(Endorse/Submit/CommitStatus)操作组合成一个单独的阻塞SubmitTransaction函数,以支持使用单行代码提交事务。或者,可以调用单独的操作来支持灵活的应用程序模式。

三、软件开发工具包(SDK)

网关及其SDK旨在让您作为客户端应用程序开发人员,能够专注于应用程序的业务逻辑,而不必关心与Fabric网络相关的基础结构逻辑。因此,API提供诸如组织和契约之类的逻辑抽象,而不是诸如Peer代码和链代码之类的操作抽象。

[补充说明]很明显,管理员API想要公开这些操作抽象,但这不是管理员API。

Hyperledger Fabric目前支持三种语言的客户端应用程序开发:



四、网关如何背书交易方案

为了将交易成功提交到分类账,需要足够数量的背书才能满足背书政策。获得组织的认可需要连接到其同行之一,并让其根据其分类账副本模拟(执行)交易提案。Peer节点通过调用chaincode函数来模拟事务,该函数由提议中的名称和参数指定,并构建(和签名)读写集合。读写集合包含当前分类帐状态以及响应该函数中的状态获取/设置指令而建议的更改。

应用于事务的背书策略或多个策略的总和取决于正在调用的链代码函数的实现,可以是以下各项的组合:


  • Chaincode背书政策。这些是通道成员在批准其组织的链代码定义时同意的策略。如果chaincode函数调用另一个chaincode中的一个函数,那么这两个策略都需要得到满足。
  • 私人数据收集背书政策。如果chaincode函数写入私有数据集合中的某个状态,则该集合的背书策略将覆盖该状态的chaincode策略。如果chaincode函数是从私有数据集合中读取的,那么它将被限制为该集合的成员组织。
  • 基于状态的背书(SBE:State-based endorsement)政策。也称为密钥级签名策略,这些策略可以应用于各个状态,并将覆盖私有数据收集状态的链码策略或收集策略。背书政策本身存储在分类账中,可以通过新的交易进行更新。

应用于交易方案的背书策略组合是在链代码运行时确定的,不一定是从静态分析中派生出来的。

Fabric Gateway使用以下流程来代表客户端实现管理交易认可的复杂性:


  • Fabric网关通过识别具有最高分类账块高度的(可用)Peer节点,从网关Peer节点的组织(MSPID)中选择认可Peer节点。假设网关Peer节点组织中的所有Peer都受到连接到网关Peer的客户端应用程序的信任。
  • 在选定的背书Peer节点上模拟交易提案。该模拟捕获有关访问状态的信息,从而捕获要组合的背书策略(包括存储在背书Peer节点的分类账上的任何基于状态的单独策略)。
  • 捕获的策略信息被组装到ChaincodeInterest protobuf结构中,并传递给发现服务,以便导出特定于所提议的交易的背书计划。
  • 网关通过请求满足计划中所有策略所需的组织的认可来应用认可计划。对于每个组织,网关Peer节点请求具有最高块高度的(可用)Peer节点的认可。

网关依赖于发现服务来获得可用Peer节点和排序服务节点的连接细节,并用于计算认可事务提议所需的Peer节点的组合。因此,在启用网关服务的Peer节点上,发现服务必须始终保持启用状态。

对于作为临时数据在提案中传递的私人数据,网关认可过程更具限制性,因为它通常包含敏感或个人信息,不得传递给所有组织的Peer节点。在这种情况下,网关将把认可组织的集合限制为要访问的私有数据集合的成员(读或写)。如果对瞬态数据的这种限制不满足认可策略,则网关向客户端返回错误,而不是将私有数据转发给可能未被授权访问私有数据的组织。在这些情况下,应该编写客户端应用程序来明确定义哪些组织应该认可事务。

针对特定背书Peer节点

在某些情况下,客户应用程序必须明确选择要评估或认可交易提案的组织。例如,临时数据通常包含个人或敏感信息,这些信息必须只写入私人数据收集,从而限制了背书组织的数量。在这些情况下,客户端应用程序可以明确指定背书组织,以满足应用程序的隐私和认可要求;网关然后将从每个指定组织中选择具有最高块计数的(可用的)认可Peer节点。但是,如果客户端指定了一组不满足背书策略的组织,则该事务仍可能得到指定Peer节点的背书并提交以便排序;但是,该事务稍后将在验证和提交阶段被通道中的所有Peer节点宣布无效。该无效交易记录在分类账上,但交易的更新不会写入任何通道Peer节点的状态数据库。

重试和错误处理

Fabric网关负责处理节点连接重试尝试、错误和超时等任务,如下所述。

重试次数

网关将使用发现服务信息重试由于Peer节点或排序节点不可用而失败的任何事务。如果一个组织正在运行多个Peer节点或排序节点,则将尝试另一个符合条件的节点。如果某个组织未能认可某个交易方案,则会选择另一个。如果一个组织未能完全背书,则满足背书策略的一组组织将成为目标。只有当没有满足认可策略的可用Peer组合时,网关才会停止重试。网关将继续重试,直到所有可能的背书Peer节点的组合都尝试过一次为止。

错误处理

Fabric网关管理到网络Peer节点和排序节点的gRPC连接。如果网关服务请求错误源自网络Peer或排序节点(即网关外部),则网关会在消息Details字段中向客户端返回错误、端点和组织(MSPID)信息。如果Details字段为空,则错误源自网关Peer节点。

超时

Fabric网关中提供的EvaluateEndorse向网关外部的Peer节点发出gRPC请求。为了限制客户端必须等待这些集体响应的时间长度,可以在peer core.yaml配置文件的gateway部分重写peer.gateway.endorsementTimeout值。

每个网关SDK还提供了一种机制,用于在从客户端应用程序调用时为每个网关方法设置超时。

五、监听事件

Fabric网关为客户端应用程序的开发提供了简化的API,以接收客户端应用程序中的链代码事件。每个SDK都提供了一种机制来使用其特定语言的习惯用法来处理这些事件。

六、兼容性说明

Fabric Gateway客户端API的每个次要发布版本都针对Go的当前支持版本,以及Node和Java的当前长期支持(LTS)版本。完整功能还需要网关Peer节点的Hyperledger Fabric的特定最低版本。

下表显示了Fabric、编程语言运行时和其他经过明确测试的依赖项的版本,这些依赖项支持与Fabric Gateway客户端API一起使用。

Hyperledger Fabric v2.4亮点之Fabric Gateway_应用程序

九、关于Hyperledger Fabric Gateway Client API for Go的应用补充

如何使用

Fabric示例存储库中提供了示例,展示了如何创建连接到Hyperledger Fabric网络并与之交互的客户端应用程序:



API文档

Go语言支持下的的网关客户端API文档可在此处获取:

安装

使用以下命令将包依赖项添加到项目中:

go get github.com/hyperledger/fabric-gateway

精简小例

package main

import (
	"fmt"
	"os"

	"github.com/hyperledger/fabric-gateway/pkg/client"
	"github.com/hyperledger/fabric-gateway/pkg/identity"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
)

func main() {
	// Create gRPC client connection, which should be shared by all gateway connections to this endpoint.
	clientConnection, err := grpc.Dial("gateway.example.org:1337", grpc.WithTransportCredentials(insecure.NewCredentials()))
	panicOnError(err)
	defer clientConnection.Close()

	// Create client identity and signing implementation based on X.509 certificate and private key.
	id := NewIdentity()
	sign := NewSign()

	// Create a Gateway connection for a specific client identity.
	gateway, err := client.Connect(id, client.WithSign(sign), client.WithClientConnection(clientConnection))
	panicOnError(err)
	defer gateway.Close()

	// Obtain smart contract deployed on the network.
	network := gateway.GetNetwork("channelName")
	contract := network.GetContract("chaincodeName")

	// Submit transactions that store state to the ledger.
	submitResult, err := contract.SubmitTransaction("transactionName", "arg1", "arg2")
	panicOnError(err)
	fmt.Printf("Submit result: %s", string(submitResult))

	// Evaluate transactions that query state from the ledger.
	evaluateResult, err := contract.EvaluateTransaction("transactionName", "arg1", "arg2")
	panicOnError(err)
	fmt.Printf("Evaluate result: %s", string(evaluateResult))
}

// NewIdentity creates a client identity for this Gateway connection using an X.509 certificate.
func NewIdentity() *identity.X509Identity {
	certificatePEM, err := os.ReadFile("certificate.pem")
	panicOnError(err)

	certificate, err := identity.CertificateFromPEM(certificatePEM)
	panicOnError(err)

	id, err := identity.NewX509Identity("mspID", certificate)
	panicOnError(err)

	return id
}

// NewSign creates a function that generates a digital signature from a message digest using a private key.
func NewSign() identity.Sign {
	privateKeyPEM, err := os.ReadFile("privateKey.pem")
	panicOnError(err)

	privateKey, err := identity.PrivateKeyFromPEM(privateKeyPEM)
	panicOnError(err)

	sign, err := identity.NewPrivateKeySign(privateKey)
	panicOnError(err)

	return sign
}

func panicOnError(err error) {
	if err != nil {
  panic(err)
	}
}


十、重要参考