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