github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/common/ledger/blkstorage/fsblkstorage/block_serialization.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package fsblkstorage
    18  
    19  import (
    20  	"github.com/golang/protobuf/proto"
    21  	ledgerutil "github.com/hyperledger/fabric/common/ledger/util"
    22  	"github.com/hyperledger/fabric/protos/common"
    23  	"github.com/hyperledger/fabric/protos/utils"
    24  )
    25  
    26  type serializedBlockInfo struct {
    27  	blockHeader *common.BlockHeader
    28  	txOffsets   []*txindexInfo
    29  	metadata    *common.BlockMetadata
    30  }
    31  
    32  //The order of the transactions must be maintained for history
    33  type txindexInfo struct {
    34  	txID string
    35  	loc  *locPointer
    36  }
    37  
    38  func serializeBlock(block *common.Block) ([]byte, *serializedBlockInfo, error) {
    39  	buf := proto.NewBuffer(nil)
    40  	var err error
    41  	info := &serializedBlockInfo{}
    42  	info.blockHeader = block.Header
    43  	info.metadata = block.Metadata
    44  	if err = addHeaderBytes(block.Header, buf); err != nil {
    45  		return nil, nil, err
    46  	}
    47  	if info.txOffsets, err = addDataBytes(block.Data, buf); err != nil {
    48  		return nil, nil, err
    49  	}
    50  	if err = addMetadataBytes(block.Metadata, buf); err != nil {
    51  		return nil, nil, err
    52  	}
    53  	return buf.Bytes(), info, nil
    54  }
    55  
    56  func deserializeBlock(serializedBlockBytes []byte) (*common.Block, error) {
    57  	block := &common.Block{}
    58  	var err error
    59  	b := ledgerutil.NewBuffer(serializedBlockBytes)
    60  	if block.Header, err = extractHeader(b); err != nil {
    61  		return nil, err
    62  	}
    63  	if block.Data, _, err = extractData(b); err != nil {
    64  		return nil, err
    65  	}
    66  	if block.Metadata, err = extractMetadata(b); err != nil {
    67  		return nil, err
    68  	}
    69  	return block, nil
    70  }
    71  
    72  func extractSerializedBlockInfo(serializedBlockBytes []byte) (*serializedBlockInfo, error) {
    73  	info := &serializedBlockInfo{}
    74  	var err error
    75  	b := ledgerutil.NewBuffer(serializedBlockBytes)
    76  	info.blockHeader, err = extractHeader(b)
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  	_, info.txOffsets, err = extractData(b)
    81  	if err != nil {
    82  		return nil, err
    83  	}
    84  
    85  	info.metadata, err = extractMetadata(b)
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  
    90  	return info, nil
    91  }
    92  
    93  func addHeaderBytes(blockHeader *common.BlockHeader, buf *proto.Buffer) error {
    94  	if err := buf.EncodeVarint(blockHeader.Number); err != nil {
    95  		return err
    96  	}
    97  	if err := buf.EncodeRawBytes(blockHeader.DataHash); err != nil {
    98  		return err
    99  	}
   100  	if err := buf.EncodeRawBytes(blockHeader.PreviousHash); err != nil {
   101  		return err
   102  	}
   103  	return nil
   104  }
   105  
   106  func addDataBytes(blockData *common.BlockData, buf *proto.Buffer) ([]*txindexInfo, error) {
   107  	var txOffsets []*txindexInfo
   108  
   109  	if err := buf.EncodeVarint(uint64(len(blockData.Data))); err != nil {
   110  		return nil, err
   111  	}
   112  	for _, txEnvelopeBytes := range blockData.Data {
   113  		offset := len(buf.Bytes())
   114  		txid, err := extractTxID(txEnvelopeBytes)
   115  		if err != nil {
   116  			return nil, err
   117  		}
   118  		if err := buf.EncodeRawBytes(txEnvelopeBytes); err != nil {
   119  			return nil, err
   120  		}
   121  		idxInfo := &txindexInfo{txid, &locPointer{offset, len(buf.Bytes()) - offset}}
   122  		txOffsets = append(txOffsets, idxInfo)
   123  	}
   124  	return txOffsets, nil
   125  }
   126  
   127  func addMetadataBytes(blockMetadata *common.BlockMetadata, buf *proto.Buffer) error {
   128  	numItems := uint64(0)
   129  	if blockMetadata != nil {
   130  		numItems = uint64(len(blockMetadata.Metadata))
   131  	}
   132  	if err := buf.EncodeVarint(numItems); err != nil {
   133  		return err
   134  	}
   135  	for _, b := range blockMetadata.Metadata {
   136  		if err := buf.EncodeRawBytes(b); err != nil {
   137  			return err
   138  		}
   139  	}
   140  	return nil
   141  }
   142  
   143  func extractHeader(buf *ledgerutil.Buffer) (*common.BlockHeader, error) {
   144  	header := &common.BlockHeader{}
   145  	var err error
   146  	if header.Number, err = buf.DecodeVarint(); err != nil {
   147  		return nil, err
   148  	}
   149  	if header.DataHash, err = buf.DecodeRawBytes(false); err != nil {
   150  		return nil, err
   151  	}
   152  	if header.PreviousHash, err = buf.DecodeRawBytes(false); err != nil {
   153  		return nil, err
   154  	}
   155  	if len(header.PreviousHash) == 0 {
   156  		header.PreviousHash = nil
   157  	}
   158  	return header, nil
   159  }
   160  
   161  func extractData(buf *ledgerutil.Buffer) (*common.BlockData, []*txindexInfo, error) {
   162  	data := &common.BlockData{}
   163  	var txOffsets []*txindexInfo
   164  	var numItems uint64
   165  	var err error
   166  
   167  	if numItems, err = buf.DecodeVarint(); err != nil {
   168  		return nil, nil, err
   169  	}
   170  	for i := uint64(0); i < numItems; i++ {
   171  		var txEnvBytes []byte
   172  		var txid string
   173  		txOffset := buf.GetBytesConsumed()
   174  		if txEnvBytes, err = buf.DecodeRawBytes(false); err != nil {
   175  			return nil, nil, err
   176  		}
   177  		if txid, err = extractTxID(txEnvBytes); err != nil {
   178  			return nil, nil, err
   179  		}
   180  		data.Data = append(data.Data, txEnvBytes)
   181  		idxInfo := &txindexInfo{txid, &locPointer{txOffset, buf.GetBytesConsumed() - txOffset}}
   182  		txOffsets = append(txOffsets, idxInfo)
   183  	}
   184  	return data, txOffsets, nil
   185  }
   186  
   187  func extractMetadata(buf *ledgerutil.Buffer) (*common.BlockMetadata, error) {
   188  	metadata := &common.BlockMetadata{}
   189  	var numItems uint64
   190  	var metadataEntry []byte
   191  	var err error
   192  	if numItems, err = buf.DecodeVarint(); err != nil {
   193  		return nil, err
   194  	}
   195  	for i := uint64(0); i < numItems; i++ {
   196  		if metadataEntry, err = buf.DecodeRawBytes(false); err != nil {
   197  			return nil, err
   198  		}
   199  		metadata.Metadata = append(metadata.Metadata, metadataEntry)
   200  	}
   201  	return metadata, nil
   202  }
   203  
   204  func extractTxID(txEnvelopBytes []byte) (string, error) {
   205  	txEnvelope, err := utils.GetEnvelopeFromBlock(txEnvelopBytes)
   206  	if err != nil {
   207  		return "", err
   208  	}
   209  	txPayload, err := utils.GetPayload(txEnvelope)
   210  	if err != nil {
   211  		return "", nil
   212  	}
   213  	chdr, err := utils.UnmarshalChannelHeader(txPayload.Header.ChannelHeader)
   214  	if err != nil {
   215  		return "", err
   216  	}
   217  	return chdr.TxId, nil
   218  }