Skip to content

Commit

Permalink
nit
Browse files Browse the repository at this point in the history
abi87 committed Nov 2, 2023
1 parent 6ded29a commit 2550a87
Showing 1 changed file with 158 additions and 21 deletions.
179 changes: 158 additions & 21 deletions vms/proposervm/state_sync_block_backfilling_test.go
Original file line number Diff line number Diff line change
@@ -106,7 +106,7 @@ func TestBlockBackfillEnabled(t *testing.T) {
require.ErrorIs(err, block.ErrBlockBackfillingNotEnabled)
}

func TestBlockBackfill(t *testing.T) {
func TestBlockBackfillSuccess(t *testing.T) {
// setup VM with backfill enabled
require := require.New(t)
toEngineCh := make(chan common.Message)
@@ -116,9 +116,11 @@ func TestBlockBackfill(t *testing.T) {
}()

var (
forkHeight = uint64(100)
blkCount = 10
startBlkHeight = uint64(1492)
forkHeight = uint64(100)
blkCount = 10
startBlkHeight = uint64(1492)

// create a list of consecutive blocks and build state summary of top of them
proBlks, innerBlks = createTestBlocks(t, vm, blkCount, startBlkHeight)

innerTopBlk = innerBlks[len(innerBlks)-1]
@@ -173,30 +175,20 @@ func TestBlockBackfill(t *testing.T) {

// Backfill some blocks
innerVM.ParseBlockF = func(_ context.Context, b []byte) (snowman.Block, error) {
idx := -1
for i, blk := range innerBlks {
for _, blk := range innerBlks {
if bytes.Equal(b, blk.Bytes()) {
idx = i
break
return blk, nil
}
}
if idx == -1 {
return nil, database.ErrNotFound
}
return innerBlks[idx], nil
return nil, database.ErrNotFound
}
innerVM.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) {
idx := -1
for i, blk := range innerBlks {
for _, blk := range innerBlks {
if blkID == blk.ID() {
idx = i
break
return blk, nil
}
}
if idx == -1 {
return nil, database.ErrNotFound
}
return innerBlks[idx], nil
return nil, database.ErrNotFound
}
innerVM.BackfillBlocksF = func(_ context.Context, b [][]byte) (ids.ID, uint64, error) {
lowestblk := innerBlks[0]
@@ -216,6 +208,144 @@ func TestBlockBackfill(t *testing.T) {
require.NoError(err)
require.Equal(proBlks[0].Parent(), nextBlkID)
require.Equal(proBlks[0].Height()-1, nextBlkHeight)

// check proBlocks have been indexed
for _, blk := range proBlks {
blkID, err := vm.GetBlockIDAtHeight(ctx, blk.Height())
require.NoError(err)
require.Equal(blk.ID(), blkID)

_, err = vm.GetBlock(ctx, blkID)
require.NoError(err)
}
}

func TestBlockBackfillPartialSuccess(t *testing.T) {
// setup VM with backfill enabled
require := require.New(t)
toEngineCh := make(chan common.Message)
innerVM, vm, fromInnerVMCh := setupBlockBackfillingVM(t, toEngineCh)
defer func() {
require.NoError(vm.Shutdown(context.Background()))
}()

var (
forkHeight = uint64(100)
blkCount = 10
startBlkHeight = uint64(1492)

// create a list of consecutive blocks and build state summary of top of them
proBlks, innerBlks = createTestBlocks(t, vm, blkCount, startBlkHeight)

innerTopBlk = innerBlks[len(innerBlks)-1]
proTopBlk = proBlks[len(proBlks)-1]
stateSummaryHeight = innerTopBlk.Height() + 1
)

innerSummary := &block.TestStateSummary{
IDV: ids.ID{'s', 'u', 'm', 'm', 'a', 'r', 'y', 'I', 'D'},
HeightV: stateSummaryHeight,
BytesV: []byte{'i', 'n', 'n', 'e', 'r'},
}
innerStateSyncedBlk := &snowman.TestBlock{
TestDecidable: choices.TestDecidable{
IDV: ids.ID{'i', 'n', 'n', 'e', 'r', 'S', 'y', 'n', 'c', 'e', 'd'},
},
ParentV: innerTopBlk.ID(),
HeightV: innerSummary.Height(),
BytesV: []byte("inner state synced block"),
}
stateSummary := createTestStateSummary(t, vm, proTopBlk.ID(), forkHeight, innerVM, innerSummary, innerStateSyncedBlk)

innerSummary.AcceptF = func(ctx context.Context) (block.StateSyncMode, error) {
return block.StateSyncStatic, nil
}

ctx := context.Background()
_, err := stateSummary.Accept(ctx)
require.NoError(err)

innerVM.LastAcceptedF = func(context.Context) (ids.ID, error) {
return innerStateSyncedBlk.ID(), nil
}
innerVM.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) {
switch blkID {
case innerStateSyncedBlk.ID():
return innerStateSyncedBlk, nil
default:
return nil, database.ErrNotFound
}
}

fromInnerVMCh <- common.StateSyncDone
<-toEngineCh

innerVM.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, uint64, error) {
return innerStateSyncedBlk.ID(), innerStateSyncedBlk.Height() - 1, nil
}
blkID, height, err := vm.BackfillBlocksEnabled(ctx)
require.NoError(err)
require.Equal(proTopBlk.ID(), blkID)
require.Equal(proTopBlk.Height(), height)

// Backfill some blocks
innerVM.ParseBlockF = func(_ context.Context, b []byte) (snowman.Block, error) {
for _, blk := range innerBlks {
if bytes.Equal(b, blk.Bytes()) {
return blk, nil
}
}
return nil, database.ErrNotFound
}

// simulate that lower half of backfilled blocks won't be accepted by innerVM
idx := len(innerBlks) / 2
innerVM.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) {
for _, blk := range innerBlks {
if blkID != blk.ID() {
continue
}
// if it's one of the lower half blocks, assume it's not stored
// since it was rejected
if blk.Height() <= innerBlks[idx].Height() {
return nil, database.ErrNotFound
}
return blk, nil
}
return nil, database.ErrNotFound
}

innerVM.BackfillBlocksF = func(_ context.Context, b [][]byte) (ids.ID, uint64, error) {
// assume lowest half blocks fails verification
return innerBlks[idx].ID(), innerBlks[idx].Height(), nil
}

blkBytes := make([][]byte, 0, len(proBlks))
for _, blk := range proBlks {
blkBytes = append(blkBytes, blk.Bytes())
}
nextBlkID, nextBlkHeight, err := vm.BackfillBlocks(ctx, blkBytes)
require.NoError(err)
require.Equal(proBlks[idx].ID(), nextBlkID)
require.Equal(proBlks[idx].Height(), nextBlkHeight)

// check only upper half of blocks have been indexed
for i, blk := range proBlks {
if i <= idx {
_, err := vm.GetBlockIDAtHeight(ctx, blk.Height())
require.ErrorIs(err, database.ErrNotFound)

_, err = vm.GetBlock(ctx, blk.ID())
require.ErrorIs(err, database.ErrNotFound)
} else {
blkID, err := vm.GetBlockIDAtHeight(ctx, blk.Height())
require.NoError(err)
require.Equal(blk.ID(), blkID)

_, err = vm.GetBlock(ctx, blkID)
require.NoError(err)
}
}
}

func createTestBlocks(
@@ -311,7 +441,14 @@ func createTestStateSummary(
return summary
}

func setupBlockBackfillingVM(t *testing.T, toEngineCh chan<- common.Message) (*fullVM, *VM, chan<- common.Message) {
func setupBlockBackfillingVM(
t *testing.T,
toEngineCh chan<- common.Message,
) (
*fullVM,
*VM,
chan<- common.Message,
) {
require := require.New(t)

innerVM := &fullVM{

0 comments on commit 2550a87

Please sign in to comment.