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

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文件读取block对象的例子,block文件可以从peer channel fetch <BLOCKID> block.pb -o ${ORDERERADDR} -c ${CHANNEL}得到:

import (
 "github.com/golang/protobuf/proto"
 cb "github.com/hyperledger/fabric/protos/common"
)
...
 blockBytes, err := ioutil.ReadFile("block.pb")
 if err != nil {
 log.Println("ioutil.ReadFile error:", err)
 return
 }
 block := &cb.Block{}
 if err = proto.Unmarshal(blockBytes, block); err != nil {
 log.Println("proto.Unmarshal block error:", err)
 return
 }
 return block; // this is a common.block

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
}
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 简介 此项目是一个模拟公民身份信息链的区块链项目 github 地址: https://github.com/ak...
    CrazyWolf_46a9 阅读 12,833评论 0赞 0
  • 年轻时,你对好身体不以为然。等你年龄渐长,就会发现,没有好身体,你拥有的其他东西都贬值了。好身体,才是你最大的不动...
    渡过你的河升 阅读 3,505评论 0赞 0
  • 今天夕阳 我看到一乌云 乌黑乌黑的 可一会儿 有魔法般 有了色彩 最后风来云去 生命也是这般变幻无常么 我看到一...
    年年有余呀570 阅读 2,778评论 6赞 8
  • 莲摇鱼戏水,柳钓小桥东。 瀑泻云天外,溪流乱石中。 孤峰沉薄雾,藓径曳微风。 久住仙乡里,好修不老翁。 平水韵 上平一东
    苍浩 阅读 4,790评论 22赞 45
  • 一个恨时光匆匆的mo
    白兔咩 阅读 1,531评论 0赞 0

友情链接更多精彩内容