分享
  1. 首页
  2. 文章

fabric如何解析一个common.block的内容

CodingCode · · 2123 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

fabric如何解析一个common.block的内容

在前面的文章 "fabric如何从ledger里面读取block的内容" 中我们介绍了如何从ledger文件里面读取一个block,然后把block的内容写到一个文件中,再使用工具configtxlator把block内容翻译成json,这样用户就可以读取block的内容了。

这篇文章中我们直接用golang借助于fabric本身的代码,利用代码来解析和读取block的内容;也就是说当我们得到一个common.block对象时,我们直接利用fabric的数据结构和函数访问block的内容,而不需要借助configtxlator。

这部分代码是一个框架,不能单独编译,必须借助于前面提到的文章"fabric如何从ledger里面读取block的内容"的部分代码。

主函数

接受一个common.block对象,然后根据是Config block还是Endorser Transaction block分别解析。

包含:

  • block number
  • block hash value
  • channel
  • txid
  • creator
package main
import (
 "fmt"
 "encoding/base64"
 "github.com/golang/protobuf/proto"
 "github.com/hyperledger/fabric/protos/common"
 "github.com/hyperledger/fabric/protos/utils"
 "github.com/hyperledger/fabric/protos/peer"
 "github.com/hyperledger/fabric/common/configtx"
 "github.com/hyperledger/fabric/core/ledger/util"
 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
)
func parseBlock(block *common.Block) error {
 var err error
 // Handle header
 fmt.Printf("Block: Number=[%d], CurrentBlockHash=[%s], PreviousBlockHash=[%s]\n",
 block.GetHeader().Number,
 base64.StdEncoding.EncodeToString(block.GetHeader().DataHash),
 base64.StdEncoding.EncodeToString(block.GetHeader().PreviousHash))
 // Handle transaction
 var tranNo int64 = -1
 txsFilter := util.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
 if len(txsFilter) == 0 {
 txsFilter = util.NewTxValidationFlags(len(block.Data.Data))
 block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = txsFilter
 }
 for _, envBytes := range block.Data.Data {
 tranNo++
 if txsFilter.IsInvalid(int(tranNo)) {
 fmt.Printf(" Transaction: No=[%d], Status=[INVALID]\n", tranNo)
 continue
 } else {
 fmt.Printf(" Transaction: No=[%d], Status=[VALID]\n", tranNo)
 }
 var env *common.Envelope
 if env, err = utils.GetEnvelopeFromBlock(envBytes); err != nil {
 return err
 }
 var payload *common.Payload
 if payload, err = utils.GetPayload(env); err != nil {
 return err
 }
 var chdr *common.ChannelHeader
 if chdr, err = utils.UnmarshalChannelHeader(payload.Header.ChannelHeader); err != nil {
 return err
 }
 fmt.Printf(" txid=[%s], channel=[%s]\n", chdr.TxId, chdr.ChannelId)
 var shdr *common.SignatureHeader
 if shdr, err = utils.GetSignatureHeader(payload.Header.SignatureHeader); err != nil {
 return err
 }
 var mspid, subject string
 if mspid, subject, err = decodeSerializedIdentity(shdr.Creator); err != nil {
 return err
 }
 fmt.Printf(" creator=[%s:%s]\n", mspid, subject)
 if common.HeaderType(chdr.Type) == common.HeaderType_CONFIG {
 fmt.Printf(" type=[CONFIG]\n")
 if err = parseConfig(payload); err != nil {
 return err
 }
 } else if common.HeaderType(chdr.Type) == common.HeaderType_ENDORSER_TRANSACTION {
 fmt.Printf(" type=[ENDORSER_TRANSACTION]\n")
 if err = parseEndorserTransaction(payload); err != nil {
 return err
 }
 } else {
 fmt.Printf(" txid=[%s], channel=[%s], type=[UNKNOWN]\n", chdr.TxId, chdr.ChannelId)
 }
 }
 return nil
}

解析endorser transaction block

这个解析并不完整,只是我们项目中需要的字段进行了解析,其他的丢弃了。
主要包括:

  • endorsers
  • RWSet (chaincode, key)
func parseEndorserTransaction(payload *common.Payload) error {
 var err error
 var tx *peer.Transaction
 if tx, err = utils.GetTransaction(payload.Data); err != nil {
 return err
 }
 fmt.Printf(" actions\n")
 for _, action := range tx.Actions {
 var capayload *peer.ChaincodeActionPayload
 var ca *peer.ChaincodeAction
 if capayload, ca, err = utils.GetPayloads(action); err != nil {
 return err
 }
 fmt.Printf(" endorsers\n")
 for _, endorser := range capayload.Action.Endorsements {
 var mspid, subject string
 if mspid, subject, err = decodeSerializedIdentity(endorser.Endorser); err != nil {
 return err
 }
 fmt.Printf(" endorser[%s:%s]\n", mspid, subject)
 }
 fmt.Printf(" RWSet\n")
 txRWSet := &rwsetutil.TxRwSet{}
 if err = txRWSet.FromProtoBytes(ca.Results); err != nil {
 return err
 }
 for _, nsRWSet := range txRWSet.NsRwSets {
 ns := nsRWSet.NameSpace
 if ns != "lscc" { // skip system chaincode
 fmt.Printf(" ns=[%v]\n", ns)
 fmt.Printf(" RDSet\n")
 for _, kvRead := range nsRWSet.KvRwSet.Reads {
 fmt.Printf(" key=[%v]\n", kvRead.Key)
 }
 fmt.Printf(" WRSet\n")
 for _, kvWrite := range nsRWSet.KvRwSet.Writes {
 if kvWrite.IsDelete {
 fmt.Printf(" key=[%v] op=[delete]\n", kvWrite.Key)
 } else {
 fmt.Printf(" key=[%v] op=[write]\n", kvWrite.Key)
 }
 }
 }
 }
 }
 return nil
}

解析 config block

和前面一样,也没有解析整个config block,只解析了我们项目中需要的字段,其实只有一个orderer address,当然其他的也很容易处理了。

func parseConfig(payload *common.Payload) error {
 var err error
 var configEnvelope *common.ConfigEnvelope
 if configEnvelope, err = configtx.UnmarshalConfigEnvelope(payload.Data); err != nil {
 return err
 }
 var configGroup * common.ConfigGroup = configEnvelope.Config.ChannelGroup
 fmt.Printf(" Groups\n")
 for k, _ := range configGroup.Groups {
 fmt.Printf(" %s\n", k)
 }
 fmt.Printf(" Values\n")
 for k, v := range configGroup.Values {
 fmt.Printf(" %s\n", k)
 if k == "OrdererAddresses" {
 addresses := &common.OrdererAddresses{}
 if err = proto.Unmarshal(v.Value, addresses); err != nil {
 return err
 }
 for _, address := range addresses.Addresses {
 fmt.Printf(" [%s]\n", address)
 }
 }
 }
 return nil
}

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:CodingCode

查看原文:fabric如何解析一个common.block的内容

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
2123 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