github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/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  	if len(header.PreviousHash) == 0 {
   164  		header.PreviousHash = nil
   165  	}
   166  	return header, nil
   167  }
   168  
   169  func extractData(buf *ledgerutil.Buffer) (*common.BlockData, []*txindexInfo, error) {
   170  	data := &common.BlockData{}
   171  	var txOffsets []*txindexInfo
   172  	var numItems uint64
   173  	var err error
   174  
   175  	if numItems, err = buf.DecodeVarint(); err != nil {
   176  		return nil, nil, err
   177  	}
   178  	for i := uint64(0); i < numItems; i++ {
   179  		var txEnvBytes []byte
   180  		var txid string
   181  		txOffset := buf.GetBytesConsumed()
   182  		if txEnvBytes, err = buf.DecodeRawBytes(false); err != nil {
   183  			return nil, nil, err
   184  		}
   185  		if txid, err = extractTxID(txEnvBytes); err != nil {
   186  			return nil, nil, err
   187  		}
   188  		data.Data = append(data.Data, txEnvBytes)
   189  		idxInfo := &txindexInfo{txid, &locPointer{txOffset, buf.GetBytesConsumed() - txOffset}}
   190  		txOffsets = append(txOffsets, idxInfo)
   191  	}
   192  	return data, txOffsets, nil
   193  }
   194  
   195  func extractMetadata(buf *ledgerutil.Buffer) (*common.BlockMetadata, error) {
   196  	metadata := &common.BlockMetadata{}
   197  	var numItems uint64
   198  	var metadataEntry []byte
   199  	var err error
   200  	if numItems, err = buf.DecodeVarint(); err != nil {
   201  		return nil, err
   202  	}
   203  	for i := uint64(0); i < numItems; i++ {
   204  		if metadataEntry, err = buf.DecodeRawBytes(false); err != nil {
   205  			return nil, err
   206  		}
   207  		metadata.Metadata = append(metadata.Metadata, metadataEntry)
   208  	}
   209  	return metadata, nil
   210  }
   211  
   212  func extractTxID(txEnvelopBytes []byte) (string, error) {
   213  	txEnvelope, err := utils.GetEnvelopeFromBlock(txEnvelopBytes)
   214  	if err != nil {
   215  		return "", err
   216  	}
   217  	txPayload, err := utils.GetPayload(txEnvelope)
   218  	if err != nil {
   219  		return "", nil
   220  	}
   221  	chdr, err := utils.UnmarshalChannelHeader(txPayload.Header.ChannelHeader)
   222  	if err != nil {
   223  		return "", err
   224  	}
   225  	return chdr.TxId, nil
   226  }