From 54805800cdb9622c718573a87f9861a745475e38 Mon Sep 17 00:00:00 2001 From: dhrubabasu <7675102+dhrubabasu@users.noreply.github.com> Date: Fri, 21 Jul 2023 17:22:01 -0700 Subject: [PATCH 1/3] support storing both `stateBlk`s and `Block`s in `blockDB` --- vms/platformvm/state/state.go | 41 ++++++++--- vms/platformvm/state/state_test.go | 106 +++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 11 deletions(-) diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index 7b36fc34ca4a..87faa505258e 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -1576,24 +1576,18 @@ func (s *state) GetStatelessBlock(blockID ids.ID) (blocks.Block, error) { return nil, err } - // Note: stored blocks are verified, so it's safe to unmarshal them with GenesisCodec - blkState := stateBlk{} - if _, err := blocks.GenesisCodec.Unmarshal(blkBytes, &blkState); err != nil { + blk, status, _, err := parseStoredBlock(blkBytes) + if err != nil { return nil, err } - if blkState.Status != choices.Accepted { + if status != choices.Accepted { s.blockCache.Put(blockID, nil) return nil, database.ErrNotFound } - blkState.Blk, err = blocks.Parse(blocks.GenesisCodec, blkState.Bytes) - if err != nil { - return nil, err - } - - s.blockCache.Put(blockID, blkState.Blk) - return blkState.Blk, nil + s.blockCache.Put(blockID, blk) + return blk, nil } func (s *state) writeCurrentStakers(updateValidators bool, height uint64) error { @@ -1994,3 +1988,28 @@ func (s *state) writeMetadata() error { } return nil } + +// Returns the block, status of the block, and whether it is a [stateBlk]. +// Invariant: blkBytes is safe to parse with blocks.GenesisCodec +// +// TODO: Remove after v1.11.x is activated +func parseStoredBlock(blkBytes []byte) (blocks.Block, choices.Status, bool, error) { + // Attempt to parse as blocks.Block directly. + blk, err := blocks.Parse(blocks.GenesisCodec, blkBytes) + if err == nil { + return blk, choices.Accepted, false, nil + } + + // Fallback to [stateBlk]. + blkState := stateBlk{} + if _, err := blocks.GenesisCodec.Unmarshal(blkBytes, &blkState); err != nil { + return nil, choices.Processing, false, err + } + + blkState.Blk, err = blocks.Parse(blocks.GenesisCodec, blkState.Bytes) + if err != nil { + return nil, choices.Processing, false, err + } + + return blkState.Blk, blkState.Status, true, nil +} diff --git a/vms/platformvm/state/state_test.go b/vms/platformvm/state/state_test.go index fecdecf9f5aa..36b43120148a 100644 --- a/vms/platformvm/state/state_test.go +++ b/vms/platformvm/state/state_test.go @@ -17,6 +17,7 @@ import ( "github.com/ava-labs/avalanchego/database/memdb" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow" + "github.com/ava-labs/avalanchego/snow/choices" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/constants" @@ -838,3 +839,108 @@ func TestStateAddRemoveValidator(t *testing.T) { require.Equal(diff.expectedPublicKeyDiff, gotPublicKeyDiffs) } } + +func TestParsedStateBlock(t *testing.T) { + require := require.New(t) + + var blks []blocks.Block + + { + blk, err := blocks.NewApricotAbortBlock(ids.GenerateTestID(), 1000) + require.NoError(err) + blks = append(blks, blk) + } + + { + blk, err := blocks.NewApricotAtomicBlock(ids.GenerateTestID(), 1000, &txs.Tx{ + Unsigned: &txs.AdvanceTimeTx{ + Time: 1000, + }, + }) + require.NoError(err) + blks = append(blks, blk) + } + + { + blk, err := blocks.NewApricotCommitBlock(ids.GenerateTestID(), 1000) + require.NoError(err) + blks = append(blks, blk) + } + + { + blk, err := blocks.NewApricotProposalBlock(ids.GenerateTestID(), 1000, &txs.Tx{ + Unsigned: &txs.RewardValidatorTx{ + TxID: ids.GenerateTestID(), + }, + }) + require.NoError(err) + blks = append(blks, blk) + } + + { + blk, err := blocks.NewApricotStandardBlock(ids.GenerateTestID(), 1000, []*txs.Tx{ + { + Unsigned: &txs.RewardValidatorTx{ + TxID: ids.GenerateTestID(), + }, + }, + }) + require.NoError(err) + blks = append(blks, blk) + } + + { + blk, err := blocks.NewBanffAbortBlock(time.Now(), ids.GenerateTestID(), 1000) + require.NoError(err) + blks = append(blks, blk) + } + + { + blk, err := blocks.NewBanffCommitBlock(time.Now(), ids.GenerateTestID(), 1000) + require.NoError(err) + blks = append(blks, blk) + } + + { + blk, err := blocks.NewBanffProposalBlock(time.Now(), ids.GenerateTestID(), 1000, &txs.Tx{ + Unsigned: &txs.RewardValidatorTx{ + TxID: ids.GenerateTestID(), + }, + }) + require.NoError(err) + blks = append(blks, blk) + } + + { + blk, err := blocks.NewBanffStandardBlock(time.Now(), ids.GenerateTestID(), 1000, []*txs.Tx{ + { + Unsigned: &txs.RewardValidatorTx{ + TxID: ids.GenerateTestID(), + }, + }, + }) + require.NoError(err) + blks = append(blks, blk) + } + + for _, blk := range blks { + stBlk := stateBlk{ + Blk: blk, + Bytes: blk.Bytes(), + Status: choices.Accepted, + } + + stBlkBytes, err := blocks.GenesisCodec.Marshal(blocks.Version, &stBlk) + require.NoError(err) + + gotBlk, _, isStateBlk, err := parseStoredBlock(stBlkBytes) + require.NoError(err) + require.True(isStateBlk) + require.Equal(blk.ID(), gotBlk.ID()) + + gotBlk, _, isStateBlk, err = parseStoredBlock(blk.Bytes()) + require.NoError(err) + require.False(isStateBlk) + require.Equal(blk.ID(), gotBlk.ID()) + } +} From 927e01675b5b68bc355d4601f38a75cdd72fa830 Mon Sep 17 00:00:00 2001 From: dhrubabasu <7675102+dhrubabasu@users.noreply.github.com> Date: Fri, 21 Jul 2023 17:23:57 -0700 Subject: [PATCH 2/3] nit --- vms/platformvm/state/state.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index 87faa505258e..5d75147b2bc1 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -1994,13 +1994,13 @@ func (s *state) writeMetadata() error { // // TODO: Remove after v1.11.x is activated func parseStoredBlock(blkBytes []byte) (blocks.Block, choices.Status, bool, error) { - // Attempt to parse as blocks.Block directly. + // Attempt to parse as blocks.Block blk, err := blocks.Parse(blocks.GenesisCodec, blkBytes) if err == nil { return blk, choices.Accepted, false, nil } - // Fallback to [stateBlk]. + // Fallback to [stateBlk] blkState := stateBlk{} if _, err := blocks.GenesisCodec.Unmarshal(blkBytes, &blkState); err != nil { return nil, choices.Processing, false, err From 55d45c0ec64af6046dcce0d03f860ff961063e85 Mon Sep 17 00:00:00 2001 From: dhrubabasu <7675102+dhrubabasu@users.noreply.github.com> Date: Fri, 21 Jul 2023 17:24:12 -0700 Subject: [PATCH 3/3] nit --- vms/platformvm/state/state.go | 1 + 1 file changed, 1 insertion(+) diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index 5d75147b2bc1..508c030d82ee 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -156,6 +156,7 @@ type State interface { Close() error } +// TODO: Remove after v1.11.x is activated type stateBlk struct { Blk blocks.Block Bytes []byte `serialize:"true"`