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(sync): headers commit threshold #296

Merged
merged 19 commits into from
Dec 6, 2022

Conversation

rkrasiuk
Copy link
Member

@rkrasiuk rkrasiuk commented Nov 30, 2022

Modify the headers stage to download the block headers in batches. Add a commit_threshold parameter for aggregated commits

blocked by #310

@rkrasiuk rkrasiuk added C-enhancement New feature or request A-staged-sync Related to staged sync (pipelines and stages) labels Nov 30, 2022
@rkrasiuk rkrasiuk marked this pull request as draft November 30, 2022 09:33
@codecov
Copy link

codecov bot commented Nov 30, 2022

Codecov Report

Merging #296 (3a4eb06) into main (c7ec451) will increase coverage by 0.00%.
The diff coverage is 95.00%.

@@           Coverage Diff            @@
##             main     #296    +/-   ##
========================================
  Coverage   73.73%   73.74%            
========================================
  Files         229      230     +1     
  Lines       21081    21393   +312     
========================================
+ Hits        15544    15776   +232     
- Misses       5537     5617    +80     
Impacted Files Coverage Δ
crates/interfaces/src/p2p/headers/downloader.rs 57.14% <ø> (ø)
crates/interfaces/src/test_utils/headers.rs 76.77% <90.00%> (-7.92%) ⬇️
crates/net/headers-downloaders/src/linear.rs 86.97% <95.23%> (+10.08%) ⬆️
crates/primitives/src/header.rs 93.85% <100.00%> (+0.07%) ⬆️
crates/stages/src/stages/headers.rs 97.34% <100.00%> (+0.74%) ⬆️
crates/codecs/src/lib.rs 94.22% <0.00%> (-5.41%) ⬇️
crates/net/network/src/network.rs 53.24% <0.00%> (-4.50%) ⬇️
crates/net/discv4/src/lib.rs 66.13% <0.00%> (-2.46%) ⬇️
crates/net/discv4/src/proto.rs 90.69% <0.00%> (-2.33%) ⬇️
... and 19 more

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

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.

the stream looks alright,
since we need to day a lot of checks and conditionally return it makes sense to solve this with macros here

crates/net/headers-downloaders/src/linear.rs Outdated Show resolved Hide resolved
crates/net/headers-downloaders/src/linear.rs Outdated Show resolved Hide resolved
crates/net/headers-downloaders/src/linear.rs Outdated Show resolved Hide resolved
@rkrasiuk rkrasiuk marked this pull request as ready for review December 2, 2022 07:24
Copy link
Member

@gakonst gakonst left a comment

Choose a reason for hiding this comment

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

nice work. some nits, requests for more docs, and questions aroudn if we had bugs before

let mut headers = resp.0.into_iter().skip(1).map(|h| h.seal()).collect::<Vec<_>>();
headers.sort_unstable_by_key(|h| h.number);
Poll::Ready(Ok(headers))
Poll::Ready(Ok(headers.into_iter().rev().collect()))
Copy link
Member

Choose a reason for hiding this comment

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

why rev here? why was it not before?

Copy link
Member Author

Choose a reason for hiding this comment

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

initially, we returned it in reverse. then it was changed during a recent refactor. that made sense for the Future implementation alone, but it doesn't for the Stream which returns reverse batches. i changed it back to keep it consistent

Copy link
Member

Choose a reason for hiding this comment

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

crates/net/headers-downloaders/src/linear.rs Show resolved Hide resolved
crates/net/headers-downloaders/src/linear.rs Outdated Show resolved Hide resolved
crates/net/headers-downloaders/src/linear.rs Show resolved Hide resolved
crates/net/headers-downloaders/src/linear.rs Show resolved Hide resolved
while let Some(header) = headers_iter.next() {
ensure_parent(header, headers_iter.peek().unwrap_or(&&head))
.map_err(|err| StageError::Download(err.to_string()))?;
if let Some(parent) = headers_iter.peek() {
Copy link
Member

Choose a reason for hiding this comment

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

what if there's no parent? should this error?

Copy link
Member Author

Choose a reason for hiding this comment

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

this means that the parent will come in the next batch. best we can do is to validate upon receiving that batch

Copy link
Member

Choose a reason for hiding this comment

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

ok lets add that comment then

crates/net/headers-downloaders/src/linear.rs Outdated Show resolved Hide resolved
}
}

