Op pool and gossip for BLS to execution changes (#3726)

This commit is contained in:
Michael Sproul
2022-11-25 07:09:26 +11:00
committed by GitHub
parent 58b54f0a53
commit 788b337951
27 changed files with 539 additions and 69 deletions

View File

@@ -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.
///

View File

@@ -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]
}
}