Files
lighthouse/beacon_node/http_api/src/produce_block.rs
Michael Sproul 4de08f1b4a Remove more mentions of "pending"/"full" states (#9156)
Just a little naming cleanup (no semantic changes) to remove mentions of pending and full states that were still lurking.

This hopefully helps Claude forget about the concept (it defaults to naming variables `pending_state`s without this change).


  


Co-Authored-By: Michael Sproul <michael@sigmaprime.io>
2026-04-22 02:03:13 +00:00

315 lines
11 KiB
Rust

use crate::{
build_block_contents,
version::{
ResponseIncludesVersion, add_consensus_block_value_header, add_consensus_version_header,
add_execution_payload_blinded_header, add_execution_payload_value_header,
add_ssz_content_type_header, beacon_response, inconsistent_fork_rejection,
},
};
use beacon_chain::graffiti_calculator::GraffitiSettings;
use beacon_chain::{
BeaconBlockResponseWrapper, BeaconChain, BeaconChainTypes, ProduceBlockVerification,
};
use eth2::types::{self as api_types, ProduceBlockV3Metadata, SkipRandaoVerification};
use eth2::{beacon_response::ForkVersionedResponse, types::ProduceBlockV4Metadata};
use ssz::Encode;
use std::sync::Arc;
use tracing::instrument;
use types::{execution::BlockProductionVersion, *};
use warp::{
Reply,
hyper::{Body, Response},
};
/// If default boost factor is provided in validator/blocks v3 request, we will skip the calculation
/// to keep the precision.
const DEFAULT_BOOST_FACTOR: u64 = 100;
pub fn get_randao_verification(
query: &api_types::ValidatorBlocksQuery,
randao_reveal_infinity: bool,
) -> Result<ProduceBlockVerification, warp::Rejection> {
let randao_verification = if query.skip_randao_verification == SkipRandaoVerification::Yes {
if !randao_reveal_infinity {
return Err(warp_utils::reject::custom_bad_request(
"randao_reveal must be point-at-infinity if verification is skipped".into(),
));
}
ProduceBlockVerification::NoVerification
} else {
ProduceBlockVerification::VerifyRandao
};
Ok(randao_verification)
}
#[instrument(
name = "lh_produce_block_v4",
skip_all,
fields(%slot)
)]
pub async fn produce_block_v4<T: BeaconChainTypes>(
accept_header: Option<api_types::Accept>,
chain: Arc<BeaconChain<T>>,
slot: Slot,
query: api_types::ValidatorBlocksQuery,
) -> Result<Response<Body>, warp::Rejection> {
let randao_reveal = query.randao_reveal.decompress().map_err(|e| {
warp_utils::reject::custom_bad_request(format!(
"randao reveal is not a valid BLS signature: {:?}",
e
))
})?;
let randao_verification = get_randao_verification(&query, randao_reveal.is_infinity())?;
let builder_boost_factor = if query.builder_boost_factor == Some(DEFAULT_BOOST_FACTOR) {
None
} else {
query.builder_boost_factor
};
let graffiti_settings = GraffitiSettings::new(query.graffiti, query.graffiti_policy);
let (block, _block_state, consensus_block_value) = chain
.produce_block_with_verification_gloas(
randao_reveal,
slot,
graffiti_settings,
randao_verification,
builder_boost_factor,
)
.await
.map_err(|e| {
warp_utils::reject::custom_bad_request(format!("failed to fetch a block: {:?}", e))
})?;
build_response_v4::<T>(block, consensus_block_value, accept_header, &chain.spec)
}
#[instrument(
name = "lh_produce_block_v3",
skip_all,
fields(%slot)
)]
pub async fn produce_block_v3<T: BeaconChainTypes>(
accept_header: Option<api_types::Accept>,
chain: Arc<BeaconChain<T>>,
slot: Slot,
query: api_types::ValidatorBlocksQuery,
) -> Result<Response<Body>, warp::Rejection> {
let randao_reveal = query.randao_reveal.decompress().map_err(|e| {
warp_utils::reject::custom_bad_request(format!(
"randao reveal is not a valid BLS signature: {:?}",
e
))
})?;
let randao_verification = get_randao_verification(&query, randao_reveal.is_infinity())?;
let builder_boost_factor = if query.builder_boost_factor == Some(DEFAULT_BOOST_FACTOR) {
None
} else {
query.builder_boost_factor
};
let graffiti_settings = GraffitiSettings::new(query.graffiti, query.graffiti_policy);
let block_response_type = chain
.produce_block_with_verification(
randao_reveal,
slot,
graffiti_settings,
randao_verification,
builder_boost_factor,
BlockProductionVersion::V3,
)
.await
.map_err(|e| {
warp_utils::reject::custom_bad_request(format!("failed to fetch a block: {:?}", e))
})?;
build_response_v3(chain, block_response_type, accept_header)
}
pub fn build_response_v4<T: BeaconChainTypes>(
block: BeaconBlock<T::EthSpec, FullPayload<T::EthSpec>>,
consensus_block_value: u64,
accept_header: Option<api_types::Accept>,
spec: &ChainSpec,
) -> Result<Response<Body>, warp::Rejection> {
let fork_name = block
.to_ref()
.fork_name(spec)
.map_err(inconsistent_fork_rejection)?;
let consensus_block_value_wei =
Uint256::from(consensus_block_value) * Uint256::from(1_000_000_000u64);
let metadata = ProduceBlockV4Metadata {
consensus_version: fork_name,
consensus_block_value: consensus_block_value_wei,
};
match accept_header {
Some(api_types::Accept::Ssz) => Response::builder()
.status(200)
.body(block.as_ssz_bytes().into())
.map(|res: Response<Body>| add_ssz_content_type_header(res))
.map(|res: Response<Body>| add_consensus_version_header(res, fork_name))
.map(|res| add_consensus_block_value_header(res, consensus_block_value_wei))
.map_err(|e| -> warp::Rejection {
warp_utils::reject::custom_server_error(format!("failed to create response: {}", e))
}),
_ => Ok(warp::reply::json(&ForkVersionedResponse {
version: fork_name,
metadata,
data: block,
})
.into_response())
.map(|res| add_consensus_version_header(res, fork_name))
.map(|res| add_consensus_block_value_header(res, consensus_block_value_wei)),
}
}
pub fn build_response_v3<T: BeaconChainTypes>(
chain: Arc<BeaconChain<T>>,
block_response: BeaconBlockResponseWrapper<T::EthSpec>,
accept_header: Option<api_types::Accept>,
) -> Result<Response<Body>, warp::Rejection> {
let fork_name = block_response
.fork_name(&chain.spec)
.map_err(inconsistent_fork_rejection)?;
let execution_payload_value = block_response.execution_payload_value();
let consensus_block_value = block_response.consensus_block_value_wei();
let execution_payload_blinded = block_response.is_blinded();
let metadata = ProduceBlockV3Metadata {
consensus_version: fork_name,
execution_payload_blinded,
execution_payload_value,
consensus_block_value,
};
let block_contents = build_block_contents::build_block_contents(fork_name, block_response)?;
match accept_header {
Some(api_types::Accept::Ssz) => Response::builder()
.status(200)
.body(block_contents.as_ssz_bytes().into())
.map(|res: Response<Body>| add_ssz_content_type_header(res))
.map(|res: Response<Body>| add_consensus_version_header(res, fork_name))
.map(|res| add_execution_payload_blinded_header(res, execution_payload_blinded))
.map(|res: Response<Body>| {
add_execution_payload_value_header(res, execution_payload_value)
})
.map(|res| add_consensus_block_value_header(res, consensus_block_value))
.map_err(|e| -> warp::Rejection {
warp_utils::reject::custom_server_error(format!("failed to create response: {}", e))
}),
_ => Ok(warp::reply::json(&ForkVersionedResponse {
version: fork_name,
metadata,
data: block_contents,
})
.into_response())
.map(|res| res.into_response())
.map(|res| add_consensus_version_header(res, fork_name))
.map(|res| add_execution_payload_blinded_header(res, execution_payload_blinded))
.map(|res| add_execution_payload_value_header(res, execution_payload_value))
.map(|res| add_consensus_block_value_header(res, consensus_block_value)),
}
}
pub async fn produce_blinded_block_v2<T: BeaconChainTypes>(
accept_header: Option<api_types::Accept>,
chain: Arc<BeaconChain<T>>,
slot: Slot,
query: api_types::ValidatorBlocksQuery,
) -> Result<Response<Body>, warp::Rejection> {
let randao_reveal = query.randao_reveal.decompress().map_err(|e| {
warp_utils::reject::custom_bad_request(format!(
"randao reveal is not a valid BLS signature: {:?}",
e
))
})?;
let randao_verification = get_randao_verification(&query, randao_reveal.is_infinity())?;
let graffiti_settings = GraffitiSettings::new(query.graffiti, query.graffiti_policy);
let block_response_type = chain
.produce_block_with_verification(
randao_reveal,
slot,
graffiti_settings,
randao_verification,
None,
BlockProductionVersion::BlindedV2,
)
.await
.map_err(warp_utils::reject::unhandled_error)?;
build_response_v2(chain, block_response_type, accept_header)
}
#[instrument(
name = "lh_produce_block_v2",
skip_all,
fields(%slot)
)]
pub async fn produce_block_v2<T: BeaconChainTypes>(
accept_header: Option<api_types::Accept>,
chain: Arc<BeaconChain<T>>,
slot: Slot,
query: api_types::ValidatorBlocksQuery,
) -> Result<Response<Body>, warp::Rejection> {
let randao_reveal = query.randao_reveal.decompress().map_err(|e| {
warp_utils::reject::custom_bad_request(format!(
"randao reveal is not a valid BLS signature: {:?}",
e
))
})?;
let randao_verification = get_randao_verification(&query, randao_reveal.is_infinity())?;
let graffiti_settings = GraffitiSettings::new(query.graffiti, query.graffiti_policy);
let block_response_type = chain
.produce_block_with_verification(
randao_reveal,
slot,
graffiti_settings,
randao_verification,
None,
BlockProductionVersion::FullV2,
)
.await
.map_err(warp_utils::reject::unhandled_error)?;
build_response_v2(chain, block_response_type, accept_header)
}
pub fn build_response_v2<T: BeaconChainTypes>(
chain: Arc<BeaconChain<T>>,
block_response: BeaconBlockResponseWrapper<T::EthSpec>,
accept_header: Option<api_types::Accept>,
) -> Result<Response<Body>, warp::Rejection> {
let fork_name = block_response
.fork_name(&chain.spec)
.map_err(inconsistent_fork_rejection)?;
let block_contents = build_block_contents::build_block_contents(fork_name, block_response)?;
match accept_header {
Some(api_types::Accept::Ssz) => Response::builder()
.status(200)
.body(block_contents.as_ssz_bytes().into())
.map(|res: Response<Body>| add_ssz_content_type_header(res))
.map(|res: Response<Body>| add_consensus_version_header(res, fork_name))
.map_err(|e| {
warp_utils::reject::custom_server_error(format!("failed to create response: {}", e))
}),
_ => Ok(warp::reply::json(&beacon_response(
ResponseIncludesVersion::Yes(fork_name),
block_contents,
))
.into_response()),
}
}