github.com/true-sqn/fabric@v2.1.1+incompatible/common/ledger/blkstorage/fsblkstorage/block_serialization.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package fsblkstorage
     8  
     9  import (
    10  	"github.com/golang/protobuf/proto"
    11  	"github.com/hyperledger/fabric-protos-go/common"
    12  	"github.com/hyperledger/fabric/protoutil"
    13  	"github.com/pkg/errors"
    14  )
    15  
    16  type serializedBlockInfo struct {
    17  	blockHeader *common.BlockHeader
    18  	txOffsets   []*txindexInfo
    19  	metadata    *common.BlockMetadata
    20  }
    21  
    22  //The order of the transactions must be maintained for history
    23  type txindexInfo struct {
    24  	txID string
    25  	loc  *locPointer
    26  }
    27  
    28  func serializeBlock(block *common.Block) ([]byte, *serializedBlockInfo, error) {
    29  	buf := proto.NewBuffer(nil)
    30  	var err error
    31  	info := &serializedBlockInfo{}
    32  	info.blockHeader = block.Header
    33  	info.metadata = block.Metadata
    34  	if err = addHeaderBytes(block.Header, buf); err != nil {
    35  		return nil, nil, err
    36  	}
    37  	if info.txOffsets, err = addDataBytesAndConstructTxIndexInfo(block.Data, buf); err != nil {
    38  		return nil, nil, err
    39  	}
    40  	if err = addMetadataBytes(block.Metadata, buf); err != nil {
    41  		return nil, nil, err
    42  	}
    43  	return buf.Bytes(), info, nil
    44  }
    45  
    46  func deserializeBlock(serializedBlockBytes []byte) (*common.Block, error) {
    47  	block := &common.Block{}
    48  	var err error
    49  	b := newBuffer(serializedBlockBytes)
    50  	if block.Header, err = extractHeader(b); err != nil {
    51  		return nil, err
    52  	}
    53  	if block.Data, _, err = extractData(b); err != nil {
    54  		return nil, err
    55  	}
    56  	if block.Metadata, err = extractMetadata(b); err != nil {
    57  		return nil, err
    58  	}
    59  	return block, nil
    60  }
    61  
    62  func extractSerializedBlockInfo(serializedBlockBytes []byte) (*serializedBlockInfo, error) {
    63  	info := &serializedBlockInfo{}
    64  	var err error
    65  	b := newBuffer(serializedBlockBytes)
    66  	info.blockHeader, err = extractHeader(b)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  	_, info.txOffsets, err = extractData(b)
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  
    75  	info.metadata, err = extractMetadata(b)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	return info, nil
    80  }
    81  
    82  func addHeaderBytes(blockHeader *common.BlockHeader, buf *proto.Buffer) error {
    83  	if err := buf.EncodeVarint(blockHeader.Number); err != nil {
    84  		return errors.Wrapf(err, "error encoding the block number [%d]", blockHeader.Number)
    85  	}
    86  	if err := buf.EncodeRawBytes(blockHeader.DataHash); err != nil {
    87  		return errors.Wrapf(err, "error encoding the data hash [%v]", blockHeader.DataHash)
    88  	}
    89  	if err := buf.EncodeRawBytes(blockHeader.PreviousHash); err != nil {
    90  		return errors.Wrapf(err, "error encoding the previous hash [%v]", blockHeader.PreviousHash)
    91  	}
    92  	return nil
    93  }
    94  
    95  func addDataBytesAndConstructTxIndexInfo(blockData *common.BlockData, buf *proto.Buffer) ([]*txindexInfo, error) {
    96  	var txOffsets []*txindexInfo
    97  
    98  	if err := buf.EncodeVarint(uint64(len(blockData.Data))); err != nil {
    99  		return nil, errors.Wrap(err, "error encoding the length of block data")
   100  	}
   101  	for _, txEnvelopeBytes := range blockData.Data {
   102  		offset := len(buf.Bytes())
   103  		txid, err := protoutil.GetOrComputeTxIDFromEnvelope(txEnvelopeBytes)
   104  		if err != nil {
   105  			logger.Warningf("error while extracting txid from tx envelope bytes during serialization of block. Ignoring this error as this is caused by a malformed transaction. Error:%s",
   106  				err)
   107  		}
   108  		if err := buf.EncodeRawBytes(txEnvelopeBytes); err != nil {
   109  			return nil, errors.Wrap(err, "error encoding the transaction envelope")
   110  		}
   111  		idxInfo := &txindexInfo{txID: txid, loc: &locPointer{offset, len(buf.Bytes()) - offset}}
   112  		txOffsets = append(txOffsets, idxInfo)
   113  	}
   114  	return txOffsets, nil
   115  }
   116  
   117  func addMetadataBytes(blockMetadata *common.BlockMetadata, buf *proto.Buffer) error {
   118  	numItems := uint64(0)
   119  	if blockMetadata != nil {
   120  		numItems = uint64(len(blockMetadata.Metadata))
   121  	}
   122  	if err := buf.EncodeVarint(numItems); err != nil {
   123  		return errors.Wrap(err, "error encoding the length of metadata")
   124  	}
   125  	for _, b := range blockMetadata.Metadata {
   126  		if err := buf.EncodeRawBytes(b); err != nil {
   127  			return errors.Wrap(err, "error encoding the block metadata")
   128  		}
   129  	}
   130  	return nil
   131  }
   132  
   133  func extractHeader(buf *buffer) (*common.BlockHeader, error) {
   134  	header := &common.BlockHeader{}
   135  	var err error
   136  	if header.Number, err = buf.DecodeVarint(); err != nil {
   137  		return nil, errors.Wrap(err, "error decoding the block number")
   138  	}
   139  	if header.DataHash, err = buf.DecodeRawBytes(false); err != nil {
   140  		return nil, errors.Wrap(err, "error decoding the data hash")
   141  	}
   142  	if header.PreviousHash, err = buf.DecodeRawBytes(false); err != nil {
   143  		return nil, errors.Wrap(err, "error decoding the previous hash")
   144  	}
   145  	if len(header.PreviousHash) == 0 {
   146  		header.PreviousHash = nil
   147  	}
   148  	return header, nil
   149  }
   150  
   151  func extractData(buf *buffer) (*common.BlockData, []*txindexInfo, error) {
   152  	data := &common.BlockData{}
   153  	var txOffsets []*txindexInfo
   154  	var numItems uint64
   155  	var err error
   156  
   157  	if numItems, err = buf.DecodeVarint(); err != nil {
   158  		return nil, nil, errors.Wrap(err, "error decoding the length of block data")
   159  	}
   160  	for i := uint64(0); i < numItems; i++ {
   161  		var txEnvBytes []byte
   162  		var txid string
   163  		txOffset := buf.GetBytesConsumed()
   164  		if txEnvBytes, err = buf.DecodeRawBytes(false); err != nil {
   165  			return nil, nil, errors.Wrap(err, "error decoding the transaction enevelope")
   166  		}
   167  		if txid, err = protoutil.GetOrComputeTxIDFromEnvelope(txEnvBytes); err != nil {
   168  			logger.Warningf("error while extracting txid from tx envelope bytes during deserialization of block. Ignoring this error as this is caused by a malformed transaction. Error:%s",
   169  				err)
   170  
   171  		}
   172  		data.Data = append(data.Data, txEnvBytes)
   173  		idxInfo := &txindexInfo{txID: txid, loc: &locPointer{txOffset, buf.GetBytesConsumed() - txOffset}}
   174  		txOffsets = append(txOffsets, idxInfo)
   175  	}
   176  	return data, txOffsets, nil
   177  }
   178  
   179  func extractMetadata(buf *buffer) (*common.BlockMetadata, error) {
   180  	metadata := &common.BlockMetadata{}
   181  	var numItems uint64
   182  	var metadataEntry []byte
   183  	var err error
   184  	if numItems, err = buf.DecodeVarint(); err != nil {
   185  		return nil, errors.Wrap(err, "error decoding the length of block metadata")
   186  	}
   187  	for i := uint64(0); i < numItems; i++ {
   188  		if metadataEntry, err = buf.DecodeRawBytes(false); err != nil {
   189  			return nil, errors.Wrap(err, "error decoding the block metadata")
   190  		}
   191  		metadata.Metadata = append(metadata.Metadata, metadataEntry)
   192  	}
   193  	return metadata, nil
   194  }