Handle self-building and use builder domain for envelopes

This commit is contained in:
Michael Sproul
2026-01-19 14:46:02 +11:00
parent 2985ede062
commit 9e365e535f
5 changed files with 50 additions and 19 deletions

View File

@@ -372,6 +372,8 @@ where
E: EthSpec,
F: Fn(usize) -> Option<Cow<'a, PublicKey>>,
{
let proposer_index = state.latest_block_header().proposer_index;
let builder_index = signed_envelope.message.builder_index(proposer_index);
let domain = spec.get_domain(
state.current_epoch(),
Domain::BeaconBuilder,
@@ -379,9 +381,8 @@ where
state.genesis_validators_root(),
);
let message = signed_envelope.message.signing_root(domain);
let pubkey = get_pubkey(signed_envelope.message.builder_index as usize).ok_or(
Error::ValidatorUnknown(signed_envelope.message.builder_index),
)?;
let pubkey =
get_pubkey(builder_index as usize).ok_or(Error::ValidatorUnknown(builder_index))?;
Ok(SignatureSet::single_pubkey(
&signed_envelope.signature,
@@ -400,6 +401,7 @@ where
E: EthSpec,
F: Fn(usize) -> Option<Cow<'a, PublicKey>>,
{
// TODO(EIP-7732): needs to handle self building!
let domain = spec.get_domain(
state.current_epoch(),
Domain::BeaconBuilder,

View File

@@ -25,3 +25,6 @@ pub mod bellatrix {
pub mod deneb {
pub use kzg::VERSIONED_HASH_VERSION_KZG;
}
pub mod gloas {
pub const BUILDER_INDEX_SELF_BUILD: u64 = u64::MAX;
}

View File

@@ -1,3 +1,4 @@
use crate::consts::gloas::BUILDER_INDEX_SELF_BUILD;
use crate::test_utils::TestRandom;
use crate::{
EthSpec, ExecutionPayloadGloas, ExecutionRequests, ForkName, Hash256, KzgCommitments,
@@ -17,8 +18,10 @@ use tree_hash_derive::TreeHash;
pub struct ExecutionPayloadEnvelope<E: EthSpec> {
pub payload: ExecutionPayloadGloas<E>,
pub execution_requests: ExecutionRequests<E>,
// The builder index is private so that callers are forced to handle the case where it equals
// BUILDER_INDEX_SELF_BUILD.
#[serde(with = "serde_utils::quoted_u64")]
pub builder_index: u64,
builder_index: u64,
pub beacon_block_root: Hash256,
pub slot: Slot,
pub blob_kzg_commitments: KzgCommitments<E>,
@@ -27,6 +30,28 @@ pub struct ExecutionPayloadEnvelope<E: EthSpec> {
impl<E: EthSpec> SignedRoot for ExecutionPayloadEnvelope<E> {}
impl<E: EthSpec> ExecutionPayloadEnvelope<E> {
/// Fetch the validator index of the builder of this execution payload.
///
/// This falls back to the provided `proposer_index` if the builder index indicates
/// self-building.
pub fn builder_index(&self, proposer_index: u64) -> u64 {
if self.builder_index == BUILDER_INDEX_SELF_BUILD {
proposer_index
} else {
self.builder_index
}
}
/// Fetch the raw builder index, which may be `BUILDER_INDEX_SELF_BUILD` to indicate
/// self-building.
///
/// This method should be used sparingly.
pub fn raw_builder_index(&self) -> u64 {
self.builder_index
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -39,12 +39,14 @@ impl<E: EthSpec> SignedExecutionPayloadEnvelope<E> {
///
/// The `parent_state` is the post-state of the beacon block with
/// block_root = self.message.beacon_block_root
/// TODO(EIP-7732): maybe delete this function later
/// TODO(EIP-7732): maybe delete this function later (it is inefficient)
pub fn verify_signature_with_state(
&self,
parent_state: &BeaconState<E>,
spec: &ChainSpec,
) -> Result<bool, BeaconStateError> {
let proposer_index = parent_state.latest_block_header().proposer_index;
let builder_index = self.message.builder_index(proposer_index) as usize;
let domain = spec.get_domain(
parent_state.current_epoch(),
Domain::BeaconBuilder,
@@ -53,23 +55,18 @@ impl<E: EthSpec> SignedExecutionPayloadEnvelope<E> {
);
let pubkey = parent_state
.validators()
.get(self.message.builder_index as usize)
.get(builder_index)
.and_then(|v| {
let pk: Option<PublicKey> = v.pubkey.decompress().ok();
pk
})
.ok_or(BeaconStateError::UnknownValidator(
self.message.builder_index as usize,
))?;
.ok_or(BeaconStateError::UnknownValidator(builder_index))?;
let message = self.message.signing_root(domain);
Ok(self.signature.verify(&pubkey, message))
}
/// Verify `self.signature`.
///
/// If the root of `block.message` is already known it can be passed in via `object_root_opt`.
/// Otherwise, it will be computed locally.
pub fn verify_signature(
&self,
pubkey: &PublicKey,
@@ -77,9 +74,11 @@ impl<E: EthSpec> SignedExecutionPayloadEnvelope<E> {
genesis_validators_root: Hash256,
spec: &ChainSpec,
) -> bool {
// Signed envelopes using the new BeaconBuilder domain per the spec:
// https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.1/specs/gloas/beacon-chain.md#new-verify_execution_payload_envelope_signature
let domain = spec.get_domain(
self.epoch(),
Domain::BeaconProposer,
Domain::BeaconBuilder,
fork,
genesis_validators_root,
);