mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-08 17:26:04 +00:00
Refactor mock builder to separate functionality
This commit is contained in:
@@ -287,8 +287,339 @@ impl<E: EthSpec> MockBuilder<E> {
|
|||||||
op.apply(bid);
|
op.apply(bid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the public key of the builder
|
||||||
|
pub fn public_key(&self) -> PublicKeyBytes {
|
||||||
|
self.builder_sk.public_key().compress()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn register_validators(
|
||||||
|
&self,
|
||||||
|
registrations: Vec<SignedValidatorRegistrationData>,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
for registration in registrations {
|
||||||
|
if !registration.verify_signature(&self.spec) {
|
||||||
|
return Err("invalid signature".to_string());
|
||||||
|
}
|
||||||
|
self.val_registration_cache
|
||||||
|
.write()
|
||||||
|
.insert(registration.message.pubkey, registration);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn submit_blinded_block(
|
||||||
|
&self,
|
||||||
|
block: SignedBlindedBeaconBlock<E>,
|
||||||
|
) -> Result<ExecutionPayload<E>, String> {
|
||||||
|
let root = match &block {
|
||||||
|
SignedBlindedBeaconBlock::Base(_) | types::SignedBeaconBlock::Altair(_) => {
|
||||||
|
return Err("invalid fork".to_string());
|
||||||
|
}
|
||||||
|
SignedBlindedBeaconBlock::Bellatrix(block) => {
|
||||||
|
block.message.body.execution_payload.tree_hash_root()
|
||||||
|
}
|
||||||
|
SignedBlindedBeaconBlock::Capella(block) => {
|
||||||
|
block.message.body.execution_payload.tree_hash_root()
|
||||||
|
}
|
||||||
|
SignedBlindedBeaconBlock::Deneb(block) => {
|
||||||
|
block.message.body.execution_payload.tree_hash_root()
|
||||||
|
}
|
||||||
|
SignedBlindedBeaconBlock::Electra(block) => {
|
||||||
|
block.message.body.execution_payload.tree_hash_root()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let payload = self
|
||||||
|
.el
|
||||||
|
.get_payload_by_root(&root)
|
||||||
|
.ok_or_else(|| "missing payload for tx root".to_string())?;
|
||||||
|
let (payload, _) = payload.deconstruct();
|
||||||
|
// TODO(pawan): the reconstruction in the beacon client should propagate the
|
||||||
|
// blobs as well. If that doesn't happen then its probably a bug here
|
||||||
|
self.beacon_client
|
||||||
|
.post_beacon_blinded_blocks(&block)
|
||||||
|
.await
|
||||||
|
.map_err(|e| format!("Failed to post blinded block {:?}", e))?;
|
||||||
|
Ok(payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_header(
|
||||||
|
&self,
|
||||||
|
slot: Slot,
|
||||||
|
parent_hash: ExecutionBlockHash,
|
||||||
|
pubkey: PublicKeyBytes,
|
||||||
|
) -> Result<SignedBuilderBid<E>, String> {
|
||||||
|
let fork = self.fork_name_at_slot(slot);
|
||||||
|
let signed_cached_data = self
|
||||||
|
.val_registration_cache
|
||||||
|
.read()
|
||||||
|
.get(&pubkey)
|
||||||
|
.ok_or_else(|| "missing registration".to_string())?
|
||||||
|
.clone();
|
||||||
|
let cached_data = signed_cached_data.message;
|
||||||
|
|
||||||
|
let head = self
|
||||||
|
.beacon_client
|
||||||
|
.get_beacon_blocks::<E>(BlockId::Head)
|
||||||
|
.await
|
||||||
|
.map_err(|_| "couldn't get head".to_string())?
|
||||||
|
.ok_or_else(|| "missing head block".to_string())?;
|
||||||
|
|
||||||
|
let block = head.data.message();
|
||||||
|
let head_block_root = block.tree_hash_root();
|
||||||
|
let head_execution_hash = block
|
||||||
|
.body()
|
||||||
|
.execution_payload()
|
||||||
|
.map_err(|_| "pre-merge block".to_string())?
|
||||||
|
.block_hash();
|
||||||
|
if head_execution_hash != parent_hash {
|
||||||
|
return Err("head mismatch".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let finalized_execution_hash = self
|
||||||
|
.beacon_client
|
||||||
|
.get_beacon_blocks::<E>(BlockId::Finalized)
|
||||||
|
.await
|
||||||
|
.map_err(|_| "couldn't get finalized block".to_string())?
|
||||||
|
.ok_or_else(|| "missing finalized block".to_string())?
|
||||||
|
.data
|
||||||
|
.message()
|
||||||
|
.body()
|
||||||
|
.execution_payload()
|
||||||
|
.map_err(|_| "pre-merge block".to_string())?
|
||||||
|
.block_hash();
|
||||||
|
|
||||||
|
let justified_execution_hash = self
|
||||||
|
.beacon_client
|
||||||
|
.get_beacon_blocks::<E>(BlockId::Justified)
|
||||||
|
.await
|
||||||
|
.map_err(|_| "couldn't get justified block".to_string())?
|
||||||
|
.ok_or_else(|| "missing justified block".to_string())?
|
||||||
|
.data
|
||||||
|
.message()
|
||||||
|
.body()
|
||||||
|
.execution_payload()
|
||||||
|
.map_err(|_| "pre-merge block".to_string())?
|
||||||
|
.block_hash();
|
||||||
|
|
||||||
|
let val_index = self
|
||||||
|
.beacon_client
|
||||||
|
.get_beacon_states_validator_id(StateId::Head, &ValidatorId::PublicKey(pubkey))
|
||||||
|
.await
|
||||||
|
.map_err(|_| "couldn't get validator".to_string())?
|
||||||
|
.ok_or_else(|| "missing validator".to_string())?
|
||||||
|
.data
|
||||||
|
.index;
|
||||||
|
let fee_recipient = cached_data.fee_recipient;
|
||||||
|
let slots_since_genesis = slot.as_u64() - self.spec.genesis_slot.as_u64();
|
||||||
|
|
||||||
|
// TODO(pawan): cache this call
|
||||||
|
let genesis_data = self
|
||||||
|
.beacon_client
|
||||||
|
.get_beacon_genesis()
|
||||||
|
.await
|
||||||
|
.map_err(|_| "couldn't get beacon genesis".to_string())?
|
||||||
|
.data;
|
||||||
|
let genesis_time = genesis_data.genesis_time;
|
||||||
|
let timestamp = (slots_since_genesis * self.spec.seconds_per_slot) + genesis_time;
|
||||||
|
|
||||||
|
let head_state: BeaconState<E> = self
|
||||||
|
.beacon_client
|
||||||
|
.get_debug_beacon_states(StateId::Head)
|
||||||
|
.await
|
||||||
|
.map_err(|_| "couldn't get state".to_string())?
|
||||||
|
.ok_or_else(|| "missing state".to_string())?
|
||||||
|
.data;
|
||||||
|
let prev_randao = head_state
|
||||||
|
.get_randao_mix(head_state.current_epoch())
|
||||||
|
.map_err(|_| "couldn't get prev randao".to_string())?;
|
||||||
|
|
||||||
|
let expected_withdrawals = if fork.capella_enabled() {
|
||||||
|
Some(
|
||||||
|
self.beacon_client
|
||||||
|
.get_expected_withdrawals(&StateId::Head)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.data,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let payload_attributes = match fork {
|
||||||
|
// the withdrawals root is filled in by operations, but we supply the valid withdrawals
|
||||||
|
// first to avoid polluting the execution block generator with invalid payload attributes
|
||||||
|
// NOTE: this was part of an effort to add payload attribute uniqueness checks,
|
||||||
|
// which was abandoned because it broke too many tests in subtle ways.
|
||||||
|
ForkName::Bellatrix | ForkName::Capella => PayloadAttributes::new(
|
||||||
|
timestamp,
|
||||||
|
*prev_randao,
|
||||||
|
fee_recipient,
|
||||||
|
expected_withdrawals,
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
ForkName::Deneb | ForkName::Electra => PayloadAttributes::new(
|
||||||
|
timestamp,
|
||||||
|
*prev_randao,
|
||||||
|
fee_recipient,
|
||||||
|
expected_withdrawals,
|
||||||
|
Some(head_block_root),
|
||||||
|
),
|
||||||
|
ForkName::Base | ForkName::Altair => {
|
||||||
|
return Err("invalid fork".to_string());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.el
|
||||||
|
.insert_proposer(slot, head_block_root, val_index, payload_attributes.clone())
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let forkchoice_update_params = ForkchoiceUpdateParameters {
|
||||||
|
head_root: Hash256::zero(),
|
||||||
|
head_hash: None,
|
||||||
|
justified_hash: Some(justified_execution_hash),
|
||||||
|
finalized_hash: Some(finalized_execution_hash),
|
||||||
|
};
|
||||||
|
|
||||||
|
let payload_response_type = self
|
||||||
|
.el
|
||||||
|
.get_full_payload_caching(
|
||||||
|
head_execution_hash,
|
||||||
|
&payload_attributes,
|
||||||
|
forkchoice_update_params,
|
||||||
|
fork,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(|_| "couldn't get payload".to_string())?;
|
||||||
|
|
||||||
|
let mut message = match payload_response_type {
|
||||||
|
crate::GetPayloadResponseType::Full(payload_response) => {
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
let (payload, value, maybe_blobs_bundle, maybe_requests): (
|
||||||
|
ExecutionPayload<E>,
|
||||||
|
Uint256,
|
||||||
|
Option<BlobsBundle<E>>,
|
||||||
|
Option<ExecutionRequests<E>>,
|
||||||
|
) = payload_response.into();
|
||||||
|
|
||||||
|
match fork {
|
||||||
|
ForkName::Electra => BuilderBid::Electra(BuilderBidElectra {
|
||||||
|
header: payload
|
||||||
|
.as_electra()
|
||||||
|
.map_err(|_| "incorrect payload variant".to_string())?
|
||||||
|
.into(),
|
||||||
|
blob_kzg_commitments: maybe_blobs_bundle
|
||||||
|
.map(|b| b.commitments)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
value,
|
||||||
|
pubkey: self.builder_sk.public_key().compress(),
|
||||||
|
execution_requests: maybe_requests.unwrap_or_default(),
|
||||||
|
}),
|
||||||
|
ForkName::Deneb => BuilderBid::Deneb(BuilderBidDeneb {
|
||||||
|
header: payload
|
||||||
|
.as_deneb()
|
||||||
|
.map_err(|_| "incorrect payload variant".to_string())?
|
||||||
|
.into(),
|
||||||
|
blob_kzg_commitments: maybe_blobs_bundle
|
||||||
|
.map(|b| b.commitments)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
value,
|
||||||
|
pubkey: self.builder_sk.public_key().compress(),
|
||||||
|
}),
|
||||||
|
ForkName::Capella => BuilderBid::Capella(BuilderBidCapella {
|
||||||
|
header: payload
|
||||||
|
.as_capella()
|
||||||
|
.map_err(|_| "incorrect payload variant".to_string())?
|
||||||
|
.into(),
|
||||||
|
value,
|
||||||
|
pubkey: self.builder_sk.public_key().compress(),
|
||||||
|
}),
|
||||||
|
ForkName::Bellatrix => BuilderBid::Bellatrix(BuilderBidBellatrix {
|
||||||
|
header: payload
|
||||||
|
.as_bellatrix()
|
||||||
|
.map_err(|_| "incorrect payload variant".to_string())?
|
||||||
|
.into(),
|
||||||
|
value,
|
||||||
|
pubkey: self.builder_sk.public_key().compress(),
|
||||||
|
}),
|
||||||
|
ForkName::Base | ForkName::Altair => return Err("invalid fork".to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crate::GetPayloadResponseType::Blinded(payload_response) => {
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
let (payload, value, maybe_blobs_bundle, maybe_requests): (
|
||||||
|
ExecutionPayload<E>,
|
||||||
|
Uint256,
|
||||||
|
Option<BlobsBundle<E>>,
|
||||||
|
Option<ExecutionRequests<E>>,
|
||||||
|
) = payload_response.into();
|
||||||
|
match fork {
|
||||||
|
ForkName::Electra => BuilderBid::Electra(BuilderBidElectra {
|
||||||
|
header: payload
|
||||||
|
.as_electra()
|
||||||
|
.map_err(|_| "incorrect payload variant".to_string())?
|
||||||
|
.into(),
|
||||||
|
blob_kzg_commitments: maybe_blobs_bundle
|
||||||
|
.map(|b| b.commitments)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
value,
|
||||||
|
pubkey: self.builder_sk.public_key().compress(),
|
||||||
|
execution_requests: maybe_requests.unwrap_or_default(),
|
||||||
|
}),
|
||||||
|
ForkName::Deneb => BuilderBid::Deneb(BuilderBidDeneb {
|
||||||
|
header: payload
|
||||||
|
.as_deneb()
|
||||||
|
.map_err(|_| "incorrect payload variant".to_string())?
|
||||||
|
.into(),
|
||||||
|
blob_kzg_commitments: maybe_blobs_bundle
|
||||||
|
.map(|b| b.commitments)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
value,
|
||||||
|
pubkey: self.builder_sk.public_key().compress(),
|
||||||
|
}),
|
||||||
|
ForkName::Capella => BuilderBid::Capella(BuilderBidCapella {
|
||||||
|
header: payload
|
||||||
|
.as_capella()
|
||||||
|
.map_err(|_| "incorrect payload variant".to_string())?
|
||||||
|
.into(),
|
||||||
|
value,
|
||||||
|
pubkey: self.builder_sk.public_key().compress(),
|
||||||
|
}),
|
||||||
|
ForkName::Bellatrix => BuilderBid::Bellatrix(BuilderBidBellatrix {
|
||||||
|
header: payload
|
||||||
|
.as_bellatrix()
|
||||||
|
.map_err(|_| "incorrect payload variant".to_string())?
|
||||||
|
.into(),
|
||||||
|
value,
|
||||||
|
pubkey: self.builder_sk.public_key().compress(),
|
||||||
|
}),
|
||||||
|
ForkName::Base | ForkName::Altair => return Err("invalid fork".to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
message.set_gas_limit(cached_data.gas_limit);
|
||||||
|
|
||||||
|
self.apply_operations(&mut message);
|
||||||
|
|
||||||
|
let mut signature = message.sign_builder_message(&self.builder_sk, &self.spec);
|
||||||
|
|
||||||
|
if *self.invalidate_signatures.read() {
|
||||||
|
signature = Signature::empty();
|
||||||
|
};
|
||||||
|
let signed_bid = SignedBuilderBid { message, signature };
|
||||||
|
Ok(signed_bid)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fork_name_at_slot(&self, slot: Slot) -> ForkName {
|
||||||
|
self.spec.fork_name_at_slot::<E>(slot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serve the builder api using warp. Uses the functions defined in `MockBuilder` to serve
|
||||||
|
/// the requests.
|
||||||
|
///
|
||||||
|
/// We should eventually move this to axum when we move everything else.
|
||||||
pub fn serve<E: EthSpec>(
|
pub fn serve<E: EthSpec>(
|
||||||
listen_addr: Ipv4Addr,
|
listen_addr: Ipv4Addr,
|
||||||
listen_port: u16,
|
listen_port: u16,
|
||||||
@@ -308,18 +639,10 @@ pub fn serve<E: EthSpec>(
|
|||||||
.and(ctx_filter.clone())
|
.and(ctx_filter.clone())
|
||||||
.and_then(
|
.and_then(
|
||||||
|registrations: Vec<SignedValidatorRegistrationData>, builder: MockBuilder<E>| async move {
|
|registrations: Vec<SignedValidatorRegistrationData>, builder: MockBuilder<E>| async move {
|
||||||
for registration in registrations {
|
builder.register_validators(registrations).await.map_err(|e|warp::reject::custom(Custom(e)))?;
|
||||||
if !registration.verify_signature(&builder.spec) {
|
Ok::<_, Rejection>(warp::reply())
|
||||||
return Err(reject("invalid signature"));
|
|
||||||
}
|
|
||||||
builder
|
|
||||||
.val_registration_cache
|
|
||||||
.write()
|
|
||||||
.insert(registration.message.pubkey, registration);
|
|
||||||
}
|
|
||||||
Ok(warp::reply())
|
|
||||||
},
|
},
|
||||||
);
|
).boxed();
|
||||||
|
|
||||||
let blinded_block =
|
let blinded_block =
|
||||||
prefix
|
prefix
|
||||||
@@ -332,27 +655,10 @@ pub fn serve<E: EthSpec>(
|
|||||||
|block: SignedBlindedBeaconBlock<E>,
|
|block: SignedBlindedBeaconBlock<E>,
|
||||||
fork_name: ForkName,
|
fork_name: ForkName,
|
||||||
builder: MockBuilder<E>| async move {
|
builder: MockBuilder<E>| async move {
|
||||||
let root = match block {
|
|
||||||
SignedBlindedBeaconBlock::Base(_) | types::SignedBeaconBlock::Altair(_) => {
|
|
||||||
return Err(reject("invalid fork"));
|
|
||||||
}
|
|
||||||
SignedBlindedBeaconBlock::Bellatrix(block) => {
|
|
||||||
block.message.body.execution_payload.tree_hash_root()
|
|
||||||
}
|
|
||||||
SignedBlindedBeaconBlock::Capella(block) => {
|
|
||||||
block.message.body.execution_payload.tree_hash_root()
|
|
||||||
}
|
|
||||||
SignedBlindedBeaconBlock::Deneb(block) => {
|
|
||||||
block.message.body.execution_payload.tree_hash_root()
|
|
||||||
}
|
|
||||||
SignedBlindedBeaconBlock::Electra(block) => {
|
|
||||||
block.message.body.execution_payload.tree_hash_root()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let payload = builder
|
let payload = builder
|
||||||
.el
|
.submit_blinded_block(block)
|
||||||
.get_payload_by_root(&root)
|
.await
|
||||||
.ok_or_else(|| reject("missing payload for tx root"))?;
|
.map_err(|e| warp::reject::custom(Custom(e)))?;
|
||||||
let resp: ForkVersionedResponse<_> = ForkVersionedResponse {
|
let resp: ForkVersionedResponse<_> = ForkVersionedResponse {
|
||||||
version: Some(fork_name),
|
version: Some(fork_name),
|
||||||
metadata: Default::default(),
|
metadata: Default::default(),
|
||||||
@@ -395,276 +701,12 @@ pub fn serve<E: EthSpec>(
|
|||||||
parent_hash: ExecutionBlockHash,
|
parent_hash: ExecutionBlockHash,
|
||||||
pubkey: PublicKeyBytes,
|
pubkey: PublicKeyBytes,
|
||||||
builder: MockBuilder<E>| async move {
|
builder: MockBuilder<E>| async move {
|
||||||
let fork = builder.spec.fork_name_at_slot::<E>(slot);
|
let fork_name = builder.fork_name_at_slot(slot);
|
||||||
let signed_cached_data = builder
|
let signed_bid = builder
|
||||||
.val_registration_cache
|
.get_header(slot, parent_hash, pubkey)
|
||||||
.read()
|
|
||||||
.get(&pubkey)
|
|
||||||
.ok_or_else(|| reject("missing registration"))?
|
|
||||||
.clone();
|
|
||||||
let cached_data = signed_cached_data.message;
|
|
||||||
|
|
||||||
let head = builder
|
|
||||||
.beacon_client
|
|
||||||
.get_beacon_blocks::<E>(BlockId::Head)
|
|
||||||
.await
|
.await
|
||||||
.map_err(|_| reject("couldn't get head"))?
|
.map_err(|e| warp::reject::custom(Custom(e)))?;
|
||||||
.ok_or_else(|| reject("missing head block"))?;
|
|
||||||
|
|
||||||
let block = head.data.message();
|
|
||||||
let head_block_root = block.tree_hash_root();
|
|
||||||
let head_execution_hash = block
|
|
||||||
.body()
|
|
||||||
.execution_payload()
|
|
||||||
.map_err(|_| reject("pre-merge block"))?
|
|
||||||
.block_hash();
|
|
||||||
if head_execution_hash != parent_hash {
|
|
||||||
return Err(reject("head mismatch"));
|
|
||||||
}
|
|
||||||
|
|
||||||
let finalized_execution_hash = builder
|
|
||||||
.beacon_client
|
|
||||||
.get_beacon_blocks::<E>(BlockId::Finalized)
|
|
||||||
.await
|
|
||||||
.map_err(|_| reject("couldn't get finalized block"))?
|
|
||||||
.ok_or_else(|| reject("missing finalized block"))?
|
|
||||||
.data
|
|
||||||
.message()
|
|
||||||
.body()
|
|
||||||
.execution_payload()
|
|
||||||
.map_err(|_| reject("pre-merge block"))?
|
|
||||||
.block_hash();
|
|
||||||
|
|
||||||
let justified_execution_hash = builder
|
|
||||||
.beacon_client
|
|
||||||
.get_beacon_blocks::<E>(BlockId::Justified)
|
|
||||||
.await
|
|
||||||
.map_err(|_| reject("couldn't get justified block"))?
|
|
||||||
.ok_or_else(|| reject("missing justified block"))?
|
|
||||||
.data
|
|
||||||
.message()
|
|
||||||
.body()
|
|
||||||
.execution_payload()
|
|
||||||
.map_err(|_| reject("pre-merge block"))?
|
|
||||||
.block_hash();
|
|
||||||
|
|
||||||
let val_index = builder
|
|
||||||
.beacon_client
|
|
||||||
.get_beacon_states_validator_id(StateId::Head, &ValidatorId::PublicKey(pubkey))
|
|
||||||
.await
|
|
||||||
.map_err(|_| reject("couldn't get validator"))?
|
|
||||||
.ok_or_else(|| reject("missing validator"))?
|
|
||||||
.data
|
|
||||||
.index;
|
|
||||||
let fee_recipient = cached_data.fee_recipient;
|
|
||||||
let slots_since_genesis = slot.as_u64() - builder.spec.genesis_slot.as_u64();
|
|
||||||
|
|
||||||
let genesis_data = builder
|
|
||||||
.beacon_client
|
|
||||||
.get_beacon_genesis()
|
|
||||||
.await
|
|
||||||
.map_err(|_| reject("couldn't get beacon genesis"))?
|
|
||||||
.data;
|
|
||||||
let genesis_time = genesis_data.genesis_time;
|
|
||||||
let timestamp =
|
|
||||||
(slots_since_genesis * builder.spec.seconds_per_slot) + genesis_time;
|
|
||||||
|
|
||||||
let head_state: BeaconState<E> = builder
|
|
||||||
.beacon_client
|
|
||||||
.get_debug_beacon_states(StateId::Head)
|
|
||||||
.await
|
|
||||||
.map_err(|_| reject("couldn't get state"))?
|
|
||||||
.ok_or_else(|| reject("missing state"))?
|
|
||||||
.data;
|
|
||||||
let prev_randao = head_state
|
|
||||||
.get_randao_mix(head_state.current_epoch())
|
|
||||||
.map_err(|_| reject("couldn't get prev randao"))?;
|
|
||||||
|
|
||||||
let expected_withdrawals = if fork.capella_enabled() {
|
|
||||||
Some(
|
|
||||||
builder
|
|
||||||
.beacon_client
|
|
||||||
.get_expected_withdrawals(&StateId::Head)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.data,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let payload_attributes = match fork {
|
|
||||||
// the withdrawals root is filled in by operations, but we supply the valid withdrawals
|
|
||||||
// first to avoid polluting the execution block generator with invalid payload attributes
|
|
||||||
// NOTE: this was part of an effort to add payload attribute uniqueness checks,
|
|
||||||
// which was abandoned because it broke too many tests in subtle ways.
|
|
||||||
ForkName::Bellatrix | ForkName::Capella => PayloadAttributes::new(
|
|
||||||
timestamp,
|
|
||||||
*prev_randao,
|
|
||||||
fee_recipient,
|
|
||||||
expected_withdrawals,
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
ForkName::Deneb | ForkName::Electra => PayloadAttributes::new(
|
|
||||||
timestamp,
|
|
||||||
*prev_randao,
|
|
||||||
fee_recipient,
|
|
||||||
expected_withdrawals,
|
|
||||||
Some(head_block_root),
|
|
||||||
),
|
|
||||||
ForkName::Base | ForkName::Altair => {
|
|
||||||
return Err(reject("invalid fork"));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
builder
|
|
||||||
.el
|
|
||||||
.insert_proposer(slot, head_block_root, val_index, payload_attributes.clone())
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let forkchoice_update_params = ForkchoiceUpdateParameters {
|
|
||||||
head_root: Hash256::zero(),
|
|
||||||
head_hash: None,
|
|
||||||
justified_hash: Some(justified_execution_hash),
|
|
||||||
finalized_hash: Some(finalized_execution_hash),
|
|
||||||
};
|
|
||||||
|
|
||||||
let payload_response_type = builder
|
|
||||||
.el
|
|
||||||
.get_full_payload_caching(
|
|
||||||
head_execution_hash,
|
|
||||||
&payload_attributes,
|
|
||||||
forkchoice_update_params,
|
|
||||||
fork,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.map_err(|_| reject("couldn't get payload"))?;
|
|
||||||
|
|
||||||
let mut message = match payload_response_type {
|
|
||||||
crate::GetPayloadResponseType::Full(payload_response) => {
|
|
||||||
#[allow(clippy::type_complexity)]
|
|
||||||
let (payload, value, maybe_blobs_bundle, maybe_requests): (
|
|
||||||
ExecutionPayload<E>,
|
|
||||||
Uint256,
|
|
||||||
Option<BlobsBundle<E>>,
|
|
||||||
Option<ExecutionRequests<E>>,
|
|
||||||
) = payload_response.into();
|
|
||||||
|
|
||||||
match fork {
|
|
||||||
ForkName::Electra => BuilderBid::Electra(BuilderBidElectra {
|
|
||||||
header: payload
|
|
||||||
.as_electra()
|
|
||||||
.map_err(|_| reject("incorrect payload variant"))?
|
|
||||||
.into(),
|
|
||||||
blob_kzg_commitments: maybe_blobs_bundle
|
|
||||||
.map(|b| b.commitments)
|
|
||||||
.unwrap_or_default(),
|
|
||||||
value,
|
|
||||||
pubkey: builder.builder_sk.public_key().compress(),
|
|
||||||
execution_requests: maybe_requests.unwrap_or_default(),
|
|
||||||
}),
|
|
||||||
ForkName::Deneb => BuilderBid::Deneb(BuilderBidDeneb {
|
|
||||||
header: payload
|
|
||||||
.as_deneb()
|
|
||||||
.map_err(|_| reject("incorrect payload variant"))?
|
|
||||||
.into(),
|
|
||||||
blob_kzg_commitments: maybe_blobs_bundle
|
|
||||||
.map(|b| b.commitments)
|
|
||||||
.unwrap_or_default(),
|
|
||||||
value,
|
|
||||||
pubkey: builder.builder_sk.public_key().compress(),
|
|
||||||
}),
|
|
||||||
ForkName::Capella => BuilderBid::Capella(BuilderBidCapella {
|
|
||||||
header: payload
|
|
||||||
.as_capella()
|
|
||||||
.map_err(|_| reject("incorrect payload variant"))?
|
|
||||||
.into(),
|
|
||||||
value,
|
|
||||||
pubkey: builder.builder_sk.public_key().compress(),
|
|
||||||
}),
|
|
||||||
ForkName::Bellatrix => BuilderBid::Bellatrix(BuilderBidBellatrix {
|
|
||||||
header: payload
|
|
||||||
.as_bellatrix()
|
|
||||||
.map_err(|_| reject("incorrect payload variant"))?
|
|
||||||
.into(),
|
|
||||||
value,
|
|
||||||
pubkey: builder.builder_sk.public_key().compress(),
|
|
||||||
}),
|
|
||||||
ForkName::Base | ForkName::Altair => {
|
|
||||||
return Err(reject("invalid fork"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
crate::GetPayloadResponseType::Blinded(payload_response) => {
|
|
||||||
#[allow(clippy::type_complexity)]
|
|
||||||
let (payload, value, maybe_blobs_bundle, maybe_requests): (
|
|
||||||
ExecutionPayload<E>,
|
|
||||||
Uint256,
|
|
||||||
Option<BlobsBundle<E>>,
|
|
||||||
Option<ExecutionRequests<E>>,
|
|
||||||
) = payload_response.into();
|
|
||||||
match fork {
|
|
||||||
ForkName::Electra => BuilderBid::Electra(BuilderBidElectra {
|
|
||||||
header: payload
|
|
||||||
.as_electra()
|
|
||||||
.map_err(|_| reject("incorrect payload variant"))?
|
|
||||||
.into(),
|
|
||||||
blob_kzg_commitments: maybe_blobs_bundle
|
|
||||||
.map(|b| b.commitments)
|
|
||||||
.unwrap_or_default(),
|
|
||||||
value,
|
|
||||||
pubkey: builder.builder_sk.public_key().compress(),
|
|
||||||
execution_requests: maybe_requests.unwrap_or_default(),
|
|
||||||
}),
|
|
||||||
ForkName::Deneb => BuilderBid::Deneb(BuilderBidDeneb {
|
|
||||||
header: payload
|
|
||||||
.as_deneb()
|
|
||||||
.map_err(|_| reject("incorrect payload variant"))?
|
|
||||||
.into(),
|
|
||||||
blob_kzg_commitments: maybe_blobs_bundle
|
|
||||||
.map(|b| b.commitments)
|
|
||||||
.unwrap_or_default(),
|
|
||||||
value,
|
|
||||||
pubkey: builder.builder_sk.public_key().compress(),
|
|
||||||
}),
|
|
||||||
ForkName::Capella => BuilderBid::Capella(BuilderBidCapella {
|
|
||||||
header: payload
|
|
||||||
.as_capella()
|
|
||||||
.map_err(|_| reject("incorrect payload variant"))?
|
|
||||||
.into(),
|
|
||||||
value,
|
|
||||||
pubkey: builder.builder_sk.public_key().compress(),
|
|
||||||
}),
|
|
||||||
ForkName::Bellatrix => BuilderBid::Bellatrix(BuilderBidBellatrix {
|
|
||||||
header: payload
|
|
||||||
.as_bellatrix()
|
|
||||||
.map_err(|_| reject("incorrect payload variant"))?
|
|
||||||
.into(),
|
|
||||||
value,
|
|
||||||
pubkey: builder.builder_sk.public_key().compress(),
|
|
||||||
}),
|
|
||||||
ForkName::Base | ForkName::Altair => {
|
|
||||||
return Err(reject("invalid fork"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
message.set_gas_limit(cached_data.gas_limit);
|
|
||||||
|
|
||||||
builder.apply_operations(&mut message);
|
|
||||||
|
|
||||||
let mut signature =
|
|
||||||
message.sign_builder_message(&builder.builder_sk, &builder.spec);
|
|
||||||
|
|
||||||
if *builder.invalidate_signatures.read() {
|
|
||||||
signature = Signature::empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
let fork_name = builder
|
|
||||||
.spec
|
|
||||||
.fork_name_at_epoch(slot.epoch(E::slots_per_epoch()));
|
|
||||||
let signed_bid = SignedBuilderBid { message, signature };
|
|
||||||
let resp: ForkVersionedResponse<_> = ForkVersionedResponse {
|
let resp: ForkVersionedResponse<_> = ForkVersionedResponse {
|
||||||
version: Some(fork_name),
|
version: Some(fork_name),
|
||||||
metadata: Default::default(),
|
metadata: Default::default(),
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ pub use execution_block_generator::{
|
|||||||
static_valid_tx, Block, ExecutionBlockGenerator,
|
static_valid_tx, Block, ExecutionBlockGenerator,
|
||||||
};
|
};
|
||||||
pub use hook::Hook;
|
pub use hook::Hook;
|
||||||
pub use mock_builder::{MockBuilder, Operation, serve as serve_mock_builder};
|
pub use mock_builder::{MockBuilder, Operation};
|
||||||
pub use mock_execution_layer::MockExecutionLayer;
|
pub use mock_execution_layer::MockExecutionLayer;
|
||||||
|
|
||||||
pub const DEFAULT_TERMINAL_DIFFICULTY: u64 = 6400;
|
pub const DEFAULT_TERMINAL_DIFFICULTY: u64 = 6400;
|
||||||
|
|||||||
Reference in New Issue
Block a user