From 40de56f1f48e5608b42ebfb62102bb134baac82b Mon Sep 17 00:00:00 2001 From: samliok Date: Thu, 21 Aug 2025 14:07:13 -0400 Subject: [PATCH 1/6] break large createChainMethod into helpers --- chains/manager.go | 592 ++++++++++++++++++++++++++-------------------- 1 file changed, 333 insertions(+), 259 deletions(-) diff --git a/chains/manager.go b/chains/manager.go index 4ac3764a3087..2543abe20339 100644 --- a/chains/manager.go +++ b/chains/manager.go @@ -1069,25 +1069,246 @@ func (m *manager) createSnowmanChain( }) primaryAlias := m.PrimaryAliasOrDefault(ctx.ChainID) - meterDBReg, err := metrics.MakeAndRegister( - m.MeterDBMetrics, - primaryAlias, + + vmDB, bootstrappingDB, err := m.createSnowmanDBs(primaryAlias, ctx.ChainID) + if err != nil { + return nil, fmt.Errorf("error while creating snowman dbs: %w", err) + } + + messageSender, err := m.createSnowmanMessageSender(ctx, sb) + if err != nil { + return nil, fmt.Errorf("couldn't initialize message sender: %w", err) + } + + connectedValidators, err := m.createSnowmanTrackedPeers(primaryAlias) + if err != nil { + return nil, fmt.Errorf("error creating connected validators: %w", err) + } + vdrs.RegisterSetCallbackListener(ctx.SubnetID, connectedValidators) + + peerTracker, err := m.createSnowmanPeerTracker(ctx, primaryAlias) + if err != nil { + return nil, fmt.Errorf("error creating peer tracking: %w", err) + } + + cn, proposerVM, err := m.createSnowmanVMs(ctx, vm, vmDB, primaryAlias, genesisData, messageSender, fxs) + if err != nil { + return nil, fmt.Errorf("couldn't create snowman VMs: %w", err) + } + + var halter common.Halter + h, err := m.createSnowmanHandler(ctx, cn, vdrs, sb, primaryAlias, connectedValidators, peerTracker, halter) + if err != nil { + return nil, fmt.Errorf("couldn't create snowman handler: %w", err) + } + + engine, err := m.createSnowmanEngine(ctx, cn, proposerVM.ParseBlock, sb, beacons, messageSender, bootstrappingDB, vdrs, connectedValidators, peerTracker, halter) + if err != nil { + return nil, fmt.Errorf("couldn't create snowman engine: %w", err) + } + + h.SetEngineManager(&handler.EngineManager{ + Avalanche: nil, + Snowman: engine, + }) + + // Register health checks + if err := m.Health.RegisterHealthCheck(primaryAlias, h, ctx.SubnetID.String()); err != nil { + return nil, fmt.Errorf("couldn't add health check for chain %s: %w", primaryAlias, err) + } + + return &chain{ + Name: primaryAlias, + Context: ctx, + VM: vm, + Handler: h, + }, nil +} + +func (m *manager) IsBootstrapped(id ids.ID) bool { + m.chainsLock.Lock() + chain, exists := m.chains[id] + m.chainsLock.Unlock() + if !exists { + return false + } + + return chain.Context().State.Get().State == snow.NormalOp +} + +func (m *manager) registerBootstrappedHealthChecks() error { + bootstrappedCheck := health.CheckerFunc(func(context.Context) (interface{}, error) { + if subnetIDs := m.Subnets.Bootstrapping(); len(subnetIDs) != 0 { + return subnetIDs, errNotBootstrapped + } + return []ids.ID{}, nil + }) + if err := m.Health.RegisterReadinessCheck("bootstrapped", bootstrappedCheck, health.ApplicationTag); err != nil { + return fmt.Errorf("couldn't register bootstrapped readiness check: %w", err) + } + if err := m.Health.RegisterHealthCheck("bootstrapped", bootstrappedCheck, health.ApplicationTag); err != nil { + return fmt.Errorf("couldn't register bootstrapped health check: %w", err) + } + + // We should only report unhealthy if the node is partially syncing the + // primary network and is a validator. + if !m.PartialSyncPrimaryNetwork { + return nil + } + + partialSyncCheck := health.CheckerFunc(func(context.Context) (interface{}, error) { + // Note: The health check is skipped during bootstrapping to allow a + // node to sync the network even if it was previously a validator. + if !m.IsBootstrapped(constants.PlatformChainID) { + return "node is currently bootstrapping", nil + } + if _, ok := m.Validators.GetValidator(constants.PrimaryNetworkID, m.NodeID); !ok { + return "node is not a primary network validator", nil + } + + m.Log.Warn("node is a primary network validator", + zap.Error(errPartialSyncAsAValidator), + ) + return "node is a primary network validator", errPartialSyncAsAValidator + }) + + if err := m.Health.RegisterHealthCheck("validation", partialSyncCheck, health.ApplicationTag); err != nil { + return fmt.Errorf("couldn't register validation health check: %w", err) + } + return nil +} + +// Starts chain creation loop to process queued chains +func (m *manager) StartChainCreator(platformParams ChainParameters) error { + // Add the P-Chain to the Primary Network + sb, _ := m.Subnets.GetOrCreate(constants.PrimaryNetworkID) + sb.AddChain(platformParams.ID) + + // The P-chain is created synchronously to ensure that `VM.Initialize` has + // finished before returning from this function. This is required because + // the P-chain initializes state that the rest of the node initialization + // depends on. + m.createChain(platformParams) + + m.Log.Info("starting chain creator") + m.chainCreatorExited.Add(1) + go m.dispatchChainCreator() + return nil +} + +func (m *manager) dispatchChainCreator() { + defer m.chainCreatorExited.Done() + + select { + // This channel will be closed when Shutdown is called on the manager. + case <-m.chainCreatorShutdownCh: + return + case <-m.unblockChainCreatorCh: + } + + // Handle chain creations + for { + // Get the next chain we should create. + // Dequeue waits until an element is pushed, so this is not + // busy-looping. + chainParams, ok := m.chainsQueue.PopLeft() + if !ok { // queue is closed, return directly + return + } + m.createChain(chainParams) + } +} + +// Shutdown stops all the chains +func (m *manager) Shutdown() { + m.Log.Info("shutting down chain manager") + m.chainsQueue.Close() + close(m.chainCreatorShutdownCh) + m.chainCreatorExited.Wait() + m.ManagerConfig.Router.Shutdown(context.TODO()) +} + +// LookupVM returns the ID of the VM associated with an alias +func (m *manager) LookupVM(alias string) (ids.ID, error) { + return m.VMManager.Lookup(alias) +} + +// Notify registrants [those who want to know about the creation of chains] +// that the specified chain has been created +func (m *manager) notifyRegistrants(name string, ctx *snow.ConsensusContext, vm common.VM) { + for _, registrant := range m.registrants { + registrant.RegisterChain(name, ctx, vm) + } +} + +// getChainConfig returns value of a entry by looking at ID key and alias key +// it first searches ID key, then falls back to it's corresponding primary alias +func (m *manager) getChainConfig(id ids.ID) (ChainConfig, error) { + if val, ok := m.ManagerConfig.ChainConfigs[id.String()]; ok { + return val, nil + } + aliases, err := m.Aliases(id) + if err != nil { + return ChainConfig{}, err + } + for _, alias := range aliases { + if val, ok := m.ManagerConfig.ChainConfigs[alias]; ok { + return val, nil + } + } + + return ChainConfig{}, nil +} + +func (m *manager) getOrMakeVMGatherer(vmID ids.ID) (metrics.MultiGatherer, error) { + vmGatherer, ok := m.vmGatherer[vmID] + if ok { + return vmGatherer, nil + } + + vmName := constants.VMName(vmID) + vmNamespace := metric.AppendNamespace(constants.PlatformName, vmName) + vmGatherer = metrics.NewLabelGatherer(ChainLabel) + err := m.Metrics.Register( + vmNamespace, + vmGatherer, ) if err != nil { return nil, err } + m.vmGatherer[vmID] = vmGatherer + return vmGatherer, nil +} - meterDB, err := meterdb.New(meterDBReg, m.DB) +func (m *manager) createSnowmanHandler(ctx *snow.ConsensusContext, vm *block.ChangeNotifier, vdrs validators.Manager, sb subnets.Subnet, primaryAlias string, connectedValidators tracker.Peers, peerTracker *p2p.PeerTracker, halter common.Halter) (handler.Handler, error) { + handlerReg, err := metrics.MakeAndRegister( + m.handlerGatherer, + primaryAlias, + ) if err != nil { return nil, err } - prefixDB := prefixdb.New(ctx.ChainID[:], meterDB) - vmDB := prefixdb.New(VMDBPrefix, prefixDB) - bootstrappingDB := prefixdb.New(ChainBootstrappingDBPrefix, prefixDB) + // Asynchronously passes messages from the network to the consensus engine + return handler.New( + ctx, + vm, + vm.WaitForEvent, + vdrs, + m.FrontierPollFrequency, + m.ConsensusAppConcurrency, + m.ResourceTracker, + sb, + connectedValidators, + peerTracker, + handlerReg, + halter.Halt, + ) +} - // Passes messages from the consensus engine to the network - messageSender, err := sender.New( +// createSnowmanMessageSender creates a sender that passes messages from the consensus engine to the network +func (m *manager) createSnowmanMessageSender(ctx *snow.ConsensusContext, sb subnets.Subnet) (common.Sender, error) { + msgSender, err := sender.New( ctx, m.MsgCreator, m.Net, @@ -1098,21 +1319,48 @@ func (m *manager) createSnowmanChain( ctx.Registerer, ) if err != nil { - return nil, fmt.Errorf("couldn't initialize sender: %w", err) + return nil, fmt.Errorf("couldn't initialize snowman sender: %w", err) } if m.TracingEnabled { - messageSender = sender.Trace(messageSender, m.Tracer) + msgSender = sender.Trace(msgSender, m.Tracer) } - var bootstrapFunc func() + return msgSender, nil +} + +// createSnowmanDBs creates a database used during bootstrapping and a database used by the VM. +// The bootstrapping DB acts as an ephemeral database during bootstrapping to store blocks +// we have fetched but not yet verified. +// The VM DB is used to store blocks and transactions that have been verified and accepted. +func (m *manager) createSnowmanDBs(primaryAlias string, chainID ids.ID) (*prefixdb.Database, *prefixdb.Database, error) { + meterDBReg, err := metrics.MakeAndRegister( + m.MeterDBMetrics, + primaryAlias, + ) + if err != nil { + return nil, nil, err + } + + meterDB, err := meterdb.New(meterDBReg, m.DB) + if err != nil { + return nil, nil, err + } + + prefixDB := prefixdb.New(chainID[:], meterDB) + vmDB := prefixdb.New(VMDBPrefix, prefixDB) + bootstrappingDB := prefixdb.New(ChainBootstrappingDBPrefix, prefixDB) + return vmDB, bootstrappingDB, nil +} + +func (m *manager) maybeSetupPChainState(ctx *snow.ConsensusContext, vm block.ChainVM) (bool, error) { // If [m.validatorState] is nil then we are creating the P-Chain. Since the // P-Chain is the first chain to be created, we can use it to initialize // required interfaces for the other chains if m.validatorState == nil { valState, ok := vm.(validators.State) if !ok { - return nil, fmt.Errorf("expected validators.State but got %T", vm) + return false, fmt.Errorf("expected validators.State but got %T", vm) } if m.TracingEnabled { @@ -1139,15 +1387,55 @@ func (m *manager) createSnowmanChain( // // The snowman bootstrapper ensures this function is only executed once, so // we don't need to be concerned about closing this channel multiple times. - bootstrapFunc = func() { - close(m.unblockChainCreatorCh) - } + return true, nil + } + + return false, nil +} + +func (m *manager) createSnowmanTrackedPeers(primaryAlias string) (tracker.Peers, error) { + stakeReg, err := metrics.MakeAndRegister( + m.stakeGatherer, + primaryAlias, + ) + if err != nil { + return nil, err + } + connectedValidators, err := tracker.NewMeteredPeers(stakeReg) + if err != nil { + return nil, fmt.Errorf("error creating peer tracker: %w", err) + } + return connectedValidators, nil +} + +// createSnowmanPeerTracker creates a peer tracker for the Snowman consensus engine +func (m *manager) createSnowmanPeerTracker(ctx *snow.ConsensusContext, primaryAlias string) (*p2p.PeerTracker, error) { + p2pReg, err := metrics.MakeAndRegister( + m.p2pGatherer, + primaryAlias, + ) + if err != nil { + return nil, err + } + + peerTracker, err := p2p.NewPeerTracker( + ctx.Log, + "peer_tracker", + p2pReg, + set.Of(ctx.NodeID), + nil, + ) + if err != nil { + return nil, fmt.Errorf("error creating peer tracker: %w", err) } + return peerTracker, nil +} +func (m *manager) createSnowmanVMs(ctx *snow.ConsensusContext, vm block.ChainVM, db *prefixdb.Database, primaryAlias string, genesisData []byte, messageSender common.Sender, fxs []*common.Fx) (*block.ChangeNotifier, *proposervm.VM, error) { // Initialize the ProposerVM and the vm wrapped inside it chainConfig, err := m.getChainConfig(ctx.ChainID) if err != nil { - return nil, fmt.Errorf("error while fetching chain config: %w", err) + return nil, nil, fmt.Errorf("error while fetching chain config: %w", err) } var ( @@ -1172,7 +1460,7 @@ func (m *manager) createSnowmanChain( primaryAlias, ) if err != nil { - return nil, err + return nil, nil, err } proposerVM := proposervm.New( @@ -1195,7 +1483,7 @@ func (m *manager) createSnowmanChain( primaryAlias, ) if err != nil { - return nil, err + return nil, nil, err } vm = metervm.NewBlockVM(vm, meterchainvmReg) @@ -1212,87 +1500,44 @@ func (m *manager) createSnowmanChain( if err := vm.Initialize( context.TODO(), ctx.Context, - vmDB, + db, genesisData, chainConfig.Upgrade, chainConfig.Config, fxs, messageSender, ); err != nil { - return nil, err - } - - bootstrapWeight, err := beacons.TotalWeight(ctx.SubnetID) - if err != nil { - return nil, fmt.Errorf("error while fetching weight for subnet %s: %w", ctx.SubnetID, err) + return nil, nil, err } - consensusParams := sb.Config().ConsensusParameters - sampleK := consensusParams.K - if uint64(sampleK) > bootstrapWeight { - sampleK = int(bootstrapWeight) - } - - stakeReg, err := metrics.MakeAndRegister( - m.stakeGatherer, - primaryAlias, - ) - if err != nil { - return nil, err - } - - connectedValidators, err := tracker.NewMeteredPeers(stakeReg) - if err != nil { - return nil, fmt.Errorf("error creating peer tracker: %w", err) - } - vdrs.RegisterSetCallbackListener(ctx.SubnetID, connectedValidators) + return cn, proposerVM, nil +} - p2pReg, err := metrics.MakeAndRegister( - m.p2pGatherer, - primaryAlias, - ) +// createSnowmanEngine creates a Snowman engine with the provided context, VM, and other parameters. +// It sets up the consensus engine, bootstrapper, and state syncer. +// It also handles setting up the P-Chain if necessary. +func (m *manager) createSnowmanEngine(ctx *snow.ConsensusContext, vm block.ChainVM, nonVerifyingParseFunc block.ParseFunc, sb subnets.Subnet, beacons validators.Manager, messageSender common.Sender, bootstrappingDB *prefixdb.Database, vdrs validators.Manager, connectedValidators tracker.Peers, peerTracker *p2p.PeerTracker, halter common.Halter) (*handler.Engine, error) { + isPChain, err := m.maybeSetupPChainState(ctx, vm) if err != nil { - return nil, err + return nil, fmt.Errorf("couldn't setup P Chain state: %w", err) } - peerTracker, err := p2p.NewPeerTracker( - ctx.Log, - "peer_tracker", - p2pReg, - set.Of(ctx.NodeID), - nil, - ) - if err != nil { - return nil, fmt.Errorf("error creating peer tracker: %w", err) + var bootstrapFunc func() + if isPChain { + bootstrapFunc = func() { + close(m.unblockChainCreatorCh) + } } - handlerReg, err := metrics.MakeAndRegister( - m.handlerGatherer, - primaryAlias, - ) + bootstrapWeight, err := beacons.TotalWeight(ctx.SubnetID) if err != nil { - return nil, err + return nil, fmt.Errorf("error while fetching weight for subnet %s: %w", ctx.SubnetID, err) } - var halter common.Halter - - // Asynchronously passes messages from the network to the consensus engine - h, err := handler.New( - ctx, - cn, - vm.WaitForEvent, - vdrs, - m.FrontierPollFrequency, - m.ConsensusAppConcurrency, - m.ResourceTracker, - sb, - connectedValidators, - peerTracker, - handlerReg, - halter.Halt, - ) - if err != nil { - return nil, fmt.Errorf("couldn't initialize message handler: %w", err) + consensusParams := sb.Config().ConsensusParameters + sampleK := consensusParams.K + if uint64(sampleK) > bootstrapWeight { + sampleK = int(bootstrapWeight) } connectedBeacons := tracker.NewPeers() @@ -1342,7 +1587,7 @@ func (m *manager) createSnowmanChain( // create bootstrap gear bootstrapCfg := smbootstrap.Config{ Haltable: &halter, - NonVerifyingParse: block.ParseFunc(proposerVM.ParseLocalBlock), + NonVerifyingParse: nonVerifyingParseFunc, AllGetsServer: snowGetHandler, Ctx: ctx, Beacons: beacons, @@ -1392,180 +1637,9 @@ func (m *manager) createSnowmanChain( if m.TracingEnabled { stateSyncer = common.TraceStateSyncer(stateSyncer, m.Tracer) } - - h.SetEngineManager(&handler.EngineManager{ - Avalanche: nil, - Snowman: &handler.Engine{ - StateSyncer: stateSyncer, - Bootstrapper: bootstrapper, - Consensus: engine, - }, - }) - - // Register health checks - if err := m.Health.RegisterHealthCheck(primaryAlias, h, ctx.SubnetID.String()); err != nil { - return nil, fmt.Errorf("couldn't add health check for chain %s: %w", primaryAlias, err) - } - - return &chain{ - Name: primaryAlias, - Context: ctx, - VM: vm, - Handler: h, + return &handler.Engine{ + StateSyncer: stateSyncer, + Bootstrapper: bootstrapper, + Consensus: engine, }, nil } - -func (m *manager) IsBootstrapped(id ids.ID) bool { - m.chainsLock.Lock() - chain, exists := m.chains[id] - m.chainsLock.Unlock() - if !exists { - return false - } - - return chain.Context().State.Get().State == snow.NormalOp -} - -func (m *manager) registerBootstrappedHealthChecks() error { - bootstrappedCheck := health.CheckerFunc(func(context.Context) (interface{}, error) { - if subnetIDs := m.Subnets.Bootstrapping(); len(subnetIDs) != 0 { - return subnetIDs, errNotBootstrapped - } - return []ids.ID{}, nil - }) - if err := m.Health.RegisterReadinessCheck("bootstrapped", bootstrappedCheck, health.ApplicationTag); err != nil { - return fmt.Errorf("couldn't register bootstrapped readiness check: %w", err) - } - if err := m.Health.RegisterHealthCheck("bootstrapped", bootstrappedCheck, health.ApplicationTag); err != nil { - return fmt.Errorf("couldn't register bootstrapped health check: %w", err) - } - - // We should only report unhealthy if the node is partially syncing the - // primary network and is a validator. - if !m.PartialSyncPrimaryNetwork { - return nil - } - - partialSyncCheck := health.CheckerFunc(func(context.Context) (interface{}, error) { - // Note: The health check is skipped during bootstrapping to allow a - // node to sync the network even if it was previously a validator. - if !m.IsBootstrapped(constants.PlatformChainID) { - return "node is currently bootstrapping", nil - } - if _, ok := m.Validators.GetValidator(constants.PrimaryNetworkID, m.NodeID); !ok { - return "node is not a primary network validator", nil - } - - m.Log.Warn("node is a primary network validator", - zap.Error(errPartialSyncAsAValidator), - ) - return "node is a primary network validator", errPartialSyncAsAValidator - }) - - if err := m.Health.RegisterHealthCheck("validation", partialSyncCheck, health.ApplicationTag); err != nil { - return fmt.Errorf("couldn't register validation health check: %w", err) - } - return nil -} - -// Starts chain creation loop to process queued chains -func (m *manager) StartChainCreator(platformParams ChainParameters) error { - // Add the P-Chain to the Primary Network - sb, _ := m.Subnets.GetOrCreate(constants.PrimaryNetworkID) - sb.AddChain(platformParams.ID) - - // The P-chain is created synchronously to ensure that `VM.Initialize` has - // finished before returning from this function. This is required because - // the P-chain initializes state that the rest of the node initialization - // depends on. - m.createChain(platformParams) - - m.Log.Info("starting chain creator") - m.chainCreatorExited.Add(1) - go m.dispatchChainCreator() - return nil -} - -func (m *manager) dispatchChainCreator() { - defer m.chainCreatorExited.Done() - - select { - // This channel will be closed when Shutdown is called on the manager. - case <-m.chainCreatorShutdownCh: - return - case <-m.unblockChainCreatorCh: - } - - // Handle chain creations - for { - // Get the next chain we should create. - // Dequeue waits until an element is pushed, so this is not - // busy-looping. - chainParams, ok := m.chainsQueue.PopLeft() - if !ok { // queue is closed, return directly - return - } - m.createChain(chainParams) - } -} - -// Shutdown stops all the chains -func (m *manager) Shutdown() { - m.Log.Info("shutting down chain manager") - m.chainsQueue.Close() - close(m.chainCreatorShutdownCh) - m.chainCreatorExited.Wait() - m.ManagerConfig.Router.Shutdown(context.TODO()) -} - -// LookupVM returns the ID of the VM associated with an alias -func (m *manager) LookupVM(alias string) (ids.ID, error) { - return m.VMManager.Lookup(alias) -} - -// Notify registrants [those who want to know about the creation of chains] -// that the specified chain has been created -func (m *manager) notifyRegistrants(name string, ctx *snow.ConsensusContext, vm common.VM) { - for _, registrant := range m.registrants { - registrant.RegisterChain(name, ctx, vm) - } -} - -// getChainConfig returns value of a entry by looking at ID key and alias key -// it first searches ID key, then falls back to it's corresponding primary alias -func (m *manager) getChainConfig(id ids.ID) (ChainConfig, error) { - if val, ok := m.ManagerConfig.ChainConfigs[id.String()]; ok { - return val, nil - } - aliases, err := m.Aliases(id) - if err != nil { - return ChainConfig{}, err - } - for _, alias := range aliases { - if val, ok := m.ManagerConfig.ChainConfigs[alias]; ok { - return val, nil - } - } - - return ChainConfig{}, nil -} - -func (m *manager) getOrMakeVMGatherer(vmID ids.ID) (metrics.MultiGatherer, error) { - vmGatherer, ok := m.vmGatherer[vmID] - if ok { - return vmGatherer, nil - } - - vmName := constants.VMName(vmID) - vmNamespace := metric.AppendNamespace(constants.PlatformName, vmName) - vmGatherer = metrics.NewLabelGatherer(ChainLabel) - err := m.Metrics.Register( - vmNamespace, - vmGatherer, - ) - if err != nil { - return nil, err - } - m.vmGatherer[vmID] = vmGatherer - return vmGatherer, nil -} From 6f7a1569c29133bd8e35c1bfa19b278f47e1c2b5 Mon Sep 17 00:00:00 2001 From: samliok Date: Thu, 21 Aug 2025 14:46:13 -0400 Subject: [PATCH 2/6] reordering --- chains/manager.go | 46 +++++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/chains/manager.go b/chains/manager.go index 2543abe20339..893039c821c0 100644 --- a/chains/manager.go +++ b/chains/manager.go @@ -1080,6 +1080,16 @@ func (m *manager) createSnowmanChain( return nil, fmt.Errorf("couldn't initialize message sender: %w", err) } + bootstrapFunc, err := m.maybeSetupPChain(ctx, vm) + if err != nil { + return nil, fmt.Errorf("couldn't setup P Chain state: %w", err) + } + + cn, proposerVM, err := m.createSnowmanVMs(ctx, vm, vmDB, primaryAlias, genesisData, messageSender, fxs) + if err != nil { + return nil, fmt.Errorf("couldn't create snowman VMs: %w", err) + } + connectedValidators, err := m.createSnowmanTrackedPeers(primaryAlias) if err != nil { return nil, fmt.Errorf("error creating connected validators: %w", err) @@ -1091,18 +1101,13 @@ func (m *manager) createSnowmanChain( return nil, fmt.Errorf("error creating peer tracking: %w", err) } - cn, proposerVM, err := m.createSnowmanVMs(ctx, vm, vmDB, primaryAlias, genesisData, messageSender, fxs) - if err != nil { - return nil, fmt.Errorf("couldn't create snowman VMs: %w", err) - } - var halter common.Halter h, err := m.createSnowmanHandler(ctx, cn, vdrs, sb, primaryAlias, connectedValidators, peerTracker, halter) if err != nil { return nil, fmt.Errorf("couldn't create snowman handler: %w", err) } - engine, err := m.createSnowmanEngine(ctx, cn, proposerVM.ParseBlock, sb, beacons, messageSender, bootstrappingDB, vdrs, connectedValidators, peerTracker, halter) + engine, err := m.createSnowmanEngine(ctx, cn, proposerVM.ParseBlock, sb, beacons, messageSender, bootstrappingDB, bootstrapFunc, vdrs, connectedValidators, peerTracker, halter) if err != nil { return nil, fmt.Errorf("couldn't create snowman engine: %w", err) } @@ -1353,14 +1358,17 @@ func (m *manager) createSnowmanDBs(primaryAlias string, chainID ids.ID) (*prefix return vmDB, bootstrappingDB, nil } -func (m *manager) maybeSetupPChainState(ctx *snow.ConsensusContext, vm block.ChainVM) (bool, error) { +// maybeSetupPChain checks if we are creating the P-Chain and +// sets up the manager and context if so. It returns a function that +// is called once bootstrapping is complete. +func (m *manager) maybeSetupPChain(ctx *snow.ConsensusContext, vm block.ChainVM) (func(), error) { // If [m.validatorState] is nil then we are creating the P-Chain. Since the // P-Chain is the first chain to be created, we can use it to initialize // required interfaces for the other chains if m.validatorState == nil { valState, ok := vm.(validators.State) if !ok { - return false, fmt.Errorf("expected validators.State but got %T", vm) + return nil, fmt.Errorf("expected validators.State but got %T", vm) } if m.TracingEnabled { @@ -1382,15 +1390,16 @@ func (m *manager) maybeSetupPChainState(ctx *snow.ConsensusContext, vm block.Cha m.validatorState = validators.NewNoValidatorsState(m.validatorState) ctx.ValidatorState = validators.NewNoValidatorsState(ctx.ValidatorState) } - // Set this func only for platform // // The snowman bootstrapper ensures this function is only executed once, so // we don't need to be concerned about closing this channel multiple times. - return true, nil + return func() { + close(m.unblockChainCreatorCh) + }, nil } - return false, nil + return func() {}, nil } func (m *manager) createSnowmanTrackedPeers(primaryAlias string) (tracker.Peers, error) { @@ -1515,20 +1524,7 @@ func (m *manager) createSnowmanVMs(ctx *snow.ConsensusContext, vm block.ChainVM, // createSnowmanEngine creates a Snowman engine with the provided context, VM, and other parameters. // It sets up the consensus engine, bootstrapper, and state syncer. -// It also handles setting up the P-Chain if necessary. -func (m *manager) createSnowmanEngine(ctx *snow.ConsensusContext, vm block.ChainVM, nonVerifyingParseFunc block.ParseFunc, sb subnets.Subnet, beacons validators.Manager, messageSender common.Sender, bootstrappingDB *prefixdb.Database, vdrs validators.Manager, connectedValidators tracker.Peers, peerTracker *p2p.PeerTracker, halter common.Halter) (*handler.Engine, error) { - isPChain, err := m.maybeSetupPChainState(ctx, vm) - if err != nil { - return nil, fmt.Errorf("couldn't setup P Chain state: %w", err) - } - - var bootstrapFunc func() - if isPChain { - bootstrapFunc = func() { - close(m.unblockChainCreatorCh) - } - } - +func (m *manager) createSnowmanEngine(ctx *snow.ConsensusContext, vm block.ChainVM, nonVerifyingParseFunc block.ParseFunc, sb subnets.Subnet, beacons validators.Manager, messageSender common.Sender, bootstrappingDB *prefixdb.Database, bootstrapFunc func(), vdrs validators.Manager, connectedValidators tracker.Peers, peerTracker *p2p.PeerTracker, halter common.Halter) (*handler.Engine, error) { bootstrapWeight, err := beacons.TotalWeight(ctx.SubnetID) if err != nil { return nil, fmt.Errorf("error while fetching weight for subnet %s: %w", ctx.SubnetID, err) From a388c19975020dfb05e4f6d60a5301e26ad0ce20 Mon Sep 17 00:00:00 2001 From: samliok Date: Thu, 21 Aug 2025 14:47:57 -0400 Subject: [PATCH 3/6] fmt --- chains/manager.go | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/chains/manager.go b/chains/manager.go index 893039c821c0..ec7805469410 100644 --- a/chains/manager.go +++ b/chains/manager.go @@ -1440,7 +1440,14 @@ func (m *manager) createSnowmanPeerTracker(ctx *snow.ConsensusContext, primaryAl return peerTracker, nil } -func (m *manager) createSnowmanVMs(ctx *snow.ConsensusContext, vm block.ChainVM, db *prefixdb.Database, primaryAlias string, genesisData []byte, messageSender common.Sender, fxs []*common.Fx) (*block.ChangeNotifier, *proposervm.VM, error) { +func (m *manager) createSnowmanVMs( + ctx *snow.ConsensusContext, + vm block.ChainVM, + db *prefixdb.Database, + primaryAlias string, + genesisData []byte, + messageSender common.Sender, + fxs []*common.Fx) (*block.ChangeNotifier, *proposervm.VM, error) { // Initialize the ProposerVM and the vm wrapped inside it chainConfig, err := m.getChainConfig(ctx.ChainID) if err != nil { @@ -1524,7 +1531,19 @@ func (m *manager) createSnowmanVMs(ctx *snow.ConsensusContext, vm block.ChainVM, // createSnowmanEngine creates a Snowman engine with the provided context, VM, and other parameters. // It sets up the consensus engine, bootstrapper, and state syncer. -func (m *manager) createSnowmanEngine(ctx *snow.ConsensusContext, vm block.ChainVM, nonVerifyingParseFunc block.ParseFunc, sb subnets.Subnet, beacons validators.Manager, messageSender common.Sender, bootstrappingDB *prefixdb.Database, bootstrapFunc func(), vdrs validators.Manager, connectedValidators tracker.Peers, peerTracker *p2p.PeerTracker, halter common.Halter) (*handler.Engine, error) { +func (m *manager) createSnowmanEngine( + ctx *snow.ConsensusContext, + vm block.ChainVM, + nonVerifyingParseFunc block.ParseFunc, + sb subnets.Subnet, + beacons validators.Manager, + messageSender common.Sender, + bootstrappingDB *prefixdb.Database, + bootstrapFunc func(), + vdrs validators.Manager, + connectedValidators tracker.Peers, + peerTracker *p2p.PeerTracker, + halter common.Halter) (*handler.Engine, error) { bootstrapWeight, err := beacons.TotalWeight(ctx.SubnetID) if err != nil { return nil, fmt.Errorf("error while fetching weight for subnet %s: %w", ctx.SubnetID, err) From 6168ee29dfb309bbff40318137a41b4db61dc597 Mon Sep 17 00:00:00 2001 From: samliok Date: Thu, 21 Aug 2025 14:58:30 -0400 Subject: [PATCH 4/6] go fmt --- chains/manager.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chains/manager.go b/chains/manager.go index ec7805469410..442bb41309a4 100644 --- a/chains/manager.go +++ b/chains/manager.go @@ -1447,7 +1447,8 @@ func (m *manager) createSnowmanVMs( primaryAlias string, genesisData []byte, messageSender common.Sender, - fxs []*common.Fx) (*block.ChangeNotifier, *proposervm.VM, error) { + fxs []*common.Fx, +) (*block.ChangeNotifier, *proposervm.VM, error) { // Initialize the ProposerVM and the vm wrapped inside it chainConfig, err := m.getChainConfig(ctx.ChainID) if err != nil { From 3d015d1032e62fbe94e22b8f2ab2734787a264ab Mon Sep 17 00:00:00 2001 From: samliok Date: Thu, 21 Aug 2025 15:21:44 -0400 Subject: [PATCH 5/6] go fmt --- chains/manager.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chains/manager.go b/chains/manager.go index 442bb41309a4..b1f57a3d69e7 100644 --- a/chains/manager.go +++ b/chains/manager.go @@ -1544,7 +1544,8 @@ func (m *manager) createSnowmanEngine( vdrs validators.Manager, connectedValidators tracker.Peers, peerTracker *p2p.PeerTracker, - halter common.Halter) (*handler.Engine, error) { + halter common.Halter, +) (*handler.Engine, error) { bootstrapWeight, err := beacons.TotalWeight(ctx.SubnetID) if err != nil { return nil, fmt.Errorf("error while fetching weight for subnet %s: %w", ctx.SubnetID, err) From cd8ad9bac2b3a11493d5eaa4c57bfe83e313d947 Mon Sep 17 00:00:00 2001 From: samliok Date: Fri, 22 Aug 2025 13:04:33 -0400 Subject: [PATCH 6/6] remove validators from sigs --- chains/manager.go | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/chains/manager.go b/chains/manager.go index 07f1e07dca60..2adaf0474617 100644 --- a/chains/manager.go +++ b/chains/manager.go @@ -569,7 +569,6 @@ func (m *manager) buildChain(chainParams ChainParameters, sb subnets.Subnet) (*c chain, err = m.createSnowmanChain( ctx, chainParams.GenesisData, - m.Validators, beacons, vm, chainFxs, @@ -1054,7 +1053,6 @@ func (m *manager) createAvalancheChain( func (m *manager) createSnowmanChain( ctx *snow.ConsensusContext, genesisData []byte, - vdrs validators.Manager, beacons validators.Manager, vm block.ChainVM, fxs []*common.Fx, @@ -1094,7 +1092,7 @@ func (m *manager) createSnowmanChain( if err != nil { return nil, fmt.Errorf("error creating connected validators: %w", err) } - vdrs.RegisterSetCallbackListener(ctx.SubnetID, connectedValidators) + m.Validators.RegisterSetCallbackListener(ctx.SubnetID, connectedValidators) peerTracker, err := m.createSnowmanPeerTracker(ctx, primaryAlias) if err != nil { @@ -1102,19 +1100,19 @@ func (m *manager) createSnowmanChain( } var halter common.Halter - h, err := m.createSnowmanHandler(ctx, cn, vdrs, sb, primaryAlias, connectedValidators, peerTracker, halter) + h, err := m.createSnowmanHandler(ctx, cn, sb, primaryAlias, connectedValidators, peerTracker, halter) if err != nil { return nil, fmt.Errorf("couldn't create snowman handler: %w", err) } - engine, err := m.createSnowmanEngine(ctx, cn, proposerVM.ParseBlock, sb, beacons, messageSender, bootstrappingDB, bootstrapFunc, vdrs, connectedValidators, peerTracker, halter) + engine, err := m.createSnowmanEngine(ctx, cn, proposerVM.ParseBlock, sb, beacons, messageSender, bootstrappingDB, bootstrapFunc, connectedValidators, peerTracker, halter) if err != nil { return nil, fmt.Errorf("couldn't create snowman engine: %w", err) } h.SetEngineManager(&handler.EngineManager{ - Avalanche: nil, - Snowman: engine, + DAG: nil, + Chain: engine, }) // Register health checks @@ -1285,7 +1283,7 @@ func (m *manager) getOrMakeVMGatherer(vmID ids.ID) (metrics.MultiGatherer, error return vmGatherer, nil } -func (m *manager) createSnowmanHandler(ctx *snow.ConsensusContext, vm *block.ChangeNotifier, vdrs validators.Manager, sb subnets.Subnet, primaryAlias string, connectedValidators tracker.Peers, peerTracker *p2p.PeerTracker, halter common.Halter) (handler.Handler, error) { +func (m *manager) createSnowmanHandler(ctx *snow.ConsensusContext, vm *block.ChangeNotifier, sb subnets.Subnet, primaryAlias string, connectedValidators tracker.Peers, peerTracker *p2p.PeerTracker, halter common.Halter) (handler.Handler, error) { handlerReg, err := metrics.MakeAndRegister( m.handlerGatherer, primaryAlias, @@ -1299,7 +1297,7 @@ func (m *manager) createSnowmanHandler(ctx *snow.ConsensusContext, vm *block.Cha ctx, vm, vm.WaitForEvent, - vdrs, + m.Validators, m.FrontierPollFrequency, m.ConsensusAppConcurrency, m.ResourceTracker, @@ -1541,7 +1539,6 @@ func (m *manager) createSnowmanEngine( messageSender common.Sender, bootstrappingDB *prefixdb.Database, bootstrapFunc func(), - vdrs validators.Manager, connectedValidators tracker.Peers, peerTracker *p2p.PeerTracker, halter common.Halter, @@ -1585,7 +1582,7 @@ func (m *manager) createSnowmanEngine( AllGetsServer: snowGetHandler, VM: vm, Sender: messageSender, - Validators: vdrs, + Validators: m.Validators, ConnectedValidators: connectedValidators, Params: consensusParams, Consensus: consensus,