HyperLeger Fabric SDK开发(四)——channel
HyperLeger Fabric SDK开发(四)--channel
一、channel简介
1、channel 简介
pkg/client/channel支持访问Fabric网络上的通道。channel客户端实例提供与指定通道上的Peer节点进行交互的处理函数。channel客户端可以在指定通道上查询链码,执行链码以及注册或注销链码事件。如果应用程序需要与Fabric网络的多条通道进行交互,需要为每条通道创建一个单独的通道客户端实例。
官方文档:
https://godoc.org/github.com/hyperledger/fabric-sdk-go/pkg/client/channel
2、channel使用流程
channel使用流程如下:
A、准备通道客户端上下文
B、创建通道客户端
C、执行链码
D、查询链码
channel使用示例如下:
c, err := New(mockChannelProvider("mychannel"))if err != nil { fmt.Println("failed to create client")}response, err := c.Query(Request{ChaincodeID: "testCC", Fcn: "invoke", Args: [][]byte{[]byte("query"), []byte("data")}})if err != nil { fmt.Printf("failed to query chaincode: %s\n", err)}fmt.Println(string(response.Payload))// output:// abc
二、channel常用接口
1、类型定义
// Request 包含查询和执行一个调用交易的参数 type Request struct { ChaincodeID string Fcn string Args [][]byte TransientMap map[string][]byte // InvocationChai包含元数据,某些选择服务实现使用元数据来选择满足调用链中所有链码的背书 // 策略的背书节点 // Each chaincode may also be associated with a set of private data collection names // which are used by some Selection Services (e.g. Fabric Selection) to exclude endorsers // that do NOT have read access to the collections. // The invoked chaincode (specified by ChaincodeID) may optionally be added to the invocation // chain along with any collections, otherwise it may be omitted. InvocationChain []*fab.ChaincodeCall}//Response包含执行和查询一个调用交易的响应参数type Response struct { Proposal *fab.TransactionProposal Responses []*fab.TransactionProposalResponse TransactionID fab.TransactionID TxValidationCode pb.TxValidationCode ChaincodeStatus int32 Payload []byte}
2、获取客户端实例
type Client struct { context context.Channel membership fab.ChannelMembership eventService fab.EventService greylist *greylist.Filter clientTally // nolint}
通道客户端支持访问Fabric网络上的通道。为了与特定通道的Peer节点进行交互,通道客户端实例提供了一个处理程序。 如果应用程序需要与多个通道进行交互,应该为每个通道创建一个单独的通道客户端实例。 通道客户端只支持非管理功能。
type ClientOption func(*Client) errorfunc New(channelProvider context.ChannelProvider, opts ...ClientOption) (*Client, error)
返回通道Client实例。通道客户端可以在特定通道上查询链码,执行链码以及注册/注销链码事件。
使用示例:
ctx := mockChannelProvider("mychannel")c, err := New(ctx)if err != nil { fmt.Println(err)}if c != nil { fmt.Println("channel client created")} else { fmt.Println("channel client is nil")}// output:// channel client created
3、执行交易
func (cc *Client) Execute(request Request, options ...RequestOption) (Response, error)
使用请求和可选的请求选项进行准备并执行事务。
参数:
request包含必备链码ID和函数的相关信息
options包含可选的请求选项
返回Peer的提案回复
使用示例:
c, err := New(mockChannelProvider("mychannel"))if err != nil { fmt.Println("failed to create client")}_, err = c.Execute(Request{ChaincodeID: "testCC", Fcn: "invoke", Args: [][]byte{[]byte("move"), []byte("a"), []byte("b"), []byte("1")}})if err != nil { fmt.Println(err.Error())}fmt.Println("Chaincode transaction completed")// output:// Chaincode transaction completed
4、调用交易处理
func (cc *Client) InvokeHandler(handler invoke.Handler, request Request, options ...RequestOption) (Response, error)
InvokeHandler使用提供的请求和可选请求选项来调用处理程序
参数:
handler为要调用的处理程序
request包含必备的链码ID和函数的相关信息
options包含可选的请求选项
返回Peer的提案回复
使用示例:
c, err := New(mockChannelProvider("mychannel"))if err != nil { fmt.Println("failed to create client")}response, err := c.InvokeHandler(&exampleHandler{}, Request{ChaincodeID: "testCC", Fcn: "invoke", Args: [][]byte{[]byte("query"), []byte("data")}})if err != nil { fmt.Printf("failed to query chaincode: %s\n", err)}fmt.Println(string(response.Payload))// output:// custom
5、查询
func (cc *Client) Query(request Request, options ...RequestOption) (Response, error)
使用request 和可选请求选项options查询链码。
参数:
request包含必备链码ID和函数的相关信息
options包含可选的请求选项
返回值:Peer的提案回复
使用示例:
c, err := New(mockChannelProvider("mychannel"))if err != nil { fmt.Println("failed to create client")}response, err := c.Query(Request{ChaincodeID: "testCC", Fcn: "invoke", Args: [][]byte{[]byte("query"), []byte("b")}})if err != nil { fmt.Printf("failed to query chaincode: %s\n", err)}if len(response.Payload) > 0 { fmt.Println("chaincode query success")}// output:// chaincode query success
6、注册链码事件
func (cc *Client) RegisterChaincodeEvent(chainCodeID string, eventFilter string) (fab.Registration, <-chan *fab.CCEvent, error)
注册链码事件。当不再需要注册时,必须调用取消注册。
参数:
chaincodeID接收事件的链码的链码ID
eventFilter用于接收事件的链码事件过滤器(正则表达式)
返回注册和用于接收事件的通道。调用注销事件时,通道将关闭。
使用示例:
c, err := New(mockChannelProvider("mychannel"))if err != nil { fmt.Println("failed to create client")}registration, _, err := c.RegisterChaincodeEvent("examplecc", "event123")if err != nil { fmt.Println("failed to register chaincode event")}defer c.UnregisterChaincodeEvent(registration)fmt.Println("chaincode event registered successfully")// output:// chaincode event registered successfully
7、注销链码事件
func (cc *Client) UnregisterChaincodeEvent(registration fab.Registration)
删除给定的链码事件注册并关闭事件通道。
参数:
registration是从RegisterChaincodeEvent方法返回的注册句柄
8、RequestOption选项构建
type requestOptions struct { Targets []fab.Peer // targets TargetFilter fab.TargetFilter TargetSorter fab.TargetSorter Retry retry.Opts BeforeRetry retry.BeforeRetryHandler Timeouts map[fab.TimeoutType]time.Duration //timeout options for channel client operations ParentContext reqContext.Context //parent grpc context for channel client operations (query, execute, invokehandler) CCFilter invoke.CCFilter}// RequestOption func for each Opts argumenttype RequestOption func(ctx context.Client, opts *requestOptions) error
func WithBeforeRetry(beforeRetry retry.BeforeRetryHandler) RequestOption
指定在重试前调用的函数func WithChaincodeFilter(ccFilter invoke.CCFilter) RequestOption
添加一个链码过滤器,用于计算额外的背书节点func WithParentContext(parentContext reqContext.Context) RequestOption
WithParentContext封装了grpc父上下文func WithRetry(retryOpt retry.Opts) RequestOption
WithRetry生成用于配置重试的选项func WithTargetEndpoints(keys ...string) RequestOption
WithTargetEndpoints允许为请求的覆盖目标Peer节点。目标Peer节点由名称或URL指定,SDK将创建底层的Peer节点对象。func WithTargetFilter(filter fab.TargetFilter) RequestOption
WithTargetFilter指定每个请求的目标Peer节点的过滤器func WithTargets(targets ...fab.Peer) RequestOption
WithTargets允许为请求覆盖目标Peer节点func WithTimeout(timeoutType fab.TimeoutType, timeout time.Duration) RequestOption
WithTimeout封装了超时类型的键值对func WithTargetSorter(sorter fab.TargetSorter) RequestOption
指定每个请求的排序节点
三、chennel示例
ctx := sdk.ChannelContext(channelName, fabsdk.WithOrg(org), fabsdk.WithUser(user))cli, err := channel.New(ctx)if err != nil { return channel.Response{}, err}// 状态的查询resp,err := cli.Query(channel.Request{ ChaincodeID: chaincodeName, Fcn: fcn, Args: args,}, channel.WithTargetEndpoints("peer0.org1.example.com"))