From 551f8d33cbed58a0159f29e200be76c3283b0347 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Mon, 20 May 2024 22:03:28 -0400 Subject: [PATCH] Fix negative ETA caused by rollback in vm.SetState (#3036) --- snow/engine/snowman/bootstrap/bootstrapper.go | 16 +++++----- .../snowman/bootstrap/bootstrapper_test.go | 31 +++++++++++++++++++ 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index 2988ece9ba0..095ba4e63b1 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -150,6 +150,14 @@ func (b *Bootstrapper) Clear(context.Context) error { } func (b *Bootstrapper) Start(ctx context.Context, startReqID uint32) error { + b.Ctx.State.Set(snow.EngineState{ + Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, + State: snow.Bootstrapping, + }) + if err := b.VM.SetState(ctx, snow.Bootstrapping); err != nil { + return fmt.Errorf("failed to notify VM that bootstrapping has started: %w", err) + } + lastAccepted, err := b.getLastAccepted(ctx) if err != nil { return err @@ -161,14 +169,6 @@ func (b *Bootstrapper) Start(ctx context.Context, startReqID uint32) error { zap.Uint64("lastAcceptedHeight", lastAcceptedHeight), ) - b.Ctx.State.Set(snow.EngineState{ - Type: p2p.EngineType_ENGINE_TYPE_SNOWMAN, - State: snow.Bootstrapping, - }) - if err := b.VM.SetState(ctx, snow.Bootstrapping); err != nil { - return fmt.Errorf("failed to notify VM that bootstrapping has started: %w", err) - } - // Set the starting height b.startingHeight = lastAcceptedHeight b.requestID = startReqID diff --git a/snow/engine/snowman/bootstrap/bootstrapper_test.go b/snow/engine/snowman/bootstrap/bootstrapper_test.go index 159fc98fb58..5577f62fa81 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper_test.go +++ b/snow/engine/snowman/bootstrap/bootstrapper_test.go @@ -742,6 +742,37 @@ func TestBootstrapperReceiveStaleAncestorsMessage(t *testing.T) { require.Equal(snow.Bootstrapping, config.Ctx.State.Get().State) } +func TestBootstrapperRollbackOnSetState(t *testing.T) { + require := require.New(t) + + config, _, _, vm := newConfig(t) + + blks := snowmantest.BuildChain(2) + initializeVMWithBlockchain(vm, blks) + + blks[1].StatusV = choices.Accepted + + bs, err := New( + config, + func(context.Context, uint32) error { + config.Ctx.State.Set(snow.EngineState{ + Type: p2ppb.EngineType_ENGINE_TYPE_SNOWMAN, + State: snow.NormalOp, + }) + return nil + }, + ) + require.NoError(err) + + vm.SetStateF = func(context.Context, snow.State) error { + blks[1].StatusV = choices.Processing + return nil + } + + require.NoError(bs.Start(context.Background(), 0)) + require.Equal(blks[0].HeightV, bs.startingHeight) +} + func initializeVMWithBlockchain(vm *block.TestVM, blocks []*snowmantest.Block) { vm.CantSetState = false vm.LastAcceptedF = func(context.Context) (ids.ID, error) {