mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-11 18:04:18 +00:00
Gloas local block building MVP (#8754)
The flow for local block building is 1. Create execution payload and bid 2. Construct beacon block 3. Sign beacon block and publish 4. Sign execution payload and publish This PR adds the beacon block v4 flow , GET payload envelope and POST payload envelope (local block building only). The spec for these endpoints can be found here: https://github.com/ethereum/beacon-APIs/pull/552 and is subject to change. We needed a way to store the unsigned execution payload envelope associated to the execution payload bid that was included in the block. I introduced a new cache that stores these unsigned execution payload envelopes. the GET payload envelope queries this cache directly so that a proposer, after publishing a block, can fetch the payload envelope + sign and publish it. I kept payload signing and publishing within the validators block service to keep things simple for now. The idea was to build out a block production MVP for devnet 0, try not to affect any non gloas code paths and build things out in such a way that it will be easy to deprecate pre-gloas code paths later on (for example block production v2 and v3). We will eventually need to track which beacon node was queried for the block so that we can later query it for the payload. But thats not needed for the devnet. Co-Authored-By: Eitan Seri- Levi <eserilev@gmail.com> Co-Authored-By: Michael Sproul <michael@sigmaprime.io> Co-Authored-By: Jimmy Chen <jchen.tc@gmail.com> Co-Authored-By: Eitan Seri-Levi <eserilev@ucsc.edu>
This commit is contained in:
@@ -48,7 +48,6 @@ use tree_hash::TreeHash;
|
||||
use types::builder::BuilderBid;
|
||||
use types::execution::BlockProductionVersion;
|
||||
use types::kzg_ext::KzgCommitments;
|
||||
use types::new_non_zero_usize;
|
||||
use types::{
|
||||
AbstractExecPayload, BlobsList, ExecutionPayloadDeneb, ExecutionRequests, KzgProofs,
|
||||
SignedBlindedBeaconBlock,
|
||||
@@ -58,6 +57,7 @@ use types::{
|
||||
ExecutionPayloadCapella, ExecutionPayloadElectra, ExecutionPayloadFulu, FullPayload,
|
||||
ProposerPreparationData, Slot,
|
||||
};
|
||||
use types::{ExecutionPayloadGloas, new_non_zero_usize};
|
||||
|
||||
mod block_hash;
|
||||
mod engine_api;
|
||||
@@ -168,6 +168,7 @@ pub enum Error {
|
||||
BeaconStateError(BeaconStateError),
|
||||
PayloadTypeMismatch,
|
||||
VerifyingVersionedHashes(versioned_hashes::Error),
|
||||
Unexpected(String),
|
||||
}
|
||||
|
||||
impl From<ssz_types::Error> for Error {
|
||||
@@ -204,6 +205,26 @@ pub enum BlockProposalContentsType<E: EthSpec> {
|
||||
Blinded(BlockProposalContents<E, BlindedPayload<E>>),
|
||||
}
|
||||
|
||||
pub struct BlockProposalContentsGloas<E: EthSpec> {
|
||||
pub payload: ExecutionPayloadGloas<E>,
|
||||
pub payload_value: Uint256,
|
||||
pub blob_kzg_commitments: KzgCommitments<E>,
|
||||
pub blobs_and_proofs: (BlobsList<E>, KzgProofs<E>),
|
||||
pub execution_requests: ExecutionRequests<E>,
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<GetPayloadResponseGloas<E>> for BlockProposalContentsGloas<E> {
|
||||
fn from(response: GetPayloadResponseGloas<E>) -> Self {
|
||||
Self {
|
||||
payload: response.execution_payload,
|
||||
payload_value: response.block_value,
|
||||
blob_kzg_commitments: response.blobs_bundle.commitments,
|
||||
blobs_and_proofs: (response.blobs_bundle.blobs, response.blobs_bundle.proofs),
|
||||
execution_requests: response.requests,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum BlockProposalContents<E: EthSpec, Payload: AbstractExecPayload<E>> {
|
||||
Payload {
|
||||
payload: Payload,
|
||||
@@ -884,6 +905,43 @@ impl<E: EthSpec> ExecutionLayer<E> {
|
||||
.and_then(|entry| entry.gas_limit)
|
||||
}
|
||||
|
||||
/// Maps to the `engine_getPayload` JSON-RPC call for post-Gloas payload construction.
|
||||
///
|
||||
/// However, it will attempt to call `self.prepare_payload` if it cannot find an existing
|
||||
/// payload id for the given parameters.
|
||||
///
|
||||
/// ## Fallback Behavior
|
||||
///
|
||||
/// The result will be returned from the first node that returns successfully. No more nodes
|
||||
/// will be contacted.
|
||||
pub async fn get_payload_gloas(
|
||||
&self,
|
||||
payload_parameters: PayloadParameters<'_>,
|
||||
) -> Result<BlockProposalContentsGloas<E>, Error> {
|
||||
let payload_response_type = self.get_full_payload_caching(payload_parameters).await?;
|
||||
let GetPayloadResponseType::Full(payload_response) = payload_response_type else {
|
||||
return Err(Error::Unexpected(
|
||||
"get_payload_gloas should never return a blinded payload".to_owned(),
|
||||
));
|
||||
};
|
||||
let GetPayloadResponse::Gloas(payload_response) = payload_response else {
|
||||
return Err(Error::Unexpected(
|
||||
"get_payload_gloas should always return a gloas `GetPayloadResponse` variant"
|
||||
.to_owned(),
|
||||
));
|
||||
};
|
||||
metrics::inc_counter_vec(
|
||||
&metrics::EXECUTION_LAYER_GET_PAYLOAD_OUTCOME,
|
||||
&[metrics::SUCCESS],
|
||||
);
|
||||
metrics::inc_counter_vec(
|
||||
&metrics::EXECUTION_LAYER_GET_PAYLOAD_SOURCE,
|
||||
&[metrics::LOCAL],
|
||||
);
|
||||
|
||||
Ok(payload_response.into())
|
||||
}
|
||||
|
||||
/// Maps to the `engine_getPayload` JSON-RPC call.
|
||||
///
|
||||
/// However, it will attempt to call `self.prepare_payload` if it cannot find an existing
|
||||
|
||||
Reference in New Issue
Block a user