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

Implement EIP-7251 #5507

Closed
wants to merge 6 commits into from
Closed

Conversation

ethDreamer
Copy link
Member

Issue Addressed

Implement EIP-7251

@ethDreamer ethDreamer added work-in-progress PR is a work-in-progress electra Required for the Electra/Prague fork labels Apr 2, 2024
VariableList<PendingBalanceDeposit, T::PendingBalanceDepositsLimit>,
#[superstruct(only(Electra))]
pub pending_partial_withdrawals:
VariableList<PartialWithdrawal, T::PendingPartialWithdrawalsLimit>,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Updated to PendingPartialWithdrawal

| &BeaconState::Altair(_)
| &BeaconState::Merge(_)
| &BeaconState::Capella(_)
| &BeaconState::Deneb(_) => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why not do fork >= deneb { new logic } else { current logic }? No change required for the next fork.

Copy link
Member Author

Choose a reason for hiding this comment

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

In general I try to make fork-related patterns enumerate the possibilities so as to draw our attention to things that have changed from one fork to the next. When we implement new forks, the compiler will draw your attention to places where things change. Match statements of this kind also turn the code into a kind of living documentation of where things change in which fork.

Consider the activation churn limit for example.

Copy link
Collaborator

@dapplion dapplion Apr 4, 2024

Choose a reason for hiding this comment

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

Before joining LH, I hated this. There's an insane amount of boilerplate that you force everyone to deal with when they may not have to. A new fork developer will know where and when to change code, and it is almost always covered by spec tests.

Copy link
Member

Choose a reason for hiding this comment

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

I think we should put in effort to reduce this boiler plate, this is an example external contrib EIP implementation where it's really hard to even find the changes related to the EIP: https://github.com/kevinbogner/lighthouse/pull/3/files . Trying to merge this in post-electra boiler plate would probably be more painful than re-implementing it.

From our POV it's a once-per fork pain but it can be a per-POC pain for any LH contributors. Maybe adding a generic and permanent "NextFork" would help here too. Kind of ugly though.

Copy link
Member

Choose a reason for hiding this comment

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

leaning on fork order does make sense, we're attempting to embedding fork order into superstructs: sigp/superstruct#33

the places we've been burned on not doing complete matches are usually in networking code, not consensus code. We can evaluate on a case-by-case basis but I think so far it's been easier to default to complete matches only.

Copy link
Collaborator

Choose a reason for hiding this comment

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

state transition / networking is a good place to draw the line, since state transition is covered by spec tests. In Lodestar we use fork comparisons and have never had related bugs to forgetting this for forks.

.pending_partial_withdrawals_mut()
.map(|ppw| Vec::from(std::mem::replace(ppw, Vec::new().into())))
{
pending_partial_withdrawals.drain(0..partial_withdrawals_count);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This could be quite expensive with tree states done naively. It's possible to do a specialized operation on milhouse that splits the tree at some index while potentially preserving part of the hash cache @michaelsproul

@ethDreamer can you add a TODO(EIP7251) to not forget?

balance.safe_sub(balance.safe_rem(spec.effective_balance_increment)?)?,
spec.max_effective_balance,
);
let new_effective_balance = match state_fork {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would be more maintainable to to Ord on the fork here


if let Some(participation_cache) = maybe_participation_cache {
// TODO: consider changes to progressive balances cache
Copy link
Collaborator

Choose a reason for hiding this comment

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

Annotated all todos with TODO(EIP7251) or TODO(maxeb)

mod pending_balance_deposits;
mod pending_consolidations;

pub fn process_epoch<T: EthSpec>(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hold for epoch-single pass and build on top of it

earliest_exit_epoch,
consolidation_balance_to_consume,
earliest_consolidation_epoch,
pending_balance_deposits: VariableList::default(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

missing logic to skim balances of already 0x02 vals

}
}

/// TODO: consider removing fork guard?
Copy link
Collaborator

Choose a reason for hiding this comment

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

Instead of matching on the fork you should match on self.pending_balance_deposits_mut() returning Ok()

if self.has_compounding_withdrawal_credential(spec) {
spec.max_effective_balance_eip7251
} else {
// FIXME: does this need to be made fork-aware?
Copy link
Collaborator

Choose a reason for hiding this comment

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

Depending on where it's used, yes. 0x02 validators before the fork will behave as if they had 32 ETH maxeb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
electra Required for the Electra/Prague fork work-in-progress PR is a work-in-progress
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants