github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/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  	"fmt"
    21  
    22  	"github.com/golang/protobuf/proto"
    23  	ledgerutil "github.com/hyperledger/fabric/common/ledger/util"
    24  	"github.com/hyperledger/fabric/protos/common"
    25  	"github.com/hyperledger/fabric/protos/utils"
    26  )
    27  
    28  type serializedBlockInfo struct {
    29  	blockHeader *common.BlockHeader
    30  	txOffsets   []*txindexInfo
    31  	metadata    *common.BlockMetadata
    32  }
    33  
    34  //The order of the transactions must be maintained for history
    35  type txindexInfo struct {
    36  	txID string
    37  	loc  *locPointer
    38  }
    39  
    40  func serializeBlock(block *common.Block) ([]byte, *serializedBlockInfo, error) {
    41  	buf := proto.NewBuffer(nil)
    42  	var err error
    43  	info := &serializedBlockInfo{}
    44  	info.blockHeader = block.Header
    45  	info.metadata = block.Metadata
    46  	if err = addHeaderBytes(block.Header, buf); err != nil {
    47  		return nil, nil, err
    48  	}
    49  	if info.txOffsets, err = addDataBytes(block.Data, buf); err != nil {
    50  		return nil, nil, err
    51  	}
    52  	if err = addMetadataBytes(block.Metadata, buf); err != nil {
    53  		return nil, nil, err
    54  	}
    55  	return buf.Bytes(), info, nil
    56  }
    57  
    58  func deserializeBlock(serializedBlockBytes []byte) (*common.Block, error) {
    59  	block := &common.Block{}
    60  	var err error
    61  	b := ledgerutil.NewBuffer(serializedBlockBytes)
    62  	if block.Header, err = extractHeader(b); err != nil {
    63  		fmt.Printf("h:%s\n", err)
    64  		return nil, err
    65  	}
    66  	if block.Data, _, err = extractData(b); err != nil {
    67  		fmt.Printf("d:%s\n", err)
    68  		return nil, err
    69  	}
    70  	if block.Metadata, err = extractMetadata(b); err != nil {
    71  		fmt.Printf("m:%s\n", err)
    72  		return nil, err
    73  	}
    74  	return block, nil
    75  }
    76  
    77  func extractSerializedBlockInfo(serializedBlockBytes []byte) (*serializedBlockInfo, error) {
    78  	info := &serializedBlockInfo{}
    79  	var err error
    80  	b := ledgerutil.NewBuffer(serializedBlockBytes)
    81  	info.blockHeader, err = extractHeader(b)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  	_, info.txOffsets, err = extractData(b)
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  
    90  	info.metadata, err = extractMetadata(b)
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  
    95  	return info, nil
    96  }
    97  
    98  func addHeaderBytes(blockHeader *common.BlockHeader, buf *proto.Buffer) error {
    99  	if err := buf.EncodeVarint(blockHeader.Number); err != nil {
   100  		return err
   101  	}
   102  	if err := buf.EncodeRawBytes(blockHeader.DataHash); err != nil {
   103  		return err
   104  	}
   105  	if err := buf.EncodeRawBytes(blockHeader.PreviousHash); err != nil {
   106  		return err
   107  	}
   108  	return nil
   109  }
   110  
   111  func addDataBytes(blockData *common.BlockData, buf *proto.Buffer) ([]*txindexInfo, error) {
   112  	var txOffsets []*txindexInfo
   113  
   114  	if err := buf.EncodeVarint(uint64(len(blockData.Data))); err != nil {
   115  		return nil, err
   116  	}
   117  	for _, txEnvelopeBytes := range blockData.Data {
   118  		offset := len(buf.Bytes())
   119  		txid, err := extractTxID(txEnvelopeBytes)
   120  		if err != nil {
   121  			return nil, err
   122  		}
   123  		if err := buf.EncodeRawBytes(txEnvelopeBytes); err != nil {
   124  			return nil, err
   125  		}
   126  		idxInfo := &txindexInfo{txid, &locPointer{offset, len(buf.Bytes()) - offset}}
   127  		txOffsets = append(txOffsets, idxInfo)
   128  	}
   129  	return txOffsets, nil
   130  }
   131  
   132  func addMetadataBytes(blockMetadata *common.BlockMetadata, buf *proto.Buffer) error {
   133  	numItems := uint64(0)
   134  	if blockMetadata != nil {
   135  		numItems = uint64(len(blockMetadata.Metadata))
   136  	}
   137  	if err := buf.EncodeVarint(numItems); err != nil {
   138  		return err
   139  	}
   140  	if numItems == 0 {
   141  		return nil
   142  	}
   143  	for _, b := range blockMetadata.Metadata {
   144  		if err := buf.EncodeRawBytes(b); err != nil {
   145  			return err
   146  		}
   147  	}
   148  	return nil
   149  }
   150  
   151  func extractHeader(buf *ledgerutil.Buffer) (*common.BlockHeader, error) {
   152  	header := &common.BlockHeader{}
   153  	var err error
   154  	if header.Number, err = buf.DecodeVarint(); err != nil {
   155  		return nil, err
   156  	}
   157  	if header.DataHash, err = buf.DecodeRawBytes(false); err != nil {
   158  		return nil, err
   159  	}
   160  	if header.PreviousHash, err = buf.DecodeRawBytes(false); err != nil {
   161  		return nil, err
   162  	}
   163  	return header, nil
   164  }
   165  
   166  func extractData(buf *ledgerutil.Buffer) (*common.BlockData, []*txindexInfo, error) {
   167  	data := &common.BlockData{}
   168  	var txOffsets []*txindexInfo
   169  	var numItems uint64
   170  	var err error
   171  
   172  	if numItems, err = buf.DecodeVarint(); err != nil {
   173  		return nil, nil, err
   174  	}
   175  	for i := uint64(0); i < numItems; i++ {
   176  		var txEnvBytes []byte
   177  		var txid string
   178  		txOffset := buf.GetBytesConsumed()
   179  		if txEnvBytes, err = buf.DecodeRawBytes(false); err != nil {
   180  			return nil, nil, err
   181  		}
   182  		if txid, err = extractTxID(txEnvBytes); err != nil {
   183  			return nil, nil, err
   184  		}
   185  		data.Data = append(data.Data, txEnvBytes)
   186  		idxInfo := &txindexInfo{txid, &locPointer{txOffset, buf.GetBytesConsumed() - txOffset}}
   187  		txOffsets = append(txOffsets, idxInfo)
   188  	}
   189  	return data, txOffsets, nil
   190  }
   191  
   192  func extractMetadata(buf *ledgerutil.Buffer) (*common.BlockMetadata, error) {
   193  	metadata := &common.BlockMetadata{}
   194  	var numItems uint64
   195  	var metadataEntry []byte
   196  	var err error
   197  	if numItems, err = buf.DecodeVarint(); err != nil {
   198  		return nil, err
   199  	}
   200  	for i := uint64(0); i < numItems; i++ {
   201  		if metadataEntry, err = buf.DecodeRawBytes(false); err != nil {
   202  			return nil, err
   203  		}
   204  		metadata.Metadata = append(metadata.Metadata, metadataEntry)
   205  	}
   206  	return metadata, nil
   207  }
   208  
   209  func extractTxID(txEnvelopBytes []byte) (string, error) {
   210  	txEnvelope, err := utils.GetEnvelopeFromBlock(txEnvelopBytes)
   211  	if err != nil {
   212  		return "", err
   213  	}
   214  	txPayload, err := utils.GetPayload(txEnvelope)
   215  	if err != nil {
   216  		return "", nil
   217  	}
   218  	chdr, err := utils.UnmarshalChannelHeader(txPayload.Header.ChannelHeader)
   219  	if err != nil {
   220  		return "", err
   221  	}
   222  	return chdr.TxId, nil
   223  }