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

Electra alpha8 spec updates #6496

Merged
merged 33 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
3c24e2b
Fix partial withdrawals count
pawanjay176 Oct 10, 2024
3fa7790
Remove get_active_balance
pawanjay176 Oct 10, 2024
3d595e6
Remove queue_entire_balance_and_reset_validator
pawanjay176 Oct 10, 2024
0a4e6be
Switch to compounding when consolidating with source==target
pawanjay176 Oct 10, 2024
c0cac0e
Queue deposit requests and apply them during epoch processing
pawanjay176 Oct 12, 2024
b28d010
Fix ef tests
pawanjay176 Oct 16, 2024
c8dfe7d
Clear todos
pawanjay176 Oct 16, 2024
0dd215c
Fix engine api formatting issues
pawanjay176 Oct 17, 2024
061be34
Merge branch 'unstable' into electra-alpha7
pawanjay176 Oct 29, 2024
37c7658
Make add_validator_to_registry more in line with the spec
pawanjay176 Oct 29, 2024
9f85074
Address some review comments
pawanjay176 Oct 29, 2024
707338d
Cleanup
pawanjay176 Oct 29, 2024
b2b728d
Update initialize_beacon_state_from_eth1
pawanjay176 Oct 29, 2024
21da047
Merge branch 'unstable' into electra-alpha7
pawanjay176 Nov 5, 2024
2aaf9b5
Fix rpc decoding for blobs by range/root
pawanjay176 Nov 6, 2024
27ce1a0
Fix block hash computation
pawanjay176 Nov 7, 2024
da953b8
Fix process_deposits bug
pawanjay176 Nov 8, 2024
6c56dc4
Merge branch 'unstable' into electra-alpha7
pawanjay176 Nov 20, 2024
def2498
Fix topup deposit processing bug
pawanjay176 Nov 26, 2024
c5c9aca
Update builder api for electra
pawanjay176 Dec 4, 2024
6d10456
Refactor mock builder to separate functionality
pawanjay176 Dec 5, 2024
e49689b
Merge branch 'unstable' into electra-alpha7
pawanjay176 Dec 11, 2024
140d4cf
Address review comments
pawanjay176 Dec 12, 2024
da33bd6
Use copied for reference rather than cloned
michaelsproul Dec 13, 2024
0af6b0f
Optimise and simplify PendingDepositsContext::new
michaelsproul Dec 13, 2024
1af232b
Merge remote-tracking branch 'origin/unstable' into electra-alpha7
michaelsproul Dec 13, 2024
21591a3
Fix processing of deposits with invalid signatures
michaelsproul Dec 13, 2024
d5ec058
Remove redundant code in genesis init
pawanjay176 Dec 14, 2024
5a3f5df
Revert "Refactor mock builder to separate functionality"
pawanjay176 Dec 14, 2024
ff687ed
Revert "Update builder api for electra"
pawanjay176 Dec 14, 2024
75efd4f
Simplify pre-activation sorting
michaelsproul Dec 16, 2024
ebabd0f
Fix stale validators used in upgrade_to_electra
michaelsproul Dec 16, 2024
a031293
Merge branch 'unstable' into electra-alpha7
michaelsproul Dec 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion beacon_node/execution_layer/src/engine_api/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ impl HttpJsonRpc {
new_payload_request_electra.versioned_hashes,
new_payload_request_electra.parent_beacon_block_root,
new_payload_request_electra
.execution_requests_list
.execution_requests
.get_execution_requests_list(),
]);

