github.com/iotexproject/iotex-core@v1.14.1-rc1/blockchain/block/block_deserializer.go (about)

     1  // Copyright (c) 2022 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package block
     7  
     8  import (
     9  	"github.com/iotexproject/iotex-proto/golang/iotextypes"
    10  	"github.com/pkg/errors"
    11  	"google.golang.org/protobuf/proto"
    12  
    13  	"github.com/iotexproject/iotex-core/action"
    14  )
    15  
    16  // Deserializer de-serializes a block
    17  //
    18  // It's a wrapper to set certain parameters in order to correctly de-serialize a block
    19  // Currently the parameter is EVM network ID for tx in web3 format, it is called like
    20  //
    21  // blk, err := (&Deserializer{}).SetEvmNetworkID(id).FromBlockProto(pbBlock)
    22  // blk, err := (&Deserializer{}).SetEvmNetworkID(id).DeserializeBlock(buf)
    23  type Deserializer struct {
    24  	evmNetworkID uint32
    25  }
    26  
    27  // NewDeserializer creates a new deserializer
    28  func NewDeserializer(evmNetworkID uint32) *Deserializer {
    29  	return &Deserializer{
    30  		evmNetworkID: evmNetworkID,
    31  	}
    32  }
    33  
    34  // EvmNetworkID get evm network ID
    35  func (bd *Deserializer) EvmNetworkID() uint32 { return bd.evmNetworkID }
    36  
    37  // SetEvmNetworkID sets the evm network ID for web3 actions
    38  func (bd *Deserializer) SetEvmNetworkID(id uint32) *Deserializer {
    39  	bd.evmNetworkID = id
    40  	return bd
    41  }
    42  
    43  // FromBlockProto converts protobuf to block
    44  func (bd *Deserializer) FromBlockProto(pbBlock *iotextypes.Block) (*Block, error) {
    45  	var (
    46  		b   = Block{}
    47  		err error
    48  	)
    49  	if err = b.Header.LoadFromBlockHeaderProto(pbBlock.GetHeader()); err != nil {
    50  		return nil, errors.Wrap(err, "failed to deserialize block header")
    51  	}
    52  	if b.Body, err = bd.fromBodyProto(pbBlock.GetBody()); err != nil {
    53  		return nil, errors.Wrap(err, "failed to deserialize block body")
    54  	}
    55  	if err = b.ConvertFromBlockFooterPb(pbBlock.GetFooter()); err != nil {
    56  		return nil, errors.Wrap(err, "failed to deserialize block footer")
    57  	}
    58  	return &b, nil
    59  }
    60  
    61  // DeserializeBlock de-serializes a block
    62  func (bd *Deserializer) DeserializeBlock(buf []byte) (*Block, error) {
    63  	pbBlock := iotextypes.Block{}
    64  	if err := proto.Unmarshal(buf, &pbBlock); err != nil {
    65  		return nil, errors.Wrap(err, "failed to unmarshal block")
    66  	}
    67  	b, err := bd.FromBlockProto(&pbBlock)
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  	b.Receipts = nil
    72  	if err = b.VerifyTxRoot(); err != nil {
    73  		return nil, err
    74  	}
    75  	return b, nil
    76  }
    77  
    78  // fromBodyProto converts protobuf to body
    79  func (bd *Deserializer) fromBodyProto(pbBody *iotextypes.BlockBody) (Body, error) {
    80  	b := Body{}
    81  	for _, actPb := range pbBody.Actions {
    82  		act, err := (&action.Deserializer{}).SetEvmNetworkID(bd.evmNetworkID).ActionToSealedEnvelope(actPb)
    83  		if err != nil {
    84  			return b, errors.Wrap(err, "failed to deserialize block body")
    85  		}
    86  		b.Actions = append(b.Actions, act)
    87  	}
    88  	return b, nil
    89  }
    90  
    91  // DeserializeBody de-serializes a block body
    92  func (bd *Deserializer) DeserializeBody(buf []byte) (*Body, error) {
    93  	pb := iotextypes.BlockBody{}
    94  	if err := proto.Unmarshal(buf, &pb); err != nil {
    95  		return nil, errors.Wrap(err, "failed to unmarshal block body")
    96  	}
    97  	b, err := bd.fromBodyProto(&pb)
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  	return &b, nil
   102  }
   103  
   104  func (bd *Deserializer) BlockFromBlockStoreProto(pb *iotextypes.BlockStore) (*Block, error) {
   105  	return bd.blockFromBlockStoreProto(pb)
   106  }
   107  
   108  func (bd *Deserializer) blockFromBlockStoreProto(pb *iotextypes.BlockStore) (*Block, error) {
   109  	blk, err := bd.FromBlockProto(pb.Block)
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  	// TODO: Reenable this if necessary
   114  	// // verify merkle root can match after deserialize
   115  	// if err := blk.VerifyTxRoot(); err != nil {
   116  	// 	return nil, err
   117  	// }
   118  	return blk, nil
   119  }
   120  
   121  func (bd *Deserializer) ReceiptsFromBlockStoreProto(pb *iotextypes.BlockStore) ([]*action.Receipt, error) {
   122  	return bd.receiptsFromBlockStoreProto(pb)
   123  }
   124  
   125  func (bd *Deserializer) receiptsFromBlockStoreProto(pb *iotextypes.BlockStore) ([]*action.Receipt, error) {
   126  	receipts := make([]*action.Receipt, 0)
   127  	for _, receiptPb := range pb.Receipts {
   128  		receipt := &action.Receipt{}
   129  		receipt.ConvertFromReceiptPb(receiptPb)
   130  		receipts = append(receipts, receipt)
   131  	}
   132  
   133  	return receipts, nil
   134  }
   135  
   136  // DeserializeBlockStore de-serializes a block store
   137  func (bd *Deserializer) DeserializeBlockStore(buf []byte) (*Store, error) {
   138  	pb := iotextypes.BlockStore{}
   139  	if err := proto.Unmarshal(buf, &pb); err != nil {
   140  		return nil, errors.Wrap(err, "failed to unmarshal block store")
   141  	}
   142  	blk, err := bd.blockFromBlockStoreProto(&pb)
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  	receipts, err := bd.receiptsFromBlockStoreProto(&pb)
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  	return &Store{
   151  		Block:    blk,
   152  		Receipts: receipts,
   153  	}, nil
   154  }