Merge remote-tracking branch 'origin/unstable' into tree-states

This commit is contained in:
Michael Sproul
2023-12-14 09:59:43 +11:00
126 changed files with 5081 additions and 3916 deletions

View File

@@ -1,50 +1,42 @@
use beacon_chain::BlockProductionError;
use eth2::types::{BeaconBlockAndBlobSidecars, BlindedBeaconBlockAndBlobSidecars, BlockContents};
use types::{AbstractExecPayload, BeaconBlock, EthSpec, ForkName, SidecarList};
use beacon_chain::{BeaconBlockResponse, BeaconBlockResponseWrapper, BlockProductionError};
use eth2::types::{BlockContents, FullBlockContents, ProduceBlockV3Response};
use types::{EthSpec, ForkName};
type Error = warp::reject::Rejection;
pub fn build_block_contents<E: EthSpec, Payload: AbstractExecPayload<E>>(
pub fn build_block_contents<E: EthSpec>(
fork_name: ForkName,
block: BeaconBlock<E, Payload>,
maybe_blobs: Option<SidecarList<E, <Payload as AbstractExecPayload<E>>::Sidecar>>,
) -> Result<BlockContents<E, Payload>, Error> {
match Payload::block_type() {
types::BlockType::Blinded => match fork_name {
ForkName::Base | ForkName::Altair | ForkName::Merge | ForkName::Capella => {
Ok(BlockContents::Block(block))
}
block_response: BeaconBlockResponseWrapper<E>,
) -> Result<ProduceBlockV3Response<E>, Error> {
match block_response {
BeaconBlockResponseWrapper::Blinded(block) => {
Ok(ProduceBlockV3Response::Blinded(block.block))
}
BeaconBlockResponseWrapper::Full(block) => match fork_name {
ForkName::Base | ForkName::Altair | ForkName::Merge | ForkName::Capella => Ok(
ProduceBlockV3Response::Full(FullBlockContents::Block(block.block)),
),
ForkName::Deneb => {
if let Some(blinded_blob_sidecars) = maybe_blobs {
let block_and_blobs = BlindedBeaconBlockAndBlobSidecars {
blinded_block: block,
blinded_blob_sidecars,
};
let BeaconBlockResponse {
block,
state: _,
blob_items,
execution_payload_value: _,
consensus_block_value: _,
} = block;
Ok(BlockContents::BlindedBlockAndBlobSidecars(block_and_blobs))
} else {
Err(warp_utils::reject::block_production_error(
let Some((kzg_proofs, blobs)) = blob_items else {
return Err(warp_utils::reject::block_production_error(
BlockProductionError::MissingBlobs,
))
}
}
},
types::BlockType::Full => match fork_name {
ForkName::Base | ForkName::Altair | ForkName::Merge | ForkName::Capella => {
Ok(BlockContents::Block(block))
}
ForkName::Deneb => {
if let Some(blob_sidecars) = maybe_blobs {
let block_and_blobs = BeaconBlockAndBlobSidecars {
));
};
Ok(ProduceBlockV3Response::Full(
FullBlockContents::BlockContents(BlockContents {
block,
blob_sidecars,
};
Ok(BlockContents::BlockAndBlobSidecars(block_and_blobs))
} else {
Err(warp_utils::reject::block_production_error(
BlockProductionError::MissingBlobs,
))
}
kzg_proofs,
blobs,
}),
))
}
},
}

View File

@@ -26,6 +26,7 @@ pub mod test_utils;
mod ui;
mod validator;
mod validator_inclusion;
mod validators;
mod version;
use crate::produce_block::{produce_blinded_block_v2, produce_block_v2, produce_block_v3};
@@ -41,7 +42,8 @@ use bytes::Bytes;
use directory::DEFAULT_ROOT_DIR;
use eth2::types::{
self as api_types, BroadcastValidation, EndpointVersion, ForkChoice, ForkChoiceNode,
SignedBlindedBlockContents, SignedBlockContents, ValidatorId, ValidatorStatus,
PublishBlockRequest, ValidatorBalancesRequestBody, ValidatorId, ValidatorStatus,
ValidatorsRequestBody,
};
use lighthouse_network::{types::SyncState, EnrExt, NetworkGlobals, PeerId, PubsubMessage};
use lighthouse_version::version_with_platform;
@@ -75,9 +77,9 @@ use tokio_stream::{
};
use types::{
Attestation, AttestationData, AttestationShufflingId, AttesterSlashing, BeaconStateError,
BlindedPayload, CommitteeCache, ConfigAndPreset, Epoch, EthSpec, ForkName,
ForkVersionedResponse, Hash256, ProposerPreparationData, ProposerSlashing, RelativeEpoch,
SignedAggregateAndProof, SignedBlsToExecutionChange, SignedContributionAndProof,
CommitteeCache, ConfigAndPreset, Epoch, EthSpec, ForkName, ForkVersionedResponse, Hash256,
ProposerPreparationData, ProposerSlashing, RelativeEpoch, SignedAggregateAndProof,
SignedBlindedBeaconBlock, SignedBlsToExecutionChange, SignedContributionAndProof,
SignedValidatorRegistrationData, SignedVoluntaryExit, Slot, SyncCommitteeMessage,
SyncContributionData,
};
@@ -662,47 +664,32 @@ pub fn serve<T: BeaconChainTypes>(
query_res: Result<api_types::ValidatorBalancesQuery, warp::Rejection>| {
task_spawner.blocking_json_task(Priority::P1, move || {
let query = query_res?;
let (data, execution_optimistic, finalized) = state_id
.map_state_and_execution_optimistic_and_finalized(
&chain,
|state, execution_optimistic, finalized| {
Ok((
state
.validators()
.iter()
.zip(state.balances().iter())
.enumerate()
// filter by validator id(s) if provided
.filter(|(index, (validator, _))| {
query.id.as_ref().map_or(true, |ids| {
ids.iter().any(|id| match id {
ValidatorId::PublicKey(pubkey) => {
validator.pubkey() == pubkey
}
ValidatorId::Index(param_index) => {
*param_index == *index as u64
}
})
})
})
.map(|(index, (_, balance))| {
Some(api_types::ValidatorBalanceData {
index: index as u64,
balance: *balance,
})
})
.collect::<Vec<_>>(),
execution_optimistic,
finalized,
))
},
)?;
crate::validators::get_beacon_state_validator_balances(
state_id,
chain,
query.id.as_deref(),
)
})
},
);
Ok(api_types::ExecutionOptimisticFinalizedResponse {
data,
execution_optimistic: Some(execution_optimistic),
finalized: Some(finalized),
})
// POST beacon/states/{state_id}/validator_balances
let post_beacon_state_validator_balances = beacon_states_path
.clone()
.and(warp::path("validator_balances"))
.and(warp::path::end())
.and(warp::body::json())
.then(
|state_id: StateId,
task_spawner: TaskSpawner<T::EthSpec>,
chain: Arc<BeaconChain<T>>,
query: ValidatorBalancesRequestBody| {
task_spawner.blocking_json_task(Priority::P1, move || {
crate::validators::get_beacon_state_validator_balances(
state_id,
chain,
Some(&query.ids),
)
})
},
);
@@ -720,69 +707,34 @@ pub fn serve<T: BeaconChainTypes>(
query_res: Result<api_types::ValidatorsQuery, warp::Rejection>| {
task_spawner.blocking_json_task(Priority::P1, move || {
let query = query_res?;
let (data, execution_optimistic, finalized) = state_id
.map_state_and_execution_optimistic_and_finalized(
&chain,
|state, execution_optimistic, finalized| {
let epoch = state.current_epoch();
let far_future_epoch = chain.spec.far_future_epoch;
crate::validators::get_beacon_state_validators(
state_id,
chain,
&query.id,
&query.status,
)
})
},
);
Ok((
state
.validators()
.iter()
.zip(state.balances().iter())
.enumerate()
// filter by validator id(s) if provided
.filter(|(index, (validator, _))| {
query.id.as_ref().map_or(true, |ids| {
ids.iter().any(|id| match id {
ValidatorId::PublicKey(pubkey) => {
validator.pubkey() == pubkey
}
ValidatorId::Index(param_index) => {
*param_index == *index as u64
}
})
})
})
// filter by status(es) if provided and map the result
.filter_map(|(index, (validator, balance))| {
let status = api_types::ValidatorStatus::from_validator(
validator,
epoch,
far_future_epoch,
);
let status_matches =
query.status.as_ref().map_or(true, |statuses| {
statuses.contains(&status)
|| statuses.contains(&status.superstatus())
});
if status_matches {
Some(api_types::ValidatorData {
index: index as u64,
balance: *balance,
status,
validator: validator.clone(),
})
} else {
None
}
})
.collect::<Vec<_>>(),
execution_optimistic,
finalized,
))
},
)?;
Ok(api_types::ExecutionOptimisticFinalizedResponse {
data,
execution_optimistic: Some(execution_optimistic),
finalized: Some(finalized),
})
// POST beacon/states/{state_id}/validators
let post_beacon_state_validators = beacon_states_path
.clone()
.and(warp::path("validators"))
.and(warp::path::end())
.and(warp::body::json())
.then(
|state_id: StateId,
task_spawner: TaskSpawner<T::EthSpec>,
chain: Arc<BeaconChain<T>>,
query: ValidatorsRequestBody| {
task_spawner.blocking_json_task(Priority::P1, move || {
crate::validators::get_beacon_state_validators(
state_id,
chain,
&query.ids,
&query.statuses,
)
})
},
);
@@ -1304,7 +1256,7 @@ pub fn serve<T: BeaconChainTypes>(
.and(network_tx_filter.clone())
.and(log_filter.clone())
.then(
move |block_contents: SignedBlockContents<T::EthSpec>,
move |block_contents: PublishBlockRequest<T::EthSpec>,
task_spawner: TaskSpawner<T::EthSpec>,
chain: Arc<BeaconChain<T>>,
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
@@ -1340,7 +1292,7 @@ pub fn serve<T: BeaconChainTypes>(
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
log: Logger| {
task_spawner.spawn_async_with_rejection(Priority::P0, async move {
let block_contents = SignedBlockContents::<T::EthSpec>::from_ssz_bytes(
let block_contents = PublishBlockRequest::<T::EthSpec>::from_ssz_bytes(
&block_bytes,
&chain.spec,
)
@@ -1373,7 +1325,7 @@ pub fn serve<T: BeaconChainTypes>(
.and(log_filter.clone())
.then(
move |validation_level: api_types::BroadcastValidationQuery,
block_contents: SignedBlockContents<T::EthSpec>,
block_contents: PublishBlockRequest<T::EthSpec>,
task_spawner: TaskSpawner<T::EthSpec>,
chain: Arc<BeaconChain<T>>,
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
@@ -1411,7 +1363,7 @@ pub fn serve<T: BeaconChainTypes>(
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
log: Logger| {
task_spawner.spawn_async_with_rejection(Priority::P0, async move {
let block_contents = SignedBlockContents::<T::EthSpec>::from_ssz_bytes(
let block_contents = PublishBlockRequest::<T::EthSpec>::from_ssz_bytes(
&block_bytes,
&chain.spec,
)
@@ -1447,7 +1399,7 @@ pub fn serve<T: BeaconChainTypes>(
.and(network_tx_filter.clone())
.and(log_filter.clone())
.then(
move |block_contents: SignedBlindedBlockContents<T::EthSpec>,
move |block_contents: SignedBlindedBeaconBlock<T::EthSpec>,
task_spawner: TaskSpawner<T::EthSpec>,
chain: Arc<BeaconChain<T>>,
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
@@ -1483,14 +1435,13 @@ pub fn serve<T: BeaconChainTypes>(
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
log: Logger| {
task_spawner.spawn_async_with_rejection(Priority::P0, async move {
let block =
SignedBlockContents::<T::EthSpec, BlindedPayload<_>>::from_ssz_bytes(
&block_bytes,
&chain.spec,
)
.map_err(|e| {
warp_utils::reject::custom_bad_request(format!("invalid SSZ: {e:?}"))
})?;
let block = SignedBlindedBeaconBlock::<T::EthSpec>::from_ssz_bytes(
&block_bytes,
&chain.spec,
)
.map_err(|e| {
warp_utils::reject::custom_bad_request(format!("invalid SSZ: {e:?}"))
})?;
publish_blocks::publish_blinded_block(
block,
chain,
@@ -1516,14 +1467,14 @@ pub fn serve<T: BeaconChainTypes>(
.and(log_filter.clone())
.then(
move |validation_level: api_types::BroadcastValidationQuery,
block_contents: SignedBlindedBlockContents<T::EthSpec>,
blinded_block: SignedBlindedBeaconBlock<T::EthSpec>,
task_spawner: TaskSpawner<T::EthSpec>,
chain: Arc<BeaconChain<T>>,
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
log: Logger| {
task_spawner.spawn_async_with_rejection(Priority::P0, async move {
publish_blocks::publish_blinded_block(
block_contents,
blinded_block,
chain,
&network_tx,
log,
@@ -1553,14 +1504,13 @@ pub fn serve<T: BeaconChainTypes>(
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
log: Logger| {
task_spawner.spawn_async_with_rejection(Priority::P0, async move {
let block =
SignedBlockContents::<T::EthSpec, BlindedPayload<_>>::from_ssz_bytes(
&block_bytes,
&chain.spec,
)
.map_err(|e| {
warp_utils::reject::custom_bad_request(format!("invalid SSZ: {e:?}"))
})?;
let block = SignedBlindedBeaconBlock::<T::EthSpec>::from_ssz_bytes(
&block_bytes,
&chain.spec,
)
.map_err(|e| {
warp_utils::reject::custom_bad_request(format!("invalid SSZ: {e:?}"))
})?;
publish_blocks::publish_blinded_block(
block,
chain,
@@ -4709,6 +4659,8 @@ pub fn serve<T: BeaconChainTypes>(
.uor(post_beacon_pool_voluntary_exits)
.uor(post_beacon_pool_sync_committees)
.uor(post_beacon_pool_bls_to_execution_changes)
.uor(post_beacon_state_validators)
.uor(post_beacon_state_validator_balances)
.uor(post_beacon_rewards_attestations)
.uor(post_beacon_rewards_sync_committee)
.uor(post_validator_duties_attester)

View File

@@ -3,8 +3,7 @@ use std::sync::Arc;
use types::{payload::BlockProductionVersion, *};
use beacon_chain::{
BeaconBlockResponse, BeaconBlockResponseType, BeaconChain, BeaconChainTypes,
ProduceBlockVerification,
BeaconBlockResponseWrapper, BeaconChain, BeaconChainTypes, ProduceBlockVerification,
};
use eth2::types::{self as api_types, EndpointVersion, SkipRandaoVerification};
use ssz::Encode;
@@ -69,35 +68,23 @@ pub async fn produce_block_v3<T: BeaconChainTypes>(
warp_utils::reject::custom_bad_request(format!("failed to fetch a block: {:?}", e))
})?;
match block_response_type {
BeaconBlockResponseType::Full(block_response) => {
build_response_v3(chain, block_response, endpoint_version, accept_header)
}
BeaconBlockResponseType::Blinded(block_response) => {
build_response_v3(chain, block_response, endpoint_version, accept_header)
}
}
build_response_v3(chain, block_response_type, endpoint_version, accept_header)
}
pub fn build_response_v3<T: BeaconChainTypes, E: EthSpec, Payload: AbstractExecPayload<E>>(
pub fn build_response_v3<T: BeaconChainTypes>(
chain: Arc<BeaconChain<T>>,
block_response: BeaconBlockResponse<E, Payload>,
block_response: BeaconBlockResponseWrapper<T::EthSpec>,
endpoint_version: EndpointVersion,
accept_header: Option<api_types::Accept>,
) -> Result<Response<Body>, warp::Rejection> {
let fork_name = block_response
.block
.to_ref()
.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();
let execution_payload_blinded = block_response.is_blinded();
let block_contents = build_block_contents::build_block_contents(
fork_name,
block_response.block,
block_response.maybe_side_car,
)?;
let execution_payload_blinded = Payload::block_type() == BlockType::Blinded;
let block_contents = build_block_contents::build_block_contents(fork_name, block_response)?;
match accept_header {
Some(api_types::Accept::Ssz) => Response::builder()
@@ -107,9 +94,9 @@ pub fn build_response_v3<T: BeaconChainTypes, E: EthSpec, Payload: AbstractExecP
.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, block_response.execution_payload_value)
add_execution_payload_value_header(res, execution_payload_value)
})
.map(|res| add_consensus_block_value_header(res, block_response.consensus_block_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))
}),
@@ -117,10 +104,8 @@ pub fn build_response_v3<T: BeaconChainTypes, E: EthSpec, Payload: AbstractExecP
.map(|response| warp::reply::json(&response).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, block_response.execution_payload_value)
})
.map(|res| add_consensus_block_value_header(res, block_response.consensus_block_value)),
.map(|res| add_execution_payload_value_header(res, execution_payload_value))
.map(|res| add_consensus_block_value_header(res, consensus_block_value)),
}
}
@@ -150,14 +135,7 @@ pub async fn produce_blinded_block_v2<T: BeaconChainTypes>(
.await
.map_err(warp_utils::reject::block_production_error)?;
match block_response_type {
BeaconBlockResponseType::Full(block_response) => {
build_response_v2(chain, block_response, endpoint_version, accept_header)
}
BeaconBlockResponseType::Blinded(block_response) => {
build_response_v2(chain, block_response, endpoint_version, accept_header)
}
}
build_response_v2(chain, block_response_type, endpoint_version, accept_header)
}
pub async fn produce_block_v2<T: BeaconChainTypes>(
@@ -187,33 +165,20 @@ pub async fn produce_block_v2<T: BeaconChainTypes>(
.await
.map_err(warp_utils::reject::block_production_error)?;
match block_response_type {
BeaconBlockResponseType::Full(block_response) => {
build_response_v2(chain, block_response, endpoint_version, accept_header)
}
BeaconBlockResponseType::Blinded(block_response) => {
build_response_v2(chain, block_response, endpoint_version, accept_header)
}
}
build_response_v2(chain, block_response_type, endpoint_version, accept_header)
}
pub fn build_response_v2<T: BeaconChainTypes, E: EthSpec, Payload: AbstractExecPayload<E>>(
pub fn build_response_v2<T: BeaconChainTypes>(
chain: Arc<BeaconChain<T>>,
block_response: BeaconBlockResponse<E, Payload>,
block_response: BeaconBlockResponseWrapper<T::EthSpec>,
endpoint_version: EndpointVersion,
accept_header: Option<api_types::Accept>,
) -> Result<Response<Body>, warp::Rejection> {
let fork_name = block_response
.block
.to_ref()
.fork_name(&chain.spec)
.map_err(inconsistent_fork_rejection)?;
let block_contents = build_block_contents::build_block_contents(
fork_name,
block_response.block,
block_response.maybe_side_car,
)?;
let block_contents = build_block_contents::build_block_contents(fork_name, block_response)?;
match accept_header {
Some(api_types::Accept::Ssz) => Response::builder()

View File

@@ -6,8 +6,8 @@ use beacon_chain::{
AvailabilityProcessingStatus, BeaconChain, BeaconChainError, BeaconChainTypes, BlockError,
IntoGossipVerifiedBlockContents, NotifyExecutionLayer,
};
use eth2::types::{BroadcastValidation, ErrorMessage};
use eth2::types::{FullPayloadContents, SignedBlockContents};
use eth2::types::{into_full_block_and_blobs, BroadcastValidation, ErrorMessage};
use eth2::types::{FullPayloadContents, PublishBlockRequest};
use execution_layer::ProvenancedPayload;
use lighthouse_network::PubsubMessage;
use network::NetworkMessage;
@@ -19,8 +19,9 @@ use std::time::Duration;
use tokio::sync::mpsc::UnboundedSender;
use tree_hash::TreeHash;
use types::{
AbstractExecPayload, BeaconBlockRef, BlindedPayload, EthSpec, ExecPayload, ExecutionBlockHash,
ForkName, FullPayload, FullPayloadMerge, Hash256, SignedBeaconBlock, SignedBlobSidecarList,
AbstractExecPayload, BeaconBlockRef, BlobSidecarList, EthSpec, ExecPayload, ExecutionBlockHash,
ForkName, FullPayload, FullPayloadMerge, Hash256, SignedBeaconBlock, SignedBlindedBeaconBlock,
VariableList,
};
use warp::http::StatusCode;
use warp::{reply::Response, Rejection, Reply};
@@ -65,7 +66,7 @@ pub async fn publish_block<T: BeaconChainTypes, B: IntoGossipVerifiedBlockConten
/* actually publish a block */
let publish_block = move |block: Arc<SignedBeaconBlock<T::EthSpec>>,
blobs_opt: Option<SignedBlobSidecarList<T::EthSpec>>,
blobs_opt: Option<BlobSidecarList<T::EthSpec>>,
sender,
log,
seen_timestamp| {
@@ -86,8 +87,8 @@ pub async fn publish_block<T: BeaconChainTypes, B: IntoGossipVerifiedBlockConten
}
SignedBeaconBlock::Deneb(_) => {
let mut pubsub_messages = vec![PubsubMessage::BeaconBlock(block.clone())];
if let Some(signed_blobs) = blobs_opt {
for (blob_index, blob) in signed_blobs.into_iter().enumerate() {
if let Some(blob_sidecars) = blobs_opt {
for (blob_index, blob) in blob_sidecars.into_iter().enumerate() {
pubsub_messages.push(PubsubMessage::BlobSidecar(Box::new((
blob_index as u64,
blob,
@@ -108,10 +109,6 @@ pub async fn publish_block<T: BeaconChainTypes, B: IntoGossipVerifiedBlockConten
let sender_clone = network_tx.clone();
let log_clone = log.clone();
// We can clone this because the blobs are `Arc`'d in `BlockContents`, but the block is not,
// so we avoid cloning the block at this point.
let blobs_opt = block_contents.inner_blobs();
/* if we can form a `GossipVerifiedBlock`, we've passed our basic gossip checks */
let (gossip_verified_block, gossip_verified_blobs) =
match block_contents.into_gossip_verified_block(&chain) {
@@ -142,6 +139,13 @@ pub async fn publish_block<T: BeaconChainTypes, B: IntoGossipVerifiedBlockConten
// Clone here, so we can take advantage of the `Arc`. The block in `BlockContents` is not,
// `Arc`'d but blobs are.
let block = gossip_verified_block.block.block_cloned();
let blobs_opt = gossip_verified_blobs.as_ref().map(|gossip_verified_blobs| {
let blobs = gossip_verified_blobs
.into_iter()
.map(|b| b.clone_blob())
.collect::<Vec<_>>();
VariableList::from(blobs)
});
let block_root = block_root.unwrap_or(gossip_verified_block.block_root);
@@ -292,16 +296,16 @@ pub async fn publish_block<T: BeaconChainTypes, B: IntoGossipVerifiedBlockConten
/// Handles a request from the HTTP API for blinded blocks. This converts blinded blocks into full
/// blocks before publishing.
pub async fn publish_blinded_block<T: BeaconChainTypes>(
block_contents: SignedBlockContents<T::EthSpec, BlindedPayload<T::EthSpec>>,
blinded_block: SignedBlindedBeaconBlock<T::EthSpec>,
chain: Arc<BeaconChain<T>>,
network_tx: &UnboundedSender<NetworkMessage<T::EthSpec>>,
log: Logger,
validation_level: BroadcastValidation,
duplicate_status_code: StatusCode,
) -> Result<Response, Rejection> {
let block_root = block_contents.signed_block().canonical_root();
let full_block: ProvenancedBlock<T, SignedBlockContents<T::EthSpec>> =
reconstruct_block(chain.clone(), block_root, block_contents, log.clone()).await?;
let block_root = blinded_block.canonical_root();
let full_block: ProvenancedBlock<T, PublishBlockRequest<T::EthSpec>> =
reconstruct_block(chain.clone(), block_root, blinded_block, log.clone()).await?;
publish_block::<T, _>(
Some(block_root),
full_block,
@@ -320,10 +324,9 @@ pub async fn publish_blinded_block<T: BeaconChainTypes>(
pub async fn reconstruct_block<T: BeaconChainTypes>(
chain: Arc<BeaconChain<T>>,
block_root: Hash256,
block_contents: SignedBlockContents<T::EthSpec, BlindedPayload<T::EthSpec>>,
block: SignedBlindedBeaconBlock<T::EthSpec>,
log: Logger,
) -> Result<ProvenancedBlock<T, SignedBlockContents<T::EthSpec>>, Rejection> {
let block = block_contents.signed_block();
) -> Result<ProvenancedBlock<T, PublishBlockRequest<T::EthSpec>>, Rejection> {
let full_payload_opt = if let Ok(payload_header) = block.message().body().execution_payload() {
let el = chain.execution_layer.as_ref().ok_or_else(|| {
warp_utils::reject::custom_server_error("Missing execution layer".to_string())
@@ -365,7 +368,7 @@ pub async fn reconstruct_block<T: BeaconChainTypes>(
);
let full_payload = el
.propose_blinded_beacon_block(block_root, &block_contents)
.propose_blinded_beacon_block(block_root, &block)
.await
.map_err(|e| {
warp_utils::reject::custom_server_error(format!(
@@ -385,15 +388,15 @@ pub async fn reconstruct_block<T: BeaconChainTypes>(
match full_payload_opt {
// A block without a payload is pre-merge and we consider it locally
// built.
None => block_contents
.try_into_full_block_and_blobs(None)
.map(ProvenancedBlock::local),
Some(ProvenancedPayload::Local(full_payload_contents)) => block_contents
.try_into_full_block_and_blobs(Some(full_payload_contents))
.map(ProvenancedBlock::local),
Some(ProvenancedPayload::Builder(full_payload_contents)) => block_contents
.try_into_full_block_and_blobs(Some(full_payload_contents))
.map(ProvenancedBlock::builder),
None => into_full_block_and_blobs(block, None).map(ProvenancedBlock::local),
Some(ProvenancedPayload::Local(full_payload_contents)) => {
into_full_block_and_blobs(block, Some(full_payload_contents))
.map(ProvenancedBlock::local)
}
Some(ProvenancedPayload::Builder(full_payload_contents)) => {
into_full_block_and_blobs(block, Some(full_payload_contents))
.map(ProvenancedBlock::builder)
}
}
.map_err(|e| {
warp_utils::reject::custom_server_error(format!("Unable to add payload to block: {e:?}"))

View File

@@ -0,0 +1,119 @@
use crate::state_id::StateId;
use beacon_chain::{BeaconChain, BeaconChainTypes};
use eth2::types::{
self as api_types, ExecutionOptimisticFinalizedResponse, ValidatorBalanceData, ValidatorData,
ValidatorId, ValidatorStatus,
};
use std::sync::Arc;
pub fn get_beacon_state_validators<T: BeaconChainTypes>(
state_id: StateId,
chain: Arc<BeaconChain<T>>,
query_ids: &Option<Vec<ValidatorId>>,
query_statuses: &Option<Vec<ValidatorStatus>>,
) -> Result<ExecutionOptimisticFinalizedResponse<Vec<ValidatorData>>, warp::Rejection> {
let (data, execution_optimistic, finalized) = state_id
.map_state_and_execution_optimistic_and_finalized(
&chain,
|state, execution_optimistic, finalized| {
let epoch = state.current_epoch();
let far_future_epoch = chain.spec.far_future_epoch;
Ok((
state
.validators()
.iter()
.zip(state.balances().iter())
.enumerate()
// filter by validator id(s) if provided
.filter(|(index, (validator, _))| {
query_ids.as_ref().map_or(true, |ids| {
ids.iter().any(|id| match id {
ValidatorId::PublicKey(pubkey) => validator.pubkey() == pubkey,
ValidatorId::Index(param_index) => {
*param_index == *index as u64
}
})
})
})
// filter by status(es) if provided and map the result
.filter_map(|(index, (validator, balance))| {
let status = api_types::ValidatorStatus::from_validator(
validator,
epoch,
far_future_epoch,
);
let status_matches = query_statuses.as_ref().map_or(true, |statuses| {
statuses.contains(&status)
|| statuses.contains(&status.superstatus())
});
if status_matches {
Some(ValidatorData {
index: index as u64,
balance: *balance,
status,
validator: validator.clone(),
})
} else {
None
}
})
.collect::<Vec<_>>(),
execution_optimistic,
finalized,
))
},
)?;
Ok(ExecutionOptimisticFinalizedResponse {
data,
execution_optimistic: Some(execution_optimistic),
finalized: Some(finalized),
})
}
pub fn get_beacon_state_validator_balances<T: BeaconChainTypes>(
state_id: StateId,
chain: Arc<BeaconChain<T>>,
optional_ids: Option<&[ValidatorId]>,
) -> Result<ExecutionOptimisticFinalizedResponse<Vec<ValidatorBalanceData>>, warp::Rejection> {
let (data, execution_optimistic, finalized) = state_id
.map_state_and_execution_optimistic_and_finalized(
&chain,
|state, execution_optimistic, finalized| {
Ok((
state
.validators()
.iter()
.zip(state.balances().iter())
.enumerate()
// filter by validator id(s) if provided
.filter(|(index, (validator, _))| {
optional_ids.map_or(true, |ids| {
ids.iter().any(|id| match id {
ValidatorId::PublicKey(pubkey) => validator.pubkey() == pubkey,
ValidatorId::Index(param_index) => {
*param_index == *index as u64
}
})
})
})
.map(|(index, (_, balance))| ValidatorBalanceData {
index: index as u64,
balance: *balance,
})
.collect::<Vec<_>>(),
execution_optimistic,
finalized,
))
},
)?;
Ok(api_types::ExecutionOptimisticFinalizedResponse {
data,
execution_optimistic: Some(execution_optimistic),
finalized: Some(finalized),
})
}