1. 程式人生 > >HyperLeger Fabric SDK開發(七)——ledger

HyperLeger Fabric SDK開發(七)——ledger

HyperLeger Fabric SDK開發(七)——ledger

一、ledger簡介

1、ledger簡介

ledger包支援在Fabric網路上的指定通道上啟用賬本查詢。如果應用程式需要對多個通道進行賬本查詢,需要為每個通道的賬本客戶端建立一個單獨例項。賬本客戶端支援以下查詢:QueryInfo,QueryBlock,QueryBlockByHash,QueryBlockByTxID,QueryTransaction和QueryConfig。
官方文件:
https://godoc.org/github.com/hyperledger/fabric-sdk-go/pkg/client/ledger

2、ledger使用流程

ledger使用的基本流程如下:
A、準備通道上下文
B、建立分類帳客戶端
C、查詢分類帳
使用示例:

ctx := mockChannelProvider("mychannel")

c, err := New(ctx)
if err != nil {
    fmt.Println("failed to create client")
}

block, err := c.QueryBlock(1)
if err != nil {
    fmt.Printf("failed to query block: %s\n", err)
}

if block != nil {
    fmt.Println("Retrieved block #1")
}
// output:
// Retrieved block #1      

二、ledger常用介面

1、獲取賬本客戶端例項

type Client struct {
   ctx       context.Channel
   filter    fab.TargetFilter
   ledger    *channel.Ledger
   verifier  channel.ResponseVerifier
   discovery fab.DiscoveryService
}
func New(channelProvider context.ChannelProvider, opts ...ClientOption) (*Client, error) 

New返回賬本客戶端例項。賬本客戶端例項提供處理程式以查詢指定通道上的各種資訊。如果應用程式需要對多個通道進行賬本查詢,需要為每個通道的賬本客戶端建立一個單獨例項。賬本客戶端僅支援指定查詢。
使用示例:

ctx := mockChannelProvider("mychannel")

c, err := New(ctx)
if err != nil {
    fmt.Println(err)
}

if c != nil {
    fmt.Println("ledger client created")
}
// output:
// ledger client created        

2、查詢賬本

func (c *Client) QueryBlock(blockNumber uint64, options ...RequestOption) (*common.Block, error)
QueryBlock根據區塊編號查詢區塊的賬本。
引數:
blockNumber是必需的區塊號
options包含可選的請求選項
返回區塊資訊
使用示例:

c, err := New(mockChannelProvider("mychannel"))
if err != nil {
    fmt.Println("failed to create client")
}

block, err := c.QueryBlock(1)
if err != nil {
    fmt.Printf("failed to query block: %s\n", err)
}

if block != nil {
    fmt.Println("Retrieved block #1")
}
// output:
// Retrieved block #1  

func (c *Client) QueryBlockByHash(blockHash []byte, options ...RequestOption) (*common.Block, error)
QueryBlockByHash根據區塊hash查詢區塊賬本。
引數:
blockHash是區塊雜湊
options包含可選的請求選項
返回區塊資訊
使用示例:

c, err := New(mockChannelProvider("mychannel"))
if err != nil {
    fmt.Println("failed to create client")
}

block, err := c.QueryBlockByHash([]byte("hash"))
if err != nil {
    fmt.Printf("failed to query block by hash: %s\n", err)
}

if block != nil {
    fmt.Println("Retrieved block by hash")
}
// output:
// Retrieved block by hash   

func (c *Client) QueryBlockByTxID(txID fab.TransactionID, options ...RequestOption) (*common.Block, error)
QueryBlockByTxID查詢包含交易的區塊
引數:
txID是交易ID
options包含可選的請求選項
返回區塊資訊
使用示例:

c, err := New(mockChannelProvider("mychannel"))
if err != nil {
    fmt.Println("failed to create client")
}

block, err := c.QueryBlockByTxID("123")
if err != nil {
    fmt.Printf("failed to query block by transaction ID: %s\n", err)
}

if block != nil {
    fmt.Println("Retrieved block by transaction ID")
}
// output:
// Retrieved block by transaction ID   

3、查詢通道配置

func (c *Client) QueryConfig(options ...RequestOption) (fab.ChannelCfg, error)
QueryConfig查詢通道配置。
引數:
options包含可選的請求選項
返回通道配置資訊
使用示例:

c, err := New(mockChannelProvider("mychannel"))
if err != nil {
    fmt.Println("failed to create client")
}

cfg, err := c.QueryConfig(WithTargets(mockPeerWithConfigBlock()))
if err != nil {
    fmt.Printf("failed to query config: %s\n", err)
}

if cfg != nil {
    fmt.Println("Retrieved channel configuration")
}
// output:
// Retrieved channel configuration   

4、查詢通道資訊

func (c *Client) QueryInfo(options ...RequestOption) (*fab.BlockchainInfoResponse, error)
QueryInfo查詢此通道上的各種區塊鏈資訊,例如區塊高度和當前區塊雜湊。
引數:
options是可選的請求選項
返回區塊鏈資訊
使用示例:

c, err := New(mockChannelProvider("mychannel"))
if err != nil {
    fmt.Println("failed to create client")
}

bci, err := c.QueryInfo()
if err != nil {
    fmt.Printf("failed to query for blockchain info: %s\n", err)
}

if bci != nil {
    fmt.Println("Retrieved ledger info")
}
// output:
// Retrieved ledger info  

5、查詢交易資訊