Expand Down
7 changes: 4 additions & 3 deletions beacon_node/execution_layer/src/engine_api/json_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,8 @@ impl<E: EthSpec> TryFrom<JsonExecutionRequests> for ExecutionRequests<E> {

for (i, request) in value.0.into_iter().enumerate() {
// hex string
let decoded_bytes = hex::decode(request).map_err(|e| format!("Invalid hex {:?}", e))?;
let decoded_bytes = hex::decode(request.strip_prefix("0x").unwrap_or(&request))
.map_err(|e| format!("Invalid hex {:?}", e))?;
match RequestPrefix::from_prefix(i as u8) {
Some(RequestPrefix::Deposit) => {
requests.deposits = DepositRequests::<E>::from_ssz_bytes(&decoded_bytes)
Expand Down Expand Up @@ -431,7 +432,7 @@ pub struct JsonGetPayloadResponse<E: EthSpec> {
#[superstruct(only(V3, V4))]
pub should_override_builder: bool,
#[superstruct(only(V4))]
pub requests: JsonExecutionRequests,
pub execution_requests: JsonExecutionRequests,
}

impl<E: EthSpec> TryFrom<JsonGetPayloadResponse<E>> for GetPayloadResponse<E> {
Expand Down Expand Up @@ -464,7 +465,7 @@ impl<E: EthSpec> TryFrom<JsonGetPayloadResponse<E>> for GetPayloadResponse<E> {
block_value: response.block_value,
blobs_bundle: response.blobs_bundle.into(),
should_override_builder: response.should_override_builder,
requests: response.requests.try_into()?,
requests: response.execution_requests.try_into()?,
}))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub struct NewPayloadRequest<'block, E: EthSpec> {
#[superstruct(only(Deneb, Electra))]
pub parent_beacon_block_root: Hash256,
#[superstruct(only(Electra))]
pub execution_requests_list: &'block ExecutionRequests<E>,
pub execution_requests: &'block ExecutionRequests<E>,
}

impl<'block, E: EthSpec> NewPayloadRequest<'block, E> {
Expand Down Expand Up @@ -185,7 +185,7 @@ impl<'a, E: EthSpec> TryFrom<BeaconBlockRef<'a, E>> for NewPayloadRequest<'a, E>
.map(kzg_commitment_to_versioned_hash)
.collect(),
parent_beacon_block_root: block_ref.parent_root,
execution_requests_list: &block_ref.body.execution_requests,
execution_requests: &block_ref.body.execution_requests,
})),
}
}
Expand Down
2 changes: 1 addition & 1 deletion beacon_node/execution_layer/src/test_utils/handle_rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ pub async fn handle_rpc<E: EthSpec>(
.into(),
should_override_builder: false,
// TODO(electra): add EL requests in mock el
requests: Default::default(),
execution_requests: Default::default(),
})
.unwrap()
}
Expand Down
6 changes: 3 additions & 3 deletions beacon_node/store/src/partial_beacon_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ where
pub earliest_consolidation_epoch: Epoch,

