mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-30 04:37:13 +00:00
Merge remote-tracking branch 'origin/unstable' into payload-attestation-committee-cache
This commit is contained in:
@@ -916,25 +916,24 @@ pub fn process_deposit_requests_post_gloas<E: EthSpec>(
|
||||
/// Check if there is a pending deposit for a new validator with the given pubkey.
|
||||
// TODO(gloas): cache the deposit signature validation or remove this loop entirely if possible,
|
||||
// it is `O(n * m)` where `n` is max 8192 and `m` is max 128M.
|
||||
fn is_pending_validator<E: EthSpec>(
|
||||
state: &BeaconState<E>,
|
||||
pub fn is_pending_validator<'a>(
|
||||
pending_deposits: impl IntoIterator<Item = &'a PendingDeposit>,
|
||||
pubkey: &PublicKeyBytes,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<bool, BlockProcessingError> {
|
||||
for deposit in state.pending_deposits()?.iter() {
|
||||
if deposit.pubkey == *pubkey {
|
||||
let deposit_data = DepositData {
|
||||
pubkey: deposit.pubkey,
|
||||
withdrawal_credentials: deposit.withdrawal_credentials,
|
||||
amount: deposit.amount,
|
||||
signature: deposit.signature.clone(),
|
||||
};
|
||||
if is_valid_deposit_signature(&deposit_data, spec).is_ok() {
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(false)
|
||||
) -> bool {
|
||||
pending_deposits.into_iter().any(|deposit| {
|
||||
deposit.pubkey == *pubkey
|
||||
&& is_valid_deposit_signature(
|
||||
&DepositData {
|
||||
pubkey: deposit.pubkey,
|
||||
withdrawal_credentials: deposit.withdrawal_credentials,
|
||||
amount: deposit.amount,
|
||||
signature: deposit.signature.clone(),
|
||||
},
|
||||
spec,
|
||||
)
|
||||
.is_ok()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn process_deposit_request_post_gloas<E: EthSpec>(
|
||||
@@ -964,7 +963,7 @@ pub fn process_deposit_request_post_gloas<E: EthSpec>(
|
||||
if is_builder
|
||||
|| (has_builder_prefix
|
||||
&& !is_validator
|
||||
&& !is_pending_validator(state, &deposit_request.pubkey, spec)?)
|
||||
&& !is_pending_validator(state.pending_deposits()?, &deposit_request.pubkey, spec))
|
||||
{
|
||||
// Apply builder deposits immediately
|
||||
apply_deposit_for_builder(
|
||||
@@ -1003,7 +1002,7 @@ pub fn apply_deposit_for_builder<E: EthSpec>(
|
||||
signature: SignatureBytes,
|
||||
slot: Slot,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), BeaconStateError> {
|
||||
) -> Result<Option<BuilderIndex>, BeaconStateError> {
|
||||
match builder_index_opt {
|
||||
None => {
|
||||
// Verify the deposit signature (proof of possession) which is not checked by the deposit contract
|
||||
@@ -1014,13 +1013,16 @@ pub fn apply_deposit_for_builder<E: EthSpec>(
|
||||
signature,
|
||||
};
|
||||
if is_valid_deposit_signature(&deposit_data, spec).is_ok() {
|
||||
state.add_builder_to_registry(
|
||||
let builder_index = state.add_builder_to_registry(
|
||||
pubkey,
|
||||
withdrawal_credentials,
|
||||
amount,
|
||||
slot,
|
||||
spec,
|
||||
)?;
|
||||
Ok(Some(builder_index))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
Some(builder_index) => {
|
||||
@@ -1030,9 +1032,9 @@ pub fn apply_deposit_for_builder<E: EthSpec>(
|
||||
.ok_or(BeaconStateError::UnknownBuilder(builder_index))?
|
||||
.balance
|
||||
.safe_add_assign(amount)?;
|
||||
Ok(Some(builder_index))
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Make sure to build the pubkey cache before calling this function
|
||||
|
||||
@@ -367,13 +367,10 @@ where
|
||||
E: EthSpec,
|
||||
F: Fn(usize) -> Option<Cow<'a, PublicKey>>,
|
||||
{
|
||||
let fork = state.fork();
|
||||
|
||||
indexed_payload_attestation_signature_set_from_pubkeys(
|
||||
get_pubkey,
|
||||
signature,
|
||||
indexed_payload_attestation,
|
||||
&fork,
|
||||
state.genesis_validators_root(),
|
||||
spec,
|
||||
)
|
||||
@@ -383,7 +380,6 @@ pub fn indexed_payload_attestation_signature_set_from_pubkeys<'a, 'b, E, F>(
|
||||
get_pubkey: F,
|
||||
signature: &'a AggregateSignature,
|
||||
indexed_payload_attestation: &'b IndexedPayloadAttestation<E>,
|
||||
fork: &Fork,
|
||||
genesis_validators_root: Hash256,
|
||||
spec: &'a ChainSpec,
|
||||
) -> Result<SignatureSet<'a>>
|
||||
@@ -402,7 +398,8 @@ where
|
||||
.data
|
||||
.slot
|
||||
.epoch(E::slots_per_epoch());
|
||||
let domain = spec.get_domain(epoch, Domain::PTCAttester, fork, genesis_validators_root);
|
||||
let fork = spec.fork_at_epoch(epoch);
|
||||
let domain = spec.get_domain(epoch, Domain::PTCAttester, &fork, genesis_validators_root);
|
||||
|
||||
let message = indexed_payload_attestation.data.signing_root(domain);
|
||||
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
use crate::per_block_processing::{
|
||||
is_valid_deposit_signature, process_operations::apply_deposit_for_builder,
|
||||
};
|
||||
use crate::per_block_processing::process_operations::apply_deposit_for_builder;
|
||||
use crate::per_block_processing::process_operations::is_pending_validator;
|
||||
use milhouse::{List, Vector};
|
||||
use safe_arith::SafeArith;
|
||||
use ssz_types::BitVector;
|
||||
use ssz_types::FixedVector;
|
||||
use std::collections::HashSet;
|
||||
use std::collections::HashMap;
|
||||
use std::mem;
|
||||
use tree_hash::TreeHash;
|
||||
use typenum::Unsigned;
|
||||
use types::{
|
||||
BeaconState, BeaconStateError as Error, BeaconStateGloas, BuilderPendingPayment, ChainSpec,
|
||||
DepositData, EthSpec, ExecutionPayloadBid, ExecutionRequests, Fork,
|
||||
is_builder_withdrawal_credential,
|
||||
EthSpec, ExecutionPayloadBid, ExecutionRequests, Fork, is_builder_withdrawal_credential,
|
||||
};
|
||||
|
||||
/// Transform a `Fulu` state into a `Gloas` state.
|
||||
@@ -80,6 +78,7 @@ pub fn upgrade_state_to_gloas<E: EthSpec>(
|
||||
// Execution Bid
|
||||
latest_execution_payload_bid: ExecutionPayloadBid {
|
||||
block_hash: pre.latest_execution_payload_header.block_hash,
|
||||
gas_limit: pre.latest_execution_payload_header.gas_limit,
|
||||
execution_requests_root: ExecutionRequests::<E>::default().tree_hash_root(),
|
||||
..Default::default()
|
||||
},
|
||||
@@ -167,66 +166,57 @@ fn onboard_builders_from_pending_deposits<E: EthSpec>(
|
||||
state: &mut BeaconState<E>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
// Rather than tracking all `validator_pubkeys` in one place as the spec does, we keep a
|
||||
// hashset for *just* the new validator pubkeys, and use the state's efficient
|
||||
// `get_validator_index` function instead of an O(n) iteration over the full validator list.
|
||||
let mut new_validator_pubkeys = HashSet::new();
|
||||
|
||||
// Clone pending deposits to avoid borrow conflicts when mutating state.
|
||||
let current_pending_deposits = state.pending_deposits()?.clone();
|
||||
|
||||
let mut pending_deposits = List::empty();
|
||||
|
||||
// TODO(gloas): introduce a global builder pubkey cache, see:
|
||||
// https://github.com/sigp/lighthouse/issues/8783
|
||||
let mut builder_pubkey_to_index = state
|
||||
.builders()?
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, b)| (b.pubkey, i as u64))
|
||||
.collect::<HashMap<_, _>>();
|
||||
|
||||
for deposit in ¤t_pending_deposits {
|
||||
// Deposits for existing validators stay in the pending queue.
|
||||
if new_validator_pubkeys.contains(&deposit.pubkey)
|
||||
|| state.get_validator_index(&deposit.pubkey)?.is_some()
|
||||
{
|
||||
if state.get_validator_index(&deposit.pubkey)?.is_some() {
|
||||
pending_deposits.push(deposit.clone())?;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Re-scan builder list each iteration because `apply_deposit_for_builder` may add
|
||||
// new builders to the registry.
|
||||
// TODO(gloas): this linear scan could be optimized, see:
|
||||
// https://github.com/sigp/lighthouse/issues/8783
|
||||
let builder_index = state
|
||||
.builders()?
|
||||
.iter()
|
||||
.position(|b| b.pubkey == deposit.pubkey);
|
||||
if !builder_pubkey_to_index.contains_key(&deposit.pubkey) {
|
||||
// Deposits without builder withdrawal credentials are for new validators.
|
||||
if !is_builder_withdrawal_credential(deposit.withdrawal_credentials, spec) {
|
||||
pending_deposits.push(deposit.clone())?;
|
||||
continue;
|
||||
}
|
||||
|
||||
let has_builder_credentials =
|
||||
is_builder_withdrawal_credential(deposit.withdrawal_credentials, spec);
|
||||
|
||||
if builder_index.is_some() || has_builder_credentials {
|
||||
let builder_index_opt = builder_index.map(|i| i as u64);
|
||||
apply_deposit_for_builder(
|
||||
state,
|
||||
builder_index_opt,
|
||||
deposit.pubkey,
|
||||
deposit.withdrawal_credentials,
|
||||
deposit.amount,
|
||||
deposit.signature.clone(),
|
||||
deposit.slot,
|
||||
spec,
|
||||
)?;
|
||||
continue;
|
||||
// If there is a valid pending deposit for a new validator with this pubkey,
|
||||
// keep this deposit in the pending queue to be applied to that validator later.
|
||||
if is_pending_validator(&pending_deposits, &deposit.pubkey, spec) {
|
||||
pending_deposits.push(deposit.clone())?;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// If there is a pending deposit for a new validator that has a valid signature,
|
||||
// track the pubkey so that subsequent builder deposits for the same pubkey stay
|
||||
// in pending (applied to the validator later) rather than creating a builder.
|
||||
// Deposits with invalid signatures are dropped since they would fail in
|
||||
// apply_pending_deposit anyway.
|
||||
let deposit_data = DepositData {
|
||||
pubkey: deposit.pubkey,
|
||||
withdrawal_credentials: deposit.withdrawal_credentials,
|
||||
amount: deposit.amount,
|
||||
signature: deposit.signature.clone(),
|
||||
};
|
||||
if is_valid_deposit_signature(&deposit_data, spec).is_ok() {
|
||||
new_validator_pubkeys.insert(deposit.pubkey);
|
||||
pending_deposits.push(deposit.clone())?;
|
||||
let builder_index = builder_pubkey_to_index.get(&deposit.pubkey).copied();
|
||||
|
||||
if let Some(new_builder_index) = apply_deposit_for_builder(
|
||||
state,
|
||||
builder_index,
|
||||
deposit.pubkey,
|
||||
deposit.withdrawal_credentials,
|
||||
deposit.amount,
|
||||
deposit.signature.clone(),
|
||||
deposit.slot,
|
||||
spec,
|
||||
)? {
|
||||
builder_pubkey_to_index
|
||||
.entry(deposit.pubkey)
|
||||
.or_insert(new_builder_index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user