Skip to content
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

feat(snapshots): write Headers to snapshots during HeaderStage #6273

Merged
merged 51 commits into from
Feb 5, 2024

Conversation

joshieDo
Copy link
Collaborator

@joshieDo joshieDo commented Jan 29, 2024

Writes Header, HeaderTD and HeaderHash to static files during the HeaderStage.

Some necessary changes that might require a more careful look at

  • genesis initialization takes a ProviderFactory equipped with a snapshot provider
  • sync_gap() and the header downloader changes.

Tested holesky + sepolia ✔️

@joshieDo joshieDo added the A-static-files Related to static files label Jan 29, 2024
Copy link
Collaborator

@mattsse mattsse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fairly readable, and I was able to follow along, tho I didn't review all checks in detail

pending @shekhirin


debug!(target: "reth::cli", chain=%self.chain.chain, genesis=?self.chain.genesis_hash(), "Initializing genesis");

init_genesis(db.clone(), self.chain.clone())?;
init_genesis(provider_factory.clone())?;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is better!!

Copy link
Collaborator

@shekhirin shekhirin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, only not sure about the changes in sync_gap logic, as it's quite different now

return Ok(hash)
}
// Check if we already have the genesis header or if we have the wrong one.
match factory.sealed_header(0) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use factory.block_hash() here? should be easier because we just need the hash

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm, im not sure i understand your question. here we check if what's in static files exists OR if it's the right one

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we use only hash from the retrieved header, can we use factory.block_hash(0) instead, and match on Ok(Some(hash)) => { ... }? saves us retrieving the actual header

Comment on lines 221 to 231
match snapshot_provider.header_by_number(0) {
Ok(None) | Err(ProviderError::MissingSnapshotBlock(SnapshotSegment::Headers, 0)) => {
let (difficulty, hash) = (header.difficulty, header.hash);
let mut writer = snapshot_provider.latest_writer(SnapshotSegment::Headers)?;
writer.append_header(header.header, difficulty, hash)?;
writer.commit()?;
}
Ok(Some(_)) => {}
Err(e) => return Err(e),
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we're sure at this point that no header for block 0 is written just as before, right? so we can just write to snapshot using the provider

Copy link
Collaborator Author

@joshieDo joshieDo Jan 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not quite, the stage drop command calls this function on a drop bodystage for example

HeaderSyncMode::Continuous => SyncTarget::TipNum(head_num + 1),
},
_ => return Err(ProviderError::InconsistentHeaderGap.into()),
let target = match mode {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/// provider.
/// * `fetch_from_database` - A closure that defines how to fetch the data from the database
/// when the snapshot doesn't contain the required data or is not available.
pub fn get_with_snapshot_or_database<T, FS, FD>(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this a duplicate from another function which was part of DatabaseProvider, will dedup on a follow-up

/// * `predicate` - A function used to evaluate each item in the fetched data. Fetching is
/// terminated when this function returns false, thereby filtering the data based on the
/// provided condition.
pub fn get_range_with_snapshot_or_database<T, P, FS, FD>(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this a duplicate from another function which was part of DatabaseProvider, will dedup on a follow-up


let gap = provider.sync_gap(mode.clone(), checkpoint).unwrap();
assert_eq!(gap.local_head, head);
assert_eq!(gap.target.tip(), consensus_tip.into());

Copy link
Collaborator Author

@joshieDo joshieDo Jan 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with static files, we no longer push to storage in reverse order, so this scenario no longer holds

@joshieDo
Copy link
Collaborator Author

joshieDo commented Feb 1, 2024

rfr, state tests are failing because they're getting canceled , they pass locally

@joshieDo joshieDo marked this pull request as ready for review February 1, 2024 02:10

if hashes.len() < num_hashes {
let snapshot_provider =
self.provider_factory.snapshot_provider().expect("should exist");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better to return the result so there is more context if this fails?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

being removed in another PR: #6344 it will no longer be an Option<_>

let snapshot_provider =
self.provider_factory.snapshot_provider().expect("should exist");
let total_headers = snapshot_provider.count_entries::<tables::Headers>()? as u64;
if total_headers > 0 {
Copy link
Member

@onbjerg onbjerg Feb 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm this is ok for now, i'd add a comment on what this is doing, but ideally the switch between fetching from db vs snapshots would be a bit more transparent 😬

self.executor_factory.with_state(LatestStateProviderRef::new(provider.tx_ref()));
let mut executor = self.executor_factory.with_state(LatestStateProviderRef::new(
provider.tx_ref(),
provider.snapshot_provider().expect("should exist").clone(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above, rly not a big fan of us doing expect in a stage

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

being removed in another PR: #6344 it will no longer be an Option<_>


for entry in provider.fetch_range_iter(
SnapshotSegment::Headers,
*range.start()..*range.end() + 1,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this take a RangeInclusive instead? big opportunity for off by one errors

Co-authored-by: Alexey Shekhirin <a.shekhirin@gmail.com>
Copy link
Member

@onbjerg onbjerg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm given expects are going away in a sep pr

@joshieDo joshieDo requested a review from emhane as a code owner February 2, 2024 19:11
@shekhirin shekhirin removed the request for review from emhane February 2, 2024 19:12
@joshieDo joshieDo merged commit 1a67329 into feat/static-files Feb 5, 2024
22 of 24 checks passed
@joshieDo joshieDo deleted the feat/headers-snap-historical branch February 5, 2024 15:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-static-files Related to static files
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants