Skip to content

Commit

Permalink
[block] add block deserializer (#3186)
Browse files Browse the repository at this point in the history
  • Loading branch information
dustinxie authored Mar 14, 2022
1 parent 90b4836 commit 8209ad3
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 29 deletions.
67 changes: 67 additions & 0 deletions blockchain/block/block_deserializer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) 2022 IoTeX Foundation
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
// License 2.0 that can be found in the LICENSE file.

package block

import (
"github.com/iotexproject/iotex-proto/golang/iotextypes"
"github.com/pkg/errors"
"google.golang.org/protobuf/proto"
)

// Deserializer de-serializes a block
type Deserializer struct {
}

// FromBlockProto converts protobuf to block
func (bd *Deserializer) FromBlockProto(pbBlock *iotextypes.Block) (*Block, error) {
b := Block{}
if err := b.Header.LoadFromBlockHeaderProto(pbBlock.GetHeader()); err != nil {
return nil, errors.Wrap(err, "failed to deserialize block header")
}
if err := b.Body.LoadProto(pbBlock.GetBody()); err != nil {
return nil, errors.Wrap(err, "failed to deserialize block body")
}
if err := b.ConvertFromBlockFooterPb(pbBlock.GetFooter()); err != nil {
return nil, errors.Wrap(err, "failed to deserialize block footer")
}
return &b, nil
}

// DeserializeBlock de-serializes a block
func (bd *Deserializer) DeserializeBlock(buf []byte) (*Block, error) {
pbBlock := iotextypes.Block{}
if err := proto.Unmarshal(buf, &pbBlock); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal block")
}
b, err := bd.FromBlockProto(&pbBlock)
if err != nil {
return nil, err
}
b.Receipts = nil
if err = b.VerifyTxRoot(); err != nil {
return nil, err
}
return b, nil
}

// FromBodyProto converts protobuf to body
func (bd *Deserializer) FromBodyProto(pbBody *iotextypes.BlockBody) (*Body, error) {
b := Body{}
if err := b.LoadProto(pbBody); err != nil {
return nil, errors.Wrap(err, "failed to deserialize block body")
}
return &b, nil
}

// DeserializeBody de-serializes a block body
func (bd *Deserializer) DeserializeBody(buf []byte) (*Body, error) {
pb := iotextypes.BlockBody{}
if err := proto.Unmarshal(buf, &pb); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal block body")
}
return bd.FromBodyProto(&pb)
}
37 changes: 37 additions & 0 deletions blockchain/block/block_deserializer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) 2022 IoTeX Foundation
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
// License 2.0 that can be found in the LICENSE file.

package block

import (
"testing"

"github.com/golang/protobuf/proto"
"github.com/iotexproject/go-pkgs/hash"
"github.com/stretchr/testify/require"
)

func TestBlockDeserializer(t *testing.T) {
r := require.New(t)
bd := Deserializer{}
blk, err := bd.FromBlockProto(&pbBlock)
r.NoError(err)
body, err := bd.FromBodyProto(pbBlock.Body)
r.NoError(err)
r.Equal(body, &blk.Body)

txHash, err := blk.CalculateTxRoot()
r.NoError(err)
blk.Header.txRoot = txHash
blk.Header.receiptRoot = hash.Hash256b(([]byte)("test"))
pb := blk.ConvertToBlockPb()
raw, err := proto.Marshal(pb)
r.NoError(err)

newblk, err := (&Deserializer{}).DeserializeBlock(raw)
r.NoError(err)
r.Equal(blk, newblk)
}
35 changes: 24 additions & 11 deletions blockchain/block/block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,45 +76,58 @@ func TestMerkle(t *testing.T) {
t.Log("Merkle root match pass\n")
}