#[superstruct(only(Electra))]
pub pending_balance_deposits: List<PendingBalanceDeposit, E::PendingBalanceDepositsLimit>,
pub pending_deposits: List<PendingDeposit, E::PendingDepositsLimit>,
#[superstruct(only(Electra))]
pub pending_partial_withdrawals:
List<PendingPartialWithdrawal, E::PendingPartialWithdrawalsLimit>,
Expand Down Expand Up @@ -290,7 +290,7 @@ impl<E: EthSpec> PartialBeaconState<E> {
earliest_exit_epoch,
consolidation_balance_to_consume,
earliest_consolidation_epoch,
pending_balance_deposits,
pending_deposits,
pending_partial_withdrawals,
pending_consolidations
],
Expand Down Expand Up @@ -563,7 +563,7 @@ impl<E: EthSpec> TryInto<BeaconState<E>> for PartialBeaconState<E> {
earliest_exit_epoch,
consolidation_balance_to_consume,
earliest_consolidation_epoch,
pending_balance_deposits,
pending_deposits,
pending_partial_withdrawals,
pending_consolidations
],
Expand Down
3 changes: 3 additions & 0 deletions consensus/state_processing/src/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ pub fn initialize_beacon_state_from_eth1<E: EthSpec>(
let post = upgrade_state_to_electra(&mut state, Epoch::new(0), Epoch::new(0), spec)?;
state = post;

// TODO(electra): do we need to iterate over an empty pending_deposits list here and increase balance?
// in accordance with `initialize_beacon_state_from_eth1` function from the spec

// Remove intermediate Deneb fork from `state.fork`.
state.fork_mut().previous_version = spec.electra_fork_version;

Expand Down
4 changes: 3 additions & 1 deletion consensus/state_processing/src/per_block_processing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,7 @@ pub fn get_expected_withdrawals<E: EthSpec>(
// Consume pending partial withdrawals
let partial_withdrawals_count =
if let Ok(partial_withdrawals) = state.pending_partial_withdrawals() {
let mut partial_withdrawals_count = 0;
for withdrawal in partial_withdrawals {
if withdrawal.withdrawable_epoch > epoch
|| withdrawals.len() == spec.max_pending_partials_per_withdrawals_sweep as usize
Expand Down Expand Up @@ -546,8 +547,9 @@ pub fn get_expected_withdrawals<E: EthSpec>(
});
withdrawal_index.safe_add_assign(1)?;
}
partial_withdrawals_count.safe_add_assign(1)?;
}
Some(withdrawals.len())
Some(partial_withdrawals_count)
} else {
None
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use crate::per_block_processing::errors::{BlockProcessingError, IntoWithIndex};
use crate::VerifySignatures;
use types::consts::altair::{PARTICIPATION_FLAG_WEIGHTS, PROPOSER_WEIGHT, WEIGHT_DENOMINATOR};
use types::typenum::U33;
use types::validator::is_compounding_withdrawal_credential;

pub fn process_operations<E: EthSpec, Payload: AbstractExecPayload<E>>(
state: &mut BeaconState<E>,
Expand Down Expand Up @@ -450,59 +449,69 @@ pub fn apply_deposit<E: EthSpec>(

if let Some(index) = validator_index {
// [Modified in Electra:EIP7251]
if let Ok(pending_balance_deposits) = state.pending_balance_deposits_mut() {
pending_balance_deposits.push(PendingBalanceDeposit { index, amount })?;

let validator = state
.validators()
.get(index as usize)
.ok_or(BeaconStateError::UnknownValidator(index as usize))?;

if is_compounding_withdrawal_credential(deposit_data.withdrawal_credentials, spec)
&& validator.has_eth1_withdrawal_credential(spec)
&& is_valid_deposit_signature(&deposit_data, spec).is_ok()
{
state.switch_to_compounding_validator(index as usize, spec)?;
}
if let Ok(pending_deposits) = state.pending_deposits_mut() {
pending_deposits.push(PendingDeposit {
pubkey: deposit_data.pubkey,
withdrawal_credentials: deposit_data.withdrawal_credentials,
amount,
signature: deposit_data.signature,
slot: spec.genesis_slot, // Use `genesis_slot` to distinguish from a pending deposit request
})?;
} else {
// Update the existing validator balance.
increase_balance(state, index as usize, amount)?;
}
} else {
}
// New validator
else {
// The signature should be checked for new validators. Return early for a bad
// signature.
if is_valid_deposit_signature(&deposit_data, spec).is_err() {
return Ok(());
}

let new_validator_index = state.validators().len();

// [Modified in Electra:EIP7251]
let (effective_balance, state_balance) = if state.fork_name_unchecked() >= ForkName::Electra
{
(0, 0)
if state.fork_name_unchecked() >= ForkName::Electra {
let amount = 0;
// Create a new validator.
let mut validator = Validator {
pubkey: deposit_data.pubkey,
withdrawal_credentials: deposit_data.withdrawal_credentials,
activation_eligibility_epoch: spec.far_future_epoch,
activation_epoch: spec.far_future_epoch,
exit_epoch: spec.far_future_epoch,
withdrawable_epoch: spec.far_future_epoch,
effective_balance: 0,
slashed: false,
};
let max_effective_balance =
validator.get_max_effective_balance(spec, state.fork_name_unchecked());
validator.effective_balance = std::cmp::min(
amount.safe_sub(amount.safe_rem(spec.effective_balance_increment)?)?,
max_effective_balance,
);

state.validators_mut().push(validator)?;
// state balances is set to 0 in electra
state.balances_mut().push(0)?;
} else {
(
std::cmp::min(
let validator = Validator {
pubkey: deposit_data.pubkey,
withdrawal_credentials: deposit_data.withdrawal_credentials,
activation_eligibility_epoch: spec.far_future_epoch,
activation_epoch: spec.far_future_epoch,
exit_epoch: spec.far_future_epoch,
withdrawable_epoch: spec.far_future_epoch,
effective_balance: std::cmp::min(
amount.safe_sub(amount.safe_rem(spec.effective_balance_increment)?)?,
spec.max_effective_balance,
),
amount,
)
};
// Create a new validator.
let validator = Validator {
pubkey: deposit_data.pubkey,
withdrawal_credentials: deposit_data.withdrawal_credentials,
activation_eligibility_epoch: spec.far_future_epoch,
activation_epoch: spec.far_future_epoch,
exit_epoch: spec.far_future_epoch,
withdrawable_epoch: spec.far_future_epoch,
effective_balance,
slashed: false,
slashed: false,
};
state.validators_mut().push(validator)?;
// state balances is set to 0 in electra
state.balances_mut().push(amount)?;
};
state.validators_mut().push(validator)?;
state.balances_mut().push(state_balance)?;

// Altair or later initializations.
if let Ok(previous_epoch_participation) = state.previous_epoch_participation_mut() {
Expand All @@ -516,10 +525,13 @@ pub fn apply_deposit<E: EthSpec>(
}

// [New in Electra:EIP7251]
if let Ok(pending_balance_deposits) = state.pending_balance_deposits_mut() {
pending_balance_deposits.push(PendingBalanceDeposit {
index: new_validator_index as u64,
if let Ok(pending_deposits) = state.pending_deposits_mut() {
pending_deposits.push(PendingDeposit {
pubkey: deposit_data.pubkey,
withdrawal_credentials: deposit_data.withdrawal_credentials,
amount,
signature: deposit_data.signature,
slot: spec.genesis_slot, // Use `genesis_slot` to distinguish from a pending deposit request
})?;
}
}
Expand Down Expand Up @@ -633,13 +645,18 @@ pub fn process_deposit_requests<E: EthSpec>(
if state.deposit_requests_start_index()? == spec.unset_deposit_requests_start_index {
*state.deposit_requests_start_index_mut()? = request.index
}
let deposit_data = DepositData {
pubkey: request.pubkey,
withdrawal_credentials: request.withdrawal_credentials,
amount: request.amount,
signature: request.signature.clone().into(),
};
apply_deposit(state, deposit_data, None, false, spec)?
let slot = state.slot();

// [New in Electra:EIP7251]
if let Ok(pending_deposits) = state.pending_deposits_mut() {
pending_deposits.push(PendingDeposit {
pubkey: request.pubkey,
withdrawal_credentials: request.withdrawal_credentials,
amount: request.amount,
signature: request.signature.clone(),
slot,
})?;
}
}

Ok(())
Expand All @@ -658,11 +675,73 @@ pub fn process_consolidation_requests<E: EthSpec>(
Ok(())
}

fn is_valid_switch_to_compounding_request<E: EthSpec>(
state: &BeaconState<E>,
consolidation_request: &ConsolidationRequest,
spec: &ChainSpec,
) -> Result<bool, Error> {
// Switch to compounding requires source and target be equal
if consolidation_request.source_pubkey != consolidation_request.target_pubkey {
return Ok(false);
}

// Verify pubkey exists
let Some(source_index) = state
.pubkey_cache()
.get(&consolidation_request.source_pubkey)
else {
// source validator doesn't exist
return Ok(false);
};

let source_validator = state.get_validator(source_index)?;
// Verify the source withdrawal credentials
if let Some(withdrawal_address) = source_validator.get_eth1_withdrawal_credential(spec) {
if withdrawal_address != consolidation_request.source_address {
return Ok(false);
}
} else {
// Source doen't have execution withdrawal credentials
return Ok(false);
}

// Verify the source is active
let current_epoch = state.current_epoch();
if !source_validator.is_active_at(current_epoch) {
return Ok(false);
}
// Verify exits for source has not been initiated
if source_validator.exit_epoch != spec.far_future_epoch {
return Ok(false);
}

Ok(true)
}

pub fn process_consolidation_request<E: EthSpec>(
state: &mut BeaconState<E>,
consolidation_request: &ConsolidationRequest,
spec: &ChainSpec,
) -> Result<(), BlockProcessingError> {
dbg!("here");
if is_valid_switch_to_compounding_request(state, consolidation_request, spec)? {
let Some(source_index) = state
.pubkey_cache()
.get(&consolidation_request.source_pubkey)
else {
// source validator doesn't exist. This is unreachable as `is_valid_switch_to_compounding_request`
// will return false in that case.
return Ok(());
};
state.switch_to_compounding_validator(source_index, spec)?;
return Ok(());
}

// Verify that source != target, so a consolidation cannot be used as an exit.
if consolidation_request.source_pubkey == consolidation_request.target_pubkey {
return Ok(());
}

// If the pending consolidations queue is full, consolidation requests are ignored
if state.pending_consolidations()?.len() == E::PendingConsolidationsLimit::to_usize() {
return Ok(());
Expand All @@ -686,10 +765,6 @@ pub fn process_consolidation_request<E: EthSpec>(
// target validator doesn't exist
return Ok(());
};
// Verify that source != target, so a consolidation cannot be used as an exit.
if source_index == target_index {
return Ok(());
}

let source_validator = state.get_validator(source_index)?;
// Verify the source withdrawal credentials
Expand Down Expand Up @@ -736,5 +811,10 @@ pub fn process_consolidation_request<E: EthSpec>(
target_index: target_index as u64,
})?;

let target_validator = state.get_validator(target_index)?;
// Churn any target excess active balance of target and raise its max
if target_validator.has_eth1_withdrawal_credential(spec) {
state.switch_to_compounding_validator(target_index, spec)?;
}
Ok(())
}
Loading
Loading