-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Conversation
4157e96
to
2a643d2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did a first read, looks good, even if I am not sure IIUC a few points.
I also wonder how will behave state pruning for the blocks imported from the gap?
@@ -65,6 +68,9 @@ pub fn load_epoch_changes<Block: BlockT, B: AuxStore>( | |||
Some(1) => | |||
load_decode::<_, EpochChangesFor<Block, EpochV0>>(backend, BABE_EPOCH_CHANGES_KEY)? | |||
.map(|v1| v1.map(|_, _, epoch| epoch.migrate(config))), | |||
Some(2) => | |||
load_decode::<_, EpochChangesForV1<Block, Epoch>>(backend, BABE_EPOCH_CHANGES_KEY)? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we use EpochChangeForV2
instead of EpochChangeForV1
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's some confusion to versions here. V1
means version of the epoch definition, rather than epoch changes. I'll rename the type to indicate the version of epoch changes instead.
@@ -65,6 +68,9 @@ pub fn load_epoch_changes<Block: BlockT, B: AuxStore>( | |||
Some(1) => | |||
load_decode::<_, EpochChangesFor<Block, EpochV0>>(backend, BABE_EPOCH_CHANGES_KEY)? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it EpochChangeForV1
now?
@@ -65,6 +68,9 @@ pub fn load_epoch_changes<Block: BlockT, B: AuxStore>( | |||
Some(1) => | |||
load_decode::<_, EpochChangesFor<Block, EpochV0>>(backend, BABE_EPOCH_CHANGES_KEY)? | |||
.map(|v1| v1.map(|_, _, epoch| epoch.migrate(config))), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function being called 'migrate' is confusing to me (fwiu it migrates from v2 to v1 and the new migrate does V2 to V3), maybe renaming it to 'migrate_to_previous_version' or anything could be better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
both migrate
functions migrate to the latest version, not the previous.
Ok(()) => return Ok(()), | ||
Err(e) => e, | ||
} | ||
} else if !self.epochs.is_empty() && matches!(epoch, PersistedEpoch::Genesis(_, _)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC import genesis when already an epoch indicates warp sync case, maybe worth a comment if it is the case.
&(start, end).encode(), | ||
); | ||
} | ||
} else if number > best_num + One::one() && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The point checked here is first block imported after a warp sync triggers gap download?
I first thought it should be 'number > best_num',
but maybe here 'best_num' is not changed by warp_sync and is the start of gap (gap init suggests that).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The point checked here is first block imported after a warp sync triggers gap download?
This is triggered when we import a warp block. I.e. we start at genesis and warp to block 10000. Block 10000 is imported with state. Gap is detected. No need to wait for the next block.
With number > best_num
it would be a false detection. E.g. block 43 is imported after 42 is the normal case. Only if we import 44 after 42 there's a gap.
These blocks are not executed and don't have any state. Only headers are verified. State pruning starts working normally starting from the warp target block. |
origin: block_data.origin, | ||
allow_missing_state: true, | ||
import_existing: self.import_existing, | ||
skip_execution: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 (+ demonstrates babe/grandpa do not need chain state to run)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
babe/grandpa warpsync LGTM.
Co-authored-by: cheme <emericchevalier.pro@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic for dealing with gaps on BABE and GRANDPA seems correct to me. I'd like to give this one more pass for the rest of the changes.
client/consensus/epochs/src/lib.rs
Outdated
#[derive(Clone, Encode, Decode, Debug)] | ||
pub struct GapEpochs<Hash, Number, E: Epoch> { | ||
current: (Hash, Number, PersistedEpoch<E>), | ||
next: Option<(Hash, Number, PersistedEpoch<E>)>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Next is always guaranteed to be PersistedEpoch::Regular
right? Maybe we can change the type to just take E
.
@@ -264,6 +279,25 @@ impl<E: Epoch> Clone for PersistedEpochHeader<E> { | |||
} | |||
} | |||
|
|||
impl<E: Epoch> PersistedEpochHeader<E> { | |||
/// Map the epoch header to a different type. | |||
pub fn map<B>(self) -> PersistedEpochHeader<B> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't really have a strong opinion on this, map
usually takes a function to do the mapping.
@@ -230,6 +236,8 @@ pub struct ChainSync<B: BlockT> { | |||
/// Enable importing existing blocks. This is used used after the state download to | |||
/// catch up to the latest state while re-importing blocks. | |||
import_existing: bool, | |||
/// Gap download process. | |||
gap_sync: Option<GapSync<B>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to somehow move this into warp_sync
? If gap_sync
is Some
then we know we warp synced but we're still downloading the old blocks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer to keep them separate. I see warp sync and old block download as two independent features. Even though the only way you can currently end up with the block gap is the warp sync, this may change in the future. I.e. when importing the state from a file or chain spec snapshot. Or after disabling block body pruning.
utils/fork-tree/src/lib.rs
Outdated
@@ -744,6 +744,10 @@ mod node_implementation { | |||
if *number < self.number { | |||
return Ok(FindOutcome::Failure(false)) | |||
} | |||
if *number == self.number && hash == &self.hash { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't remember all the details to know the implications of this, could you just drop a line why this was needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not actually needed. Just an optimization I've made while fixing an unrelated issue. Saves a database query for the header. I guess it does not belong to this PR indeed, so I'll remove it.
Hey, is anyone still working on this? Due to the inactivity this issue has been automatically marked as stale. It will be closed if no further activity occurs. Thank you for your contributions. |
Still waiting for reviews |
load_decode::<_, EpochChangesV1For<Block, Epoch>>(backend, BABE_EPOCH_CHANGES_KEY)? | ||
.map(|v2| v2.migrate()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a comment why we use EpochChangesV1For
here as well?
if number <= self.inner.info().finalized_number { | ||
// Importing an old block. Just save justifications and authority set changes | ||
if let Some(_) = self.check_new_change(&block.header, hash) { | ||
assert!(block.justifications.is_some()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A proper proof here would be nice
Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
Companion approval would be appreciated |
bot merge |
Trying merge. |
This enables background block download after warp sync. The bulk of the changes is epoch management for GRANDPA to allow for verification and import of old blocks.
Polkadot companion: paritytech/polkadot#3564
Also required for warp sync to work properly on kusama: #9239