-
Notifications
You must be signed in to change notification settings - Fork 140
fix(dot/digest): verify if next epoch already contains some definition #2472
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 14 commits
18bf1d7
5ca05d0
44c3892
d69c694
27bd2e8
bbddab4
71309cf
58edb99
47c8836
931e8a0
73e3c33
38ddcaa
dfd06d2
89a119f
f4cc36a
71ee157
cdd29ea
d231f5a
16f35dc
1149c1f
ac0bdd4
1fd682d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -540,11 +540,29 @@ func (s *EpochState) StoreBABENextConfigData(epoch uint64, hash common.Hash, nex | |
// getting the set of hashes from the received epoch and for each hash | ||
// check if the header is in the database then it's been finalized and | ||
// thus we can also set the corresponding EpochData in the database | ||
func (s *EpochState) FinalizeBABENextEpochData(epoch uint64) error { | ||
func (s *EpochState) FinalizeBABENextEpochData(finalizedHeader *types.Header) error { | ||
s.nextEpochDataLock.Lock() | ||
defer s.nextEpochDataLock.Unlock() | ||
|
||
finalizedNextEpochData, err := lookupForNextEpochPersistedHash(s.nextEpochData, s, epoch) | ||
finalizedBlockEpoch, err := s.GetEpochForBlock(finalizedHeader) | ||
if err != nil { | ||
return fmt.Errorf("cannot get epoch for block %d (%s): %w", | ||
finalizedHeader.Number, finalizedHeader.Hash(), err) | ||
} | ||
|
||
nextEpoch := finalizedBlockEpoch + 1 | ||
|
||
epochInDatabase, err := s.getEpochDataInDatabase(nextEpoch) | ||
EclesioMeloJunior marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if err != nil && !errors.Is(err, chaindb.ErrKeyNotFound) { | ||
return fmt.Errorf("cannot check if next epoch data is already defined for epoch %d: %w", nextEpoch, err) | ||
} | ||
|
||
// config already defined we don't need to lookup in the map | ||
EclesioMeloJunior marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if epochInDatabase != nil { | ||
return nil | ||
} | ||
|
||
finalizedNextEpochData, err := findFinalizedHeaderForEpoch(s.nextEpochData, s, nextEpoch) | ||
if err != nil { | ||
return fmt.Errorf("cannot find next epoch data: %w", err) | ||
} | ||
|
@@ -554,14 +572,14 @@ func (s *EpochState) FinalizeBABENextEpochData(epoch uint64) error { | |
return fmt.Errorf("cannot transform epoch data: %w", err) | ||
} | ||
|
||
err = s.SetEpochData(epoch, ed) | ||
err = s.SetEpochData(nextEpoch, ed) | ||
if err != nil { | ||
return fmt.Errorf("cannot set epoch data: %w", err) | ||
} | ||
|
||
// remove previous epochs from the memory | ||
for e := range s.nextEpochData { | ||
if e <= epoch { | ||
if e <= nextEpoch { | ||
delete(s.nextEpochData, e) | ||
} | ||
} | ||
|
@@ -573,35 +591,56 @@ func (s *EpochState) FinalizeBABENextEpochData(epoch uint64) error { | |
// getting the set of hashes from the received epoch and for each hash | ||
// check if the header is in the database then it's been finalized and | ||
// thus we can also set the corresponding NextConfigData in the database | ||
func (s *EpochState) FinalizeBABENextConfigData(epoch uint64) error { | ||
func (s *EpochState) FinalizeBABENextConfigData(finalizedHeader *types.Header) error { | ||
s.nextConfigDataLock.Lock() | ||
defer s.nextConfigDataLock.Unlock() | ||
|
||
finalizedNextConfigData, err := lookupForNextEpochPersistedHash(s.nextConfigData, s, epoch) | ||
finalizedBlockEpoch, err := s.GetEpochForBlock(finalizedHeader) | ||
if err != nil { | ||
return fmt.Errorf("cannot get epoch for block %d (%s): %w", | ||
finalizedHeader.Number, finalizedHeader.Hash(), err) | ||
} | ||
|
||
nextEpoch := finalizedBlockEpoch + 1 | ||
|
||
configInDatabase, err := s.getConfigDataInDatabase(nextEpoch) | ||
EclesioMeloJunior marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if err != nil && !errors.Is(err, chaindb.ErrKeyNotFound) { | ||
return fmt.Errorf("cannot check if next epoch config is already defined for epoch %d: %w", nextEpoch, err) | ||
} | ||
|
||
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. Have you forgotten to cover the case when 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. This is deliberate, I call the |
||
// config already defined we don't need to lookup in the map | ||
if configInDatabase != nil { | ||
return nil | ||
} | ||
|
||
// not every epoch will have `ConfigData` | ||
finalizedNextConfigData, err := findFinalizedHeaderForEpoch(s.nextConfigData, s, nextEpoch) | ||
if errors.Is(err, ErrEpochNotInMemory) { | ||
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. Are we likely to come across 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. I'm not sure but, in this case, we will always use the previous epoch config data. 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. Added a |
||
return nil | ||
} else if err != nil { | ||
return fmt.Errorf("cannot find next config data: %w", err) | ||
} | ||
|
||
cd := finalizedNextConfigData.ToConfigData() | ||
err = s.SetConfigData(epoch, cd) | ||
err = s.SetConfigData(nextEpoch, cd) | ||
if err != nil { | ||
return fmt.Errorf("cannot set config data: %w", err) | ||
} | ||
|
||
// remove previous epochs from the memory | ||
for e := range s.nextConfigData { | ||
if e <= epoch { | ||
if e <= nextEpoch { | ||
delete(s.nextConfigData, e) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// lookupForNextEpochPersistedHash given a specific epoch (the key) will go through the hashes looking | ||
// findFinalizedHeaderForEpoch given a specific epoch (the key) will go through the hashes looking | ||
// for a database persisted hash (belonging to the finalized chain) | ||
// which contains the right configuration to be persisted and safely used | ||
EclesioMeloJunior marked this conversation as resolved.
Show resolved
Hide resolved
|
||
func lookupForNextEpochPersistedHash[T types.NextConfigData | types.NextEpochData]( | ||
func findFinalizedHeaderForEpoch[T types.NextConfigData | types.NextEpochData]( | ||
nextEpochMap map[uint64]map[common.Hash]T, es *EpochState, epoch uint64) (next *T, err error) { | ||
hashes, has := nextEpochMap[epoch] | ||
if !has { | ||
|
Uh oh!
There was an error while loading. Please reload this page.