func (c *Client) QueryTransaction(transactionID fab.TransactionID, options ...RequestOption) (*pb.ProcessedTransaction, error)
QueryTransaction通過交易ID查詢賬本上的已處理交易。
引數:
txID是必需的交易ID
options包含可選的請求選項
返回已經處理交易的資訊
使用示例:

c, err := New(mockChannelProvider("mychannel"))
if err != nil {
    fmt.Println("failed to create client")
}

t, err := c.QueryTransaction("123")
if err != nil {
    fmt.Printf("failed to query transaction: %s\n", err)
}

if t != nil {
    fmt.Println("Retrieved transaction")
}
// output:
// Retrieved transaction  

6、為客戶端設定過濾器

type ClientOption func(*Client) error

// WithDefaultTargetFilter option to configure new
func WithDefaultTargetFilter(filter fab.TargetFilter) ClientOption 
使用示例:
ctx := mockChannelProvider("mychannel")

c, err := New(ctx, WithDefaultTargetFilter(&urlTargetFilter{url: "example.com"}))
if err != nil {
    fmt.Println(err)
}

if c != nil {
    fmt.Println("ledger client created with url target filter")
}
// output:
// ledger client created with url target filter   

7、RequestOption引數構建

type RequestOption func(ctx context.Client, opts *requestOptions) error

//requestOptions contains options for operations performed by LedgerClient
type requestOptions struct {
   Targets       []fab.Peer                        // target peers
   TargetFilter  fab.TargetFilter                  // target filter
   MaxTargets    int                               // maximum number of targets to select
   MinTargets    int                               // min number of targets that have to respond with no error (or agree on result)
   Timeouts      map[fab.TimeoutType]time.Duration //timeout options for ledger query operations
   ParentContext reqContext.Context                //parent grpc context for ledger operations
}
func WithMaxTargets(maxTargets int) RequestOption

WithMaxTargets指定每個請求選擇的最大目標數。最大目標數的預設值為1.
func WithMinTargets(minTargets int) RequestOption
WithMinTargets指定必須響應且沒有錯誤(或同意結果)的最小目標數。 最小目標數的預設值為1。
func WithParentContext(parentContext reqContext.Context) RequestOption
WithParentContext封裝了grpc父上下文
使用示例:

c, err := New(mockChannelProvider("mychannel"))
if err != nil {
    fmt.Println(err)
}

channelContext, err := mockChannelProvider("mychannel")()
if err != nil {
    fmt.Println("failed to return channel context")
    return
}

// get parent context and cancel
parentContext, cancel := sdkCtx.NewRequest(channelContext, sdkCtx.WithTimeout(20*time.Second))
defer cancel()

bci, err := c.QueryInfo(WithParentContext(parentContext))
if err != nil {
    fmt.Printf("failed to query for blockchain info: %s\n", err)
}

if bci != nil {
    fmt.Println("Retrieved blockchain info")
}
// output:
// Retrieved blockchain info      

func WithTargetEndpoints(keys ...string) RequestOption
withTargetEndpoints允許每個請求覆蓋目標Peer節點。目標由名稱或URL指定,SDK將建立底層Peer節點物件。
func WithTargetFilter(targetFilter fab.TargetFilter) RequestOption
WithTargetFilter指定每個請求的目標Peer節點過濾器。
使用示例:

c, err := New(mockChannelProvider("mychannel"))
if err != nil {
    fmt.Println(err)
}

block, err := c.QueryBlock(1, WithTargetFilter(&urlTargetFilter{url: "example.com"}))
if err != nil {
    fmt.Printf("failed to query block: %s\n", err)
}

if block != nil {
    fmt.Println("Retrieved block #1 from example.com")
}
// output:
// Retrieved block #1 from example.com

func WithTargets(targets ...fab.Peer) RequestOption
WithTargets允許每個請求覆蓋目標Peer節點。
使用示例:

c, err := New(mockChannelProvider("mychannel"))
if err != nil {
    fmt.Println("failed to create client")
}

cfg, err := c.QueryConfig(WithTargets(mockPeerWithConfigBlock()))
if err != nil {
    fmt.Printf("failed to query config with target peer: %s\n", err)
}

if cfg != nil {
    fmt.Println("Retrieved config from target peer")
}
// output:
// Retrieved config from target peer 

func WithTimeout(timeoutType fab.TimeoutType, timeout time.Duration) RequestOption
WithTimeout封裝了超時型別、超時時間的鍵值對到Options選項,次選項用於QueryInfo,QueryBlock,QueryBlockByHash,QueryBlockByTxID,QueryTransaction,QueryConfig等函式。

三、ledger示例

var (
   sdk           *fabsdk.FabricSDK
   channelName   = "assetchannel"
   org           = "org1"
   user          = "Admin"
)

// 賬本查詢
func queryBlockchain() {
   ctx := sdk.ChannelContext(channelName, fabsdk.WithOrg(org), fabsdk.WithUser(user))

   cli, err := ledger.New(ctx)
   if err != nil {
      panic(err)
   }

   resp, err := cli.QueryInfo(ledger.WithTargetEndpoints("peer0.org1.example.com"))
   if err != nil {
      panic(err)
   }

   fmt.Println(resp)

   // 1
   cli.QueryBlockByHash(resp.BCI.CurrentBlockHash)

   // 2
   for i := uint64(0); i <= resp.BCI.Height; i++ {
      cli.QueryBlock(i)
   }
}