diff --git a/api/admin/service.go b/api/admin/service.go index cf57a28264e7..933f79e688d9 100644 --- a/api/admin/service.go +++ b/api/admin/service.go @@ -15,7 +15,6 @@ import ( "github.com/ava-labs/avalanchego/api" "github.com/ava-labs/avalanchego/api/server" - "github.com/ava-labs/avalanchego/chains" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/constants" @@ -40,14 +39,14 @@ var ( ) type Config struct { - Log logging.Logger - ProfileDir string - LogFactory logging.Factory - NodeConfig interface{} - ChainManager chains.Manager - HTTPServer server.PathAdderWithReadLock - VMRegistry registry.VMRegistry - VMManager vms.Manager + Log logging.Logger + ProfileDir string + LogFactory logging.Factory + NodeConfig interface{} + Aliaser ids.Aliaser + HTTPServer server.PathAdderWithReadLock + VMRegistry registry.VMRegistry + VMManager vms.Manager } // Admin is the API service for node admin management @@ -165,7 +164,7 @@ func (a *Admin) AliasChain(_ *http.Request, args *AliasChainArgs, _ *api.EmptyRe if len(args.Alias) > maxAliasLength { return errAliasTooLong } - chainID, err := a.ChainManager.Lookup(args.Chain) + chainID, err := a.Aliaser.Lookup(args.Chain) if err != nil { return err } @@ -173,7 +172,7 @@ func (a *Admin) AliasChain(_ *http.Request, args *AliasChainArgs, _ *api.EmptyRe a.lock.Lock() defer a.lock.Unlock() - if err := a.ChainManager.Alias(chainID, args.Alias); err != nil { + if err := a.Aliaser.Alias(chainID, args.Alias); err != nil { return err } @@ -205,7 +204,7 @@ func (a *Admin) GetChainAliases(_ *http.Request, args *GetChainAliasesArgs, repl return err } - reply.Aliases, err = a.ChainManager.Aliases(id) + reply.Aliases, err = a.Aliaser.Aliases(id) return err } diff --git a/api/info/service.go b/api/info/service.go index 9bdf245569a5..71daa0539a10 100644 --- a/api/info/service.go +++ b/api/info/service.go @@ -40,7 +40,8 @@ type Info struct { validators validators.Manager myIP ips.DynamicIPPort networking network.Network - chainManager chains.Manager + aliaser ids.Aliaser + chainCreator *chains.Manager vmManager vms.Manager benchlist benchlist.Manager } @@ -66,7 +67,8 @@ func NewService( parameters Parameters, log logging.Logger, validators validators.Manager, - chainManager chains.Manager, + aliaser ids.Aliaser, + chainCreator *chains.Manager, vmManager vms.Manager, myIP ips.DynamicIPPort, network network.Network, @@ -81,7 +83,8 @@ func NewService( Parameters: parameters, log: log, validators: validators, - chainManager: chainManager, + aliaser: aliaser, + chainCreator: chainCreator, vmManager: vmManager, myIP: myIP, networking: network, @@ -203,7 +206,7 @@ func (i *Info) GetBlockchainID(_ *http.Request, args *GetBlockchainIDArgs, reply zap.String("method", "getBlockchainID"), ) - bID, err := i.chainManager.Lookup(args.Alias) + bID, err := i.aliaser.Lookup(args.Alias) reply.BlockchainID = bID return err } @@ -240,7 +243,7 @@ func (i *Info) Peers(_ *http.Request, args *PeersArgs, reply *PeersReply) error benchedIDs := i.benchlist.GetBenched(peer.ID) benchedAliases := make([]string, len(benchedIDs)) for idx, id := range benchedIDs { - alias, err := i.chainManager.PrimaryAlias(id) + alias, err := i.aliaser.PrimaryAlias(id) if err != nil { return fmt.Errorf("failed to get primary alias for chain ID %s: %w", id, err) } @@ -282,11 +285,11 @@ func (i *Info) IsBootstrapped(_ *http.Request, args *IsBootstrappedArgs, reply * if args.Chain == "" { return errNoChainProvided } - chainID, err := i.chainManager.Lookup(args.Chain) + chainID, err := i.aliaser.Lookup(args.Chain) if err != nil { return fmt.Errorf("there is no chain with alias/ID '%s'", args.Chain) } - reply.IsBootstrapped = i.chainManager.IsBootstrapped(chainID) + reply.IsBootstrapped = i.chainCreator.IsBootstrapped(chainID) return nil } diff --git a/api/ipcs/service.go b/api/ipcs/service.go index efe6f2e7280b..db8d392dbafa 100644 --- a/api/ipcs/service.go +++ b/api/ipcs/service.go @@ -12,7 +12,6 @@ import ( "go.uber.org/zap" "github.com/ava-labs/avalanchego/api" - "github.com/ava-labs/avalanchego/chains" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/ipcs" "github.com/ava-labs/avalanchego/utils/json" @@ -20,22 +19,22 @@ import ( ) type Service struct { - log logging.Logger - chainManager chains.Manager - lock sync.RWMutex - ipcs *ipcs.ChainIPCs + log logging.Logger + aliaser ids.Aliaser + lock sync.RWMutex + ipcs *ipcs.ChainIPCs } -func NewService(log logging.Logger, chainManager chains.Manager, ipcs *ipcs.ChainIPCs) (http.Handler, error) { +func NewService(log logging.Logger, aliaser ids.Aliaser, ipcs *ipcs.ChainIPCs) (http.Handler, error) { server := rpc.NewServer() codec := json.NewCodec() server.RegisterCodec(codec, "application/json") server.RegisterCodec(codec, "application/json;charset=UTF-8") return server, server.RegisterService( &Service{ - log: log, - chainManager: chainManager, - ipcs: ipcs, + log: log, + aliaser: aliaser, + ipcs: ipcs, }, "ipcs", ) @@ -59,7 +58,7 @@ func (s *Service) PublishBlockchain(_ *http.Request, args *PublishBlockchainArgs logging.UserString("blockchainID", args.BlockchainID), ) - chainID, err := s.chainManager.Lookup(args.BlockchainID) + chainID, err := s.aliaser.Lookup(args.BlockchainID) if err != nil { s.log.Error("chain lookup failed", logging.UserString("blockchainID", args.BlockchainID), @@ -98,7 +97,7 @@ func (s *Service) UnpublishBlockchain(_ *http.Request, args *UnpublishBlockchain logging.UserString("blockchainID", args.BlockchainID), ) - chainID, err := s.chainManager.Lookup(args.BlockchainID) + chainID, err := s.aliaser.Lookup(args.BlockchainID) if err != nil { s.log.Error("chain lookup failed", logging.UserString("blockchainID", args.BlockchainID), diff --git a/chains/manager.go b/chains/manager.go index 50b278361664..b0b5bd220717 100644 --- a/chains/manager.go +++ b/chains/manager.go @@ -12,7 +12,6 @@ import ( "os" "path/filepath" "sync" - "time" "github.com/prometheus/client_golang/prometheus" @@ -21,7 +20,6 @@ import ( "github.com/ava-labs/avalanchego/api/health" "github.com/ava-labs/avalanchego/api/keystore" "github.com/ava-labs/avalanchego/api/metrics" - "github.com/ava-labs/avalanchego/api/server" "github.com/ava-labs/avalanchego/chains/atomic" "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/database/meterdb" @@ -31,17 +29,26 @@ import ( "github.com/ava-labs/avalanchego/network" "github.com/ava-labs/avalanchego/proto/pb/p2p" "github.com/ava-labs/avalanchego/snow" + smcon "github.com/ava-labs/avalanchego/snow/consensus/snowman" + aveng "github.com/ava-labs/avalanchego/snow/engine/avalanche" + avbootstrap "github.com/ava-labs/avalanchego/snow/engine/avalanche/bootstrap" + avagetter "github.com/ava-labs/avalanchego/snow/engine/avalanche/getter" "github.com/ava-labs/avalanchego/snow/engine/avalanche/state" "github.com/ava-labs/avalanchego/snow/engine/avalanche/vertex" "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/engine/common/queue" "github.com/ava-labs/avalanchego/snow/engine/common/tracker" + smeng "github.com/ava-labs/avalanchego/snow/engine/snowman" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" + smbootstrap "github.com/ava-labs/avalanchego/snow/engine/snowman/bootstrap" + snowgetter "github.com/ava-labs/avalanchego/snow/engine/snowman/getter" "github.com/ava-labs/avalanchego/snow/engine/snowman/syncer" "github.com/ava-labs/avalanchego/snow/networking/handler" "github.com/ava-labs/avalanchego/snow/networking/router" "github.com/ava-labs/avalanchego/snow/networking/sender" "github.com/ava-labs/avalanchego/snow/networking/timeout" + timetracker "github.com/ava-labs/avalanchego/snow/networking/tracker" + "github.com/ava-labs/avalanchego/snow/uptime" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/staking" "github.com/ava-labs/avalanchego/subnets" @@ -58,22 +65,14 @@ import ( "github.com/ava-labs/avalanchego/vms/fx" "github.com/ava-labs/avalanchego/vms/metervm" "github.com/ava-labs/avalanchego/vms/nftfx" + "github.com/ava-labs/avalanchego/vms/platformvm" + "github.com/ava-labs/avalanchego/vms/platformvm/chaincreator" + "github.com/ava-labs/avalanchego/vms/platformvm/config" "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/avalanchego/vms/propertyfx" "github.com/ava-labs/avalanchego/vms/proposervm" "github.com/ava-labs/avalanchego/vms/secp256k1fx" "github.com/ava-labs/avalanchego/vms/tracedvm" - - timetracker "github.com/ava-labs/avalanchego/snow/networking/tracker" - - aveng "github.com/ava-labs/avalanchego/snow/engine/avalanche" - avbootstrap "github.com/ava-labs/avalanchego/snow/engine/avalanche/bootstrap" - avagetter "github.com/ava-labs/avalanchego/snow/engine/avalanche/getter" - - smcon "github.com/ava-labs/avalanchego/snow/consensus/snowman" - smeng "github.com/ava-labs/avalanchego/snow/engine/snowman" - smbootstrap "github.com/ava-labs/avalanchego/snow/engine/snowman/bootstrap" - snowgetter "github.com/ava-labs/avalanchego/snow/engine/snowman/getter" ) const ( @@ -106,46 +105,11 @@ var ( propertyfx.ID: &propertyfx.Factory{}, } - _ Manager = (*manager)(nil) + _ chaincreator.Interface = (*Manager)(nil) ) -// Manager manages the chains running on this node. -// It can: -// - Create a chain -// - Add a registrant. When a chain is created, each registrant calls -// RegisterChain with the new chain as the argument. -// - Manage the aliases of chains -type Manager interface { - ids.Aliaser - - // Queues a chain to be created in the future after chain creator is unblocked. - // This is only called from the P-chain thread to create other chains - // Queued chains are created only after P-chain is bootstrapped. - // This assumes only chains in tracked subnets are queued. - QueueChainCreation(ChainParameters) - - // Add a registrant [r]. Every time a chain is - // created, [r].RegisterChain([new chain]) is called. - AddRegistrant(Registrant) - - // Given an alias, return the ID of the chain associated with that alias - Lookup(string) (ids.ID, error) - - // Given an alias, return the ID of the VM associated with that alias - LookupVM(string) (ids.ID, error) - - // Returns true iff the chain with the given ID exists and is finished bootstrapping - IsBootstrapped(ids.ID) bool - - // Starts the chain creator with the initial platform chain parameters, must - // be called once. - StartChainCreator(platformChain ChainParameters) error - - Shutdown() -} - -// ChainParameters defines the chain being created -type ChainParameters struct { +// chainParameters defines the chain being created +type chainParameters struct { // The ID of the chain being created. ID ids.ID // ID of the subnet that validates this chain. @@ -154,6 +118,8 @@ type ChainParameters struct { GenesisData []byte // The ID of the vm this chain is running. VMID ids.ID + // VMFactory creates an instance of the VM + VMFactory vms.Factory // The IDs of the feature extensions this chain is running. FxIDs []ids.ID // Invariant: Only used when [ID] is the P-chain ID. @@ -176,71 +142,42 @@ type ChainConfig struct { Upgrade []byte } -type ManagerConfig struct { - SybilProtectionEnabled bool - StakingTLSCert tls.Certificate // needed to sign snowman++ blocks - StakingBLSKey *bls.SecretKey - TracingEnabled bool +type Manager struct { + config.Config + vmFactory *platformvm.Factory + genesis []byte + aliaser ids.Aliaser + stakingBLSKey *bls.SecretKey // Must not be used unless [TracingEnabled] is true as this may be nil. - Tracer trace.Tracer - Log logging.Logger - LogFactory logging.Factory - VMManager vms.Manager // Manage mappings from vm ID --> vm - BlockAcceptorGroup snow.AcceptorGroup - TxAcceptorGroup snow.AcceptorGroup - VertexAcceptorGroup snow.AcceptorGroup - DB database.Database - MsgCreator message.OutboundMsgBuilder // message creator, shared with network - Router router.Router // Routes incoming messages to the appropriate chain - Net network.Network // Sends consensus messages to other validators - Validators validators.Manager // Validators validating on this chain - NodeID ids.NodeID // The ID of this node - NetworkID uint32 // ID of the network this node is connected to - PartialSyncPrimaryNetwork bool - Server server.Server // Handles HTTP API calls - Keystore keystore.Keystore - AtomicMemory *atomic.Memory - AVAXAssetID ids.ID - XChainID ids.ID // ID of the X-Chain, - CChainID ids.ID // ID of the C-Chain, - CriticalChains set.Set[ids.ID] // Chains that can't exit gracefully - TimeoutManager timeout.Manager // Manages request timeouts when sending messages to other validators - Health health.Registerer - SubnetConfigs map[ids.ID]subnets.Config // ID -> SubnetConfig - ChainConfigs map[string]ChainConfig // alias -> ChainConfig - // ShutdownNodeFunc allows the chain manager to issue a request to shutdown the node - ShutdownNodeFunc func(exitCode int) - MeterVMEnabled bool // Should each VM be wrapped with a MeterVM - Metrics metrics.MultiGatherer - - FrontierPollFrequency time.Duration - ConsensusAppConcurrency int - - // Max Time to spend fetching a container and its - // ancestors when responding to a GetAncestors - BootstrapMaxTimeGetAncestors time.Duration - // Max number of containers in an ancestors message sent by this node. - BootstrapAncestorsMaxContainersSent int - // This node will only consider the first [AncestorsMaxContainersReceived] - // containers in an ancestors message it receives. - BootstrapAncestorsMaxContainersReceived int - - ApricotPhase4Time time.Time - ApricotPhase4MinPChainHeight uint64 + tracer trace.Tracer + log logging.Logger + logFactory logging.Factory + vmManager vms.Manager // Manage mappings from vm ID --> vm + blockAcceptorGroup snow.AcceptorGroup + txAcceptorGroup snow.AcceptorGroup + vertexAcceptorGroup snow.AcceptorGroup + db database.Database + msgCreator message.OutboundMsgBuilder // message creator, shared with network + router router.Router // Routes incoming messages to the appropriate chain + net network.Network // Sends consensus messages to other validators + bootstrappers validators.Manager + validators validators.Manager // Validators validating on this chain + nodeID ids.NodeID // The ID of this node + keystore keystore.Keystore + atomicMemory *atomic.Memory + xChainID ids.ID // ID of the X-Chain, + cChainID ids.ID // ID of the C-Chain, + criticalChains set.Set[ids.ID] // Chains that can't exit gracefully + timeoutManager timeout.Manager // Manages request timeouts when sending messages to other validators + health health.Registerer + subnetConfigs map[ids.ID]subnets.Config // ID -> SubnetConfig + chainConfigs map[string]ChainConfig // alias -> ChainConfig + // ShutdownNodeFunc allows the Manager to issue a request to shutdown the node + shutdownNodeFunc func(exitCode int) + metrics metrics.MultiGatherer // Tracks CPU/disk usage caused by each peer. - ResourceTracker timetracker.ResourceTracker - - StateSyncBeacons []ids.NodeID - - ChainDataDir string -} - -type manager struct { - // Note: The string representation of a chain's ID is also considered to be an alias of the chain - // That is, [chainID].String() is an alias for the chain, too - ids.Aliaser - ManagerConfig + resourceTracker timetracker.ResourceTracker stakingSigner crypto.Signer stakingCert *staking.Certificate @@ -249,7 +186,7 @@ type manager struct { registrants []Registrant // queue that holds chain create requests - chainsQueue buffer.BlockingDeque[ChainParameters] + chainsQueue buffer.BlockingDeque[chainParameters] // unblocks chain creator to start processing the queue unblockChainCreatorCh chan struct{} // shutdown the chain creator goroutine if the queue hasn't started to be @@ -267,69 +204,171 @@ type manager struct { // Value: The chain chains map[ids.ID]handler.Handler + // TODO refactor // snowman++ related interface to allow validators retrieval validatorState validators.State } // New returns a new Manager -func New(config *ManagerConfig) Manager { - return &manager{ - Aliaser: ids.NewAliaser(), - ManagerConfig: *config, - stakingSigner: config.StakingTLSCert.PrivateKey.(crypto.Signer), - stakingCert: staking.CertificateFromX509(config.StakingTLSCert.Leaf), - subnets: make(map[ids.ID]subnets.Subnet), - chains: make(map[ids.ID]handler.Handler), - chainsQueue: buffer.NewUnboundedBlockingDeque[ChainParameters](initialQueueSize), +func NewManager( + config config.Config, + genesis []byte, + aliaser ids.Aliaser, + tlsCertificate tls.Certificate, + blsKey *bls.SecretKey, + tracer trace.Tracer, + log logging.Logger, + logFactory logging.Factory, + vmManager vms.Manager, + blockAcceptorGroup snow.AcceptorGroup, + txAcceptorGroup snow.AcceptorGroup, + vertexAcceptorGroup snow.AcceptorGroup, + db database.Database, + msgCreator message.OutboundMsgBuilder, + router router.Router, + net network.Network, + bootstrappers validators.Manager, + validators validators.Manager, + nodeID ids.NodeID, + keystore keystore.Keystore, + atomicMemory *atomic.Memory, + xChainID ids.ID, + cChainID ids.ID, + criticalChains set.Set[ids.ID], + timeoutManager timeout.Manager, + health health.Registerer, + subnetConfigs map[ids.ID]subnets.Config, + chainConfigs map[string]ChainConfig, + shutdownNodeFunc func(exitCode int), + metrics metrics.MultiGatherer, + resourceTracker timetracker.ResourceTracker, + calculator uptime.LockedCalculator, +) *Manager { + c := &Manager{ + Config: config, + vmFactory: nil, + genesis: genesis, + aliaser: aliaser, + stakingBLSKey: blsKey, + tracer: tracer, + log: log, + logFactory: logFactory, + vmManager: vmManager, + blockAcceptorGroup: blockAcceptorGroup, + txAcceptorGroup: txAcceptorGroup, + vertexAcceptorGroup: vertexAcceptorGroup, + db: db, + msgCreator: msgCreator, + router: router, + net: net, + bootstrappers: bootstrappers, + validators: validators, + nodeID: nodeID, + keystore: keystore, + atomicMemory: atomicMemory, + xChainID: xChainID, + cChainID: cChainID, + criticalChains: criticalChains, + timeoutManager: timeoutManager, + health: health, + subnetConfigs: subnetConfigs, + chainConfigs: chainConfigs, + shutdownNodeFunc: shutdownNodeFunc, + metrics: metrics, + resourceTracker: resourceTracker, + stakingSigner: tlsCertificate.PrivateKey.(crypto.Signer), + stakingCert: staking.CertificateFromX509(tlsCertificate.Leaf), + chainsQueue: buffer.NewUnboundedBlockingDeque[chainParameters](initialQueueSize), unblockChainCreatorCh: make(chan struct{}), chainCreatorShutdownCh: make(chan struct{}), + chainCreatorExited: sync.WaitGroup{}, + subnetsLock: sync.RWMutex{}, + subnets: make(map[ids.ID]subnets.Subnet), + chainsLock: sync.Mutex{}, + chains: make(map[ids.ID]handler.Handler), + validatorState: nil, } + + c.vmFactory = platformvm.NewFactory( + config, + c, + aliaser, + validators, + calculator, + ) + + return c } -// QueueChainCreation queues a chain creation request -// Invariant: Tracked Subnet must be checked before calling this function -func (m *manager) QueueChainCreation(chainParams ChainParameters) { +// Create the blockchain if this node is a member of the subnet that validates +// the chain +// +// TODO verify Note: it is expected for the subnet to already have the chain registered as +// bootstrapping before this function is called +func (m *Manager) CreateChain(chainID ids.ID, subnetID ids.ID, genesis []byte, vmID ids.ID, fxs []ids.ID) error { + if m.SybilProtectionEnabled && // Sybil protection is enabled, so nodes might not validate all chains + constants.PrimaryNetworkID != subnetID && // All nodes must validate the primary network + !m.TrackedSubnets.Contains(subnetID) { // This node doesn't validate this blockchain + return nil + } + + // Get a vmFactory for the m we want to use on our chain + vmFactory, err := m.vmManager.GetFactory(vmID) + if err != nil { + // TODO should this fatal? + return fmt.Errorf("error while getting vmFactory: %w", err) + } + m.subnetsLock.Lock() - subnetID := chainParams.SubnetID sb, exists := m.subnets[subnetID] if !exists { - sbConfig, ok := m.SubnetConfigs[subnetID] + sbConfig, ok := m.subnetConfigs[subnetID] if !ok { // default to primary subnet config - sbConfig = m.SubnetConfigs[constants.PrimaryNetworkID] + sbConfig = m.subnetConfigs[constants.PrimaryNetworkID] } - sb = subnets.New(m.NodeID, sbConfig) - m.subnets[chainParams.SubnetID] = sb + sb = subnets.New(m.nodeID, sbConfig) + m.subnets[subnetID] = sb } - addedChain := sb.AddChain(chainParams.ID) + addedChain := sb.AddChain(chainID) m.subnetsLock.Unlock() if !addedChain { - m.Log.Debug("skipping chain creation", + m.log.Debug("skipping chain creation", zap.String("reason", "chain already staged"), zap.Stringer("subnetID", subnetID), - zap.Stringer("chainID", chainParams.ID), - zap.Stringer("vmID", chainParams.VMID), + zap.Stringer("chainID", chainID), + zap.Stringer("vmID", vmID), ) - return + return nil } - if ok := m.chainsQueue.PushRight(chainParams); !ok { - m.Log.Warn("skipping chain creation", + if ok := m.chainsQueue.PushRight(chainParameters{ + ID: chainID, + SubnetID: subnetID, + GenesisData: genesis, + VMID: vmID, + VMFactory: vmFactory, + FxIDs: fxs, + //TODO custom beacons case + }); !ok { + m.log.Warn("skipping chain creation", zap.String("reason", "couldn't enqueue chain"), zap.Stringer("subnetID", subnetID), - zap.Stringer("chainID", chainParams.ID), - zap.Stringer("vmID", chainParams.VMID), + zap.Stringer("chainID", chainID), + zap.Stringer("vmID", vmID), ) } + + return nil } // createChain creates and starts the chain // // Note: it is expected for the subnet to already have the chain registered as // bootstrapping before this function is called -func (m *manager) createChain(chainParams ChainParameters) { - m.Log.Info("creating chain", +func (m *Manager) createChain(chainParams chainParameters) error { + m.log.Info("creating chain", zap.Stringer("subnetID", chainParams.SubnetID), zap.Stringer("chainID", chainParams.ID), zap.Stringer("vmID", chainParams.VMID), @@ -342,24 +381,25 @@ func (m *manager) createChain(chainParams ChainParameters) { // Note: buildChain builds all chain's relevant objects (notably engine and handler) // but does not start their operations. Starting of the handler (which could potentially // issue some internal messages), is delayed until chain dispatching is started and - // the chain is registered in the manager. This ensures that no message generated by handler + // the chain is registered in the ChainManager. This ensures that no message generated by handler // upon start is dropped. chain, err := m.buildChain(chainParams, sb) if err != nil { - if m.CriticalChains.Contains(chainParams.ID) { + if m.criticalChains.Contains(chainParams.ID) { // Shut down if we fail to create a required chain (i.e. X, P or C) - m.Log.Fatal("error creating required chain", + m.log.Fatal("error creating required chain", zap.Stringer("subnetID", chainParams.SubnetID), zap.Stringer("chainID", chainParams.ID), zap.Stringer("vmID", chainParams.VMID), zap.Error(err), ) - go m.ShutdownNodeFunc(1) - return + //TODO handle shutdown case in the caller of vmFactory.New() + go m.shutdownNodeFunc(1) + return fmt.Errorf("error creating required chain: %w", err) } - chainAlias := m.PrimaryAliasOrDefault(chainParams.ID) - m.Log.Error("error creating chain", + chainAlias := m.aliaser.PrimaryAliasOrDefault(chainParams.ID) + m.log.Error("error creating chain", zap.Stringer("subnetID", chainParams.SubnetID), zap.Stringer("chainID", chainParams.ID), zap.String("chainAlias", chainAlias), @@ -372,7 +412,7 @@ func (m *manager) createChain(chainParams ChainParameters) { // node may not be properly validating the subnet they expect to be // validating. healthCheckErr := fmt.Errorf("failed to create chain on subnet %s: %w", chainParams.SubnetID, err) - err := m.Health.RegisterHealthCheck( + err := m.health.RegisterHealthCheck( chainAlias, health.CheckerFunc(func(context.Context) (interface{}, error) { return nil, healthCheckErr @@ -380,15 +420,15 @@ func (m *manager) createChain(chainParams ChainParameters) { chainParams.SubnetID.String(), ) if err != nil { - m.Log.Error("failed to register failing health check", + m.log.Error("failed to register failing health check", zap.Stringer("subnetID", chainParams.SubnetID), zap.Stringer("chainID", chainParams.ID), zap.String("chainAlias", chainAlias), zap.Stringer("vmID", chainParams.VMID), zap.Error(err), ) + return err } - return } m.chainsLock.Lock() @@ -396,8 +436,8 @@ func (m *manager) createChain(chainParams ChainParameters) { m.chainsLock.Unlock() // Associate the newly created chain with its default alias - if err := m.Alias(chainParams.ID, chainParams.ID.String()); err != nil { - m.Log.Error("failed to alias the new chain with itself", + if err := m.aliaser.Alias(chainParams.ID, chainParams.ID.String()); err != nil { + m.log.Error("failed to alias the new chain with itself", zap.Stringer("subnetID", chainParams.SubnetID), zap.Stringer("chainID", chainParams.ID), zap.Stringer("vmID", chainParams.VMID), @@ -411,14 +451,14 @@ func (m *manager) createChain(chainParams ChainParameters) { // Allows messages to be routed to the new chain. If the handler hasn't been // started and a message is forwarded, then the message will block until the // handler is started. - m.ManagerConfig.Router.AddChain(context.TODO(), chain.Handler) + m.router.AddChain(context.TODO(), chain.Handler) // Register bootstrapped health checks after P chain has been added to // chains. // // Note: Registering this after the chain has been tracked prevents a race // condition between the health check and adding the first chain to - // the manager. + // the ChainManager. if chainParams.ID == constants.PlatformChainID { if err := m.registerBootstrappedHealthChecks(); err != nil { chain.Handler.StopWithError(context.TODO(), err) @@ -427,15 +467,16 @@ func (m *manager) createChain(chainParams ChainParameters) { // Tell the chain to start processing messages. // If the X, P, or C Chain panics, do not attempt to recover - chain.Handler.Start(context.TODO(), !m.CriticalChains.Contains(chainParams.ID)) + chain.Handler.Start(context.TODO(), !m.criticalChains.Contains(chainParams.ID)) + return nil } // Create a chain -func (m *manager) buildChain(chainParams ChainParameters, sb subnets.Subnet) (*chain, error) { +func (m *Manager) buildChain(chainParams chainParameters, sb subnets.Subnet) (*chain, error) { if chainParams.ID != constants.PlatformChainID && chainParams.VMID == constants.PlatformVMID { return nil, errCreatePlatformVM } - primaryAlias := m.PrimaryAliasOrDefault(chainParams.ID) + primaryAlias := m.aliaser.PrimaryAliasOrDefault(chainParams.ID) // Create this chain's data directory chainDataDir := filepath.Join(m.ChainDataDir, chainParams.ID.String()) @@ -444,14 +485,14 @@ func (m *manager) buildChain(chainParams ChainParameters, sb subnets.Subnet) (*c } // Create the log and context of the chain - chainLog, err := m.LogFactory.MakeChain(primaryAlias) + chainLog, err := m.logFactory.MakeChain(primaryAlias) if err != nil { return nil, fmt.Errorf("error while creating chain's log %w", err) } consensusMetrics := prometheus.NewRegistry() chainNamespace := metric.AppendNamespace(constants.PlatformName, primaryAlias) - if err := m.Metrics.Register(chainNamespace, consensusMetrics); err != nil { + if err := m.metrics.Register(chainNamespace, consensusMetrics); err != nil { return nil, fmt.Errorf("error while registering chain's metrics %w", err) } @@ -460,13 +501,13 @@ func (m *manager) buildChain(chainParams ChainParameters, sb subnets.Subnet) (*c // there are no conflicts when registering the Snowman consensus metrics. avalancheConsensusMetrics := prometheus.NewRegistry() avalancheDAGNamespace := metric.AppendNamespace(chainNamespace, "avalanche") - if err := m.Metrics.Register(avalancheDAGNamespace, avalancheConsensusMetrics); err != nil { + if err := m.metrics.Register(avalancheDAGNamespace, avalancheConsensusMetrics); err != nil { return nil, fmt.Errorf("error while registering DAG metrics %w", err) } vmMetrics := metrics.NewOptionalGatherer() vmNamespace := metric.AppendNamespace(chainNamespace, "vm") - if err := m.Metrics.Register(vmNamespace, vmMetrics); err != nil { + if err := m.metrics.Register(vmNamespace, vmMetrics); err != nil { return nil, fmt.Errorf("error while registering vm's metrics %w", err) } @@ -475,41 +516,35 @@ func (m *manager) buildChain(chainParams ChainParameters, sb subnets.Subnet) (*c NetworkID: m.NetworkID, SubnetID: chainParams.SubnetID, ChainID: chainParams.ID, - NodeID: m.NodeID, - PublicKey: bls.PublicFromSecretKey(m.StakingBLSKey), + NodeID: m.nodeID, + PublicKey: bls.PublicFromSecretKey(m.stakingBLSKey), - XChainID: m.XChainID, - CChainID: m.CChainID, + XChainID: m.xChainID, + CChainID: m.cChainID, AVAXAssetID: m.AVAXAssetID, Log: chainLog, - Keystore: m.Keystore.NewBlockchainKeyStore(chainParams.ID), - SharedMemory: m.AtomicMemory.NewSharedMemory(chainParams.ID), - BCLookup: m, + Keystore: m.keystore.NewBlockchainKeyStore(chainParams.ID), + SharedMemory: m.atomicMemory.NewSharedMemory(chainParams.ID), + BCLookup: m.aliaser, Metrics: vmMetrics, - WarpSigner: warp.NewSigner(m.StakingBLSKey, m.NetworkID, chainParams.ID), + WarpSigner: warp.NewSigner(m.stakingBLSKey, m.NetworkID, chainParams.ID), ValidatorState: m.validatorState, ChainDataDir: chainDataDir, }, - BlockAcceptor: m.BlockAcceptorGroup, - TxAcceptor: m.TxAcceptorGroup, - VertexAcceptor: m.VertexAcceptorGroup, + BlockAcceptor: m.blockAcceptorGroup, + TxAcceptor: m.txAcceptorGroup, + VertexAcceptor: m.vertexAcceptorGroup, Registerer: consensusMetrics, AvalancheRegisterer: avalancheConsensusMetrics, } - // Get a factory for the vm we want to use on our chain - vmFactory, err := m.VMManager.GetFactory(chainParams.VMID) - if err != nil { - return nil, fmt.Errorf("error while getting vmFactory: %w", err) - } - // Create the chain - vm, err := vmFactory.New(chainLog) + vm, err := chainParams.VMFactory.New(chainLog) if err != nil { - return nil, fmt.Errorf("error while creating vm: %w", err) + return nil, fmt.Errorf("error while creating m: %w", err) } // TODO: Shutdown VM if an error occurs @@ -532,50 +567,50 @@ func (m *manager) buildChain(chainParams ChainParameters, sb subnets.Subnet) (*c chain, err = m.createAvalancheChain( ctx, chainParams.GenesisData, - m.Validators, + m.validators, vm, chainFxs, sb, ) if err != nil { - return nil, fmt.Errorf("error while creating new avalanche vm %w", err) + return nil, fmt.Errorf("error while creating new avalanche m %w", err) } case block.ChainVM: - beacons := m.Validators + beacons := m.validators if chainParams.ID == constants.PlatformChainID { - beacons = chainParams.CustomBeacons + beacons = m.bootstrappers } chain, err = m.createSnowmanChain( ctx, chainParams.GenesisData, - m.Validators, + m.validators, beacons, vm, chainFxs, sb, ) if err != nil { - return nil, fmt.Errorf("error while creating new snowman vm %w", err) + return nil, fmt.Errorf("error while creating new snowman m %w", err) } default: return nil, errUnknownVMType } - // Register the chain with the timeout manager - if err := m.TimeoutManager.RegisterChain(ctx); err != nil { + // Register the chain with the timeout ChainManager + if err := m.timeoutManager.RegisterChain(ctx); err != nil { return nil, err } return chain, nil } -func (m *manager) AddRegistrant(r Registrant) { +func (m *Manager) AddRegistrant(r Registrant) { m.registrants = append(m.registrants, r) } // Create a DAG-based blockchain that uses Avalanche -func (m *manager) createAvalancheChain( +func (m *Manager) createAvalancheChain( ctx *snow.ConsensusContext, genesisData []byte, vdrs validators.Manager, @@ -591,7 +626,7 @@ func (m *manager) createAvalancheChain( State: snow.Initializing, }) - meterDB, err := meterdb.New("db", ctx.Registerer, m.DB) + meterDB, err := meterdb.New("db", ctx.Registerer, m.db) if err != nil { return nil, err } @@ -618,10 +653,10 @@ func (m *manager) createAvalancheChain( // Passes messages from the avalanche engines to the network avalancheMessageSender, err := sender.New( ctx, - m.MsgCreator, - m.Net, - m.ManagerConfig.Router, - m.TimeoutManager, + m.msgCreator, + m.net, + m.router, + m.timeoutManager, p2p.EngineType_ENGINE_TYPE_AVALANCHE, sb, ) @@ -630,10 +665,10 @@ func (m *manager) createAvalancheChain( } if m.TracingEnabled { - avalancheMessageSender = sender.Trace(avalancheMessageSender, m.Tracer) + avalancheMessageSender = sender.Trace(avalancheMessageSender, m.tracer) } - err = m.VertexAcceptorGroup.RegisterAcceptor( + err = m.vertexAcceptorGroup.RegisterAcceptor( ctx.ChainID, "gossip", avalancheMessageSender, @@ -646,10 +681,10 @@ func (m *manager) createAvalancheChain( // Passes messages from the snowman engines to the network snowmanMessageSender, err := sender.New( ctx, - m.MsgCreator, - m.Net, - m.ManagerConfig.Router, - m.TimeoutManager, + m.msgCreator, + m.net, + m.router, + m.timeoutManager, p2p.EngineType_ENGINE_TYPE_SNOWMAN, sb, ) @@ -658,10 +693,10 @@ func (m *manager) createAvalancheChain( } if m.TracingEnabled { - snowmanMessageSender = sender.Trace(snowmanMessageSender, m.Tracer) + snowmanMessageSender = sender.Trace(snowmanMessageSender, m.tracer) } - err = m.BlockAcceptorGroup.RegisterAcceptor( + err = m.blockAcceptorGroup.RegisterAcceptor( ctx.ChainID, "gossip", snowmanMessageSender, @@ -681,7 +716,7 @@ func (m *manager) createAvalancheChain( dagVM = metervm.NewVertexVM(dagVM) } if m.TracingEnabled { - dagVM = tracedvm.NewVertexVM(dagVM, m.Tracer) + dagVM = tracedvm.NewVertexVM(dagVM, m.tracer) } // Handles serialization/deserialization of vertices and also the @@ -732,33 +767,33 @@ func (m *manager) createAvalancheChain( snowmanMessageSender, ) if err != nil { - return nil, fmt.Errorf("error during vm's Initialize: %w", err) + return nil, fmt.Errorf("error during m's Initialize: %w", err) } - // Initialize the ProposerVM and the vm wrapped inside it + // Initialize the ProposerVM and the m wrapped inside it var ( minBlockDelay = proposervm.DefaultMinBlockDelay numHistoricalBlocks = proposervm.DefaultNumHistoricalBlocks ) - if subnetCfg, ok := m.SubnetConfigs[ctx.SubnetID]; ok { + if subnetCfg, ok := m.subnetConfigs[ctx.SubnetID]; ok { minBlockDelay = subnetCfg.ProposerMinBlockDelay numHistoricalBlocks = subnetCfg.ProposerNumHistoricalBlocks } - m.Log.Info("creating proposervm wrapper", + m.log.Info("creating proposervm wrapper", zap.Time("activationTime", m.ApricotPhase4Time), zap.Uint64("minPChainHeight", m.ApricotPhase4MinPChainHeight), zap.Duration("minBlockDelay", minBlockDelay), zap.Uint64("numHistoricalBlocks", numHistoricalBlocks), ) - chainAlias := m.PrimaryAliasOrDefault(ctx.ChainID) + chainAlias := m.aliaser.PrimaryAliasOrDefault(ctx.ChainID) - // Note: this does not use [dagVM] to ensure we use the [vm]'s height index. + // Note: this does not use [dagVM] to ensure we use the [m]'s height index. untracedVMWrappedInsideProposerVM := NewLinearizeOnInitializeVM(vm) var vmWrappedInsideProposerVM block.ChainVM = untracedVMWrappedInsideProposerVM if m.TracingEnabled { - vmWrappedInsideProposerVM = tracedvm.NewBlockVM(vmWrappedInsideProposerVM, chainAlias, m.Tracer) + vmWrappedInsideProposerVM = tracedvm.NewBlockVM(vmWrappedInsideProposerVM, chainAlias, m.tracer) } // Note: vmWrappingProposerVM is the VM that the Snowman engines should be @@ -780,7 +815,7 @@ func (m *manager) createAvalancheChain( vmWrappingProposerVM = metervm.NewBlockVM(vmWrappingProposerVM) } if m.TracingEnabled { - vmWrappingProposerVM = tracedvm.NewBlockVM(vmWrappingProposerVM, "proposervm", m.Tracer) + vmWrappingProposerVM = tracedvm.NewBlockVM(vmWrappingProposerVM, "proposervm", m.tracer) } // Note: linearizableVM is the VM that the Avalanche engines should be @@ -825,7 +860,7 @@ func (m *manager) createAvalancheChain( msgChan, m.FrontierPollFrequency, m.ConsensusAppConcurrency, - m.ResourceTracker, + m.resourceTracker, validators.UnhandledSubnetConnector, // avalanche chains don't use subnet connector sb, connectedValidators, @@ -852,7 +887,7 @@ func (m *manager) createAvalancheChain( var snowmanConsensus smcon.Consensus = &smcon.Topological{} if m.TracingEnabled { - snowmanConsensus = smcon.Trace(snowmanConsensus, m.Tracer) + snowmanConsensus = smcon.Trace(snowmanConsensus, m.tracer) } // Create engine, bootstrapper and state-syncer in this order, @@ -873,10 +908,10 @@ func (m *manager) createAvalancheChain( } if m.TracingEnabled { - snowmanEngine = smeng.TraceEngine(snowmanEngine, m.Tracer) + snowmanEngine = smeng.TraceEngine(snowmanEngine, m.tracer) } - // create bootstrap gear + // create smbootstrap gear bootstrapCfg := smbootstrap.Config{ AllGetsServer: snowGetHandler, Ctx: ctx, @@ -900,7 +935,7 @@ func (m *manager) createAvalancheChain( } if m.TracingEnabled { - snowmanBootstrapper = common.TraceBootstrapableEngine(snowmanBootstrapper, m.Tracer) + snowmanBootstrapper = common.TraceBootstrapableEngine(snowmanBootstrapper, m.tracer) } avaGetHandler, err := avagetter.New( @@ -918,10 +953,10 @@ func (m *manager) createAvalancheChain( // create engine gear avalancheEngine := aveng.New(ctx, avaGetHandler, linearizableVM) if m.TracingEnabled { - avalancheEngine = common.TraceEngine(avalancheEngine, m.Tracer) + avalancheEngine = common.TraceEngine(avalancheEngine, m.tracer) } - // create bootstrap gear + // create smbootstrap gear avalancheBootstrapperConfig := avbootstrap.Config{ AllGetsServer: avaGetHandler, Ctx: ctx, @@ -934,7 +969,7 @@ func (m *manager) createAvalancheChain( Manager: vtxManager, VM: linearizableVM, } - if ctx.ChainID == m.XChainID { + if ctx.ChainID == m.xChainID { avalancheBootstrapperConfig.StopVertexID = version.CortinaXChainStopVertexID[ctx.NetworkID] } @@ -947,7 +982,7 @@ func (m *manager) createAvalancheChain( } if m.TracingEnabled { - avalancheBootstrapper = common.TraceBootstrapableEngine(avalancheBootstrapper, m.Tracer) + avalancheBootstrapper = common.TraceBootstrapableEngine(avalancheBootstrapper, m.tracer) } h.SetEngineManager(&handler.EngineManager{ @@ -964,7 +999,7 @@ func (m *manager) createAvalancheChain( }) // Register health check for this chain - if err := m.Health.RegisterHealthCheck(chainAlias, h, ctx.SubnetID.String()); err != nil { + if err := m.health.RegisterHealthCheck(chainAlias, h, ctx.SubnetID.String()); err != nil { return nil, fmt.Errorf("couldn't add health check for chain %s: %w", chainAlias, err) } @@ -977,7 +1012,7 @@ func (m *manager) createAvalancheChain( } // Create a linear chain using the Snowman consensus engine -func (m *manager) createSnowmanChain( +func (m *Manager) createSnowmanChain( ctx *snow.ConsensusContext, genesisData []byte, vdrs validators.Manager, @@ -994,7 +1029,7 @@ func (m *manager) createSnowmanChain( State: snow.Initializing, }) - meterDB, err := meterdb.New("db", ctx.Registerer, m.DB) + meterDB, err := meterdb.New("db", ctx.Registerer, m.db) if err != nil { return nil, err } @@ -1010,10 +1045,10 @@ func (m *manager) createSnowmanChain( // Passes messages from the consensus engine to the network messageSender, err := sender.New( ctx, - m.MsgCreator, - m.Net, - m.ManagerConfig.Router, - m.TimeoutManager, + m.msgCreator, + m.net, + m.router, + m.timeoutManager, p2p.EngineType_ENGINE_TYPE_SNOWMAN, sb, ) @@ -1022,10 +1057,10 @@ func (m *manager) createSnowmanChain( } if m.TracingEnabled { - messageSender = sender.Trace(messageSender, m.Tracer) + messageSender = sender.Trace(messageSender, m.tracer) } - err = m.BlockAcceptorGroup.RegisterAcceptor( + err = m.blockAcceptorGroup.RegisterAcceptor( ctx.ChainID, "gossip", messageSender, @@ -1045,11 +1080,11 @@ func (m *manager) createSnowmanChain( if m.validatorState == nil { valState, ok := vm.(validators.State) if !ok { - return nil, fmt.Errorf("expected validators.State but got %T", vm) + return nil, fmt.Errorf("expected validators.State but got %T", m) } if m.TracingEnabled { - valState = validators.Trace(valState, "platformvm", m.Tracer) + valState = validators.Trace(valState, "platformvm", m.tracer) } // Notice that this context is left unlocked. This is because the @@ -1060,10 +1095,10 @@ func (m *manager) createSnowmanChain( // Initialize the validator state for future chains. m.validatorState = validators.NewLockedState(&ctx.Lock, valState) if m.TracingEnabled { - m.validatorState = validators.Trace(m.validatorState, "lockedState", m.Tracer) + m.validatorState = validators.Trace(m.validatorState, "lockedState", m.tracer) } - if !m.ManagerConfig.SybilProtectionEnabled { + if !m.SybilProtectionEnabled { m.validatorState = validators.NewNoValidatorsState(m.validatorState) ctx.ValidatorState = validators.NewNoValidatorsState(ctx.ValidatorState) } @@ -1079,11 +1114,11 @@ func (m *manager) createSnowmanChain( // Set up the subnet connector for the P-Chain subnetConnector, ok = vm.(validators.SubnetConnector) if !ok { - return nil, fmt.Errorf("expected validators.SubnetConnector but got %T", vm) + return nil, fmt.Errorf("expected validators.SubnetConnector but got %T", m) } } - // Initialize the ProposerVM and the vm wrapped inside it + // Initialize the ProposerVM and the m wrapped inside it chainConfig, err := m.getChainConfig(ctx.ChainID) if err != nil { return nil, fmt.Errorf("error while fetching chain config: %w", err) @@ -1093,20 +1128,20 @@ func (m *manager) createSnowmanChain( minBlockDelay = proposervm.DefaultMinBlockDelay numHistoricalBlocks = proposervm.DefaultNumHistoricalBlocks ) - if subnetCfg, ok := m.SubnetConfigs[ctx.SubnetID]; ok { + if subnetCfg, ok := m.subnetConfigs[ctx.SubnetID]; ok { minBlockDelay = subnetCfg.ProposerMinBlockDelay numHistoricalBlocks = subnetCfg.ProposerNumHistoricalBlocks } - m.Log.Info("creating proposervm wrapper", + m.log.Info("creating proposervm wrapper", zap.Time("activationTime", m.ApricotPhase4Time), zap.Uint64("minPChainHeight", m.ApricotPhase4MinPChainHeight), zap.Duration("minBlockDelay", minBlockDelay), zap.Uint64("numHistoricalBlocks", numHistoricalBlocks), ) - chainAlias := m.PrimaryAliasOrDefault(ctx.ChainID) + chainAlias := m.aliaser.PrimaryAliasOrDefault(ctx.ChainID) if m.TracingEnabled { - vm = tracedvm.NewBlockVM(vm, chainAlias, m.Tracer) + vm = tracedvm.NewBlockVM(vm, chainAlias, m.tracer) } vm = proposervm.New( @@ -1126,7 +1161,7 @@ func (m *manager) createSnowmanChain( vm = metervm.NewBlockVM(vm) } if m.TracingEnabled { - vm = tracedvm.NewBlockVM(vm, "proposervm", m.Tracer) + vm = tracedvm.NewBlockVM(vm, "proposervm", m.tracer) } // The channel through which a VM may send messages to the consensus engine @@ -1171,7 +1206,7 @@ func (m *manager) createSnowmanChain( msgChan, m.FrontierPollFrequency, m.ConsensusAppConcurrency, - m.ResourceTracker, + m.resourceTracker, subnetConnector, sb, connectedValidators, @@ -1198,7 +1233,7 @@ func (m *manager) createSnowmanChain( var consensus smcon.Consensus = &smcon.Topological{} if m.TracingEnabled { - consensus = smcon.Trace(consensus, m.Tracer) + consensus = smcon.Trace(consensus, m.tracer) } // Create engine, bootstrapper and state-syncer in this order, @@ -1220,10 +1255,10 @@ func (m *manager) createSnowmanChain( } if m.TracingEnabled { - engine = smeng.TraceEngine(engine, m.Tracer) + engine = smeng.TraceEngine(engine, m.tracer) } - // create bootstrap gear + // create smbootstrap gear bootstrapCfg := smbootstrap.Config{ AllGetsServer: snowGetHandler, Ctx: ctx, @@ -1248,7 +1283,7 @@ func (m *manager) createSnowmanChain( } if m.TracingEnabled { - bootstrapper = common.TraceBootstrapableEngine(bootstrapper, m.Tracer) + bootstrapper = common.TraceBootstrapableEngine(bootstrapper, m.tracer) } // create state sync gear @@ -1272,7 +1307,7 @@ func (m *manager) createSnowmanChain( ) if m.TracingEnabled { - stateSyncer = common.TraceStateSyncer(stateSyncer, m.Tracer) + stateSyncer = common.TraceStateSyncer(stateSyncer, m.tracer) } h.SetEngineManager(&handler.EngineManager{ @@ -1285,7 +1320,7 @@ func (m *manager) createSnowmanChain( }) // Register health checks - if err := m.Health.RegisterHealthCheck(chainAlias, h, ctx.SubnetID.String()); err != nil { + if err := m.health.RegisterHealthCheck(chainAlias, h, ctx.SubnetID.String()); err != nil { return nil, fmt.Errorf("couldn't add health check for chain %s: %w", chainAlias, err) } @@ -1297,7 +1332,7 @@ func (m *manager) createSnowmanChain( }, nil } -func (m *manager) IsBootstrapped(id ids.ID) bool { +func (m *Manager) IsBootstrapped(id ids.ID) bool { m.chainsLock.Lock() chain, exists := m.chains[id] m.chainsLock.Unlock() @@ -1308,7 +1343,7 @@ func (m *manager) IsBootstrapped(id ids.ID) bool { return chain.Context().State.Get().State == snow.NormalOp } -func (m *manager) subnetsNotBootstrapped() []ids.ID { +func (m *Manager) subnetsNotBootstrapped() []ids.ID { m.subnetsLock.RLock() defer m.subnetsLock.RUnlock() @@ -1321,7 +1356,7 @@ func (m *manager) subnetsNotBootstrapped() []ids.ID { return subnetsBootstrapping } -func (m *manager) registerBootstrappedHealthChecks() error { +func (m *Manager) registerBootstrappedHealthChecks() error { bootstrappedCheck := health.CheckerFunc(func(context.Context) (interface{}, error) { subnetIDs := m.subnetsNotBootstrapped() if len(subnetIDs) != 0 { @@ -1329,10 +1364,10 @@ func (m *manager) registerBootstrappedHealthChecks() error { } return []ids.ID{}, nil }) - if err := m.Health.RegisterReadinessCheck("bootstrapped", bootstrappedCheck, health.ApplicationTag); err != 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 { + if err := m.health.RegisterHealthCheck("bootstrapped", bootstrappedCheck, health.ApplicationTag); err != nil { return fmt.Errorf("couldn't register bootstrapped health check: %w", err) } @@ -1348,50 +1383,59 @@ func (m *manager) registerBootstrappedHealthChecks() error { if !m.IsBootstrapped(constants.PlatformChainID) { return "node is currently bootstrapping", nil } - if _, ok := m.Validators.GetValidator(constants.PrimaryNetworkID, m.NodeID); !ok { + 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", + 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 { + 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 { +func (m *Manager) StartChainCreator() error { // Get the Primary Network's subnet config. If it wasn't registered, then we // throw a fatal error. - sbConfig, ok := m.SubnetConfigs[constants.PrimaryNetworkID] + sbConfig, ok := m.subnetConfigs[constants.PrimaryNetworkID] if !ok { return errNoPrimaryNetworkConfig } - sb := subnets.New(m.NodeID, sbConfig) + sb := subnets.New(m.nodeID, sbConfig) m.subnetsLock.Lock() - m.subnets[platformParams.SubnetID] = sb - sb.AddChain(platformParams.ID) + m.subnets[constants.PrimaryNetworkID] = sb + sb.AddChain(constants.PlatformChainID) m.subnetsLock.Unlock() // 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") + if err := m.createChain(chainParameters{ + ID: constants.PlatformChainID, + SubnetID: constants.PrimaryNetworkID, + GenesisData: m.genesis, + VMID: constants.PlatformVMID, + VMFactory: m.vmFactory, + CustomBeacons: m.bootstrappers, + }); err != nil { + return err + } + + m.log.Info("starting chain creator") m.chainCreatorExited.Add(1) go m.dispatchChainCreator() return nil } -func (m *manager) dispatchChainCreator() { +func (m *Manager) dispatchChainCreator() { defer m.chainCreatorExited.Done() select { @@ -1410,44 +1454,41 @@ func (m *manager) dispatchChainCreator() { if !ok { // queue is closed, return directly return } - m.createChain(chainParams) + if err := m.createChain(chainParams); err != nil { + m.log.Error("failed to create chain", zap.Error(err)) + } } } // Shutdown stops all the chains -func (m *manager) Shutdown() { - m.Log.Info("shutting down chain manager") +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) + m.router.Shutdown(context.TODO()) } // 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) { +func (m *Manager) notifyRegistrants(name string, ctx *snow.ConsensusContext, created common.VM) { for _, registrant := range m.registrants { - registrant.RegisterChain(name, ctx, vm) + registrant.RegisterChain(name, ctx, created) } } // 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 { +func (m *Manager) getChainConfig(id ids.ID) (ChainConfig, error) { + if val, ok := m.chainConfigs[id.String()]; ok { return val, nil } - aliases, err := m.Aliases(id) + aliases, err := m.aliaser.Aliases(id) if err != nil { return ChainConfig{}, err } for _, alias := range aliases { - if val, ok := m.ManagerConfig.ChainConfigs[alias]; ok { + if val, ok := m.chainConfigs[alias]; ok { return val, nil } } diff --git a/chains/test_manager.go b/chains/test_manager.go deleted file mode 100644 index f7b98b29b587..000000000000 --- a/chains/test_manager.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package chains - -import "github.com/ava-labs/avalanchego/ids" - -// TestManager implements Manager but does nothing. Always returns nil error. -// To be used only in tests -var TestManager Manager = testManager{} - -type testManager struct{} - -func (testManager) QueueChainCreation(ChainParameters) {} - -func (testManager) ForceCreateChain(ChainParameters) {} - -func (testManager) AddRegistrant(Registrant) {} - -func (testManager) Aliases(ids.ID) ([]string, error) { - return nil, nil -} - -func (testManager) PrimaryAlias(ids.ID) (string, error) { - return "", nil -} - -func (testManager) PrimaryAliasOrDefault(ids.ID) string { - return "" -} - -func (testManager) Alias(ids.ID, string) error { - return nil -} - -func (testManager) RemoveAliases(ids.ID) {} - -func (testManager) Shutdown() {} - -func (testManager) StartChainCreator(ChainParameters) error { - return nil -} - -func (testManager) SubnetID(ids.ID) (ids.ID, error) { - return ids.ID{}, nil -} - -func (testManager) IsBootstrapped(ids.ID) bool { - return false -} - -func (testManager) Lookup(s string) (ids.ID, error) { - return ids.FromString(s) -} - -func (testManager) LookupVM(s string) (ids.ID, error) { - return ids.FromString(s) -} diff --git a/node/node.go b/node/node.go index 7842259c8a93..0fb2d50705ec 100644 --- a/node/node.go +++ b/node/node.go @@ -78,8 +78,8 @@ import ( "github.com/ava-labs/avalanchego/version" "github.com/ava-labs/avalanchego/vms" "github.com/ava-labs/avalanchego/vms/avm" - "github.com/ava-labs/avalanchego/vms/platformvm" "github.com/ava-labs/avalanchego/vms/platformvm/block" + "github.com/ava-labs/avalanchego/vms/platformvm/config" "github.com/ava-labs/avalanchego/vms/platformvm/signer" "github.com/ava-labs/avalanchego/vms/platformvm/txs" "github.com/ava-labs/avalanchego/vms/registry" @@ -87,7 +87,6 @@ import ( ipcsapi "github.com/ava-labs/avalanchego/api/ipcs" avmconfig "github.com/ava-labs/avalanchego/vms/avm/config" - platformconfig "github.com/ava-labs/avalanchego/vms/platformvm/config" ) const ( @@ -125,6 +124,7 @@ func New( LogFactory: logFactory, ID: ids.NodeIDFromCert(stakingCert), Config: config, + aliaser: ids.NewAliaser(), } n.DoneShuttingDown.Add(1) @@ -181,10 +181,10 @@ func New( n.initSharedMemory() // Initialize shared memory - // message.Creator is shared between networking, chainManager and the engine. + // message.Manager is shared between networking, chainManager and the engine. // It must be initiated before networking (initNetworking), chain manager (initChainManager) // and the engine (initChains) but after the metrics (initMetricsAPI) - // message.Creator currently record metrics under network namespace + // message.Manager currently record metrics under network namespace n.networkNamespace = "network" n.msgCreator, err = message.NewCreator( n.Log, @@ -222,18 +222,12 @@ func New( if err := n.addDefaultVMAliases(); err != nil { return nil, fmt.Errorf("couldn't initialize API aliases: %w", err) } - if err := n.initChainManager(n.Config.AvaxAssetID); err != nil { // Set up the chain manager - return nil, fmt.Errorf("couldn't initialize chain manager: %w", err) - } if err := n.initVMs(); err != nil { // Initialize the VM registry. return nil, fmt.Errorf("couldn't initialize VM registry: %w", err) } if err := n.initAdminAPI(); err != nil { // Start the Admin API return nil, fmt.Errorf("couldn't initialize admin API: %w", err) } - if err := n.initInfoAPI(); err != nil { // Start the Info API - return nil, fmt.Errorf("couldn't initialize info API: %w", err) - } if err := n.initIPCs(); err != nil { // Start the IPCs return nil, fmt.Errorf("couldn't initialize IPCs: %w", err) } @@ -250,13 +244,18 @@ func New( return nil, fmt.Errorf("couldn't initialize indexer: %w", err) } - n.health.Start(context.TODO(), n.Config.HealthCheckFreq) - n.initProfiler() - // Start the Platform chain - if err := n.initChains(n.Config.GenesisBytes); err != nil { + if err := n.initChains(); err != nil { return nil, fmt.Errorf("couldn't initialize chains: %w", err) } + + if err := n.initInfoAPI(); err != nil { // Start the Info API + return nil, fmt.Errorf("couldn't initialize info API: %w", err) + } + + n.health.Start(context.TODO(), n.Config.HealthCheckFreq) + n.initProfiler() + return n, nil } @@ -273,9 +272,11 @@ type Node struct { // Storage for this node DB database.Database - router nat.Router - portMapper *nat.Mapper - ipUpdater dynamicip.Updater + chainCreator *chains.Manager + aliaser ids.Aliaser + router nat.Router + portMapper *nat.Mapper + ipUpdater dynamicip.Updater // Profiles the process. Nil if continuous profiling is disabled. profiler profiler.ContinuousProfiler @@ -299,7 +300,7 @@ type Node struct { timeoutManager timeout.Manager // Manages creation of blockchains and routing messages to them - chainManager chains.Manager + //chainManager *platformvm.VM // Manages validator benching benchlistManager benchlist.Manager @@ -678,7 +679,9 @@ func (n *Node) Dispatch() error { } // Start P2P connections - err := n.Net.Dispatch() + if err := n.Net.Dispatch(); err != nil { + return err + } // If the P2P server isn't running, shut down the node. // If node is already shutting down, this does nothing. @@ -706,7 +709,7 @@ func (n *Node) Dispatch() error { ) } - return err + return nil } /* @@ -872,27 +875,149 @@ func (n *Node) initIndexer() error { return fmt.Errorf("couldn't create index for txs: %w", err) } - // Chain manager will notify indexer when a chain is created - n.chainManager.AddRegistrant(n.indexer) - return nil } // Initializes the Platform chain. // Its genesis data specifies the other chains that should be created. -func (n *Node) initChains(genesisBytes []byte) error { +func (n *Node) initChains() error { n.Log.Info("initializing chains") - platformChain := chains.ChainParameters{ - ID: constants.PlatformChainID, - SubnetID: constants.PrimaryNetworkID, - GenesisData: genesisBytes, // Specifies other chains to create - VMID: constants.PlatformVMID, - CustomBeacons: n.bootstrappers, + createAVMTx, err := genesis.VMGenesis(n.Config.GenesisBytes, constants.AVMID) + if err != nil { + return err + } + xChainID := createAVMTx.ID() + + createEVMTx, err := genesis.VMGenesis(n.Config.GenesisBytes, constants.EVMID) + if err != nil { + return err } + cChainID := createEVMTx.ID() + + // If any of these chains die, the node shuts down + criticalChains := set.Of( + constants.PlatformChainID, + xChainID, + cChainID, + ) + + n.timeoutManager, err = timeout.NewManager( + &n.Config.AdaptiveTimeoutConfig, + n.benchlistManager, + "requests", + n.MetricsRegisterer, + ) + if err != nil { + return err + } + go n.Log.RecoverAndPanic(n.timeoutManager.Dispatch) + + // Routes incoming messages from peers to the appropriate chain + err = n.Config.ConsensusRouter.Initialize( + n.ID, + n.Log, + n.timeoutManager, + n.Config.ConsensusShutdownTimeout, + criticalChains, + n.Config.SybilProtectionEnabled, + n.Config.TrackedSubnets, + n.Shutdown, + n.Config.RouterHealthConfig, + "requests", + n.MetricsRegisterer, + ) + if err != nil { + return fmt.Errorf("couldn't initialize chain router: %w", err) + } + + vdrs := n.vdrs + + // If sybil protection is disabled, we provide the P-chain its own local + // validator manager that will not be used by the rest of the node. This + // allows the node's validator sets to be determined by network connections. + if !n.Config.SybilProtectionEnabled { + vdrs = validators.NewManager() + } + + n.chainCreator = chains.NewManager( + config.Config{ + SybilProtectionEnabled: n.Config.SybilProtectionEnabled, + PartialSyncPrimaryNetwork: n.Config.PartialSyncPrimaryNetwork, + TrackedSubnets: n.Config.TrackedSubnets, + TxFee: n.Config.TxFee, + CreateAssetTxFee: n.Config.CreateAssetTxFee, + CreateSubnetTxFee: n.Config.CreateSubnetTxFee, + TransformSubnetTxFee: n.Config.TransformSubnetTxFee, + CreateBlockchainTxFee: n.Config.CreateBlockchainTxFee, + AddPrimaryNetworkValidatorFee: n.Config.AddPrimaryNetworkValidatorFee, + AddPrimaryNetworkDelegatorFee: n.Config.AddPrimaryNetworkDelegatorFee, + AddSubnetValidatorFee: n.Config.AddSubnetValidatorFee, + AddSubnetDelegatorFee: n.Config.AddSubnetDelegatorFee, + MinValidatorStake: n.Config.MinValidatorStake, + MaxValidatorStake: n.Config.MaxValidatorStake, + MinDelegatorStake: n.Config.MinDelegatorStake, + MinDelegationFee: n.Config.MinDelegationFee, + UptimePercentage: n.Config.UptimeRequirement, + MinStakeDuration: n.Config.MinStakeDuration, + MaxStakeDuration: n.Config.MaxStakeDuration, + RewardConfig: n.Config.RewardConfig, + ApricotPhase3Time: version.GetApricotPhase3Time(n.Config.NetworkID), + ApricotPhase4Time: version.GetApricotPhase4Time(n.Config.NetworkID), + //ApricotPhase4MinPChainHeight: //TODO + ApricotPhase5Time: version.GetApricotPhase5Time(n.Config.NetworkID), + BanffTime: version.GetBanffTime(n.Config.NetworkID), + CortinaTime: version.GetCortinaTime(n.Config.NetworkID), + DurangoTime: version.GetDurangoTime(n.Config.NetworkID), + UseCurrentHeight: n.Config.UseCurrentHeight, + TracingEnabled: n.Config.TraceConfig.Enabled, + NetworkID: n.Config.NetworkID, + AVAXAssetID: n.Config.AvaxAssetID, + MeterVMEnabled: n.Config.MeterVMEnabled, + FrontierPollFrequency: n.Config.FrontierPollFrequency, + ConsensusAppConcurrency: n.Config.ConsensusAppConcurrency, + BootstrapMaxTimeGetAncestors: n.Config.BootstrapMaxTimeGetAncestors, + BootstrapAncestorsMaxContainersSent: n.Config.BootstrapAncestorsMaxContainersSent, + BootstrapAncestorsMaxContainersReceived: n.Config.BootstrapAncestorsMaxContainersReceived, + StateSyncBeacons: n.Config.StateSyncIDs, + ChainDataDir: n.Config.ChainDataDir, + }, + n.Config.GenesisBytes, + n.aliaser, + n.Config.StakingTLSCert, + n.Config.StakingSigningKey, + n.tracer, + n.Log, + n.LogFactory, + n.VMManager, + n.BlockAcceptorGroup, + n.TxAcceptorGroup, + n.VertexAcceptorGroup, + n.DB, + n.msgCreator, + n.Config.ConsensusRouter, + n.Net, + n.bootstrappers, + vdrs, + n.ID, + n.keystore, + n.sharedMemory, + xChainID, + cChainID, + criticalChains, + n.timeoutManager, + n.health, + n.Config.SubnetConfigs, + n.Config.ChainConfigs, + n.Shutdown, + n.MetricsGatherer, + n.resourceTracker, + n.uptimeCalculator, + ) + n.chainCreator.AddRegistrant(n.APIServer) + n.chainCreator.AddRegistrant(n.indexer) - // Start the chain creator with the Platform Chain - return n.chainManager.StartChainCreator(platformChain) + return n.chainCreator.StartChainCreator() } func (n *Node) initMetrics() { @@ -1053,122 +1178,10 @@ func (n *Node) addDefaultVMAliases() error { return nil } -// Create the chainManager and register the following VMs: -// AVM, Simple Payments DAG, Simple Payments Chain, and Platform VM -// Assumes n.DBManager, n.vdrs all initialized (non-nil) -func (n *Node) initChainManager(avaxAssetID ids.ID) error { - createAVMTx, err := genesis.VMGenesis(n.Config.GenesisBytes, constants.AVMID) - if err != nil { - return err - } - xChainID := createAVMTx.ID() - - createEVMTx, err := genesis.VMGenesis(n.Config.GenesisBytes, constants.EVMID) - if err != nil { - return err - } - cChainID := createEVMTx.ID() - - // If any of these chains die, the node shuts down - criticalChains := set.Of( - constants.PlatformChainID, - xChainID, - cChainID, - ) - - n.timeoutManager, err = timeout.NewManager( - &n.Config.AdaptiveTimeoutConfig, - n.benchlistManager, - "requests", - n.MetricsRegisterer, - ) - if err != nil { - return err - } - go n.Log.RecoverAndPanic(n.timeoutManager.Dispatch) - - // Routes incoming messages from peers to the appropriate chain - err = n.Config.ConsensusRouter.Initialize( - n.ID, - n.Log, - n.timeoutManager, - n.Config.ConsensusShutdownTimeout, - criticalChains, - n.Config.SybilProtectionEnabled, - n.Config.TrackedSubnets, - n.Shutdown, - n.Config.RouterHealthConfig, - "requests", - n.MetricsRegisterer, - ) - if err != nil { - return fmt.Errorf("couldn't initialize chain router: %w", err) - } - - n.chainManager = chains.New(&chains.ManagerConfig{ - SybilProtectionEnabled: n.Config.SybilProtectionEnabled, - StakingTLSCert: n.Config.StakingTLSCert, - StakingBLSKey: n.Config.StakingSigningKey, - Log: n.Log, - LogFactory: n.LogFactory, - VMManager: n.VMManager, - BlockAcceptorGroup: n.BlockAcceptorGroup, - TxAcceptorGroup: n.TxAcceptorGroup, - VertexAcceptorGroup: n.VertexAcceptorGroup, - DB: n.DB, - MsgCreator: n.msgCreator, - Router: n.Config.ConsensusRouter, - Net: n.Net, - Validators: n.vdrs, - PartialSyncPrimaryNetwork: n.Config.PartialSyncPrimaryNetwork, - NodeID: n.ID, - NetworkID: n.Config.NetworkID, - Server: n.APIServer, - Keystore: n.keystore, - AtomicMemory: n.sharedMemory, - AVAXAssetID: avaxAssetID, - XChainID: xChainID, - CChainID: cChainID, - CriticalChains: criticalChains, - TimeoutManager: n.timeoutManager, - Health: n.health, - ShutdownNodeFunc: n.Shutdown, - MeterVMEnabled: n.Config.MeterVMEnabled, - Metrics: n.MetricsGatherer, - SubnetConfigs: n.Config.SubnetConfigs, - ChainConfigs: n.Config.ChainConfigs, - FrontierPollFrequency: n.Config.FrontierPollFrequency, - ConsensusAppConcurrency: n.Config.ConsensusAppConcurrency, - BootstrapMaxTimeGetAncestors: n.Config.BootstrapMaxTimeGetAncestors, - BootstrapAncestorsMaxContainersSent: n.Config.BootstrapAncestorsMaxContainersSent, - BootstrapAncestorsMaxContainersReceived: n.Config.BootstrapAncestorsMaxContainersReceived, - ApricotPhase4Time: version.GetApricotPhase4Time(n.Config.NetworkID), - ApricotPhase4MinPChainHeight: version.ApricotPhase4MinPChainHeight[n.Config.NetworkID], - ResourceTracker: n.resourceTracker, - StateSyncBeacons: n.Config.StateSyncIDs, - TracingEnabled: n.Config.TraceConfig.Enabled, - Tracer: n.tracer, - ChainDataDir: n.Config.ChainDataDir, - }) - - // Notify the API server when new chains are created - n.chainManager.AddRegistrant(n.APIServer) - return nil -} - // initVMs initializes the VMs Avalanche supports + any additional vms installed as plugins. func (n *Node) initVMs() error { n.Log.Info("initializing VMs") - vdrs := n.vdrs - - // If sybil protection is disabled, we provide the P-chain its own local - // validator manager that will not be used by the rest of the node. This - // allows the node's validator sets to be determined by network connections. - if !n.Config.SybilProtectionEnabled { - vdrs = validators.NewManager() - } - durangoTime := version.GetDurangoTime(n.Config.NetworkID) if err := txs.InitCodec(durangoTime); err != nil { return err @@ -1182,39 +1195,6 @@ func (n *Node) initVMs() error { // Register the VMs that Avalanche supports err := utils.Err( - n.VMManager.RegisterFactory(context.TODO(), constants.PlatformVMID, &platformvm.Factory{ - Config: platformconfig.Config{ - Chains: n.chainManager, - Validators: vdrs, - UptimeLockedCalculator: n.uptimeCalculator, - SybilProtectionEnabled: n.Config.SybilProtectionEnabled, - PartialSyncPrimaryNetwork: n.Config.PartialSyncPrimaryNetwork, - TrackedSubnets: n.Config.TrackedSubnets, - TxFee: n.Config.TxFee, - CreateAssetTxFee: n.Config.CreateAssetTxFee, - CreateSubnetTxFee: n.Config.CreateSubnetTxFee, - TransformSubnetTxFee: n.Config.TransformSubnetTxFee, - CreateBlockchainTxFee: n.Config.CreateBlockchainTxFee, - AddPrimaryNetworkValidatorFee: n.Config.AddPrimaryNetworkValidatorFee, - AddPrimaryNetworkDelegatorFee: n.Config.AddPrimaryNetworkDelegatorFee, - AddSubnetValidatorFee: n.Config.AddSubnetValidatorFee, - AddSubnetDelegatorFee: n.Config.AddSubnetDelegatorFee, - UptimePercentage: n.Config.UptimeRequirement, - MinValidatorStake: n.Config.MinValidatorStake, - MaxValidatorStake: n.Config.MaxValidatorStake, - MinDelegatorStake: n.Config.MinDelegatorStake, - MinDelegationFee: n.Config.MinDelegationFee, - MinStakeDuration: n.Config.MinStakeDuration, - MaxStakeDuration: n.Config.MaxStakeDuration, - RewardConfig: n.Config.RewardConfig, - ApricotPhase3Time: version.GetApricotPhase3Time(n.Config.NetworkID), - ApricotPhase5Time: version.GetApricotPhase5Time(n.Config.NetworkID), - BanffTime: version.GetBanffTime(n.Config.NetworkID), - CortinaTime: version.GetCortinaTime(n.Config.NetworkID), - DurangoTime: durangoTime, - UseCurrentHeight: n.Config.UseCurrentHeight, - }, - }), n.VMManager.RegisterFactory(context.TODO(), constants.AVMID, &avm.Factory{ Config: avmconfig.Config{ TxFee: n.Config.TxFee, @@ -1324,14 +1304,14 @@ func (n *Node) initAdminAPI() error { n.Log.Info("initializing admin API") service, err := admin.NewService( admin.Config{ - Log: n.Log, - ChainManager: n.chainManager, - HTTPServer: n.APIServer, - ProfileDir: n.Config.ProfilerConfig.Dir, - LogFactory: n.LogFactory, - NodeConfig: n.Config, - VMManager: n.VMManager, - VMRegistry: n.VMRegistry, + Log: n.Log, + Aliaser: n.aliaser, + HTTPServer: n.APIServer, + ProfileDir: n.Config.ProfilerConfig.Dir, + LogFactory: n.LogFactory, + NodeConfig: n.Config, + VMManager: n.VMManager, + VMRegistry: n.VMRegistry, }, ) if err != nil { @@ -1395,7 +1375,8 @@ func (n *Node) initInfoAPI() error { }, n.Log, n.vdrs, - n.chainManager, + n.aliaser, + n.chainCreator, n.VMManager, n.Config.NetworkConfig.MyIPPort, n.Net, @@ -1516,7 +1497,7 @@ func (n *Node) initIPCAPI() error { return nil } n.Log.Warn("initializing deprecated ipc API") - service, err := ipcsapi.NewService(n.Log, n.chainManager, n.IPCs) + service, err := ipcsapi.NewService(n.Log, n.aliaser, n.IPCs) if err != nil { return err } @@ -1537,7 +1518,7 @@ func (n *Node) initChainAliases(genesisBytes []byte) error { for chainID, aliases := range chainAliases { for _, alias := range aliases { - if err := n.chainManager.Alias(chainID, alias); err != nil { + if err := n.aliaser.Alias(chainID, alias); err != nil { return err } } @@ -1545,7 +1526,7 @@ func (n *Node) initChainAliases(genesisBytes []byte) error { for chainID, aliases := range n.Config.ChainAliases { for _, alias := range aliases { - if err := n.chainManager.Alias(chainID, alias); err != nil { + if err := n.aliaser.Alias(chainID, alias); err != nil { return err } } @@ -1660,8 +1641,8 @@ func (n *Node) shutdown() { } } n.timeoutManager.Stop() - if n.chainManager != nil { - n.chainManager.Shutdown() + if n.chainCreator != nil { + n.chainCreator.Shutdown() } if n.profiler != nil { n.profiler.Shutdown() diff --git a/version/constants.go b/version/constants.go index 35320d4ccf33..410c13a04d17 100644 --- a/version/constants.go +++ b/version/constants.go @@ -4,11 +4,10 @@ package version import ( + _ "embed" "encoding/json" "time" - _ "embed" - "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/constants" ) diff --git a/vms/platformvm/block/builder/helpers_test.go b/vms/platformvm/block/builder/helpers_test.go index f2d15195ad07..71ff53905375 100644 --- a/vms/platformvm/block/builder/helpers_test.go +++ b/vms/platformvm/block/builder/helpers_test.go @@ -12,7 +12,6 @@ import ( "github.com/stretchr/testify/require" - "github.com/ava-labs/avalanchego/chains" "github.com/ava-labs/avalanchego/chains/atomic" "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/codec/linearcodec" @@ -25,7 +24,6 @@ import ( "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/snowtest" "github.com/ava-labs/avalanchego/snow/uptime" - "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" @@ -296,17 +294,17 @@ func defaultState( func defaultConfig() *config.Config { return &config.Config{ - Chains: chains.TestManager, - UptimeLockedCalculator: uptime.NewLockedCalculator(), - Validators: validators.NewManager(), - TxFee: defaultTxFee, - CreateSubnetTxFee: 100 * defaultTxFee, - CreateBlockchainTxFee: 100 * defaultTxFee, - MinValidatorStake: 5 * units.MilliAvax, - MaxValidatorStake: 500 * units.MilliAvax, - MinDelegatorStake: 1 * units.MilliAvax, - MinStakeDuration: defaultMinStakingDuration, - MaxStakeDuration: defaultMaxStakingDuration, + //Chains: chains.TestManager, + //UptimeLockedCalculator: uptime.NewLockedCalculator(), + //Validators: validators.NewManager(), + TxFee: defaultTxFee, + CreateSubnetTxFee: 100 * defaultTxFee, + CreateBlockchainTxFee: 100 * defaultTxFee, + MinValidatorStake: 5 * units.MilliAvax, + MaxValidatorStake: 500 * units.MilliAvax, + MinDelegatorStake: 1 * units.MilliAvax, + MinStakeDuration: defaultMinStakingDuration, + MaxStakeDuration: defaultMaxStakingDuration, RewardConfig: reward.Config{ MaxConsumptionRate: .12 * reward.PercentDenominator, MinConsumptionRate: .10 * reward.PercentDenominator, diff --git a/vms/platformvm/block/executor/helpers_test.go b/vms/platformvm/block/executor/helpers_test.go index 1a3d2993328b..4caf90d0262d 100644 --- a/vms/platformvm/block/executor/helpers_test.go +++ b/vms/platformvm/block/executor/helpers_test.go @@ -14,7 +14,6 @@ import ( "go.uber.org/mock/gomock" - "github.com/ava-labs/avalanchego/chains" "github.com/ava-labs/avalanchego/chains/atomic" "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/codec/linearcodec" @@ -27,7 +26,6 @@ import ( "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/snowtest" "github.com/ava-labs/avalanchego/snow/uptime" - "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" @@ -323,17 +321,17 @@ func defaultState( func defaultConfig() *config.Config { return &config.Config{ - Chains: chains.TestManager, - UptimeLockedCalculator: uptime.NewLockedCalculator(), - Validators: validators.NewManager(), - TxFee: defaultTxFee, - CreateSubnetTxFee: 100 * defaultTxFee, - CreateBlockchainTxFee: 100 * defaultTxFee, - MinValidatorStake: 5 * units.MilliAvax, - MaxValidatorStake: 500 * units.MilliAvax, - MinDelegatorStake: 1 * units.MilliAvax, - MinStakeDuration: defaultMinStakingDuration, - MaxStakeDuration: defaultMaxStakingDuration, + //Chains: chains.TestManager, + //UptimeLockedCalculator: uptime.NewLockedCalculator(), + //Validators: validators.NewManager(), + TxFee: defaultTxFee, + CreateSubnetTxFee: 100 * defaultTxFee, + CreateBlockchainTxFee: 100 * defaultTxFee, + MinValidatorStake: 5 * units.MilliAvax, + MaxValidatorStake: 500 * units.MilliAvax, + MinDelegatorStake: 1 * units.MilliAvax, + MinStakeDuration: defaultMinStakingDuration, + MaxStakeDuration: defaultMaxStakingDuration, RewardConfig: reward.Config{ MaxConsumptionRate: .12 * reward.PercentDenominator, MinConsumptionRate: .10 * reward.PercentDenominator, diff --git a/vms/platformvm/block/executor/verifier_test.go b/vms/platformvm/block/executor/verifier_test.go index ccac3da3b7e3..d8fcc2e27079 100644 --- a/vms/platformvm/block/executor/verifier_test.go +++ b/vms/platformvm/block/executor/verifier_test.go @@ -229,9 +229,8 @@ func TestVerifierVisitStandardBlock(t *testing.T) { } verifier := &verifier{ txExecutorBackend: &executor.Backend{ - Config: &config.Config{ - ApricotPhase5Time: time.Now().Add(time.Hour), - BanffTime: mockable.MaxTime, // banff is not activated + TxConfig: txs.Config{ + BanffTime: mockable.MaxTime, // banff is not activated }, Clk: &mockable.Clock{}, }, diff --git a/vms/platformvm/chaincreator/interface.go b/vms/platformvm/chaincreator/interface.go new file mode 100644 index 000000000000..5c3f2097d512 --- /dev/null +++ b/vms/platformvm/chaincreator/interface.go @@ -0,0 +1,13 @@ +package chaincreator + +import "github.com/ava-labs/avalanchego/ids" + +type Interface interface { + CreateChain( + chainID ids.ID, + subnetID ids.ID, + genesis []byte, + vmID ids.ID, + fxs []ids.ID, + ) error +} diff --git a/vms/platformvm/config/config.go b/vms/platformvm/config/config.go index 50628c422afd..4566ad5b599b 100644 --- a/vms/platformvm/config/config.go +++ b/vms/platformvm/config/config.go @@ -6,32 +6,13 @@ package config import ( "time" - "github.com/ava-labs/avalanchego/chains" "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/snow/uptime" - "github.com/ava-labs/avalanchego/snow/validators" - "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/reward" - "github.com/ava-labs/avalanchego/vms/platformvm/txs" ) // Struct collecting all foundational parameters of PlatformVM type Config struct { - // The node's chain manager - Chains chains.Manager - - // Node's validator set maps subnetID -> validators of the subnet - // - // Invariant: The primary network's validator set should have been added to - // the manager before calling VM.Initialize. - // Invariant: The primary network's validator set should be empty before - // calling VM.Initialize. - Validators validators.Manager - - // Provides access to the uptime manager as a thread safe data structure - UptimeLockedCalculator uptime.LockedCalculator - // True if the node is being run with staking enabled SybilProtectionEnabled bool @@ -93,8 +74,9 @@ type Config struct { RewardConfig reward.Config // Time of the AP3 network upgrade - ApricotPhase3Time time.Time - + ApricotPhase3Time time.Time + ApricotPhase4Time time.Time + ApricotPhase4MinPChainHeight uint64 // Time of the AP5 network upgrade ApricotPhase5Time time.Time @@ -114,9 +96,26 @@ type Config struct { // This config is particularly useful for triggering proposervm activation // on recently created subnets (without this, users need to wait for // [recentlyAcceptedWindowTTL] to pass for activation to occur). - UseCurrentHeight bool + UseCurrentHeight bool + TracingEnabled bool + NetworkID uint32 // ID of the network this node is connected to + AVAXAssetID ids.ID + MeterVMEnabled bool // Should each VM be wrapped with a MeterVM + FrontierPollFrequency time.Duration + ConsensusAppConcurrency int + // Max Time to spend fetching a container and its + // ancestors when responding to a GetAncestors + BootstrapMaxTimeGetAncestors time.Duration + // Max number of containers in an ancestors message sent by this node. + BootstrapAncestorsMaxContainersSent int + // This node will only consider the first [AncestorsMaxContainersReceived] + // containers in an ancestors message it receives. + BootstrapAncestorsMaxContainersReceived int + StateSyncBeacons []ids.NodeID + ChainDataDir string } +// TODO delete IsForkActivated functions func (c *Config) IsApricotPhase3Activated(timestamp time.Time) bool { return !timestamp.Before(c.ApricotPhase3Time) } @@ -150,23 +149,3 @@ func (c *Config) GetCreateSubnetTxFee(timestamp time.Time) uint64 { } return c.CreateAssetTxFee } - -// Create the blockchain described in [tx], but only if this node is a member of -// the subnet that validates the chain -func (c *Config) CreateChain(chainID ids.ID, tx *txs.CreateChainTx) { - if c.SybilProtectionEnabled && // Sybil protection is enabled, so nodes might not validate all chains - constants.PrimaryNetworkID != tx.SubnetID && // All nodes must validate the primary network - !c.TrackedSubnets.Contains(tx.SubnetID) { // This node doesn't validate this blockchain - return - } - - chainParams := chains.ChainParameters{ - ID: chainID, - SubnetID: tx.SubnetID, - GenesisData: tx.GenesisData, - VMID: tx.VMID, - FxIDs: tx.FxIDs, - } - - c.Chains.QueueChainCreation(chainParams) -} diff --git a/vms/platformvm/factory.go b/vms/platformvm/factory.go index 834c9c8f2450..63c898692457 100644 --- a/vms/platformvm/factory.go +++ b/vms/platformvm/factory.go @@ -4,19 +4,48 @@ package platformvm import ( + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow/uptime" + "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/vms" + "github.com/ava-labs/avalanchego/vms/platformvm/chaincreator" "github.com/ava-labs/avalanchego/vms/platformvm/config" ) var _ vms.Factory = (*Factory)(nil) -// Factory can create new instances of the Platform Chain +func NewFactory( + config config.Config, + chainCreator chaincreator.Interface, + aliaser ids.Aliaser, + validators validators.Manager, + uptimeLockedCalculator uptime.LockedCalculator, +) *Factory { + return &Factory{ + config: config, + chainCreator: chainCreator, + aliaser: aliaser, + validators: validators, + uptimeLockedCalculator: uptimeLockedCalculator, + } +} + type Factory struct { - config.Config + config config.Config + chainCreator chaincreator.Interface + aliaser ids.Aliaser + validators validators.Manager + uptimeLockedCalculator uptime.LockedCalculator } -// New returns a new instance of the Platform Chain +// New returns a new instance of the PlatformVM func (f *Factory) New(logging.Logger) (interface{}, error) { - return &VM{Config: f.Config}, nil + return &VM{ + Config: f.config, + aliaser: f.aliaser, + Validators: f.validators, + UptimeLockedCalculator: f.uptimeLockedCalculator, + chainCreator: f.chainCreator, + }, nil } diff --git a/vms/platformvm/service.go b/vms/platformvm/service.go index 16e5b16844c6..428e96f6c4df 100644 --- a/vms/platformvm/service.go +++ b/vms/platformvm/service.go @@ -5,14 +5,13 @@ package platformvm import ( "context" + stdjson "encoding/json" "errors" "fmt" "math" "net/http" "time" - stdjson "encoding/json" - "go.uber.org/zap" "golang.org/x/exp/maps" @@ -85,6 +84,7 @@ var ( // Service defines the API calls that can be made to the platform chain type Service struct { vm *VM + aliaser ids.Aliaser addrManager avax.AddressManager stakerAttributesCache *cache.LRU[ids.ID, *stakerAttributes] } @@ -1868,14 +1868,14 @@ func (s *Service) buildCreateBlockchainTx(args *CreateBlockchainArgs) (*txs.Tx, return nil, ids.ShortEmpty, fmt.Errorf("problem parsing genesis data: %w", err) } - vmID, err := s.vm.Chains.LookupVM(args.VMID) + vmID, err := s.aliaser.Lookup(args.VMID) if err != nil { return nil, ids.ShortEmpty, fmt.Errorf("no VM with ID '%s' found", args.VMID) } fxIDs := []ids.ID(nil) for _, fxIDStr := range args.FxIDs { - fxID, err := s.vm.Chains.LookupVM(fxIDStr) + fxID, err := s.aliaser.Lookup(fxIDStr) if err != nil { return nil, ids.ShortEmpty, fmt.Errorf("no FX with ID '%s' found", fxIDStr) } @@ -1969,7 +1969,7 @@ func (s *Service) GetBlockchainStatus(r *http.Request, args *GetBlockchainStatus defer s.vm.ctx.Lock.Unlock() // if its aliased then vm created this chain. - if aliasedID, err := s.vm.Chains.Lookup(args.BlockchainID); err == nil { + if aliasedID, err := s.aliaser.Lookup(args.BlockchainID); err == nil { if s.nodeValidates(aliasedID) { reply.Status = status.Validating return nil diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index 92e646ed6975..50774bbdb0d6 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -453,6 +453,7 @@ func New( db database.Database, genesisBytes []byte, metricsReg prometheus.Registerer, + validators validators.Manager, cfg *config.Config, execCfg *config.ExecutionConfig, ctx *snow.Context, @@ -462,6 +463,7 @@ func New( s, err := newState( db, metrics, + validators, cfg, execCfg, ctx, @@ -506,6 +508,7 @@ func New( func newState( db database.Database, metrics metrics.Metrics, + validators validators.Manager, cfg *config.Config, execCfg *config.ExecutionConfig, ctx *snow.Context, @@ -629,7 +632,7 @@ func newState( return &state{ validatorState: newValidatorState(), - validators: cfg.Validators, + validators: validators, ctx: ctx, cfg: cfg, metrics: metrics, diff --git a/vms/platformvm/state/state_test.go b/vms/platformvm/state/state_test.go index c0fdb1e60269..1885016f60f9 100644 --- a/vms/platformvm/state/state_test.go +++ b/vms/platformvm/state/state_test.go @@ -27,6 +27,7 @@ import ( "github.com/ava-labs/avalanchego/utils/units" "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/platformvm" "github.com/ava-labs/avalanchego/vms/platformvm/block" "github.com/ava-labs/avalanchego/vms/platformvm/config" "github.com/ava-labs/avalanchego/vms/platformvm/fx" @@ -149,7 +150,7 @@ func TestPersistStakers(t *testing.T) { r.Equal(staker, retrievedStaker) }, checkValidatorsSet: func(r *require.Assertions, s *state, staker *Staker) { - valsMap := s.cfg.Validators.GetMap(staker.SubnetID) + valsMap := s.validators.GetMap(staker.SubnetID) r.Len(valsMap, 1) valOut, found := valsMap[staker.NodeID] r.True(found) @@ -254,7 +255,7 @@ func TestPersistStakers(t *testing.T) { val, err := s.GetCurrentValidator(staker.SubnetID, staker.NodeID) r.NoError(err) - valsMap := s.cfg.Validators.GetMap(staker.SubnetID) + valsMap := s.validators.GetMap(staker.SubnetID) r.Len(valsMap, 1) valOut, found := valsMap[staker.NodeID] r.True(found) @@ -311,7 +312,7 @@ func TestPersistStakers(t *testing.T) { }, checkValidatorsSet: func(r *require.Assertions, s *state, staker *Staker) { // pending validators are not showed in validators set - valsMap := s.cfg.Validators.GetMap(staker.SubnetID) + valsMap := s.validators.GetMap(staker.SubnetID) r.Len(valsMap, 0) }, checkValidatorUptimes: func(r *require.Assertions, s *state, staker *Staker) { @@ -386,7 +387,7 @@ func TestPersistStakers(t *testing.T) { r.Equal(staker, retrievedDelegator) }, checkValidatorsSet: func(r *require.Assertions, s *state, staker *Staker) { - valsMap := s.cfg.Validators.GetMap(staker.SubnetID) + valsMap := s.validators.GetMap(staker.SubnetID) r.Len(valsMap, 0) }, checkValidatorUptimes: func(r *require.Assertions, s *state, staker *Staker) { @@ -437,7 +438,7 @@ func TestPersistStakers(t *testing.T) { }, checkValidatorsSet: func(r *require.Assertions, s *state, staker *Staker) { // deleted validators are not showed in the validators set anymore - valsMap := s.cfg.Validators.GetMap(staker.SubnetID) + valsMap := s.validators.GetMap(staker.SubnetID) r.Len(valsMap, 0) }, checkValidatorUptimes: func(r *require.Assertions, s *state, staker *Staker) { @@ -534,7 +535,7 @@ func TestPersistStakers(t *testing.T) { val, err := s.GetCurrentValidator(staker.SubnetID, staker.NodeID) r.NoError(err) - valsMap := s.cfg.Validators.GetMap(staker.SubnetID) + valsMap := s.validators.GetMap(staker.SubnetID) r.Len(valsMap, 1) valOut, found := valsMap[staker.NodeID] r.True(found) @@ -594,7 +595,7 @@ func TestPersistStakers(t *testing.T) { r.ErrorIs(err, database.ErrNotFound) }, checkValidatorsSet: func(r *require.Assertions, s *state, staker *Staker) { - valsMap := s.cfg.Validators.GetMap(staker.SubnetID) + valsMap := s.validators.GetMap(staker.SubnetID) r.Len(valsMap, 0) }, checkValidatorUptimes: func(r *require.Assertions, s *state, staker *Staker) { @@ -665,7 +666,7 @@ func TestPersistStakers(t *testing.T) { delIt.Release() }, checkValidatorsSet: func(r *require.Assertions, s *state, staker *Staker) { - valsMap := s.cfg.Validators.GetMap(staker.SubnetID) + valsMap := s.validators.GetMap(staker.SubnetID) r.Len(valsMap, 0) }, checkValidatorUptimes: func(r *require.Assertions, s *state, staker *Staker) { @@ -787,7 +788,7 @@ func newStateFromDB(require *require.Assertions, db database.Database) *state { state, err := newState( db, metrics.Noop, - &config.Config{ + &platformvm.Config{ Validators: validators.NewManager(), }, execCfg, diff --git a/vms/platformvm/txs/builder/builder.go b/vms/platformvm/txs/builder/builder.go index 3427bf2b1015..cec89bd8dd0e 100644 --- a/vms/platformvm/txs/builder/builder.go +++ b/vms/platformvm/txs/builder/builder.go @@ -194,7 +194,7 @@ type ProposalTxBuilder interface { func New( ctx *snow.Context, - cfg *config.Config, + cfg config.Config, clk *mockable.Clock, fx fx.Fx, state state.State, @@ -217,7 +217,7 @@ type builder struct { utxo.Spender state state.State - cfg *config.Config + cfg config.Config ctx *snow.Context clk *mockable.Clock fx fx.Fx diff --git a/vms/platformvm/txs/executor/backend.go b/vms/platformvm/txs/executor/backend.go index 847aefc16499..6c41c2b90471 100644 --- a/vms/platformvm/txs/executor/backend.go +++ b/vms/platformvm/txs/executor/backend.go @@ -8,6 +8,7 @@ import ( "github.com/ava-labs/avalanchego/snow/uptime" "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/timer/mockable" + "github.com/ava-labs/avalanchego/vms/platformvm/chaincreator" "github.com/ava-labs/avalanchego/vms/platformvm/config" "github.com/ava-labs/avalanchego/vms/platformvm/fx" "github.com/ava-labs/avalanchego/vms/platformvm/reward" @@ -16,6 +17,7 @@ import ( type Backend struct { Config *config.Config + ChainCreator chaincreator.Interface Ctx *snow.Context Clk *mockable.Clock Fx fx.Fx diff --git a/vms/platformvm/txs/executor/helpers_test.go b/vms/platformvm/txs/executor/helpers_test.go index b2654ec7c8c9..3f74d682fd80 100644 --- a/vms/platformvm/txs/executor/helpers_test.go +++ b/vms/platformvm/txs/executor/helpers_test.go @@ -13,7 +13,6 @@ import ( "github.com/stretchr/testify/require" - "github.com/ava-labs/avalanchego/chains" "github.com/ava-labs/avalanchego/chains/atomic" "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/codec/linearcodec" @@ -24,7 +23,6 @@ import ( "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/snowtest" "github.com/ava-labs/avalanchego/snow/uptime" - "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" @@ -286,17 +284,17 @@ func defaultConfig(postBanff, postCortina, postDurango bool) *config.Config { } return &config.Config{ - Chains: chains.TestManager, - UptimeLockedCalculator: uptime.NewLockedCalculator(), - Validators: validators.NewManager(), - TxFee: defaultTxFee, - CreateSubnetTxFee: 100 * defaultTxFee, - CreateBlockchainTxFee: 100 * defaultTxFee, - MinValidatorStake: 5 * units.MilliAvax, - MaxValidatorStake: 500 * units.MilliAvax, - MinDelegatorStake: 1 * units.MilliAvax, - MinStakeDuration: defaultMinStakingDuration, - MaxStakeDuration: defaultMaxStakingDuration, + //Chains: chains.TestManager, + //UptimeLockedCalculator: uptime.NewLockedCalculator(), + //Validators: validators.NewManager(), + TxFee: defaultTxFee, + CreateSubnetTxFee: 100 * defaultTxFee, + CreateBlockchainTxFee: 100 * defaultTxFee, + MinValidatorStake: 5 * units.MilliAvax, + MaxValidatorStake: 500 * units.MilliAvax, + MinDelegatorStake: 1 * units.MilliAvax, + MinStakeDuration: defaultMinStakingDuration, + MaxStakeDuration: defaultMaxStakingDuration, RewardConfig: reward.Config{ MaxConsumptionRate: .12 * reward.PercentDenominator, MinConsumptionRate: .10 * reward.PercentDenominator, diff --git a/vms/platformvm/txs/executor/staker_tx_verification_test.go b/vms/platformvm/txs/executor/staker_tx_verification_test.go index 1431f32e56f5..2bdc642dbaa5 100644 --- a/vms/platformvm/txs/executor/staker_tx_verification_test.go +++ b/vms/platformvm/txs/executor/staker_tx_verification_test.go @@ -339,7 +339,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { bootstrapped.Set(true) return &Backend{ Ctx: ctx, - Config: &config.Config{ + TxConfig: executor.Config{ DurangoTime: activeForkTime, // activate latest fork }, Bootstrapped: bootstrapped, diff --git a/vms/platformvm/txs/executor/standard_tx_executor.go b/vms/platformvm/txs/executor/standard_tx_executor.go index aa3ea9a2aafe..2dda33c9678f 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor.go +++ b/vms/platformvm/txs/executor/standard_tx_executor.go @@ -94,7 +94,14 @@ func (e *StandardTxExecutor) CreateChainTx(tx *txs.CreateChainTx) error { // If this proposal is committed and this node is a member of the subnet // that validates the blockchain, create the blockchain e.OnAccept = func() { - e.Config.CreateChain(txID, tx) + //TODO error + _ = e.ChainCreator.CreateChain( + txID, + tx.SubnetID, + tx.GenesisData, + tx.VMID, + tx.FxIDs, + ) } return nil } diff --git a/vms/platformvm/txs/executor/standard_tx_executor_test.go b/vms/platformvm/txs/executor/standard_tx_executor_test.go index f9c54367facd..d0d9d5728537 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor_test.go +++ b/vms/platformvm/txs/executor/standard_tx_executor_test.go @@ -2161,7 +2161,7 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { ).Return(ErrFlowCheckFailed) e := &StandardTxExecutor{ Backend: &Backend{ - Config: &config.Config{ + TxConfig: executor.Config{ BanffTime: env.latestForkTime, CortinaTime: env.latestForkTime, DurangoTime: env.latestForkTime, diff --git a/vms/platformvm/validator_set_property_test.go b/vms/platformvm/validator_set_property_test.go index 5ca5bfd6c241..5de02af7cc40 100644 --- a/vms/platformvm/validator_set_property_test.go +++ b/vms/platformvm/validator_set_property_test.go @@ -18,7 +18,6 @@ import ( "golang.org/x/exp/maps" - "github.com/ava-labs/avalanchego/chains" "github.com/ava-labs/avalanchego/chains/atomic" "github.com/ava-labs/avalanchego/database/memdb" "github.com/ava-labs/avalanchego/database/prefixdb" @@ -712,7 +711,7 @@ func TestTimestampListGenerator(t *testing.T) { func buildVM(t *testing.T) (*VM, ids.ID, error) { forkTime := defaultGenesisTime vm := &VM{Config: config.Config{ - Chains: chains.TestManager, + Chains: TestManager, UptimeLockedCalculator: uptime.NewLockedCalculator(), SybilProtectionEnabled: true, Validators: validators.NewManager(), diff --git a/vms/platformvm/validators/manager.go b/vms/platformvm/validators/manager.go index 2c8b025a128b..18d08ca7777a 100644 --- a/vms/platformvm/validators/manager.go +++ b/vms/platformvm/validators/manager.go @@ -87,17 +87,19 @@ type State interface { func NewManager( log logging.Logger, cfg config.Config, + validatorManager validators.Manager, state State, metrics metrics.Metrics, clk *mockable.Clock, ) Manager { return &manager{ - log: log, - cfg: cfg, - state: state, - metrics: metrics, - clk: clk, - caches: make(map[ids.ID]cache.Cacher[uint64, map[ids.NodeID]*validators.GetValidatorOutput]), + log: log, + cfg: cfg, + validators: validatorManager, + state: state, + metrics: metrics, + clk: clk, + caches: make(map[ids.ID]cache.Cacher[uint64, map[ids.NodeID]*validators.GetValidatorOutput]), recentlyAccepted: window.New[ids.ID]( window.Config{ Clock: clk, @@ -112,11 +114,12 @@ func NewManager( // TODO: Remove requirement for the P-chain's context lock to be held when // calling exported functions. type manager struct { - log logging.Logger - cfg config.Config - state State - metrics metrics.Metrics - clk *mockable.Clock + log logging.Logger + cfg config.Config + validators validators.Manager + state State + metrics metrics.Metrics + clk *mockable.Clock // Maps caches for each subnet that is currently tracked. // Key: Subnet ID @@ -280,7 +283,7 @@ func (m *manager) makePrimaryNetworkValidatorSet( func (m *manager) getCurrentPrimaryValidatorSet( ctx context.Context, ) (map[ids.NodeID]*validators.GetValidatorOutput, uint64, error) { - primaryMap := m.cfg.Validators.GetMap(constants.PrimaryNetworkID) + primaryMap := m.validators.GetMap(constants.PrimaryNetworkID) currentHeight, err := m.getCurrentHeight(ctx) return primaryMap, currentHeight, err } @@ -342,8 +345,8 @@ func (m *manager) getCurrentValidatorSets( ctx context.Context, subnetID ids.ID, ) (map[ids.NodeID]*validators.GetValidatorOutput, map[ids.NodeID]*validators.GetValidatorOutput, uint64, error) { - subnetMap := m.cfg.Validators.GetMap(subnetID) - primaryMap := m.cfg.Validators.GetMap(constants.PrimaryNetworkID) + subnetMap := m.validators.GetMap(subnetID) + primaryMap := m.validators.GetMap(constants.PrimaryNetworkID) currentHeight, err := m.getCurrentHeight(ctx) return subnetMap, primaryMap, currentHeight, err } diff --git a/vms/platformvm/validators/manager_benchmark_test.go b/vms/platformvm/validators/manager_benchmark_test.go index 7c84589574df..dddbf5de799d 100644 --- a/vms/platformvm/validators/manager_benchmark_test.go +++ b/vms/platformvm/validators/manager_benchmark_test.go @@ -112,9 +112,8 @@ func BenchmarkGetValidatorSet(b *testing.B) { db, genesisBytes, prometheus.NewRegistry(), - &config.Config{ - Validators: vdrs, - }, + &config.Config{}, + vdrs, execConfig, &snow.Context{ NetworkID: constants.UnitTestID, @@ -133,9 +132,8 @@ func BenchmarkGetValidatorSet(b *testing.B) { m := NewManager( logging.NoLog{}, - config.Config{ - Validators: vdrs, - }, + config.Config{}, + vdrs, s, metrics, new(mockable.Clock), diff --git a/vms/platformvm/vm.go b/vms/platformvm/vm.go index 8c4b527e4539..ca5cc52dd10d 100644 --- a/vms/platformvm/vm.go +++ b/vms/platformvm/vm.go @@ -26,6 +26,7 @@ import ( "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/consensus/snowman" "github.com/ava-labs/avalanchego/snow/engine/common" + snowmanblock "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/snow/uptime" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils" @@ -36,6 +37,9 @@ import ( "github.com/ava-labs/avalanchego/version" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm/block" + blockbuilder "github.com/ava-labs/avalanchego/vms/platformvm/block/builder" + blockexecutor "github.com/ava-labs/avalanchego/vms/platformvm/block/executor" + "github.com/ava-labs/avalanchego/vms/platformvm/chaincreator" "github.com/ava-labs/avalanchego/vms/platformvm/config" "github.com/ava-labs/avalanchego/vms/platformvm/fx" "github.com/ava-labs/avalanchego/vms/platformvm/metrics" @@ -43,16 +47,12 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/reward" "github.com/ava-labs/avalanchego/vms/platformvm/state" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/vms/platformvm/txs/mempool" - "github.com/ava-labs/avalanchego/vms/platformvm/utxo" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - - snowmanblock "github.com/ava-labs/avalanchego/snow/engine/snowman/block" - blockbuilder "github.com/ava-labs/avalanchego/vms/platformvm/block/builder" - blockexecutor "github.com/ava-labs/avalanchego/vms/platformvm/block/executor" txbuilder "github.com/ava-labs/avalanchego/vms/platformvm/txs/builder" txexecutor "github.com/ava-labs/avalanchego/vms/platformvm/txs/executor" + "github.com/ava-labs/avalanchego/vms/platformvm/txs/mempool" + "github.com/ava-labs/avalanchego/vms/platformvm/utxo" pvalidators "github.com/ava-labs/avalanchego/vms/platformvm/validators" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" ) var ( @@ -68,6 +68,19 @@ type VM struct { network.Network validators.State + aliaser ids.Aliaser + + // Node's validator set maps subnetID -> validators of the subnet + // + // Invariant: The primary network's validator set should have been added to + // the ChainManager before calling VM.Initialize. + // Invariant: The primary network's validator set should be empty before + // calling VM.Initialize. + Validators validators.Manager + + // Provides access to the uptime ChainManager as a thread safe data structure + UptimeLockedCalculator uptime.LockedCalculator + metrics metrics.Metrics atomicUtxosManager avax.AtomicUTXOManager @@ -91,6 +104,8 @@ type VM struct { txBuilder txbuilder.Builder manager blockexecutor.Manager + chainCreator chaincreator.Interface + // Cancelled on shutdown onShutdownCtx context.Context // Call [onShutdownCtxCancel] to cancel [onShutdownCtx] during Shutdown() @@ -149,6 +164,7 @@ func (vm *VM) Initialize( vm.db, genesisBytes, registerer, + vm.Validators, &vm.Config, execConfig, vm.ctx, @@ -159,7 +175,14 @@ func (vm *VM) Initialize( return err } - validatorManager := pvalidators.NewManager(chainCtx.Log, vm.Config, vm.state, vm.metrics, &vm.clock) + validatorManager := pvalidators.NewManager( + chainCtx.Log, + vm.Config, + vm.Validators, + vm.state, + vm.metrics, + &vm.clock, + ) vm.State = validatorManager vm.atomicUtxosManager = avax.NewAtomicUTXOManager(chainCtx.SharedMemory, txs.Codec) utxoHandler := utxo.NewHandler(vm.ctx, &vm.clock, vm.fx) @@ -168,7 +191,7 @@ func (vm *VM) Initialize( vm.txBuilder = txbuilder.New( vm.ctx, - &vm.Config, + vm.Config, &vm.clock, vm.fx, vm.state, @@ -178,6 +201,7 @@ func (vm *VM) Initialize( txExecutorBackend := &txexecutor.Backend{ Config: &vm.Config, + ChainCreator: vm.chainCreator, Ctx: vm.ctx, Clk: &vm.clock, Fx: vm.fx, @@ -208,7 +232,7 @@ func (vm *VM) Initialize( chainCtx.ValidatorState, txVerifier, mempool, - txExecutorBackend.Config.PartialSyncPrimaryNetwork, + vm.Config.PartialSyncPrimaryNetwork, appSender, registerer, execConfig.Network, @@ -362,7 +386,9 @@ func (vm *VM) createSubnet(subnetID ids.ID) error { if !ok { return fmt.Errorf("expected tx type *txs.CreateChainTx but got %T", chain.Unsigned) } - vm.Config.CreateChain(chain.ID(), tx) + if err := vm.chainCreator.CreateChain(chain.ID(), tx.SubnetID, tx.GenesisData, tx.VMID, tx.FxIDs); err != nil { + return err //TODO check + } } return nil } @@ -499,6 +525,7 @@ func (vm *VM) CreateHandlers(context.Context) (map[string]http.Handler, error) { server.RegisterAfterFunc(vm.metrics.AfterRequest) service := &Service{ vm: vm, + aliaser: vm.aliaser, addrManager: avax.NewAddressManager(vm.ctx), stakerAttributesCache: &cache.LRU[ids.ID, *stakerAttributes]{ Size: stakerAttributesCacheSize, diff --git a/vms/platformvm/vm_regression_test.go b/vms/platformvm/vm_regression_test.go index 36186ec32ae0..8d93a17a4ea1 100644 --- a/vms/platformvm/vm_regression_test.go +++ b/vms/platformvm/vm_regression_test.go @@ -14,7 +14,6 @@ import ( "github.com/stretchr/testify/require" - "github.com/ava-labs/avalanchego/chains" "github.com/ava-labs/avalanchego/chains/atomic" "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/database/memdb" @@ -24,7 +23,6 @@ import ( "github.com/ava-labs/avalanchego/snow/consensus/snowman" "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/snowtest" - "github.com/ava-labs/avalanchego/snow/uptime" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/bls" @@ -364,15 +362,12 @@ func TestUnverifiedParentPanicRegression(t *testing.T) { atomicDB := prefixdb.New([]byte{1}, baseDB) vm := &VM{Config: config.Config{ - Chains: chains.TestManager, - Validators: validators.NewManager(), - UptimeLockedCalculator: uptime.NewLockedCalculator(), - MinStakeDuration: defaultMinStakingDuration, - MaxStakeDuration: defaultMaxStakingDuration, - RewardConfig: defaultRewardConfig, - BanffTime: latestForkTime, - CortinaTime: mockable.MaxTime, - DurangoTime: mockable.MaxTime, + MinStakeDuration: defaultMinStakingDuration, + MaxStakeDuration: defaultMaxStakingDuration, + RewardConfig: defaultRewardConfig, + BanffTime: latestForkTime, + CortinaTime: mockable.MaxTime, + DurangoTime: mockable.MaxTime, }} ctx := snowtest.Context(t, snowtest.PChainID) diff --git a/vms/platformvm/vm_test.go b/vms/platformvm/vm_test.go index 23e88a646368..66ed31307b78 100644 --- a/vms/platformvm/vm_test.go +++ b/vms/platformvm/vm_test.go @@ -14,7 +14,6 @@ import ( "github.com/stretchr/testify/require" - "github.com/ava-labs/avalanchego/chains" "github.com/ava-labs/avalanchego/chains/atomic" "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/database/memdb" @@ -35,7 +34,6 @@ import ( "github.com/ava-labs/avalanchego/snow/networking/sender" "github.com/ava-labs/avalanchego/snow/networking/timeout" "github.com/ava-labs/avalanchego/snow/snowtest" - "github.com/ava-labs/avalanchego/snow/uptime" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/subnets" "github.com/ava-labs/avalanchego/utils/constants" @@ -233,10 +231,7 @@ func defaultVM(t *testing.T, fork activeFork) (*VM, database.Database, *mutableS } vm := &VM{Config: config.Config{ - Chains: chains.TestManager, - UptimeLockedCalculator: uptime.NewLockedCalculator(), SybilProtectionEnabled: true, - Validators: validators.NewManager(), TxFee: defaultTxFee, CreateSubnetTxFee: 100 * defaultTxFee, TransformSubnetTxFee: 100 * defaultTxFee, @@ -1126,15 +1121,12 @@ func TestRestartFullyAccepted(t *testing.T) { firstDB := prefixdb.New([]byte{}, db) firstVM := &VM{Config: config.Config{ - Chains: chains.TestManager, - Validators: validators.NewManager(), - UptimeLockedCalculator: uptime.NewLockedCalculator(), - MinStakeDuration: defaultMinStakingDuration, - MaxStakeDuration: defaultMaxStakingDuration, - RewardConfig: defaultRewardConfig, - BanffTime: latestForkTime, - CortinaTime: latestForkTime, - DurangoTime: latestForkTime, + MinStakeDuration: defaultMinStakingDuration, + MaxStakeDuration: defaultMaxStakingDuration, + RewardConfig: defaultRewardConfig, + BanffTime: latestForkTime, + CortinaTime: latestForkTime, + DurangoTime: latestForkTime, }} firstCtx := snowtest.Context(t, snowtest.PChainID) @@ -1213,15 +1205,12 @@ func TestRestartFullyAccepted(t *testing.T) { firstCtx.Lock.Unlock() secondVM := &VM{Config: config.Config{ - Chains: chains.TestManager, - Validators: validators.NewManager(), - UptimeLockedCalculator: uptime.NewLockedCalculator(), - MinStakeDuration: defaultMinStakingDuration, - MaxStakeDuration: defaultMaxStakingDuration, - RewardConfig: defaultRewardConfig, - BanffTime: latestForkTime, - CortinaTime: latestForkTime, - DurangoTime: latestForkTime, + MinStakeDuration: defaultMinStakingDuration, + MaxStakeDuration: defaultMaxStakingDuration, + RewardConfig: defaultRewardConfig, + BanffTime: latestForkTime, + CortinaTime: latestForkTime, + DurangoTime: latestForkTime, }} secondCtx := snowtest.Context(t, snowtest.PChainID) @@ -1263,15 +1252,12 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { require.NoError(err) vm := &VM{Config: config.Config{ - Chains: chains.TestManager, - Validators: validators.NewManager(), - UptimeLockedCalculator: uptime.NewLockedCalculator(), - MinStakeDuration: defaultMinStakingDuration, - MaxStakeDuration: defaultMaxStakingDuration, - RewardConfig: defaultRewardConfig, - BanffTime: latestForkTime, - CortinaTime: latestForkTime, - DurangoTime: latestForkTime, + MinStakeDuration: defaultMinStakingDuration, + MaxStakeDuration: defaultMaxStakingDuration, + RewardConfig: defaultRewardConfig, + BanffTime: latestForkTime, + CortinaTime: latestForkTime, + DurangoTime: latestForkTime, }} initialClkTime := latestForkTime.Add(time.Second) @@ -1604,15 +1590,12 @@ func TestUnverifiedParent(t *testing.T) { require := require.New(t) vm := &VM{Config: config.Config{ - Chains: chains.TestManager, - Validators: validators.NewManager(), - UptimeLockedCalculator: uptime.NewLockedCalculator(), - MinStakeDuration: defaultMinStakingDuration, - MaxStakeDuration: defaultMaxStakingDuration, - RewardConfig: defaultRewardConfig, - BanffTime: latestForkTime, - CortinaTime: latestForkTime, - DurangoTime: latestForkTime, + MinStakeDuration: defaultMinStakingDuration, + MaxStakeDuration: defaultMaxStakingDuration, + RewardConfig: defaultRewardConfig, + BanffTime: latestForkTime, + CortinaTime: latestForkTime, + DurangoTime: latestForkTime, }} initialClkTime := latestForkTime.Add(time.Second) @@ -1768,14 +1751,11 @@ func TestUptimeDisallowedWithRestart(t *testing.T) { firstDB := prefixdb.New([]byte{}, db) const firstUptimePercentage = 20 // 20% firstVM := &VM{Config: config.Config{ - Chains: chains.TestManager, - UptimePercentage: firstUptimePercentage / 100., - RewardConfig: defaultRewardConfig, - Validators: validators.NewManager(), - UptimeLockedCalculator: uptime.NewLockedCalculator(), - BanffTime: latestForkTime, - CortinaTime: latestForkTime, - DurangoTime: latestForkTime, + UptimePercentage: firstUptimePercentage / 100., + RewardConfig: defaultRewardConfig, + BanffTime: latestForkTime, + CortinaTime: latestForkTime, + DurangoTime: latestForkTime, }} firstCtx := snowtest.Context(t, snowtest.PChainID) @@ -1817,13 +1797,10 @@ func TestUptimeDisallowedWithRestart(t *testing.T) { secondDB := prefixdb.New([]byte{}, db) const secondUptimePercentage = 21 // 21% > firstUptimePercentage, so uptime for reward is not met now secondVM := &VM{Config: config.Config{ - Chains: chains.TestManager, - UptimePercentage: secondUptimePercentage / 100., - Validators: validators.NewManager(), - UptimeLockedCalculator: uptime.NewLockedCalculator(), - BanffTime: latestForkTime, - CortinaTime: latestForkTime, - DurangoTime: latestForkTime, + UptimePercentage: secondUptimePercentage / 100., + BanffTime: latestForkTime, + CortinaTime: latestForkTime, + DurangoTime: latestForkTime, }} secondCtx := snowtest.Context(t, snowtest.PChainID) @@ -1915,14 +1892,11 @@ func TestUptimeDisallowedAfterNeverConnecting(t *testing.T) { db := memdb.New() vm := &VM{Config: config.Config{ - Chains: chains.TestManager, - UptimePercentage: .2, - RewardConfig: defaultRewardConfig, - Validators: validators.NewManager(), - UptimeLockedCalculator: uptime.NewLockedCalculator(), - BanffTime: latestForkTime, - CortinaTime: latestForkTime, - DurangoTime: latestForkTime, + UptimePercentage: .2, + RewardConfig: defaultRewardConfig, + BanffTime: latestForkTime, + CortinaTime: latestForkTime, + DurangoTime: latestForkTime, }} ctx := snowtest.Context(t, snowtest.PChainID)