mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-29 20:27:14 +00:00
Merge branch 'gloas-containers' into gloas-envelope-processing
This commit is contained in:
@@ -216,9 +216,9 @@ impl<T: BeaconChainTypes> GossipVerifiedEnvelope<T> {
|
|||||||
signed_envelope: Arc<SignedExecutionPayloadEnvelope<T::EthSpec>>,
|
signed_envelope: Arc<SignedExecutionPayloadEnvelope<T::EthSpec>>,
|
||||||
chain: &BeaconChain<T>,
|
chain: &BeaconChain<T>,
|
||||||
) -> Result<Self, EnvelopeError> {
|
) -> Result<Self, EnvelopeError> {
|
||||||
let envelope = signed_envelope.message();
|
let envelope = &signed_envelope.message;
|
||||||
let payload = envelope.payload();
|
let payload = &envelope.payload;
|
||||||
let beacon_block_root = envelope.beacon_block_root();
|
let beacon_block_root = envelope.beacon_block_root;
|
||||||
|
|
||||||
// check that we've seen the parent block of this envelope and that it passes validation
|
// check that we've seen the parent block of this envelope and that it passes validation
|
||||||
// TODO(EIP-7732): this check would fail if the block didn't pass validation right?
|
// TODO(EIP-7732): this check would fail if the block didn't pass validation right?
|
||||||
@@ -255,26 +255,26 @@ impl<T: BeaconChainTypes> GossipVerifiedEnvelope<T> {
|
|||||||
// should these kinds of checks be included for envelopes as well?
|
// should these kinds of checks be included for envelopes as well?
|
||||||
|
|
||||||
// check that the slot of the envelope matches the slot of the parent block
|
// check that the slot of the envelope matches the slot of the parent block
|
||||||
if envelope.slot() != parent_block.slot() {
|
if envelope.slot != parent_block.slot() {
|
||||||
return Err(EnvelopeError::SlotMismatch {
|
return Err(EnvelopeError::SlotMismatch {
|
||||||
parent_block: parent_block.slot(),
|
parent_block: parent_block.slot(),
|
||||||
envelope: envelope.slot(),
|
envelope: envelope.slot,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// builder index matches committed bid
|
// builder index matches committed bid
|
||||||
if envelope.builder_index() != execution_bid.builder_index {
|
if envelope.builder_index != execution_bid.builder_index {
|
||||||
return Err(EnvelopeError::BuilderIndexMismatch {
|
return Err(EnvelopeError::BuilderIndexMismatch {
|
||||||
committed_bid: execution_bid.builder_index,
|
committed_bid: execution_bid.builder_index,
|
||||||
envelope: envelope.builder_index(),
|
envelope: envelope.builder_index,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// the block hash should match the block hash of the execution bid
|
// the block hash should match the block hash of the execution bid
|
||||||
if payload.block_hash() != execution_bid.block_hash {
|
if payload.block_hash != execution_bid.block_hash {
|
||||||
return Err(EnvelopeError::BlockHashMismatch {
|
return Err(EnvelopeError::BlockHashMismatch {
|
||||||
committed_bid: execution_bid.block_hash,
|
committed_bid: execution_bid.block_hash,
|
||||||
envelope: payload.block_hash(),
|
envelope: payload.block_hash,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,7 +283,7 @@ impl<T: BeaconChainTypes> GossipVerifiedEnvelope<T> {
|
|||||||
// and so on.
|
// and so on.
|
||||||
|
|
||||||
// get the fork from the cache so we can verify the signature
|
// get the fork from the cache so we can verify the signature
|
||||||
let block_slot = envelope.slot();
|
let block_slot = envelope.slot;
|
||||||
let block_epoch = block_slot.epoch(T::EthSpec::slots_per_epoch());
|
let block_epoch = block_slot.epoch(T::EthSpec::slots_per_epoch());
|
||||||
let proposer_shuffling_decision_block =
|
let proposer_shuffling_decision_block =
|
||||||
parent_proto_block.proposer_shuffling_root_for_child_block(block_epoch, &chain.spec);
|
parent_proto_block.proposer_shuffling_root_for_child_block(block_epoch, &chain.spec);
|
||||||
@@ -311,9 +311,9 @@ impl<T: BeaconChainTypes> GossipVerifiedEnvelope<T> {
|
|||||||
let signature_is_valid = {
|
let signature_is_valid = {
|
||||||
let pubkey_cache = chain.validator_pubkey_cache.read();
|
let pubkey_cache = chain.validator_pubkey_cache.read();
|
||||||
let builder_pubkey = pubkey_cache
|
let builder_pubkey = pubkey_cache
|
||||||
.get(envelope.builder_index() as usize)
|
.get(envelope.builder_index as usize)
|
||||||
.ok_or_else(|| EnvelopeError::UnknownValidator {
|
.ok_or_else(|| EnvelopeError::UnknownValidator {
|
||||||
builder_index: envelope.builder_index(),
|
builder_index: envelope.builder_index,
|
||||||
})?;
|
})?;
|
||||||
signed_envelope.verify_signature(
|
signed_envelope.verify_signature(
|
||||||
builder_pubkey,
|
builder_pubkey,
|
||||||
@@ -360,13 +360,13 @@ impl<T: BeaconChainTypes> IntoExecutionPendingEnvelope<T> for GossipVerifiedEnve
|
|||||||
notify_execution_layer: NotifyExecutionLayer,
|
notify_execution_layer: NotifyExecutionLayer,
|
||||||
) -> Result<ExecutionPendingEnvelope<T>, EnvelopeError> {
|
) -> Result<ExecutionPendingEnvelope<T>, EnvelopeError> {
|
||||||
let signed_envelope = self.signed_envelope;
|
let signed_envelope = self.signed_envelope;
|
||||||
let envelope = signed_envelope.message();
|
let envelope = &signed_envelope.message;
|
||||||
let payload = &envelope.payload();
|
let payload = &envelope.payload;
|
||||||
|
|
||||||
// Verify the execution payload is valid
|
// Verify the execution payload is valid
|
||||||
let payload_notifier =
|
let payload_notifier =
|
||||||
PayloadNotifier::from_envelope(chain.clone(), envelope, notify_execution_layer)?;
|
PayloadNotifier::from_envelope(chain.clone(), envelope, notify_execution_layer)?;
|
||||||
let block_root = envelope.beacon_block_root();
|
let block_root = envelope.beacon_block_root;
|
||||||
let slot = self.parent_block.slot();
|
let slot = self.parent_block.slot();
|
||||||
|
|
||||||
let payload_verification_future = async move {
|
let payload_verification_future = async move {
|
||||||
@@ -417,7 +417,7 @@ impl<T: BeaconChainTypes> IntoExecutionPendingEnvelope<T> for GossipVerifiedEnve
|
|||||||
|
|
||||||
Ok(ExecutionPendingEnvelope {
|
Ok(ExecutionPendingEnvelope {
|
||||||
signed_envelope: MaybeAvailableEnvelope::AvailabilityPending {
|
signed_envelope: MaybeAvailableEnvelope::AvailabilityPending {
|
||||||
block_hash: payload.block_hash(),
|
block_hash: payload.block_hash,
|
||||||
envelope: signed_envelope,
|
envelope: signed_envelope,
|
||||||
},
|
},
|
||||||
import_data: EnvelopeImportData {
|
import_data: EnvelopeImportData {
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ impl<T: BeaconChainTypes> PayloadNotifier<T> {
|
|||||||
|
|
||||||
pub fn from_envelope(
|
pub fn from_envelope(
|
||||||
_chain: Arc<BeaconChain<T>>,
|
_chain: Arc<BeaconChain<T>>,
|
||||||
_envelope: ExecutionPayloadEnvelopeRef<T::EthSpec>,
|
_envelope: &ExecutionPayloadEnvelope<T::EthSpec>,
|
||||||
_notify_execution_layer: NotifyExecutionLayer,
|
_notify_execution_layer: NotifyExecutionLayer,
|
||||||
) -> Result<Self, EnvelopeError> {
|
) -> Result<Self, EnvelopeError> {
|
||||||
todo!(
|
todo!(
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ impl<'block, E: EthSpec> NewPayloadRequest<'block, E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO(EIP7732): Consider implmenting these as methods on the NewPayloadRequest struct
|
//TODO(EIP7732): Consider implementing these as methods on the NewPayloadRequest struct
|
||||||
impl<'a, E: EthSpec> TryFrom<BeaconBlockRef<'a, E>> for NewPayloadRequest<'a, E> {
|
impl<'a, E: EthSpec> TryFrom<BeaconBlockRef<'a, E>> for NewPayloadRequest<'a, E> {
|
||||||
type Error = BeaconStateError;
|
type Error = BeaconStateError;
|
||||||
|
|
||||||
|
|||||||
@@ -124,9 +124,9 @@ pub fn envelope_processing<E: EthSpec>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let envelope = signed_envelope.message();
|
let envelope = &signed_envelope.message;
|
||||||
let payload = envelope.payload();
|
let payload = &envelope.payload;
|
||||||
let execution_requests = envelope.execution_requests();
|
let execution_requests = &envelope.execution_requests;
|
||||||
|
|
||||||
// Cache latest block header state root
|
// Cache latest block header state root
|
||||||
if state.latest_block_header().state_root == Hash256::default() {
|
if state.latest_block_header().state_root == Hash256::default() {
|
||||||
@@ -138,16 +138,16 @@ pub fn envelope_processing<E: EthSpec>(
|
|||||||
|
|
||||||
// Verify consistency with the beacon block
|
// Verify consistency with the beacon block
|
||||||
envelope_verify!(
|
envelope_verify!(
|
||||||
envelope.beacon_block_root() == state.latest_block_header().tree_hash_root(),
|
envelope.beacon_block_root == state.latest_block_header().tree_hash_root(),
|
||||||
EnvelopeProcessingError::LatestBlockHeaderMismatch {
|
EnvelopeProcessingError::LatestBlockHeaderMismatch {
|
||||||
envelope_root: envelope.beacon_block_root(),
|
envelope_root: envelope.beacon_block_root,
|
||||||
block_header_root: state.latest_block_header().tree_hash_root(),
|
block_header_root: state.latest_block_header().tree_hash_root(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
envelope_verify!(
|
envelope_verify!(
|
||||||
envelope.slot() == state.slot(),
|
envelope.slot == state.slot(),
|
||||||
EnvelopeProcessingError::SlotMismatch {
|
EnvelopeProcessingError::SlotMismatch {
|
||||||
envelope_slot: envelope.slot(),
|
envelope_slot: envelope.slot,
|
||||||
parent_state_slot: state.slot(),
|
parent_state_slot: state.slot(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -155,75 +155,75 @@ pub fn envelope_processing<E: EthSpec>(
|
|||||||
// Verify consistency with the committed bid
|
// Verify consistency with the committed bid
|
||||||
let committed_bid = state.latest_execution_payload_bid()?;
|
let committed_bid = state.latest_execution_payload_bid()?;
|
||||||
// builder index match already verified
|
// builder index match already verified
|
||||||
if committed_bid.blob_kzg_commitments_root != envelope.blob_kzg_commitments().tree_hash_root() {
|
if committed_bid.blob_kzg_commitments_root != envelope.blob_kzg_commitments.tree_hash_root() {
|
||||||
return Err(EnvelopeProcessingError::BlobKzgCommitmentsRootMismatch {
|
return Err(EnvelopeProcessingError::BlobKzgCommitmentsRootMismatch {
|
||||||
committed_bid: committed_bid.blob_kzg_commitments_root,
|
committed_bid: committed_bid.blob_kzg_commitments_root,
|
||||||
envelope: envelope.blob_kzg_commitments().tree_hash_root(),
|
envelope: envelope.blob_kzg_commitments.tree_hash_root(),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Verify the withdrawals root
|
// Verify the withdrawals root
|
||||||
envelope_verify!(
|
envelope_verify!(
|
||||||
payload.withdrawals()?.tree_hash_root() == *state.latest_withdrawals_root()?,
|
payload.withdrawals.tree_hash_root() == *state.latest_withdrawals_root()?,
|
||||||
EnvelopeProcessingError::WithdrawalsRootMismatch {
|
EnvelopeProcessingError::WithdrawalsRootMismatch {
|
||||||
state: *state.latest_withdrawals_root()?,
|
state: *state.latest_withdrawals_root()?,
|
||||||
envelope: payload.withdrawals()?.tree_hash_root(),
|
envelope: payload.withdrawals.tree_hash_root(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Verify the gas limit
|
// Verify the gas limit
|
||||||
envelope_verify!(
|
envelope_verify!(
|
||||||
payload.gas_limit() == committed_bid.gas_limit,
|
payload.gas_limit == committed_bid.gas_limit,
|
||||||
EnvelopeProcessingError::GasLimitMismatch {
|
EnvelopeProcessingError::GasLimitMismatch {
|
||||||
committed_bid: committed_bid.gas_limit,
|
committed_bid: committed_bid.gas_limit,
|
||||||
envelope: payload.gas_limit(),
|
envelope: payload.gas_limit,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Verify the block hash
|
// Verify the block hash
|
||||||
envelope_verify!(
|
envelope_verify!(
|
||||||
committed_bid.block_hash == payload.block_hash(),
|
committed_bid.block_hash == payload.block_hash,
|
||||||
EnvelopeProcessingError::BlockHashMismatch {
|
EnvelopeProcessingError::BlockHashMismatch {
|
||||||
committed_bid: committed_bid.block_hash,
|
committed_bid: committed_bid.block_hash,
|
||||||
envelope: payload.block_hash(),
|
envelope: payload.block_hash,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Verify consistency of the parent hash with respect to the previous execution payload
|
// Verify consistency of the parent hash with respect to the previous execution payload
|
||||||
envelope_verify!(
|
envelope_verify!(
|
||||||
payload.parent_hash() == *state.latest_block_hash()?,
|
payload.parent_hash == *state.latest_block_hash()?,
|
||||||
EnvelopeProcessingError::ParentHashMismatch {
|
EnvelopeProcessingError::ParentHashMismatch {
|
||||||
state: *state.latest_block_hash()?,
|
state: *state.latest_block_hash()?,
|
||||||
envelope: payload.parent_hash(),
|
envelope: payload.parent_hash,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Verify prev_randao
|
// Verify prev_randao
|
||||||
envelope_verify!(
|
envelope_verify!(
|
||||||
payload.prev_randao() == *state.get_randao_mix(state.current_epoch())?,
|
payload.prev_randao == *state.get_randao_mix(state.current_epoch())?,
|
||||||
EnvelopeProcessingError::PrevRandaoMismatch {
|
EnvelopeProcessingError::PrevRandaoMismatch {
|
||||||
state: *state.get_randao_mix(state.current_epoch())?,
|
state: *state.get_randao_mix(state.current_epoch())?,
|
||||||
envelope: payload.prev_randao(),
|
envelope: payload.prev_randao,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Verify the timestamp
|
// Verify the timestamp
|
||||||
let state_timestamp = compute_timestamp_at_slot(state, state.slot(), spec)?;
|
let state_timestamp = compute_timestamp_at_slot(state, state.slot(), spec)?;
|
||||||
envelope_verify!(
|
envelope_verify!(
|
||||||
payload.timestamp() == state_timestamp,
|
payload.timestamp == state_timestamp,
|
||||||
EnvelopeProcessingError::TimestampMismatch {
|
EnvelopeProcessingError::TimestampMismatch {
|
||||||
state: state_timestamp,
|
state: state_timestamp,
|
||||||
envelope: payload.timestamp(),
|
envelope: payload.timestamp,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Verify the commitments are under limit
|
// Verify the commitments are under limit
|
||||||
let max_blobs = spec.max_blobs_per_block(state.current_epoch()) as usize;
|
let max_blobs = spec.max_blobs_per_block(state.current_epoch()) as usize;
|
||||||
envelope_verify!(
|
envelope_verify!(
|
||||||
envelope.blob_kzg_commitments().len() <= max_blobs,
|
envelope.blob_kzg_commitments.len() <= max_blobs,
|
||||||
EnvelopeProcessingError::BlobLimitExceeded {
|
EnvelopeProcessingError::BlobLimitExceeded {
|
||||||
max: max_blobs,
|
max: max_blobs,
|
||||||
envelope: envelope.blob_kzg_commitments().len(),
|
envelope: envelope.blob_kzg_commitments.len(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -269,14 +269,14 @@ pub fn envelope_processing<E: EthSpec>(
|
|||||||
.execution_payload_availability_mut()?
|
.execution_payload_availability_mut()?
|
||||||
.set(availability_index, true)
|
.set(availability_index, true)
|
||||||
.map_err(EnvelopeProcessingError::BitFieldError)?;
|
.map_err(EnvelopeProcessingError::BitFieldError)?;
|
||||||
*state.latest_block_hash_mut()? = payload.block_hash();
|
*state.latest_block_hash_mut()? = payload.block_hash;
|
||||||
|
|
||||||
// verify the state root
|
// verify the state root
|
||||||
envelope_verify!(
|
envelope_verify!(
|
||||||
envelope.state_root() == state.canonical_root()?,
|
envelope.state_root == state.canonical_root()?,
|
||||||
EnvelopeProcessingError::InvalidStateRoot {
|
EnvelopeProcessingError::InvalidStateRoot {
|
||||||
state: state.canonical_root()?,
|
state: state.canonical_root()?,
|
||||||
envelope: envelope.state_root(),
|
envelope: envelope.state_root,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -378,13 +378,13 @@ where
|
|||||||
&state.fork(),
|
&state.fork(),
|
||||||
state.genesis_validators_root(),
|
state.genesis_validators_root(),
|
||||||
);
|
);
|
||||||
let message = signed_envelope.message().signing_root(domain);
|
let message = signed_envelope.message.signing_root(domain);
|
||||||
let pubkey = get_pubkey(signed_envelope.message().builder_index() as usize).ok_or(
|
let pubkey = get_pubkey(signed_envelope.message.builder_index as usize).ok_or(
|
||||||
Error::ValidatorUnknown(signed_envelope.message().builder_index()),
|
Error::ValidatorUnknown(signed_envelope.message.builder_index),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(SignatureSet::single_pubkey(
|
Ok(SignatureSet::single_pubkey(
|
||||||
signed_envelope.signature(),
|
&signed_envelope.signature,
|
||||||
pubkey,
|
pubkey,
|
||||||
message,
|
message,
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -2,107 +2,33 @@ use crate::test_utils::TestRandom;
|
|||||||
use crate::*;
|
use crate::*;
|
||||||
use beacon_block_body::KzgCommitments;
|
use beacon_block_body::KzgCommitments;
|
||||||
use educe::Educe;
|
use educe::Educe;
|
||||||
use serde::de::{Deserializer, Error as _};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use ssz_derive::{Decode, Encode};
|
use ssz_derive::{Decode, Encode};
|
||||||
use superstruct::superstruct;
|
|
||||||
use test_random_derive::TestRandom;
|
use test_random_derive::TestRandom;
|
||||||
use tree_hash_derive::TreeHash;
|
use tree_hash_derive::TreeHash;
|
||||||
|
|
||||||
// in all likelihood, this will be superstructed so might as well start early eh?
|
#[derive(Debug, Clone, Serialize, Encode, Decode, Deserialize, TestRandom, TreeHash, Educe)]
|
||||||
#[superstruct(
|
|
||||||
variants(Gloas, NextFork),
|
|
||||||
variant_attributes(
|
|
||||||
derive(
|
|
||||||
Debug,
|
|
||||||
Clone,
|
|
||||||
Serialize,
|
|
||||||
Deserialize,
|
|
||||||
Encode,
|
|
||||||
Decode,
|
|
||||||
TreeHash,
|
|
||||||
TestRandom,
|
|
||||||
Educe
|
|
||||||
),
|
|
||||||
cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary)),
|
|
||||||
educe(PartialEq, Hash(bound(E: EthSpec))),
|
|
||||||
serde(bound = "E: EthSpec", deny_unknown_fields),
|
|
||||||
cfg_attr(feature = "arbitrary", arbitrary(bound = "E: EthSpec"))
|
|
||||||
),
|
|
||||||
ref_attributes(
|
|
||||||
derive(Debug, PartialEq, TreeHash),
|
|
||||||
tree_hash(enum_behaviour = "transparent")
|
|
||||||
),
|
|
||||||
cast_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant"),
|
|
||||||
partial_getter_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant")
|
|
||||||
)]
|
|
||||||
#[derive(Debug, Clone, Serialize, Encode, Deserialize, TreeHash, Educe)]
|
|
||||||
#[educe(PartialEq, Hash(bound(E: EthSpec)))]
|
#[educe(PartialEq, Hash(bound(E: EthSpec)))]
|
||||||
#[serde(bound = "E: EthSpec", untagged)]
|
#[context_deserialize(ForkName)]
|
||||||
#[ssz(enum_behaviour = "transparent")]
|
#[serde(bound = "E: EthSpec")]
|
||||||
#[tree_hash(enum_behaviour = "transparent")]
|
|
||||||
pub struct ExecutionPayloadEnvelope<E: EthSpec> {
|
pub struct ExecutionPayloadEnvelope<E: EthSpec> {
|
||||||
#[superstruct(only(Gloas), partial_getter(rename = "payload_gloas"))]
|
|
||||||
pub payload: ExecutionPayloadGloas<E>,
|
|
||||||
#[superstruct(only(NextFork), partial_getter(rename = "payload_next_fork"))]
|
|
||||||
pub payload: ExecutionPayloadGloas<E>,
|
pub payload: ExecutionPayloadGloas<E>,
|
||||||
pub execution_requests: ExecutionRequests<E>,
|
pub execution_requests: ExecutionRequests<E>,
|
||||||
#[serde(with = "serde_utils::quoted_u64")]
|
#[serde(with = "serde_utils::quoted_u64")]
|
||||||
#[superstruct(getter(copy))]
|
|
||||||
pub builder_index: u64,
|
pub builder_index: u64,
|
||||||
#[superstruct(getter(copy))]
|
|
||||||
pub beacon_block_root: Hash256,
|
pub beacon_block_root: Hash256,
|
||||||
#[superstruct(getter(copy))]
|
|
||||||
pub slot: Slot,
|
pub slot: Slot,
|
||||||
pub blob_kzg_commitments: KzgCommitments<E>,
|
pub blob_kzg_commitments: KzgCommitments<E>,
|
||||||
#[superstruct(getter(copy))]
|
|
||||||
pub state_root: Hash256,
|
pub state_root: Hash256,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: EthSpec> SignedRoot for ExecutionPayloadEnvelope<E> {}
|
impl<E: EthSpec> SignedRoot for ExecutionPayloadEnvelope<E> {}
|
||||||
impl<'a, E: EthSpec> SignedRoot for ExecutionPayloadEnvelopeRef<'a, E> {}
|
|
||||||
|
|
||||||
impl<'a, E: EthSpec> ExecutionPayloadEnvelopeRef<'a, E> {
|
|
||||||
pub fn payload(&self) -> ExecutionPayloadRef<'a, E> {
|
|
||||||
match self {
|
|
||||||
Self::Gloas(envelope) => ExecutionPayloadRef::Gloas(&envelope.payload),
|
|
||||||
Self::NextFork(envelope) => ExecutionPayloadRef::Gloas(&envelope.payload),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn block_hash(&self) -> ExecutionBlockHash {
|
|
||||||
self.payload().block_hash()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for ExecutionPayloadEnvelope<E> {
|
|
||||||
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
let value: Self = serde::Deserialize::deserialize(deserializer)?;
|
|
||||||
|
|
||||||
match (context, &value) {
|
|
||||||
(ForkName::Gloas, Self::Gloas { .. }) => Ok(value),
|
|
||||||
_ => Err(D::Error::custom(format!(
|
|
||||||
"ExecutionPayloadEnvelope does not support fork {context:?}"
|
|
||||||
))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::MainnetEthSpec;
|
use crate::MainnetEthSpec;
|
||||||
|
|
||||||
mod gloas {
|
ssz_and_tree_hash_tests!(ExecutionPayloadEnvelope<MainnetEthSpec>);
|
||||||
use super::*;
|
|
||||||
ssz_and_tree_hash_tests!(ExecutionPayloadEnvelopeGloas<MainnetEthSpec>);
|
|
||||||
}
|
|
||||||
|
|
||||||
mod next_fork {
|
|
||||||
use super::*;
|
|
||||||
ssz_and_tree_hash_tests!(ExecutionPayloadEnvelopeNextFork<MainnetEthSpec>);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,10 +187,7 @@ pub use crate::execution_payload::{
|
|||||||
Transaction, Transactions, Withdrawals,
|
Transaction, Transactions, Withdrawals,
|
||||||
};
|
};
|
||||||
pub use crate::execution_payload_bid::ExecutionPayloadBid;
|
pub use crate::execution_payload_bid::ExecutionPayloadBid;
|
||||||
pub use crate::execution_payload_envelope::{
|
pub use crate::execution_payload_envelope::ExecutionPayloadEnvelope;
|
||||||
ExecutionPayloadEnvelope, ExecutionPayloadEnvelopeGloas, ExecutionPayloadEnvelopeNextFork,
|
|
||||||
ExecutionPayloadEnvelopeRef,
|
|
||||||
};
|
|
||||||
pub use crate::execution_payload_header::{
|
pub use crate::execution_payload_header::{
|
||||||
ExecutionPayloadHeader, ExecutionPayloadHeaderBellatrix, ExecutionPayloadHeaderCapella,
|
ExecutionPayloadHeader, ExecutionPayloadHeaderBellatrix, ExecutionPayloadHeaderCapella,
|
||||||
ExecutionPayloadHeaderDeneb, ExecutionPayloadHeaderElectra, ExecutionPayloadHeaderFulu,
|
ExecutionPayloadHeaderDeneb, ExecutionPayloadHeaderElectra, ExecutionPayloadHeaderFulu,
|
||||||
|
|||||||
@@ -1,82 +1,22 @@
|
|||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use educe::Educe;
|
use educe::Educe;
|
||||||
use serde::de::{Deserializer, Error as _};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use ssz_derive::{Decode, Encode};
|
use ssz_derive::{Decode, Encode};
|
||||||
use superstruct::superstruct;
|
|
||||||
use test_random_derive::TestRandom;
|
use test_random_derive::TestRandom;
|
||||||
use tree_hash_derive::TreeHash;
|
use tree_hash_derive::TreeHash;
|
||||||
|
|
||||||
#[superstruct(
|
#[derive(Debug, Clone, Serialize, Encode, Decode, Deserialize, TestRandom, TreeHash, Educe)]
|
||||||
variants(Gloas, NextFork),
|
|
||||||
variant_attributes(
|
|
||||||
derive(
|
|
||||||
Debug,
|
|
||||||
Clone,
|
|
||||||
Serialize,
|
|
||||||
Deserialize,
|
|
||||||
Encode,
|
|
||||||
Decode,
|
|
||||||
TreeHash,
|
|
||||||
TestRandom,
|
|
||||||
Educe
|
|
||||||
),
|
|
||||||
cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary)),
|
|
||||||
educe(PartialEq, Hash(bound(E: EthSpec))),
|
|
||||||
serde(bound = "E: EthSpec", deny_unknown_fields),
|
|
||||||
cfg_attr(feature = "arbitrary", arbitrary(bound = "E: EthSpec"))
|
|
||||||
),
|
|
||||||
ref_attributes(
|
|
||||||
derive(Debug, PartialEq, TreeHash),
|
|
||||||
tree_hash(enum_behaviour = "transparent")
|
|
||||||
),
|
|
||||||
cast_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant"),
|
|
||||||
partial_getter_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant")
|
|
||||||
)]
|
|
||||||
#[derive(Debug, Clone, Serialize, Encode, Deserialize, TreeHash, Educe)]
|
|
||||||
#[educe(PartialEq, Hash(bound(E: EthSpec)))]
|
#[educe(PartialEq, Hash(bound(E: EthSpec)))]
|
||||||
#[serde(bound = "E: EthSpec", untagged)]
|
#[serde(bound = "E: EthSpec")]
|
||||||
#[ssz(enum_behaviour = "transparent")]
|
|
||||||
#[tree_hash(enum_behaviour = "transparent")]
|
|
||||||
pub struct SignedExecutionPayloadEnvelope<E: EthSpec> {
|
pub struct SignedExecutionPayloadEnvelope<E: EthSpec> {
|
||||||
#[superstruct(only(Gloas), partial_getter(rename = "message_gloas"))]
|
pub message: ExecutionPayloadEnvelope<E>,
|
||||||
pub message: ExecutionPayloadEnvelopeGloas<E>,
|
|
||||||
#[superstruct(only(NextFork), partial_getter(rename = "message_next_fork"))]
|
|
||||||
pub message: crate::execution_payload_envelope::ExecutionPayloadEnvelopeNextFork<E>,
|
|
||||||
pub signature: Signature,
|
pub signature: Signature,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: EthSpec> SignedExecutionPayloadEnvelope<E> {
|
impl<E: EthSpec> SignedExecutionPayloadEnvelope<E> {
|
||||||
/// Create a new `SignedExecutionPayloadEnvelope` from an `ExecutionPayloadEnvelope` and `Signature`.
|
|
||||||
pub fn from_envelope(envelope: ExecutionPayloadEnvelope<E>, signature: Signature) -> Self {
|
|
||||||
match envelope {
|
|
||||||
ExecutionPayloadEnvelope::Gloas(message) => SignedExecutionPayloadEnvelope::Gloas(
|
|
||||||
signed_execution_payload_envelope::SignedExecutionPayloadEnvelopeGloas {
|
|
||||||
message,
|
|
||||||
signature,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
ExecutionPayloadEnvelope::NextFork(message) => {
|
|
||||||
SignedExecutionPayloadEnvelope::NextFork(
|
|
||||||
signed_execution_payload_envelope::SignedExecutionPayloadEnvelopeNextFork {
|
|
||||||
message,
|
|
||||||
signature,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn message(&self) -> ExecutionPayloadEnvelopeRef<'_, E> {
|
|
||||||
match self {
|
|
||||||
Self::Gloas(signed) => ExecutionPayloadEnvelopeRef::Gloas(&signed.message),
|
|
||||||
Self::NextFork(signed) => ExecutionPayloadEnvelopeRef::NextFork(&signed.message),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn slot(&self) -> Slot {
|
pub fn slot(&self) -> Slot {
|
||||||
self.message().slot()
|
self.message.slot
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn epoch(&self) -> Epoch {
|
pub fn epoch(&self) -> Epoch {
|
||||||
@@ -84,11 +24,11 @@ impl<E: EthSpec> SignedExecutionPayloadEnvelope<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn beacon_block_root(&self) -> Hash256 {
|
pub fn beacon_block_root(&self) -> Hash256 {
|
||||||
self.message().beacon_block_root()
|
self.message.beacon_block_root
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn block_hash(&self) -> ExecutionBlockHash {
|
pub fn block_hash(&self) -> ExecutionBlockHash {
|
||||||
self.message().block_hash()
|
self.message.payload.block_hash
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Verify `self.signature`.
|
/// Verify `self.signature`.
|
||||||
@@ -109,17 +49,17 @@ impl<E: EthSpec> SignedExecutionPayloadEnvelope<E> {
|
|||||||
);
|
);
|
||||||
let pubkey = parent_state
|
let pubkey = parent_state
|
||||||
.validators()
|
.validators()
|
||||||
.get(self.message().builder_index() as usize)
|
.get(self.message.builder_index as usize)
|
||||||
.and_then(|v| {
|
.and_then(|v| {
|
||||||
let pk: Option<PublicKey> = v.pubkey.decompress().ok();
|
let pk: Option<PublicKey> = v.pubkey.decompress().ok();
|
||||||
pk
|
pk
|
||||||
})
|
})
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
BeaconStateError::UnknownValidator(self.message().builder_index() as usize)
|
BeaconStateError::UnknownValidator(self.message.builder_index as usize)
|
||||||
})?;
|
})?;
|
||||||
let message = self.message().signing_root(domain);
|
let message = self.message.signing_root(domain);
|
||||||
|
|
||||||
Ok(self.signature().verify(&pubkey, message))
|
Ok(self.signature.verify(&pubkey, message))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Verify `self.signature`.
|
/// Verify `self.signature`.
|
||||||
@@ -140,25 +80,9 @@ impl<E: EthSpec> SignedExecutionPayloadEnvelope<E> {
|
|||||||
genesis_validators_root,
|
genesis_validators_root,
|
||||||
);
|
);
|
||||||
|
|
||||||
let message = self.message().signing_root(domain);
|
let message = self.message.signing_root(domain);
|
||||||
|
|
||||||
self.signature().verify(pubkey, message)
|
self.signature.verify(pubkey, message)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for SignedExecutionPayloadEnvelope<E> {
|
|
||||||
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
let value: Self = Deserialize::deserialize(deserializer)?;
|
|
||||||
|
|
||||||
match (context, &value) {
|
|
||||||
(ForkName::Gloas, Self::Gloas { .. }) => Ok(value),
|
|
||||||
_ => Err(D::Error::custom(format!(
|
|
||||||
"SignedExecutionPayloadEnvelope does not support fork {context:?}"
|
|
||||||
))),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,13 +91,5 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::MainnetEthSpec;
|
use crate::MainnetEthSpec;
|
||||||
|
|
||||||
mod gloas {
|
ssz_and_tree_hash_tests!(SignedExecutionPayloadEnvelope<MainnetEthSpec>);
|
||||||
use super::*;
|
|
||||||
ssz_and_tree_hash_tests!(SignedExecutionPayloadEnvelopeGloas<MainnetEthSpec>);
|
|
||||||
}
|
|
||||||
|
|
||||||
mod next_fork {
|
|
||||||
use super::*;
|
|
||||||
ssz_and_tree_hash_tests!(SignedExecutionPayloadEnvelopeNextFork<MainnetEthSpec>);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user