mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-09 03:31:45 +00:00
Op pool and gossip for BLS to execution changes (#3726)
This commit is contained in:
@@ -158,6 +158,8 @@ where
|
||||
// Deposits are not included because they can legally have invalid signatures.
|
||||
self.include_exits(block)?;
|
||||
self.include_sync_aggregate(block)?;
|
||||
#[cfg(feature = "withdrawals")]
|
||||
self.include_bls_to_execution_changes(block)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -339,6 +341,26 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Include the signature of the block's BLS to execution changes for verification.
|
||||
#[cfg(feature = "withdrawals")]
|
||||
pub fn include_bls_to_execution_changes<Payload: AbstractExecPayload<T>>(
|
||||
&mut self,
|
||||
block: &'a SignedBeaconBlock<T, Payload>,
|
||||
) -> Result<()> {
|
||||
// FIXME(capella): to improve performance we might want to decompress the withdrawal pubkeys
|
||||
// in parallel.
|
||||
if let Ok(bls_to_execution_changes) = block.message().body().bls_to_execution_changes() {
|
||||
for bls_to_execution_change in bls_to_execution_changes {
|
||||
self.sets.push(bls_execution_change_signature_set(
|
||||
self.state,
|
||||
bls_to_execution_change,
|
||||
self.spec,
|
||||
)?);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Verify all the signatures that have been included in `self`, returning `true` if and only if
|
||||
/// all the signatures are valid.
|
||||
///
|
||||
|
||||
@@ -15,6 +15,14 @@ use types::{
|
||||
SignedVoluntaryExit,
|
||||
};
|
||||
|
||||
#[cfg(feature = "withdrawals-processing")]
|
||||
use {
|
||||
crate::per_block_processing::{
|
||||
errors::BlsExecutionChangeValidationError, verify_bls_to_execution_change,
|
||||
},
|
||||
types::SignedBlsToExecutionChange,
|
||||
};
|
||||
|
||||
const MAX_FORKS_VERIFIED_AGAINST: usize = 2;
|
||||
|
||||
/// Wrapper around an operation type that acts as proof that its signature has been checked.
|
||||
@@ -65,7 +73,7 @@ where
|
||||
fn new(op: T, state: &BeaconState<E>) -> Self {
|
||||
let verified_against = VerifiedAgainst {
|
||||
fork_versions: op
|
||||
.verification_epochs()
|
||||
.verification_epochs(state.current_epoch())
|
||||
.into_iter()
|
||||
.map(|epoch| state.fork().get_fork_version(epoch))
|
||||
.collect(),
|
||||
@@ -87,8 +95,13 @@ where
|
||||
}
|
||||
|
||||
pub fn signature_is_still_valid(&self, current_fork: &Fork) -> bool {
|
||||
// Pass the fork's epoch as the effective current epoch. If the message is a current-epoch
|
||||
// style message like `SignedBlsToExecutionChange` then `get_fork_version` will return the
|
||||
// current fork version and we'll check it matches the fork version the message was checked
|
||||
// against.
|
||||
let effective_current_epoch = current_fork.epoch;
|
||||
self.as_inner()
|
||||
.verification_epochs()
|
||||
.verification_epochs(effective_current_epoch)
|
||||
.into_iter()
|
||||
.zip(self.verified_against.fork_versions.iter())
|
||||
.all(|(epoch, verified_fork_version)| {
|
||||
@@ -118,7 +131,13 @@ pub trait VerifyOperation<E: EthSpec>: Encode + Decode + Sized {
|
||||
/// Return the epochs at which parts of this message were verified.
|
||||
///
|
||||
/// These need to map 1-to-1 to the `SigVerifiedOp::verified_against` for this type.
|
||||
fn verification_epochs(&self) -> SmallVec<[Epoch; MAX_FORKS_VERIFIED_AGAINST]>;
|
||||
///
|
||||
/// If the message contains no inherent epoch it should return the `current_epoch` that is
|
||||
/// passed in, as that's the epoch at which it was verified.
|
||||
fn verification_epochs(
|
||||
&self,
|
||||
current_epoch: Epoch,
|
||||
) -> SmallVec<[Epoch; MAX_FORKS_VERIFIED_AGAINST]>;
|
||||
}
|
||||
|
||||
impl<E: EthSpec> VerifyOperation<E> for SignedVoluntaryExit {
|
||||
@@ -134,7 +153,7 @@ impl<E: EthSpec> VerifyOperation<E> for SignedVoluntaryExit {
|
||||
}
|
||||
|
||||
#[allow(clippy::integer_arithmetic)]
|
||||
fn verification_epochs(&self) -> SmallVec<[Epoch; MAX_FORKS_VERIFIED_AGAINST]> {
|
||||
fn verification_epochs(&self, _: Epoch) -> SmallVec<[Epoch; MAX_FORKS_VERIFIED_AGAINST]> {
|
||||
smallvec![self.message.epoch]
|
||||
}
|
||||
}
|
||||
@@ -152,7 +171,7 @@ impl<E: EthSpec> VerifyOperation<E> for AttesterSlashing<E> {
|
||||
}
|
||||
|
||||
#[allow(clippy::integer_arithmetic)]
|
||||
fn verification_epochs(&self) -> SmallVec<[Epoch; MAX_FORKS_VERIFIED_AGAINST]> {
|
||||
fn verification_epochs(&self, _: Epoch) -> SmallVec<[Epoch; MAX_FORKS_VERIFIED_AGAINST]> {
|
||||
smallvec![
|
||||
self.attestation_1.data.target.epoch,
|
||||
self.attestation_2.data.target.epoch
|
||||
@@ -173,7 +192,7 @@ impl<E: EthSpec> VerifyOperation<E> for ProposerSlashing {
|
||||
}
|
||||
|
||||
#[allow(clippy::integer_arithmetic)]
|
||||
fn verification_epochs(&self) -> SmallVec<[Epoch; MAX_FORKS_VERIFIED_AGAINST]> {
|
||||
fn verification_epochs(&self, _: Epoch) -> SmallVec<[Epoch; MAX_FORKS_VERIFIED_AGAINST]> {
|
||||
// Only need a single epoch because the slots of the two headers must be equal.
|
||||
smallvec![self
|
||||
.signed_header_1
|
||||
@@ -182,3 +201,25 @@ impl<E: EthSpec> VerifyOperation<E> for ProposerSlashing {
|
||||
.epoch(E::slots_per_epoch())]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "withdrawals-processing")]
|
||||
impl<E: EthSpec> VerifyOperation<E> for SignedBlsToExecutionChange {
|
||||
type Error = BlsExecutionChangeValidationError;
|
||||
|
||||
fn validate(
|
||||
self,
|
||||
state: &BeaconState<E>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<SigVerifiedOp<Self, E>, Self::Error> {
|
||||
verify_bls_to_execution_change(state, &self, VerifySignatures::True, spec)?;
|
||||
Ok(SigVerifiedOp::new(self, state))
|
||||
}
|
||||
|
||||
#[allow(clippy::integer_arithmetic)]
|
||||
fn verification_epochs(
|
||||
&self,
|
||||
current_epoch: Epoch,
|
||||
) -> SmallVec<[Epoch; MAX_FORKS_VERIFIED_AGAINST]> {
|
||||
smallvec![current_epoch]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user