-
Notifications
You must be signed in to change notification settings - Fork 4
Ensure Non-Validators and Validators Bootstrap Before Indexing and Verifying Blocks #573
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b58c69e
2873d6b
32159a9
5b06b79
5c7afc8
b4f07f1
bc4270a
8a741ee
002a90a
2803568
bfbc3ef
64e89d4
a9d458f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -113,13 +113,8 @@ func (i *Instance) Start(ctx context.Context) error { | |
|
|
||
| context.AfterFunc(ctx, i.Stop) | ||
|
|
||
| nodes, epochNum, err := getLastAcceptedEpochAndValidatorSet(&i.Config) | ||
| if err != nil { | ||
| return fmt.Errorf("error determining latest epoch and validator set: %w", err) | ||
| } | ||
|
|
||
| if err := i.startAtEpoch(nodes); err != nil { | ||
| return fmt.Errorf("error starting instance at epoch %d: %w", epochNum, err) | ||
| if err := i.maybeReplicateEpochs(); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| go i.tick() | ||
|
|
@@ -128,6 +123,32 @@ func (i *Instance) Start(ctx context.Context) error { | |
| return nil | ||
| } | ||
|
|
||
| func (i *Instance) maybeReplicateEpochs() error { | ||
| i.Config.Logger.Debug("Checking if epoch replication is required") | ||
| latestValidatorSet, err := getLatestPlatformChainValidatorSet(i.Config.PlatformChain) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| latestIndexedEpochValidators, err := getLastAcceptedValidatorSet(&i.Config) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| // We have indexed the latest validator set, therefore we can skip epoch replication and start as a validator. | ||
| // Note: this may not be the latest epoch, but a future PR will eventually notice we are behind and transition properly. | ||
| if latestIndexedEpochValidators.Equal(latestValidatorSet.Nodes()) && latestValidatorSet.Nodes().Contains(i.Config.ID) { | ||
|
samliok marked this conversation as resolved.
|
||
| i.Config.Logger.Debug("Node skipping epoch replication because its latest epoch is up to date with the Platform Chain") | ||
| return i.startValidator(latestIndexedEpochValidators) | ||
| } | ||
|
|
||
| // Start as non-validator if our last indexed validator set does not equal, the latest p-chain validator set | ||
| // Note: the epoch may be transitioning, so the latest p-chain validator set actually points to a future epoch. | ||
| // The non-validator should finish replicating epochs and convert our non-validator to a validator in this case. | ||
| i.Config.Logger.Debug("Node starting epoch replication as a non-validator") | ||
| return i.startNonValidator(false) | ||
| } | ||
|
|
||
| func (i *Instance) startValidator(validators common.Nodes) error { | ||
| epochConfig, err := i.createEpochConfig(validators) | ||
| if err != nil { | ||
|
|
@@ -146,8 +167,10 @@ func (i *Instance) startValidator(validators common.Nodes) error { | |
| return epoch.Start() | ||
| } | ||
|
|
||
| func (i *Instance) startNonValidator() error { | ||
| config, err := i.createNonValidatorConfig() | ||
| // startNonValidator runs a non-validator. epochsReplicated is true when we already hold the | ||
| // newest sealing block, such as when a validator leaves the validator set. | ||
| func (i *Instance) startNonValidator(epochsReplicated bool) error { | ||
| config, err := i.createNonValidatorConfig(epochsReplicated) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
@@ -162,19 +185,18 @@ func (i *Instance) startNonValidator() error { | |
| return nil | ||
| } | ||
|
|
||
| func (i *Instance) createNonValidatorConfig() (nonvalidator.Config, error) { | ||
| func (i *Instance) createNonValidatorConfig(epochsReplicated bool) (nonvalidator.Config, error) { | ||
| source, err := simplex.NewRandomSource() | ||
| if err != nil { | ||
| return nonvalidator.Config{}, err | ||
| } | ||
|
|
||
| height := i.Config.PlatformChain.GetCurrentHeight() | ||
| mappings, err := i.Config.PlatformChain.GetValidatorSet(height) | ||
| latestValidatorSet, err := getLatestPlatformChainValidatorSet(i.Config.PlatformChain) | ||
| if err != nil { | ||
| return nonvalidator.Config{}, err | ||
| } | ||
|
|
||
| comm := newCommunication(i.Config.Sender, i.Config.Broadcaster, mappings.Nodes()) | ||
| comm := newCommunication(i.Config.Sender, i.Config.Broadcaster, latestValidatorSet.Nodes()) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unrelated to this PR, but... what updates the comm's validator set once we move through epochs after we bootstrap?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yea we need to change the non-validator comm to not hardcode its |
||
|
|
||
| // Plant an artificial MSM. A non-validator never verifies the state machine transition, | ||
| // it only verifies the inner block (see common.OnlyVMVerifyOpt), so this MSM is only | ||
|
|
@@ -203,6 +225,7 @@ func (i *Instance) createNonValidatorConfig() (nonvalidator.Config, error) { | |
| SignatureAggregatorCreator: i.Config.CryptoOps.CreateSignatureAggregator, | ||
| MaxSequenceWindow: simplex.DefaultMaxRoundWindow, | ||
| TransitionToValidator: i.notifyEpochChange, | ||
| EpochsReplicated: epochsReplicated, | ||
| } | ||
| return config, nil | ||
| } | ||
|
|
@@ -353,13 +376,15 @@ func (i *Instance) HandleMessage(msg *common.Message, from common.NodeID) error | |
| i.msm.HandleApproval(msg.EpochTransitionApproval, uint64(time.Now().UnixMilli())) | ||
| return nil | ||
| } | ||
|
|
||
| return i.e.HandleMessage(msg, from) | ||
| } | ||
|
|
||
| if i.nv != nil { | ||
| return i.nv.HandleMessage(msg, from) | ||
| } | ||
| return nil | ||
|
|
||
| return errors.New("we are not running as a validator or not validator") | ||
| } | ||
|
|
||
| func (i *Instance) wireReplicationResponse(msg *common.Message) error { | ||
|
|
@@ -594,7 +619,7 @@ func (i *Instance) startAtEpoch(validators common.Nodes) error { | |
| return i.startValidator(validators) | ||
| } | ||
|
|
||
| return i.startNonValidator() | ||
| return i.startNonValidator(true) | ||
| } | ||
|
|
||
| type epochConfig struct { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.