Skip to content

Commit 6a8c0bd

Browse files
Add Primary Network Partial Sync Option (#1769)
Co-authored-by: Stephen Buttolph <stephen@avalabs.org>
1 parent 0ffbfaf commit 6a8c0bd

File tree

16 files changed

+111
-18
lines changed

16 files changed

+111
-18
lines changed

chains/manager.go

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,11 @@ var (
8787
// Bootstrapping prefixes for ChainVMs
8888
bootstrappingDB = []byte("bs")
8989

90-
errUnknownVMType = errors.New("the vm should have type avalanche.DAGVM or snowman.ChainVM")
91-
errCreatePlatformVM = errors.New("attempted to create a chain running the PlatformVM")
92-
errNotBootstrapped = errors.New("subnets not bootstrapped")
93-
errNoPrimaryNetworkConfig = errors.New("no subnet config for primary network found")
90+
errUnknownVMType = errors.New("the vm should have type avalanche.DAGVM or snowman.ChainVM")
91+
errCreatePlatformVM = errors.New("attempted to create a chain running the PlatformVM")
92+
errNotBootstrapped = errors.New("subnets not bootstrapped")
93+
errNoPrimaryNetworkConfig = errors.New("no subnet config for primary network found")
94+
errPartialSyncAsAValidator = errors.New("partial sync should not be configured for a validator")
9495

9596
_ Manager = (*manager)(nil)
9697
)
@@ -185,7 +186,8 @@ type ManagerConfig struct {
185186
Validators validators.Manager // Validators validating on this chain
186187
NodeID ids.NodeID // The ID of this node
187188
NetworkID uint32 // ID of the network this node is connected to
188-
Server server.Server // Handles HTTP API calls
189+
PartialSyncPrimaryNetwork bool
190+
Server server.Server // Handles HTTP API calls
189191
Keystore keystore.Keystore
190192
AtomicMemory *atomic.Memory
191193
AVAXAssetID ids.ID
@@ -1212,6 +1214,7 @@ func (m *manager) createSnowmanChain(
12121214
Validators: vdrs,
12131215
Params: consensusParams,
12141216
Consensus: consensus,
1217+
PartialSync: m.PartialSyncPrimaryNetwork && commonCfg.Ctx.ChainID == constants.PlatformChainID,
12151218
}
12161219
engine, err := smeng.New(engineConfig)
12171220
if err != nil {
@@ -1321,6 +1324,32 @@ func (m *manager) registerBootstrappedHealthChecks() error {
13211324
if err := m.Health.RegisterHealthCheck("bootstrapped", bootstrappedCheck, health.ApplicationTag); err != nil {
13221325
return fmt.Errorf("couldn't register bootstrapped health check: %w", err)
13231326
}
1327+
1328+
// We should only report unhealthy if the node is partially syncing the
1329+
// primary network and is a validator.
1330+
if !m.PartialSyncPrimaryNetwork {
1331+
return nil
1332+
}
1333+
1334+
partialSyncCheck := health.CheckerFunc(func(ctx context.Context) (interface{}, error) {
1335+
// Note: The health check is skipped during bootstrapping to allow a
1336+
// node to sync the network even if it was previously a validator.
1337+
if !m.IsBootstrapped(constants.PlatformChainID) {
1338+
return "node is currently bootstrapping", nil
1339+
}
1340+
if !validators.Contains(m.Validators, constants.PrimaryNetworkID, m.NodeID) {
1341+
return "node is not a primary network validator", nil
1342+
}
1343+
1344+
m.Log.Warn("node is a primary network validator",
1345+
zap.Error(errPartialSyncAsAValidator),
1346+
)
1347+
return "node is a primary network validator", errPartialSyncAsAValidator
1348+
})
1349+
1350+
if err := m.Health.RegisterHealthCheck("validation", partialSyncCheck, health.ApplicationTag); err != nil {
1351+
return fmt.Errorf("couldn't register validation health check: %w", err)
1352+
}
13241353
return nil
13251354
}
13261355

config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,7 @@ func getStakingConfig(v *viper.Viper, networkID uint32) (node.StakingConfig, err
777777
config := node.StakingConfig{
778778
SybilProtectionEnabled: v.GetBool(SybilProtectionEnabledKey),
779779
SybilProtectionDisabledWeight: v.GetUint64(SybilProtectionDisabledWeightKey),
780+
PartialSyncPrimaryNetwork: v.GetBool(PartialSyncPrimaryNetworkKey),
780781
StakingKeyPath: GetExpandedArg(v, StakingTLSKeyPathKey),
781782
StakingCertPath: GetExpandedArg(v, StakingCertPathKey),
782783
StakingSignerPath: GetExpandedArg(v, StakingSignerKeyPathKey),

config/flags.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ func addNodeFlags(fs *pflag.FlagSet) {
261261
fs.String(StakingSignerKeyContentKey, "", "Specifies base64 encoded signer private key for staking")
262262
fs.Bool(SybilProtectionEnabledKey, true, "Enables sybil protection. If enabled, Network TLS is required")
263263
fs.Uint64(SybilProtectionDisabledWeightKey, 100, "Weight to provide to each peer when sybil protection is disabled")
264+
fs.Bool(PartialSyncPrimaryNetworkKey, false, "Only sync the P-chain on the Primary Network. If the node is a Primary Network validator, it will report unhealthy")
264265
// Uptime Requirement
265266
fs.Float64(UptimeRequirementKey, genesis.LocalParams.UptimeRequirement, "Fraction of time a validator must be online to receive rewards")
266267
// Minimum Stake required to validate the Primary Network

config/keys.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ const (
129129
SnowOptimalProcessingKey = "snow-optimal-processing"
130130
SnowMaxProcessingKey = "snow-max-processing"
131131
SnowMaxTimeProcessingKey = "snow-max-time-processing"
132+
PartialSyncPrimaryNetworkKey = "partial-sync-primary-network"
132133
TrackSubnetsKey = "track-subnets"
133134
AdminAPIEnabledKey = "api-admin-enabled"
134135
InfoAPIEnabledKey = "api-info-enabled"

node/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ type IPConfig struct {
9292
type StakingConfig struct {
9393
genesis.StakingConfig
9494
SybilProtectionEnabled bool `json:"sybilProtectionEnabled"`
95+
PartialSyncPrimaryNetwork bool `json:"partialSyncPrimaryNetwork"`
9596
StakingTLSCert tls.Certificate `json:"-"`
9697
StakingSigningKey *bls.SecretKey `json:"-"`
9798
SybilProtectionDisabledWeight uint64 `json:"sybilProtectionDisabledWeight"`

node/node.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,7 @@ func (n *Node) initChainManager(avaxAssetID ids.ID) error {
818818
Router: n.Config.ConsensusRouter,
819819
Net: n.Net,
820820
Validators: n.vdrs,
821+
PartialSyncPrimaryNetwork: n.Config.PartialSyncPrimaryNetwork,
821822
NodeID: n.ID,
822823
NetworkID: n.Config.NetworkID,
823824
Server: n.APIServer,
@@ -886,6 +887,7 @@ func (n *Node) initVMs() error {
886887
Validators: vdrs,
887888
UptimeLockedCalculator: n.uptimeCalculator,
888889
SybilProtectionEnabled: n.Config.SybilProtectionEnabled,
890+
PartialSyncPrimaryNetwork: n.Config.PartialSyncPrimaryNetwork,
889891
TrackedSubnets: n.Config.TrackedSubnets,
890892
TxFee: n.Config.TxFee,
891893
CreateAssetTxFee: n.Config.CreateAssetTxFee,

snow/engine/snowman/config.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ import (
1616
type Config struct {
1717
common.AllGetsServer
1818

19-
Ctx *snow.ConsensusContext
20-
VM block.ChainVM
21-
Sender common.Sender
22-
Validators validators.Set
23-
Params snowball.Parameters
24-
Consensus snowman.Consensus
19+
Ctx *snow.ConsensusContext
20+
VM block.ChainVM
21+
Sender common.Sender
22+
Validators validators.Set
23+
Params snowball.Parameters
24+
Consensus snowman.Consensus
25+
PartialSync bool
2526
}

snow/engine/snowman/transitive.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,9 @@ func (t *Transitive) GetBlock(ctx context.Context, blkID ids.ID) (snowman.Block,
455455

456456
func (t *Transitive) sendChits(ctx context.Context, nodeID ids.NodeID, requestID uint32) {
457457
lastAccepted := t.Consensus.LastAccepted()
458-
if t.Ctx.StateSyncing.Get() {
458+
// If we aren't fully verifying blocks, only vote for blocks that are widely
459+
// preferred by the validator set.
460+
if t.Ctx.StateSyncing.Get() || t.Config.PartialSync {
459461
t.Sender.SendChits(ctx, nodeID, requestID, lastAccepted, lastAccepted)
460462
} else {
461463
t.Sender.SendChits(ctx, nodeID, requestID, t.Consensus.Preference(), lastAccepted)

vms/platformvm/blocks/builder/builder.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,12 @@ func (b *builder) AddUnverifiedTx(tx *txs.Tx) error {
147147
return err
148148
}
149149

150-
if err := b.Mempool.Add(tx); err != nil {
151-
return err
150+
// If we are partially syncing the Primary Network, we should not be
151+
// maintaining the transaction mempool locally.
152+
if !b.txExecutorBackend.Config.PartialSyncPrimaryNetwork {
153+
if err := b.Mempool.Add(tx); err != nil {
154+
return err
155+
}
152156
}
153157
return b.GossipTx(tx)
154158
}

vms/platformvm/blocks/builder/network.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ type Network interface {
3737

3838
type network struct {
3939
ctx *snow.Context
40-
blkBuilder Builder
40+
blkBuilder *builder
4141

4242
// gossip related attributes
4343
appSender common.AppSender
@@ -99,6 +99,13 @@ func (n *network) AppGossip(_ context.Context, nodeID ids.NodeID, msgBytes []byt
9999
zap.Int("messageLen", len(msgBytes)),
100100
)
101101

102+
if n.blkBuilder.txExecutorBackend.Config.PartialSyncPrimaryNetwork {
103+
n.ctx.Log.Debug("dropping AppGossip message",
104+
zap.String("reason", "primary network is not being fully synced"),
105+
)
106+
return nil
107+
}
108+
102109
msgIntf, err := message.Parse(msgBytes)
103110
if err != nil {
104111
n.ctx.Log.Debug("dropping AppGossip message",

0 commit comments

Comments
 (0)