From dbc209cacb9028741e80ab060403533fb9217905 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Fri, 17 Nov 2023 14:48:54 -0500 Subject: [PATCH] Export snowman bootstrapper (#2331) --- chains/manager.go | 6 ++- snow/engine/snowman/bootstrap/bootstrapper.go | 46 +++++++++---------- .../snowman/bootstrap/bootstrapper_test.go | 18 +++----- 3 files changed, 33 insertions(+), 37 deletions(-) diff --git a/chains/manager.go b/chains/manager.go index 9121123e313f..aeb4e7bb2135 100644 --- a/chains/manager.go +++ b/chains/manager.go @@ -894,7 +894,8 @@ func (m *manager) createAvalancheChain( Blocked: blockBlocker, VM: vmWrappingProposerVM, } - snowmanBootstrapper, err := smbootstrap.New( + var snowmanBootstrapper common.BootstrapableEngine + snowmanBootstrapper, err = smbootstrap.New( bootstrapCfg, snowmanEngine.Start, ) @@ -1243,7 +1244,8 @@ func (m *manager) createSnowmanChain( VM: vm, Bootstrapped: bootstrapFunc, } - bootstrapper, err := smbootstrap.New( + var bootstrapper common.BootstrapableEngine + bootstrapper, err = smbootstrap.New( bootstrapCfg, engine.Start, ) diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index c0644fc5170a..224cded68311 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -29,7 +29,7 @@ import ( const bootstrappingDelay = 10 * time.Second var ( - _ common.BootstrapableEngine = (*bootstrapper)(nil) + _ common.BootstrapableEngine = (*Bootstrapper)(nil) errUnexpectedTimeout = errors.New("unexpected timeout fired") ) @@ -50,7 +50,7 @@ var ( // // Invariant: The VM is not guaranteed to be initialized until Start has been // called, so it must be guaranteed the VM is not used until after Start. -type bootstrapper struct { +type Bootstrapper struct { Config // list of NoOpsHandler for messages dropped by bootstrapper @@ -97,13 +97,13 @@ type bootstrapper struct { bootstrappedOnce sync.Once } -func New(config Config, onFinished func(ctx context.Context, lastReqID uint32) error) (common.BootstrapableEngine, error) { +func New(config Config, onFinished func(ctx context.Context, lastReqID uint32) error) (*Bootstrapper, error) { metrics, err := newMetrics("bs", config.Ctx.Registerer) if err != nil { return nil, err } - b := &bootstrapper{ + b := &Bootstrapper{ Config: config, metrics: metrics, StateSummaryFrontierHandler: common.NewNoOpStateSummaryFrontierHandler(config.Ctx.Log), @@ -125,11 +125,11 @@ func New(config Config, onFinished func(ctx context.Context, lastReqID uint32) e return b, nil } -func (b *bootstrapper) Context() *snow.ConsensusContext { +func (b *Bootstrapper) Context() *snow.ConsensusContext { return b.Ctx } -func (b *bootstrapper) Start(ctx context.Context, startReqID uint32) error { +func (b *Bootstrapper) Start(ctx context.Context, startReqID uint32) error { b.Ctx.Log.Info("starting bootstrapper") b.Ctx.State.Set(snow.EngineState{ @@ -166,7 +166,7 @@ func (b *bootstrapper) Start(ctx context.Context, startReqID uint32) error { return b.tryStartBootstrapping(ctx) } -func (b *bootstrapper) Connected(ctx context.Context, nodeID ids.NodeID, nodeVersion *version.Application) error { +func (b *Bootstrapper) Connected(ctx context.Context, nodeID ids.NodeID, nodeVersion *version.Application) error { if err := b.VM.Connected(ctx, nodeID, nodeVersion); err != nil { return err } @@ -182,7 +182,7 @@ func (b *bootstrapper) Connected(ctx context.Context, nodeID ids.NodeID, nodeVer return b.tryStartBootstrapping(ctx) } -func (b *bootstrapper) Disconnected(ctx context.Context, nodeID ids.NodeID) error { +func (b *Bootstrapper) Disconnected(ctx context.Context, nodeID ids.NodeID) error { if err := b.VM.Disconnected(ctx, nodeID); err != nil { return err } @@ -197,7 +197,7 @@ func (b *bootstrapper) Disconnected(ctx context.Context, nodeID ids.NodeID) erro // tryStartBootstrapping will start bootstrapping the first time it is called // while the startupTracker is reporting that the protocol should start. -func (b *bootstrapper) tryStartBootstrapping(ctx context.Context) error { +func (b *Bootstrapper) tryStartBootstrapping(ctx context.Context) error { if b.started || !b.StartupTracker.ShouldStart() { return nil } @@ -208,7 +208,7 @@ func (b *bootstrapper) tryStartBootstrapping(ctx context.Context) error { // Ancestors handles the receipt of multiple containers. Should be received in // response to a GetAncestors message to [nodeID] with request ID [requestID] -func (b *bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, requestID uint32, blks [][]byte) error { +func (b *Bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, requestID uint32, blks [][]byte) error { // Make sure this is in response to a request we made wantedBlkID, ok := b.OutstandingRequests.Remove(nodeID, requestID) if !ok { // this message isn't in response to a request we made @@ -278,7 +278,7 @@ func (b *bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, request return b.process(ctx, requestedBlock, blockSet) } -func (b *bootstrapper) GetAncestorsFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32) error { +func (b *Bootstrapper) GetAncestorsFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32) error { blkID, ok := b.OutstandingRequests.Remove(nodeID, requestID) if !ok { b.Ctx.Log.Debug("unexpectedly called GetAncestorsFailed", @@ -295,7 +295,7 @@ func (b *bootstrapper) GetAncestorsFailed(ctx context.Context, nodeID ids.NodeID return b.fetch(ctx, blkID) } -func (b *bootstrapper) Timeout(ctx context.Context) error { +func (b *Bootstrapper) Timeout(ctx context.Context) error { if !b.awaitingTimeout { return errUnexpectedTimeout } @@ -308,11 +308,11 @@ func (b *bootstrapper) Timeout(ctx context.Context) error { return b.OnFinished(ctx, b.Config.SharedCfg.RequestID) } -func (*bootstrapper) Gossip(context.Context) error { +func (*Bootstrapper) Gossip(context.Context) error { return nil } -func (b *bootstrapper) Shutdown(ctx context.Context) error { +func (b *Bootstrapper) Shutdown(ctx context.Context) error { b.Ctx.Log.Info("shutting down bootstrapper") b.Ctx.Lock.Lock() @@ -321,7 +321,7 @@ func (b *bootstrapper) Shutdown(ctx context.Context) error { return b.VM.Shutdown(ctx) } -func (b *bootstrapper) Notify(_ context.Context, msg common.Message) error { +func (b *Bootstrapper) Notify(_ context.Context, msg common.Message) error { if msg != common.StateSyncDone { b.Ctx.Log.Warn("received an unexpected message from the VM", zap.Stringer("msg", msg), @@ -333,7 +333,7 @@ func (b *bootstrapper) Notify(_ context.Context, msg common.Message) error { return nil } -func (b *bootstrapper) HealthCheck(ctx context.Context) (interface{}, error) { +func (b *Bootstrapper) HealthCheck(ctx context.Context) (interface{}, error) { b.Ctx.Lock.Lock() defer b.Ctx.Lock.Unlock() @@ -345,11 +345,11 @@ func (b *bootstrapper) HealthCheck(ctx context.Context) (interface{}, error) { return intf, vmErr } -func (b *bootstrapper) GetVM() common.VM { +func (b *Bootstrapper) GetVM() common.VM { return b.VM } -func (b *bootstrapper) ForceAccepted(ctx context.Context, acceptedContainerIDs []ids.ID) error { +func (b *Bootstrapper) ForceAccepted(ctx context.Context, acceptedContainerIDs []ids.ID) error { pendingContainerIDs := b.Blocked.MissingIDs() // Initialize the fetch from set to the currently preferred peers @@ -392,7 +392,7 @@ func (b *bootstrapper) ForceAccepted(ctx context.Context, acceptedContainerIDs [ } // Get block [blkID] and its ancestors from a validator -func (b *bootstrapper) fetch(ctx context.Context, blkID ids.ID) error { +func (b *Bootstrapper) fetch(ctx context.Context, blkID ids.ID) error { // Make sure we haven't already requested this block if b.OutstandingRequests.Contains(blkID) { return nil @@ -421,7 +421,7 @@ func (b *bootstrapper) fetch(ctx context.Context, blkID ids.ID) error { // markUnavailable removes [nodeID] from the set of peers used to fetch // ancestors. If the set becomes empty, it is reset to the currently preferred // peers so bootstrapping can continue. -func (b *bootstrapper) markUnavailable(nodeID ids.NodeID) { +func (b *Bootstrapper) markUnavailable(nodeID ids.NodeID) { b.fetchFrom.Remove(nodeID) // if [fetchFrom] has become empty, reset it to the currently preferred @@ -431,7 +431,7 @@ func (b *bootstrapper) markUnavailable(nodeID ids.NodeID) { } } -func (b *bootstrapper) Clear(context.Context) error { +func (b *Bootstrapper) Clear(context.Context) error { b.Ctx.Lock.Lock() defer b.Ctx.Lock.Unlock() @@ -451,7 +451,7 @@ func (b *bootstrapper) Clear(context.Context) error { // // If [blk]'s height is <= the last accepted height, then it will be removed // from the missingIDs set. -func (b *bootstrapper) process(ctx context.Context, blk snowman.Block, processingBlocks map[ids.ID]snowman.Block) error { +func (b *Bootstrapper) process(ctx context.Context, blk snowman.Block, processingBlocks map[ids.ID]snowman.Block) error { for { blkID := blk.ID() if b.Halted() { @@ -570,7 +570,7 @@ func (b *bootstrapper) process(ctx context.Context, blk snowman.Block, processin // checkFinish repeatedly executes pending transactions and requests new frontier vertices until there aren't any new ones // after which it finishes the bootstrap process -func (b *bootstrapper) checkFinish(ctx context.Context) error { +func (b *Bootstrapper) checkFinish(ctx context.Context) error { if numPending := b.Blocked.NumMissingIDs(); numPending != 0 { return nil } diff --git a/snow/engine/snowman/bootstrap/bootstrapper_test.go b/snow/engine/snowman/bootstrap/bootstrapper_test.go index 8bafa18fe5e1..c883de181323 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper_test.go +++ b/snow/engine/snowman/bootstrap/bootstrapper_test.go @@ -696,10 +696,10 @@ func TestBootstrapperEmptyResponse(t *testing.T) { // add another two validators to the fetch set to test behavior on empty response newPeerID := ids.GenerateTestNodeID() - bs.(*bootstrapper).fetchFrom.Add(newPeerID) + bs.fetchFrom.Add(newPeerID) newPeerID = ids.GenerateTestNodeID() - bs.(*bootstrapper).fetchFrom.Add(newPeerID) + bs.fetchFrom.Add(newPeerID) require.NoError(bs.Ancestors(context.Background(), peerID, requestID, [][]byte{blkBytes2})) require.Equal(blkID1, requestedBlock) @@ -719,7 +719,7 @@ func TestBootstrapperEmptyResponse(t *testing.T) { require.Equal(choices.Accepted, blk2.Status()) // check peerToBlacklist was removed from the fetch set - require.NotContains(bs.(*bootstrapper).fetchFrom, peerToBlacklist) + require.NotContains(bs.fetchFrom, peerToBlacklist) } // There are multiple needed blocks and Ancestors returns all at once @@ -1111,7 +1111,7 @@ func TestRestartBootstrapping(t *testing.T) { return nil, errUnknownBlock } - bsIntf, err := New( + bs, err := New( config, func(context.Context, uint32) error { config.Ctx.State.Set(snow.EngineState{ @@ -1122,8 +1122,6 @@ func TestRestartBootstrapping(t *testing.T) { }, ) require.NoError(err) - require.IsType(&bootstrapper{}, bsIntf) - bs := bsIntf.(*bootstrapper) vm.CantSetState = false require.NoError(bs.Start(context.Background(), 0)) @@ -1220,7 +1218,7 @@ func TestBootstrapOldBlockAfterStateSync(t *testing.T) { return nil, errUnknownBlock } - bsIntf, err := New( + bs, err := New( config, func(context.Context, uint32) error { config.Ctx.State.Set(snow.EngineState{ @@ -1231,8 +1229,6 @@ func TestBootstrapOldBlockAfterStateSync(t *testing.T) { }, ) require.NoError(err) - require.IsType(&bootstrapper{}, bsIntf) - bs := bsIntf.(*bootstrapper) vm.CantSetState = false require.NoError(bs.Start(context.Background(), 0)) @@ -1291,7 +1287,7 @@ func TestBootstrapContinueAfterHalt(t *testing.T) { return blk0.ID(), nil } - bsIntf, err := New( + bs, err := New( config, func(context.Context, uint32) error { config.Ctx.State.Set(snow.EngineState{ @@ -1302,8 +1298,6 @@ func TestBootstrapContinueAfterHalt(t *testing.T) { }, ) require.NoError(err) - require.IsType(&bootstrapper{}, bsIntf) - bs := bsIntf.(*bootstrapper) vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { switch blkID {