-
Notifications
You must be signed in to change notification settings - Fork 971
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|refactor(header/sync): network head determination #990
Conversation
2d627be
to
a0bc2e4
Compare
Codecov Report
@@ Coverage Diff @@
## main #990 +/- ##
==========================================
+ Coverage 56.58% 56.92% +0.34%
==========================================
Files 135 136 +1
Lines 8994 9063 +69
==========================================
+ Hits 5089 5159 +70
+ Misses 3369 3366 -3
- Partials 536 538 +2
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
033c815
to
31c39c1
Compare
Tests failed because |
db8f693
to
674ccfd
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.
Initial thoughts here -- will do a deeper review after our call.
Want to discuss objectiveHead
method.
Also we should consider splitting out process/validation-related functions into a separate file (maybe head.go
) and just leaving the sync loop logic in sync.go
ddeedce
to
a77d103
Compare
a77d103
to
53da495
Compare
@renaynay, @distractedm1nd, pls give another read to the docs. I think it's a different level now. |
53da495
to
bd3f3a7
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.
docs are great
bd3f3a7
to
5e3c233
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.
testing this against arabica and everything looks fine so far -- the problem is not enough blocks have been produced to be able to observe any larger range syncs.
I think we should each (@Wondertan and I) review this PR again with fresh eyes and then we can likely merge.
@renaynay, How do you test? Do you compare that the node's instant head is equal to the core's one? Do you request core's one directly from the validator? |
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 PR looks generally good. I think it is critical that we document the assumptions around subjective head, network head, trusted peers clearly and make any implicit assumptions very explicit to the user.
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.
Tested on all node types -- works very well. Thank you!
Co-authored-by: Rene <[email protected]>
… for Syncer improvements Co-authored-by: Rene <[email protected]>
…emination logic The previous version of Syncer struggled with two issues: * On Syncer's start, synchronization didn't start and waited for a gossiped header trigger sync and set a sync target (only when the subjective head was not expired) * This is why Node could wait up to block time second to start syncing * There was no way to request the most recent objective header of the network * I.e. if the user wanted to request the latest possible state, it wasn't able to do that besides waiting for full sync to finish. The new reimplementation fixes these two problems and improves code readability and docs. Mainly, it splits the existing `trustedHead` into two methods `subjectiveHead` and `objectiveHead`. Where the latter now relies on the latest known header timestamp and block time to determine its recency. The new reimplementation fixes these two problems and improves code readability and docs. Mainly, it splits the existing trustedHead into two methods subjectiveHead and objectiveHead. Where the latter now relies on the latest known header timestamp and block time to determine its recency. If the header is not recent, we request it from the trusted peer(s), assuming it's always synced.
Mainly, allow Start to error so that subsequent Stop does not panic. While also make lifecycle logic less confusing and less error-prone
… so that Node tests does not fail
Going further, there wiil be multiple readers that should not block each other
…any at any moment
…vements * Terminology change from the 'objective head' to the 'network head' consistent over docs and logs * More logs for unhappy cases + more information for extisting logs * Extracttion of head retrieval logic into a separate file
Co-authored-by: rene <[email protected]> Co-authored-by: Ismail Khoffi <[email protected]>
Co-authored-by: rene <[email protected]>
a06d114
to
44ab8a2
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.
morge
* feat(params|header/sync): dirty intergration of block time into Syncer Co-authored-by: Rene <[email protected]> * feat(header): new utility funcs for the ExtendedHeader in preparation for Syncer improvements Co-authored-by: Rene <[email protected]> * feat|refactor(header/sync): revision of Syncer's objective head deteremination logic The previous version of Syncer struggled with two issues: * On Syncer's start, synchronization didn't start and waited for a gossiped header trigger sync and set a sync target (only when the subjective head was not expired) * This is why Node could wait up to block time second to start syncing * There was no way to request the most recent objective header of the network * I.e. if the user wanted to request the latest possible state, it wasn't able to do that besides waiting for full sync to finish. The new reimplementation fixes these two problems and improves code readability and docs. Mainly, it splits the existing `trustedHead` into two methods `subjectiveHead` and `objectiveHead`. Where the latter now relies on the latest known header timestamp and block time to determine its recency. The new reimplementation fixes these two problems and improves code readability and docs. Mainly, it splits the existing trustedHead into two methods subjectiveHead and objectiveHead. Where the latter now relies on the latest known header timestamp and block time to determine its recency. If the header is not recent, we request it from the trusted peer(s), assuming it's always synced. * docs(header/sync): add TODO for potential optimization * refactor(header/sync): rework Syncer lifecycling Mainly, allow Start to error so that subsequent Stop does not panic. While also make lifecycle logic less confusing and less error-prone * fix(node): do not fail the Start for Syncer if it is not initialized, so that Node tests does not fail * fix(header/sync): use RWLock for sync ranges Going further, there wiil be multiple readers that should not block each other * fix(header/sync): ensure objective head is requested only once when many at any moment * chore(header/sync): cleanup syncing code and update the tests to use WaitSync * chore(header/sync): documentation, logging and code dispoisiton improvements * Terminology change from the 'objective head' to the 'network head' consistent over docs and logs * More logs for unhappy cases + more information for extisting logs * Extracttion of head retrieval logic into a separate file * Apply docs suggestions from @renaynay and @liamsi Co-authored-by: rene <[email protected]> Co-authored-by: Ismail Khoffi <[email protected]> * Update header/header.go Co-authored-by: rene <[email protected]> Co-authored-by: Rene <[email protected]> Co-authored-by: rene <[email protected]> Co-authored-by: Ismail Khoffi <[email protected]>
* feat(params|header/sync): dirty intergration of block time into Syncer Co-authored-by: Rene <[email protected]> * feat(header): new utility funcs for the ExtendedHeader in preparation for Syncer improvements Co-authored-by: Rene <[email protected]> * feat|refactor(header/sync): revision of Syncer's objective head deteremination logic The previous version of Syncer struggled with two issues: * On Syncer's start, synchronization didn't start and waited for a gossiped header trigger sync and set a sync target (only when the subjective head was not expired) * This is why Node could wait up to block time second to start syncing * There was no way to request the most recent objective header of the network * I.e. if the user wanted to request the latest possible state, it wasn't able to do that besides waiting for full sync to finish. The new reimplementation fixes these two problems and improves code readability and docs. Mainly, it splits the existing `trustedHead` into two methods `subjectiveHead` and `objectiveHead`. Where the latter now relies on the latest known header timestamp and block time to determine its recency. The new reimplementation fixes these two problems and improves code readability and docs. Mainly, it splits the existing trustedHead into two methods subjectiveHead and objectiveHead. Where the latter now relies on the latest known header timestamp and block time to determine its recency. If the header is not recent, we request it from the trusted peer(s), assuming it's always synced. * docs(header/sync): add TODO for potential optimization * refactor(header/sync): rework Syncer lifecycling Mainly, allow Start to error so that subsequent Stop does not panic. While also make lifecycle logic less confusing and less error-prone * fix(node): do not fail the Start for Syncer if it is not initialized, so that Node tests does not fail * fix(header/sync): use RWLock for sync ranges Going further, there wiil be multiple readers that should not block each other * fix(header/sync): ensure objective head is requested only once when many at any moment * chore(header/sync): cleanup syncing code and update the tests to use WaitSync * chore(header/sync): documentation, logging and code dispoisiton improvements * Terminology change from the 'objective head' to the 'network head' consistent over docs and logs * More logs for unhappy cases + more information for extisting logs * Extracttion of head retrieval logic into a separate file * Apply docs suggestions from @renaynay and @liamsi Co-authored-by: rene <[email protected]> Co-authored-by: Ismail Khoffi <[email protected]> * Update header/header.go Co-authored-by: rene <[email protected]> Co-authored-by: Rene <[email protected]> Co-authored-by: rene <[email protected]> Co-authored-by: Ismail Khoffi <[email protected]>
Context
In #978 we started adding the
Head
method to Syncer; however, it's not that straightforward, and the deeper we looked, the more issues we found in Syncer related to the newHead
method, so it was decided to extract a separate preparation PR that ensures the newHead
is safe to use by multiple routines and returns as recent header as possible.The previous version of Syncer struggled with two issues:
Changes
The new reimplementation fixes these two problems and improves code readability and docs. Mainly, it splits the existing
trustedHead
into two methodssubjectiveHead
andnetworkHead
. ThenetworkHead
is supposed to be used by the futureHead
.Where the latter now relies on the latest known header timestamp and block time to determine its recency. If the header is not recent, we request it from the trusted peer(s), assuming it's always synced.
Besides that, three more issues under
fix
commits related to multithreading were fixed with supporting tests.Other
Tested sync manually(thought with some struggles due to broken bootstrappers).
As always, review CBC and checkout locally to see the full picture.
TODO