github.com/inklabsfoundation/inkchain@v0.17.1-0.20181025012015-c3cef8062f19/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/inklabsfoundation/inkchain/common/ledger/util"
    22  	"github.com/inklabsfoundation/inkchain/protos/common"
    23  	"github.com/inklabsfoundation/inkchain/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.EncodeVarint(blockHeader.Version); err != nil {
    98  		return err
    99  	}
   100  	if err := buf.EncodeRawBytes(blockHeader.DataHash); err != nil {
   101  		return err
   102  	}
   103  	if err := buf.EncodeRawBytes(blockHeader.PreviousHash); err != nil {
   104  		return err
   105  	}
   106  	if err := buf.EncodeRawBytes(blockHeader.FeeAddress); err != nil {
   107  		return err
   108  	}
   109  	return nil
   110  }
   111  
   112  func addDataBytes(blockData *common.BlockData, buf *proto.Buffer) ([]*txindexInfo, error) {
   113  	var txOffsets []*txindexInfo
   114  
   115  	if err := buf.EncodeVarint(uint64(len(blockData.Data))); err != nil {
   116  		return nil, err
   117  	}
   118  	for _, txEnvelopeBytes := range blockData.Data {
   119  		offset := len(buf.Bytes())
   120  		txid, err := extractTxID(txEnvelopeBytes)
   121  		if err != nil {
   122  			return nil, err
   123  		}
   124  		if err := buf.EncodeRawBytes(txEnvelopeBytes); err != nil {
   125  			return nil, err
   126  		}
   127  		idxInfo := &txindexInfo{txid, &locPointer{offset, len(buf.Bytes()) - offset}}
   128  		txOffsets = append(txOffsets, idxInfo)
   129  	}
   130  	return txOffsets, nil
   131  }
   132  
   133  func addMetadataBytes(blockMetadata *common.BlockMetadata, buf *proto.Buffer) error {
   134  	numItems := uint64(0)
   135  	if blockMetadata != nil {
   136  		numItems = uint64(len(blockMetadata.Metadata))
   137  	}
   138  	if err := buf.EncodeVarint(numItems); err != nil {
   139  		return err
   140  	}
   141  	for _, b := range blockMetadata.Metadata {
   142  		if err := buf.EncodeRawBytes(b); err != nil {
   143  			return err
   144  		}
   145  	}
   146  	return nil
   147  }
   148  
   149  func extractHeader(buf *ledgerutil.Buffer) (*common.BlockHeader, error) {
   150  	header := &common.BlockHeader{}
   151  	var err error
   152  	if header.Number, err = buf.DecodeVarint(); err != nil {
   153  		return nil, err
   154  	}
   155  	if header.Version, err = buf.DecodeVarint(); err != nil {
   156  		return nil, err
   157  	}
   158  	if header.DataHash, err = buf.DecodeRawBytes(false); err != nil {
   159  		return nil, err
   160  	}
   161  	if header.PreviousHash, err = buf.DecodeRawBytes(false); err != nil {
   162  		return nil, err
   163  	}
   164  	if len(header.PreviousHash) == 0 {
   165  		header.PreviousHash = nil
   166  	}
   167  	if header.FeeAddress, err = buf.DecodeRawBytes(false); err != nil {
   168  		return nil, err
   169  	}
   170  	return header, nil
   171  }
   172  
   173  func extractData(buf *ledgerutil.Buffer) (*common.BlockData, []*txindexInfo, error) {
   174  	data := &common.BlockData{}
   175  	var txOffsets []*txindexInfo
   176  	var numItems uint64
   177  	var err error
   178  
   179  	if numItems, err = buf.DecodeVarint(); err != nil {
   180  		return nil, nil, err
   181  	}
   182  	for i := uint64(0); i < numItems; i++ {
   183  		var txEnvBytes []byte
   184  		var txid string
   185  		txOffset := buf.GetBytesConsumed()
   186  		if txEnvBytes, err = buf.DecodeRawBytes(false); err != nil {
   187  			return nil, nil, err
   188  		}
   189  		if txid, err = extractTxID(txEnvBytes); err != nil {
   190  			return nil, nil, err
   191  		}
   192  		data.Data = append(data.Data, txEnvBytes)
   193  		idxInfo := &txindexInfo{txid, &locPointer{txOffset, buf.GetBytesConsumed() - txOffset}}
   194  		txOffsets = append(txOffsets, idxInfo)
   195  	}
   196  	return data, txOffsets, nil
   197  }
   198  
   199  func extractMetadata(buf *ledgerutil.Buffer) (*common.BlockMetadata, error) {
   200  	metadata := &common.BlockMetadata{}
   201  	var numItems uint64
   202  	var metadataEntry []byte
   203  	var err error
   204  	if numItems, err = buf.DecodeVarint(); err != nil {
   205  		return nil, err
   206  	}
   207  	for i := uint64(0); i < numItems; i++ {
   208  		if metadataEntry, err = buf.DecodeRawBytes(false); err != nil {
   209  			return nil, err
   210  		}
   211  		metadata.Metadata = append(metadata.Metadata, metadataEntry)
   212  	}
   213  	return metadata, nil
   214  }
   215  
   216  func extractTxID(txEnvelopBytes []byte) (string, error) {
   217  	txEnvelope, err := utils.GetEnvelopeFromBlock(txEnvelopBytes)
   218  	if err != nil {
   219  		return "", err
   220  	}
   221  	txPayload, err := utils.GetPayload(txEnvelope)
   222  	if err != nil {
   223  		return "", nil
   224  	}
   225  	chdr, err := utils.UnmarshalChannelHeader(txPayload.Header.ChannelHeader)
   226  	if err != nil {
   227  		return "", err
   228  	}
   229  	return chdr.TxId, nil
   230  }