-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Finishing touches for the gloas fork-choice #4807
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
Conversation
…e are equivocations
specs/gloas/fork-choice.md
Outdated
| *Note*: the function `is_head_weak` now also counts weight from equivocating | ||
| validators from the committees of the head slot. This ensures that the counted | ||
| weight and the output of `is_head_weak` are monotonic: more attestations can | ||
| only increase the weight and change the output from `False` to `True`, not |
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.
increasing the weight should change the output from True to False not otherwise.
specs/gloas/fork-choice.md
Outdated
| ### New `record_block_timeliness` | ||
|
|
||
| ```python | ||
| def record_block_timeliness(store: Store, root: Root) -> None: |
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 is not New, but rather Modified right? the only difference here is PTC_TIMELINESS_INDEX
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.
Ah right it's new in the sense that I just added the helper in this PR, but it's not new to the gloas spec
Co-authored-by: satushh <satushh@gmail.com>
Co-authored-by: Justin Traglia <95511699+jtraglia@users.noreply.github.com>
Change signature from is_parent_strong(store, parent_root) to is_parent_strong(store, root) where root is the child block. The function now derives parent_root internally. This change is needed for gloas/ePBS where we need to know which child block to determine the parent's payload status (FULL vs EMPTY) via get_parent_payload_status. Also adds is_parent_strong to gloas fork-choice using get_attestation_weight with proper ForkChoiceNode. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
After merge, get_attestation_weight was renamed to get_attestation_score with an additional state parameter. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
jtraglia
left a comment
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.
LGTM! Thanks @fradamt!
There's a few changes. Firstly, there's a fix to the mechanism for setting the proposer boost root: we only update it if
block.proposer_indexmatches the expected proposer of your currenthead_state. This way you can't nullify proposer boost by just creating forks with a divergent proposer sequence. Also small refactor with the updating logic moved toupdate_proposer_boost_root, and the block timeliness logic inrecord_block_timeliness. All of this is essentially unrelated to epbs.The other changes are to make sure that the trustless payment mechanism works even if a proposer is willing to equivocate. What we want to avoid is in particular this situation:
Bwith > 40% of the weight, and no equivocationsB'B'instead ofBB', and in additionB'has a little bit of adversarial attestation weight, soBgets reorgedThe changes to handle this are:
store.block_timelinessnow records two timeliness indicators, the usual one for the attestation deadline and another one for the ptc deadline (whether the beacon block was received by the ptc deadline). As explained later, this is because when deciding whether something is an equivocation we only want to consider blocks that are received sufficiently early, so that the next proposer should have seen them. A late released block might not be seen by the next proposer, so we can't enforce them to reorg it, and moreover late released blocks are not dangerous because they can't accrue honest attestation weight.should_apply_proposer_boostis added to determine whether the proposer boost should be applied to the fork-choice. It is always applied when there are no equivocations. If there are, it is applied only when set to blocks with a parent older than one slot or not weak (more than 20% of votes), i.e. in particular it is not applied to weak, equivocating blocks from the previous slot. The idea is that these should always be reorged by the proposer, and if they don't do it we do not give them a proposer boost. This is why it's important to only consider equivocations that are seen sufficiently early, so we don't unfairly penalize the proposer.get_proposer_headhas a more aggressive behavior when there is an equivocation in the previous slot: in that case, it always reorgs a weak head regardless of the other conditions (exactly the behavior mentioned above). Here we consider any equivocations, even if received late: it is only when attesting that the timeliness matters.is_head_weaknow counts the weight of the block asget_weight(the usual weight) + the weight of equivocating validators from the committee ofblock.slot. This is so that, if a proposer sees a head as not weak (> 20% weight), it stays so for attesters even if there are some equivocations. The attesters then apply proposer boost normally, even if there are equivocations.Assuming < 20% adversary, we get builder reveal safety:
Builder reveals when seeing block
Bwith > 40% weight and no equivocations=> if the proposer extends an equivocation
B', proposer boost doesn't apply toB':B'is weak because it is late and thus does not accrue honest weight, and attesters detect the existence of an equivocation (Bis timely).=> no matter what the proposer does, the block stays canonical
Honest proposers are also still able to take advantage of proposer boost:
=> attesters do not record any equivocations as timely (in
record_block_timeliness)=> proposer boost applies normally (
should_apply_proposer_boostreturnsTrue)=> it extends the parent (
get_proposer_headreturns the parent)=> proposer boost applies since the proposal's parent is earlier than the previous slot (
should_apply_proposer_boostreturnsTrue)=> the reorg succeeds since head is weak
=> it extends the head (
get_proposer_headreturns the head)=> attesters also see the head as not weak (equivocations do not decrease the weight counted by
is_head_weak)=> proposer boost applies normally (
should_apply_proposer_boostreturnsTrue)