if !this.done && this.buffered.len() > 1 {
Copy link
Member

Choose a reason for hiding this comment

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

what if we're not done and we have only 1 buffered?

or does having only 1 buffered item mean we're done? let's document that

Copy link
Member Author

@rkrasiuk rkrasiuk Dec 2, 2022

Choose a reason for hiding this comment

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

the done flag is set to true only when the local head (latest db header at the beginning of execution) is reached. we need to keep at least one header to form the next request until we are done

crates/net/headers-downloaders/src/linear.rs Outdated Show resolved Hide resolved
crates/net/headers-downloaders/src/linear.rs Outdated Show resolved Hide resolved
rkrasiuk and others added 3 commits December 2, 2022 16:14
Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>
…oundry-rs/reth into rkrasiuk/sync-headers-commit-threshold
Comment on lines 147 to 150
let empty = SealedHeader::default();
if let Err(error) = this.consensus.validate_header(&empty, &empty) {
this.done = true;
return Poll::Ready(Some(Err(DownloadError::HeaderValidation {
Copy link
Collaborator

Choose a reason for hiding this comment

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

why are we validating the default header against the default header?

Copy link
Member Author

@rkrasiuk rkrasiuk Dec 2, 2022

Choose a reason for hiding this comment

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

we're polling consensus stub merely to see whether it will produce an error. it is set on the TestConsensus struct and it will either succeed or fail regardless of input parameters

crates/interfaces/src/test_utils/headers.rs Outdated Show resolved Hide resolved
Copy link
Member

@gakonst gakonst left a comment

Choose a reason for hiding this comment

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

lgtm - merging to get the ball rolling but pls address comments in followup

let mut headers = resp.0.into_iter().skip(1).map(|h| h.seal()).collect::<Vec<_>>();
headers.sort_unstable_by_key(|h| h.number);
Poll::Ready(Ok(headers))
Poll::Ready(Ok(headers.into_iter().rev().collect()))
Copy link
Member

Choose a reason for hiding this comment

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

}

Ok(latest)
}

/// Iterate over inserted headers and write td entries
fn write_td<DB: Database>(
Copy link
Member

Choose a reason for hiding this comment

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

sure what about a 3rd party client that wants to overwrite the difficulty table for any reason?

while let Some(header) = headers_iter.next() {
ensure_parent(header, headers_iter.peek().unwrap_or(&&head))
.map_err(|err| StageError::Download(err.to_string()))?;
if let Some(parent) = headers_iter.peek() {
Copy link
Member

Choose a reason for hiding this comment

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

ok lets add that comment then

}

Ok(latest)
}

/// Iterate over inserted headers and write td entries
fn write_td<DB: Database>(
Copy link
Member

Choose a reason for hiding this comment

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

i also think it looks weird given it doesn't need &self either

@gakonst gakonst merged commit 74d776d into main Dec 6, 2022
@gakonst gakonst deleted the rkrasiuk/sync-headers-commit-threshold branch December 6, 2022 06:28
gakonst added a commit that referenced this pull request Dec 7, 2022
* headers stream init

* fix tests

* return header if available regardless of control flow

* proper stream termination & docs

* upd headers stage to consume stream

* adjust response validation for stream

* use cursor.insert for headers

* wrap poll_next in a loop to bypass poking waker

* fix typo

* fix last td lookup

* Apply suggestions from code review

Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>

* misc

* remove waker ref

* dedup response handling logic

* clippy

* add docs to poll

Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-staged-sync Related to staged sync (pipelines and stages) C-enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants