Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 34 additions & 6 deletions chains/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,11 @@ var (
// Bootstrapping prefixes for ChainVMs
bootstrappingDB = []byte("bs")

errUnknownVMType = errors.New("the vm should have type avalanche.DAGVM or snowman.ChainVM")
errCreatePlatformVM = errors.New("attempted to create a chain running the PlatformVM")
errNotBootstrapped = errors.New("subnets not bootstrapped")
errNoPrimaryNetworkConfig = errors.New("no subnet config for primary network found")
errUnknownVMType = errors.New("the vm should have type avalanche.DAGVM or snowman.ChainVM")
errCreatePlatformVM = errors.New("attempted to create a chain running the PlatformVM")
errNotBootstrapped = errors.New("subnets not bootstrapped")
errNoPrimaryNetworkConfig = errors.New("no subnet config for primary network found")
errNoLiteSyncForValidators = errors.New("lite sync cannot be configured for a validator")

_ Manager = (*manager)(nil)
)
Expand Down Expand Up @@ -183,7 +184,7 @@ type ManagerConfig struct {
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
ReducedMode bool
LiteSyncPrimaryNetwork bool
NodeID ids.NodeID // The ID of this node
NetworkID uint32 // ID of the network this node is connected to
Server server.Server // Handles HTTP API calls
Expand Down Expand Up @@ -870,7 +871,6 @@ func (m *manager) createAvalancheChain(
Validators: vdrs,
Params: consensusParams,
Consensus: snowmanConsensus,
ReducedMode: m.ReducedMode && snowmanCommonCfg.Ctx.ChainID == constants.PlatformChainID,
}
snowmanEngine, err := smeng.New(snowmanEngineConfig)
if err != nil {
Expand Down Expand Up @@ -1214,6 +1214,7 @@ func (m *manager) createSnowmanChain(
Validators: vdrs,
Params: consensusParams,
Consensus: consensus,
LiteSync: m.LiteSyncPrimaryNetwork && commonCfg.Ctx.ChainID == constants.PlatformChainID,
}
engine, err := smeng.New(engineConfig)
if err != nil {
Expand Down Expand Up @@ -1323,6 +1324,33 @@ func (m *manager) registerBootstrappedHealthChecks() error {
if err := m.Health.RegisterHealthCheck("bootstrapped", bootstrappedCheck, health.ApplicationTag); err != nil {
return fmt.Errorf("couldn't register bootstrapped health check: %w", err)
}

// If the node is not lite syncing the Primary Network, there is no reason
// to shutdown if it is a validator.
if !m.LiteSyncPrimaryNetwork {
return nil
}

liteSyncCheck := health.CheckerFunc(func(ctx context.Context) (interface{}, error) {
// Note: The health check is skipped during bootstrapping to allow a
// node to sync the network even if it was previously a validator.
if !m.IsBootstrapped(constants.PlatformChainID) {
return "node is currently bootstrapping", nil
}
if !validators.Contains(m.Validators, constants.PrimaryNetworkID, m.NodeID) {
return "node is not a primary network validator", nil
}

m.Log.Fatal("node is a primary network validator. Shutting down...",
zap.Error(errNoLiteSyncForValidators),
)
go m.ShutdownNodeFunc(1)
return "node is a primary network validator", errNoLiteSyncForValidators
})

if err := m.Health.RegisterHealthCheck("validation", liteSyncCheck, health.ApplicationTag); err != nil {
return fmt.Errorf("couldn't register validation health check: %w", err)
}
return nil
}

Expand Down
2 changes: 1 addition & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,7 @@ func getStakingConfig(v *viper.Viper, networkID uint32) (node.StakingConfig, err
config := node.StakingConfig{
SybilProtectionEnabled: v.GetBool(SybilProtectionEnabledKey),
SybilProtectionDisabledWeight: v.GetUint64(SybilProtectionDisabledWeightKey),
ReducedMode: v.GetBool(ReducedModeKey),
LiteSyncPrimaryNetwork: v.GetBool(LiteSyncPrimaryNetworkKey),
StakingKeyPath: GetExpandedArg(v, StakingTLSKeyPathKey),
StakingCertPath: GetExpandedArg(v, StakingCertPathKey),
StakingSignerPath: GetExpandedArg(v, StakingSignerKeyPathKey),
Expand Down
2 changes: 1 addition & 1 deletion config/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ func addNodeFlags(fs *pflag.FlagSet) {
fs.String(StakingSignerKeyContentKey, "", "Specifies base64 encoded signer private key for staking")
fs.Bool(SybilProtectionEnabledKey, true, "Enables sybil protection. If enabled, Network TLS is required")
fs.Uint64(SybilProtectionDisabledWeightKey, 100, "Weight to provide to each peer when sybil protection is disabled")
fs.Bool(ReducedModeKey, false, "Disable C-chain and X-chain validation. Only allowed for non-validators. Node would shutdown otherwise")
fs.Bool(LiteSyncPrimaryNetworkKey, false, "Only sync the P-chain on the Primary Network. If the node is a Primary Network validator, it will shutdown")
// Uptime Requirement
fs.Float64(UptimeRequirementKey, genesis.LocalParams.UptimeRequirement, "Fraction of time a validator must be online to receive rewards")
// Minimum Stake required to validate the Primary Network
Expand Down
2 changes: 1 addition & 1 deletion config/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ const (
StakingSignerKeyContentKey = "staking-signer-key-file-content"
SybilProtectionEnabledKey = "sybil-protection-enabled"
SybilProtectionDisabledWeightKey = "sybil-protection-disabled-weight"
ReducedModeKey = "reduced-mode"
NetworkInitialTimeoutKey = "network-initial-timeout"
NetworkMinimumTimeoutKey = "network-minimum-timeout"
NetworkMaximumTimeoutKey = "network-maximum-timeout"
Expand Down Expand Up @@ -130,6 +129,7 @@ const (
SnowOptimalProcessingKey = "snow-optimal-processing"
SnowMaxProcessingKey = "snow-max-processing"
SnowMaxTimeProcessingKey = "snow-max-time-processing"
LiteSyncPrimaryNetworkKey = "lite-sync-primary-network"
TrackSubnetsKey = "track-subnets"
AdminAPIEnabledKey = "api-admin-enabled"
InfoAPIEnabledKey = "api-info-enabled"
Expand Down
2 changes: 1 addition & 1 deletion node/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ type IPConfig struct {
type StakingConfig struct {
genesis.StakingConfig
SybilProtectionEnabled bool `json:"sybilProtectionEnabled"`
ReducedMode bool `json:"reducedModeEnabled"`
LiteSyncPrimaryNetwork bool `json:"liteSyncPrimaryNetwork"`
StakingTLSCert tls.Certificate `json:"-"`
StakingSigningKey *bls.SecretKey `json:"-"`
SybilProtectionDisabledWeight uint64 `json:"sybilProtectionDisabledWeight"`
Expand Down
24 changes: 4 additions & 20 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,8 @@ var (
genesisHashKey = []byte("genesisID")
indexerDBPrefix = []byte{0x00}

errInvalidTLSKey = errors.New("invalid TLS key")
errShuttingDown = errors.New("server shutting down")
errNoReducedModeForValidators = errors.New("reduced mode cannot be configured for validators")
errInvalidTLSKey = errors.New("invalid TLS key")
errShuttingDown = errors.New("server shutting down")
)

// Node is an instance of an Avalanche node.
Expand Down Expand Up @@ -818,7 +817,7 @@ func (n *Node) initChainManager(avaxAssetID ids.ID) error {
Router: n.Config.ConsensusRouter,
Net: n.Net,
Validators: n.vdrs,
ReducedMode: n.Config.ReducedMode,
LiteSyncPrimaryNetwork: n.Config.LiteSyncPrimaryNetwork,
NodeID: n.ID,
NetworkID: n.Config.NetworkID,
Server: n.APIServer,
Expand Down Expand Up @@ -887,7 +886,7 @@ func (n *Node) initVMs() error {
Validators: vdrs,
UptimeLockedCalculator: n.uptimeCalculator,
SybilProtectionEnabled: n.Config.SybilProtectionEnabled,
ReducedMode: n.Config.ReducedMode,
LiteSyncPrimaryNetwork: n.Config.LiteSyncPrimaryNetwork,
TrackedSubnets: n.Config.TrackedSubnets,
TxFee: n.Config.TxFee,
CreateAssetTxFee: n.Config.CreateAssetTxFee,
Expand Down Expand Up @@ -1171,20 +1170,6 @@ func (n *Node) initHealthAPI() error {
return fmt.Errorf("couldn't register resource health check: %w", err)
}

reducedModeCheck := health.CheckerFunc(func(ctx context.Context) (interface{}, error) {
primaryValidators, _ := n.vdrs.Get(constants.PrimaryNetworkID)
if n.Config.ReducedMode && primaryValidators.GetWeight(n.ID) != 0 {
n.Log.Fatal(fmt.Sprintf("%s. Shutting down...", errNoReducedModeForValidators.Error()))
go n.Shutdown(1)
return nil, errNoReducedModeForValidators
}
return nil, nil
})
err = n.health.RegisterHealthCheck("reducedmode", reducedModeCheck, health.ApplicationTag)
if err != nil {
return fmt.Errorf("couldn't register reduced mode health check: %w", err)
}

handler, err := health.NewGetAndPostHandler(n.Log, healthChecker)
if err != nil {
return err
Expand Down Expand Up @@ -1445,7 +1430,6 @@ func (n *Node) Initialize(

// Start the Health API
// Has to be initialized before chain manager
// Has to be initialized after Validators Set
// [n.Net] must already be set
if err := n.initHealthAPI(); err != nil {
return fmt.Errorf("couldn't initialize health API: %w", err)
Expand Down
14 changes: 7 additions & 7 deletions snow/engine/snowman/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ import (
type Config struct {
common.AllGetsServer

Ctx *snow.ConsensusContext
VM block.ChainVM
Sender common.Sender
Validators validators.Set
Params snowball.Parameters
Consensus snowman.Consensus
ReducedMode bool
Ctx *snow.ConsensusContext
VM block.ChainVM
Sender common.Sender
Validators validators.Set
Params snowball.Parameters
Consensus snowman.Consensus
LiteSync bool
}
2 changes: 1 addition & 1 deletion snow/engine/snowman/transitive.go
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ func (t *Transitive) GetBlock(ctx context.Context, blkID ids.ID) (snowman.Block,

func (t *Transitive) sendChits(ctx context.Context, nodeID ids.NodeID, requestID uint32) {
lastAccepted := t.Consensus.LastAccepted()
if t.Ctx.StateSyncing.Get() || t.Config.ReducedMode {
if t.Ctx.StateSyncing.Get() || t.Config.LiteSync {
t.Sender.SendChits(ctx, nodeID, requestID, lastAccepted, lastAccepted)
} else {
t.Sender.SendChits(ctx, nodeID, requestID, t.Consensus.Preference(), lastAccepted)
Expand Down
8 changes: 6 additions & 2 deletions vms/platformvm/blocks/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,12 @@ func (b *builder) AddUnverifiedTx(tx *txs.Tx) error {
return err
}

if err := b.Mempool.Add(tx); err != nil {
return err
// If we are lite syncing the Primary Network, we should not be maintaining
// the transaction mempool locally.
if !b.txExecutorBackend.Config.LiteSyncPrimaryNetwork {
if err := b.Mempool.Add(tx); err != nil {
return err
}
}
return b.GossipTx(tx)
}
Expand Down
5 changes: 4 additions & 1 deletion vms/platformvm/blocks/executor/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ func NewManager(
validators: validatorManager,
bootstrapped: txExecutorBackend.Bootstrapped,
},
rejector: &rejector{backend: backend},
rejector: &rejector{
backend: backend,
addTxsToMempool: !txExecutorBackend.Config.LiteSyncPrimaryNetwork,
},
}
}

Expand Down
5 changes: 5 additions & 0 deletions vms/platformvm/blocks/executor/rejector.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ var _ blocks.Visitor = (*rejector)(nil)
// being shutdown.
type rejector struct {
*backend
addTxsToMempool bool
}

func (r *rejector) BanffAbortBlock(b *blocks.BanffAbortBlock) error {
Expand Down Expand Up @@ -66,6 +67,10 @@ func (r *rejector) rejectBlock(b blocks.Block, blockType string) error {
zap.Stringer("parentID", b.Parent()),
)

if !r.addTxsToMempool {
return nil
}

for _, tx := range b.Txs() {
if err := r.Mempool.Add(tx); err != nil {
r.ctx.Log.Debug(
Expand Down
1 change: 1 addition & 0 deletions vms/platformvm/blocks/executor/rejector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ func TestRejectBlock(t *testing.T) {
Mempool: mempool,
state: state,
},
addTxsToMempool: true,
}

// Set expected calls on dependencies.
Expand Down
4 changes: 2 additions & 2 deletions vms/platformvm/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ type Config struct {
// True if the node is being run with staking enabled
SybilProtectionEnabled bool

// If true, C-chain and X-chain won't be instantiated. Allowed only while node is non-validator
ReducedMode bool
// If true, only the P-chain will be instantiated on the primary network.
LiteSyncPrimaryNetwork bool

// Set of subnets that this node is validating
TrackedSubnets set.Set[ids.ID]
Expand Down
40 changes: 26 additions & 14 deletions vms/platformvm/txs/executor/standard_tx_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"fmt"
"time"

"go.uber.org/zap"

"github.com/ava-labs/avalanchego/chains/atomic"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/constants"
Expand Down Expand Up @@ -136,7 +138,7 @@ func (e *StandardTxExecutor) ImportTx(tx *txs.ImportTx) error {
utxoIDs[i] = utxoID[:]
}

if e.Bootstrapped.Get() && !e.Config.ReducedMode {
if e.Bootstrapped.Get() && !e.Config.LiteSyncPrimaryNetwork {
if err := verify.SameSubnet(context.TODO(), e.Ctx, tx.SourceChain); err != nil {
return err
}
Expand Down Expand Up @@ -187,14 +189,14 @@ func (e *StandardTxExecutor) ImportTx(tx *txs.ImportTx) error {
// Produce the UTXOS
avax.Produce(e.State, txID, tx.Outs)

// we fill atomic requests even if reducedMode is enabled
// so to allow node to smoothly switch back from reducedMode
// Note: We apply atomic requests even if we are not verifying atomic
// requests to ensure the shared state will be correct if we later start
// verifying the requests.
e.AtomicRequests = map[ids.ID]*atomic.Requests{
tx.SourceChain: {
RemoveRequests: utxoIDs,
},
}

return nil
}

Expand Down Expand Up @@ -234,8 +236,9 @@ func (e *StandardTxExecutor) ExportTx(tx *txs.ExportTx) error {
// Produce the UTXOS
avax.Produce(e.State, txID, tx.Outs)

// we fill atomic requests even if reducedMode is enabled
// so to allow node to smoothly switch back from reducedMode
// Note: We apply atomic requests even if we are not verifying atomic
// requests to ensure the shared state will be correct if we later start
// verifying the requests.
elems := make([]*atomic.Element, len(tx.ExportedOutputs))
for i, out := range tx.ExportedOutputs {
utxo := &avax.UTXO{
Expand Down Expand Up @@ -284,10 +287,6 @@ func (e *StandardTxExecutor) AddValidatorTx(tx *txs.AddValidatorTx) error {
return err
}

if e.Config.ReducedMode && (tx.NodeID() == e.Ctx.NodeID) {
e.Ctx.Log.Warn("Verified transaction that would promote node %v to validator. Reduced mode is active and node will shutdown when validation will start.")
}

txID := e.Tx.ID()
newStaker, err := state.NewPendingStaker(txID, tx)
if err != nil {
Expand All @@ -298,6 +297,14 @@ func (e *StandardTxExecutor) AddValidatorTx(tx *txs.AddValidatorTx) error {
avax.Consume(e.State, tx.Ins)
avax.Produce(e.State, txID, tx.Outs)

if e.Config.LiteSyncPrimaryNetwork && tx.Validator.NodeID == e.Ctx.NodeID {
e.Ctx.Log.Warn("verified transaction that would shutdown this node",
zap.String("reason", "primary network is not being fully synced"),
zap.Stringer("txID", txID),
zap.String("txType", "addValidator"),
zap.Stringer("nodeID", tx.Validator.NodeID),
)
}
return nil
}

Expand Down Expand Up @@ -444,10 +451,15 @@ func (e *StandardTxExecutor) AddPermissionlessValidatorTx(tx *txs.AddPermissionl
avax.Consume(e.State, tx.Ins)
avax.Produce(e.State, txID, tx.Outs)

if e.Config.ReducedMode {
if tx.SubnetID() == constants.PrimaryNetworkID && tx.NodeID() == e.Ctx.NodeID {
e.Ctx.Log.Warn("Verified transaction that would promote node %v to validator. Reduced mode is active and node will shutdown when validation will start.")
}
if e.Config.LiteSyncPrimaryNetwork &&
tx.Subnet == constants.PrimaryNetworkID &&
tx.Validator.NodeID == e.Ctx.NodeID {
e.Ctx.Log.Warn("verified transaction that would shutdown this node",
zap.String("reason", "primary network is not being fully synced"),
zap.Stringer("txID", txID),
zap.String("txType", "addPermissionlessValidator"),
zap.Stringer("nodeID", tx.Validator.NodeID),
)
}

return nil
Expand Down
11 changes: 3 additions & 8 deletions vms/platformvm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,6 @@ func (vm *VM) Initialize(
if err != nil {
return err
}
// We don't bother checking whether reducedMode is allowed here
// (node must not be a primary network validator). Node-level health checks
// will take care of this and err

validatorManager := pvalidators.NewManager(chainCtx.Log, vm.Config, vm.state, vm.metrics, &vm.clock)
vm.State = validatorManager
Expand Down Expand Up @@ -219,7 +216,9 @@ func (vm *VM) Initialize(

// Create all chains that exist that this node validates.
func (vm *VM) initBlockchains() error {
if err := vm.createSubnet(constants.PrimaryNetworkID); err != nil {
if vm.Config.LiteSyncPrimaryNetwork {
vm.ctx.Log.Info("skipping primary network chain creation")
} else if err := vm.createSubnet(constants.PrimaryNetworkID); err != nil {
return err
}

Expand Down Expand Up @@ -254,10 +253,6 @@ func (vm *VM) createSubnet(subnetID ids.ID) error {
if !ok {
return fmt.Errorf("expected tx type *txs.CreateChainTx but got %T", chain.Unsigned)
}
if vm.Config.ReducedMode && tx.SubnetID == constants.PrimaryNetworkID {
vm.ctx.Log.Info("reduced mode enabled, skipping C-chain and X-chain validation.")
continue
}
vm.Config.CreateChain(chain.ID(), tx)
}
return nil
Expand Down