func TestConvertFromBlockPb(t *testing.T) {
blk := Block{}
senderPubKey := identityset.PrivateKey(27).PublicKey()
require.NoError(t, blk.ConvertFromBlockPb(&iotextypes.Block{
var (
pkBytes = identityset.PrivateKey(27).PublicKey().Bytes()
pbBlock = iotextypes.Block{
Header: &iotextypes.BlockHeader{
Core: &iotextypes.BlockHeaderCore{
Version: version.ProtocolVersion,
Height: 123456789,
Timestamp: ptypes.TimestampNow(),
},
ProducerPubkey: senderPubKey.Bytes(),
ProducerPubkey: pkBytes,
},
Body: &iotextypes.BlockBody{
Actions: []*iotextypes.Action{
{
Core: &iotextypes.ActionCore{
Action: &iotextypes.ActionCore_Transfer{
Transfer: &iotextypes.Transfer{},
Transfer: &iotextypes.Transfer{
Amount: "100000000000000000",
Recipient: "alice",
},
},
Version: version.ProtocolVersion,
Nonce: 101,
ChainID: 1,
},
SenderPubKey: senderPubKey.Bytes(),
SenderPubKey: pkBytes,
Signature: action.ValidSig,
},
{
Core: &iotextypes.ActionCore{
Action: &iotextypes.ActionCore_Transfer{
Transfer: &iotextypes.Transfer{},
Action: &iotextypes.ActionCore_Execution{
Execution: &iotextypes.Execution{
Contract: "bob",
Amount: "200000000000000000",
Data: []byte{1, 2, 3, 4},
},
},
Version: version.ProtocolVersion,
Nonce: 102,
ChainID: 2,
},
SenderPubKey: senderPubKey.Bytes(),
SenderPubKey: pkBytes,
Signature: action.ValidSig,
},
},
},
}))
}
)

func TestConvertFromBlockPb(t *testing.T) {
blk := Block{}
require.NoError(t, blk.ConvertFromBlockPb(&pbBlock))

txHash, err := blk.CalculateTxRoot()
require.NoError(t, err)
Expand Down
7 changes: 4 additions & 3 deletions blockchain/block/blockstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,16 @@ func (in *Store) ToProto() *iotextypes.BlockStore {

// FromProto converts from proto message
func (in *Store) FromProto(pb *iotextypes.BlockStore) error {
in.Block = &Block{}
if err := in.Block.ConvertFromBlockPb(pb.Block); err != nil {
blk, err := (&Deserializer{}).FromBlockProto(pb.Block)
if err != nil {
return err
}
// verify merkle root can match after deserialize
if err := in.Block.VerifyTxRoot(); err != nil {
if err := blk.VerifyTxRoot(); err != nil {
return err
}

in.Block = blk
in.Receipts = []*action.Receipt{}
for _, receiptPb := range pb.Receipts {
receipt := &action.Receipt{}
Expand Down
8 changes: 2 additions & 6 deletions blockchain/filedao/filedao_legacy.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,15 +258,11 @@ func (fd *fileDAOLegacy) body(h hash.Hash256) (*block.Body, error) {
}
}

body := &block.Body{}
if len(value) == 0 {
// block body could be empty
return body, nil
return &block.Body{}, nil
}
if err := body.Deserialize(value); err != nil {
return nil, errors.Wrapf(err, "failed to deserialize block body %x", h)
}
return body, nil
return (&block.Deserializer{}).DeserializeBody(value)
}

func (fd *fileDAOLegacy) footer(h hash.Hash256) (*block.Footer, error) {
Expand Down
6 changes: 3 additions & 3 deletions chainservice/chainservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -519,11 +519,11 @@ func (cs *ChainService) HandleAction(ctx context.Context, actPb *iotextypes.Acti

// HandleBlock handles incoming block request.
func (cs *ChainService) HandleBlock(ctx context.Context, peer string, pbBlock *iotextypes.Block) error {
blk := &block.Block{}
if err := blk.ConvertFromBlockPb(pbBlock); err != nil {
blk, err := (&block.Deserializer{}).FromBlockProto(pbBlock)
if err != nil {
return err
}
ctx, err := cs.chain.Context(ctx)
ctx, err = cs.chain.Context(ctx)
if err != nil {
return err
}
Expand Down
5 changes: 3 additions & 2 deletions consensus/scheme/rolldpos/blockproposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,11 @@ func (bp *blockProposal) ProposerAddress() string {
}

func (bp *blockProposal) LoadProto(msg *iotextypes.BlockProposal) error {
bp.block = &block.Block{}
if err := bp.block.ConvertFromBlockPb(msg.Block); err != nil {
blk, err := (&block.Deserializer{}).FromBlockProto(msg.Block)
if err != nil {
return err
}
bp.block = blk
bp.proofOfLock = []*endorsement.Endorsement{}
for _, ePb := range msg.Endorsements {
en := &endorsement.Endorsement{}
Expand Down
8 changes: 4 additions & 4 deletions consensus/scheme/rolldpos/endorsementmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ func (bc *blockEndorsementCollection) fromProto(blockPro *endorsementpb.BlockEnd
if blockPro.Blk == nil {
bc.blk = nil
} else {
blk := &block.Block{}
if err := blk.ConvertFromBlockPb(blockPro.Blk); err != nil {
blk, err := (&block.Deserializer{}).FromBlockProto(blockPro.Blk)
if err != nil {
return err
}
bc.blk = blk
Expand Down Expand Up @@ -289,8 +289,8 @@ func (m *endorsementManager) fromProto(managerPro *endorsementpb.EndorsementMana
m.collections[managerPro.BlkHash[i]] = bc
}
if managerPro.CachedMintedBlk != nil {
blk := &block.Block{}
if err := blk.ConvertFromBlockPb(managerPro.CachedMintedBlk); err != nil {
blk, err := (&block.Deserializer{}).FromBlockProto(managerPro.CachedMintedBlk)
if err != nil {
return err
}
m.cachedMintedBlk = blk
Expand Down

0 comments on commit 8209ad3

Please sign in to comment.