-
Notifications
You must be signed in to change notification settings - Fork 254
Document how fork choice actually works #3700
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
base: main
Are you sure you want to change the base?
Conversation
🛡️ Immunefi PR ReviewsWe noticed that your project isn't set up for automatic code reviews. If you'd like this PR reviewed by the Immunefi team, you can request it manually using the link below: Once submitted, we'll take care of assigning a reviewer and follow up here. |
c064db8
to
7cdff2b
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.
This has been heavily revised, and it's now ready for review again.
There are edge cases, but they're not the ones I originally expected. (And the worst one only happens on the test runtime.)
I moved any future rule changes to a ticket: #3703 |
I'm working on fork monitoring, so I was looking at how our fork choice rule works in detail.
I think the current implementation is valid. But the code comments are an over-simplification - they don't clearly describe how the code chooses between forks.
The implementation sums the chain weights into a single
u128
, which means it is possible (but very unlikely) that a shorter fork can be temporarily chosen as the best fork. This could happen on an era transition, if the solution range differences between the forks are large.Also, a solution can be accepted by one fork but rejected by others at the start of an era, due to different solution ranges (from different block times).
So downstream consumers can't depend on the longest fork always being chosen every time. But the longest fork will be chosen after more blocks, with increasingly high probability after each new block.
Test fixes
This PR also fixes the fork choice weights for the test runtime, where all blocks had zero weight (because the runtime accepts all solutions).
This is a particular issue in tests where multiple nodes produce blocks, because they will all choose their own blocks, and never reorg.
Feedback requests
Some of the detail in the code comments (or this PR description) might be better in the spec. Please let me know which parts you'd like me to move.
I'll only merge this after we've got both the spec and code changes sorted.
Why audit?
I would like this audited because the fork choice is an important security property, and it needs to be documented accurately. Missing or outdated documentation makes it easier to introduce security issues accidentally.
Next steps
After this has been checked, we need to update the spec in a similar way:
https://github.com/subspace/protocol-specs/blob/0591efc437a095237c01b1bc61212743aea0419e/docs/decex/workflow.md?plain=1#L286-L288
(The fork choice is important for compatible implementations.)
Code contributor checklist: