mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-09 11:41:51 +00:00
Kiln mev boost (#3062)
## Issue Addressed MEV boost compatibility ## Proposed Changes See #2987 ## Additional Info This is blocked on the stabilization of a couple specs, [here](https://github.com/ethereum/beacon-APIs/pull/194) and [here](https://github.com/flashbots/mev-boost/pull/20). Additional TODO's and outstanding questions - [ ] MEV boost JWT Auth - [ ] Will `builder_proposeBlindedBlock` return the revealed payload for the BN to propogate - [ ] Should we remove `private-tx-proposals` flag and communicate BN <> VC with blinded blocks by default once these endpoints enter the beacon-API's repo? This simplifies merge transition logic. Co-authored-by: realbigsean <seananderson33@gmail.com> Co-authored-by: realbigsean <sean@sigmaprime.io>
This commit is contained in:
@@ -45,9 +45,10 @@ use std::sync::Arc;
|
||||
use tokio::sync::mpsc::UnboundedSender;
|
||||
use tokio_stream::{wrappers::BroadcastStream, StreamExt};
|
||||
use types::{
|
||||
Attestation, AttesterSlashing, BeaconStateError, CommitteeCache, ConfigAndPreset, Epoch,
|
||||
EthSpec, ForkName, ProposerPreparationData, ProposerSlashing, RelativeEpoch, Signature,
|
||||
SignedAggregateAndProof, SignedBeaconBlock, SignedContributionAndProof, SignedVoluntaryExit,
|
||||
Attestation, AttesterSlashing, BeaconBlockBodyMerge, BeaconBlockMerge, BeaconStateError,
|
||||
BlindedPayload, CommitteeCache, ConfigAndPreset, Epoch, EthSpec, ForkName, FullPayload,
|
||||
ProposerPreparationData, ProposerSlashing, RelativeEpoch, Signature, SignedAggregateAndProof,
|
||||
SignedBeaconBlock, SignedBeaconBlockMerge, SignedContributionAndProof, SignedVoluntaryExit,
|
||||
Slot, SyncCommitteeMessage, SyncContributionData,
|
||||
};
|
||||
use version::{
|
||||
@@ -1022,6 +1023,116 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
},
|
||||
);
|
||||
|
||||
/*
|
||||
* beacon/blocks
|
||||
*/
|
||||
|
||||
// POST beacon/blocks
|
||||
let post_beacon_blinded_blocks = eth1_v1
|
||||
.and(warp::path("beacon"))
|
||||
.and(warp::path("blinded_blocks"))
|
||||
.and(warp::path::end())
|
||||
.and(warp::body::json())
|
||||
.and(chain_filter.clone())
|
||||
.and(network_tx_filter.clone())
|
||||
.and(log_filter.clone())
|
||||
.and_then(
|
||||
|block: SignedBeaconBlock<T::EthSpec, BlindedPayload<_>>,
|
||||
chain: Arc<BeaconChain<T>>,
|
||||
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
|
||||
_log: Logger| {
|
||||
blocking_json_task(move || {
|
||||
if let Some(el) = chain.execution_layer.as_ref() {
|
||||
//FIXME(sean): we may not always receive the payload in this response because it
|
||||
// should be the relay's job to propogate the block. However, since this block is
|
||||
// already signed and sent this might be ok (so long as the relay validates
|
||||
// the block before revealing the payload).
|
||||
|
||||
//FIXME(sean) additionally, this endpoint should serve blocks prior to Bellatrix, and should
|
||||
// be able to support the normal block proposal flow, because at some point full block endpoints
|
||||
// will be deprecated from the beacon API. This will entail creating full blocks in
|
||||
// `validator/blinded_blocks`, caching their payloads, and transforming them into blinded
|
||||
// blocks. We will access the payload of those blocks here. This flow should happen if the
|
||||
// execution layer has no payload builders or if we have not yet finalized post-merge transition.
|
||||
let payload = el
|
||||
.block_on(|el| el.propose_blinded_beacon_block(&block))
|
||||
.map_err(|e| {
|
||||
warp_utils::reject::custom_server_error(format!(
|
||||
"proposal failed: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
let new_block = SignedBeaconBlock::Merge(SignedBeaconBlockMerge {
|
||||
message: BeaconBlockMerge {
|
||||
slot: block.message().slot(),
|
||||
proposer_index: block.message().proposer_index(),
|
||||
parent_root: block.message().parent_root(),
|
||||
state_root: block.message().state_root(),
|
||||
body: BeaconBlockBodyMerge {
|
||||
randao_reveal: block.message().body().randao_reveal().clone(),
|
||||
eth1_data: block.message().body().eth1_data().clone(),
|
||||
graffiti: *block.message().body().graffiti(),
|
||||
proposer_slashings: block
|
||||
.message()
|
||||
.body()
|
||||
.proposer_slashings()
|
||||
.clone(),
|
||||
attester_slashings: block
|
||||
.message()
|
||||
.body()
|
||||
.attester_slashings()
|
||||
.clone(),
|
||||
attestations: block.message().body().attestations().clone(),
|
||||
deposits: block.message().body().deposits().clone(),
|
||||
voluntary_exits: block
|
||||
.message()
|
||||
.body()
|
||||
.voluntary_exits()
|
||||
.clone(),
|
||||
sync_aggregate: block
|
||||
.message()
|
||||
.body()
|
||||
.sync_aggregate()
|
||||
.unwrap()
|
||||
.clone(),
|
||||
execution_payload: payload.into(),
|
||||
},
|
||||
},
|
||||
signature: block.signature().clone(),
|
||||
});
|
||||
|
||||
// Send the block, regardless of whether or not it is valid. The API
|
||||
// specification is very clear that this is the desired behaviour.
|
||||
publish_pubsub_message(
|
||||
&network_tx,
|
||||
PubsubMessage::BeaconBlock(Box::new(new_block.clone())),
|
||||
)?;
|
||||
|
||||
match chain.process_block(new_block) {
|
||||
Ok(_) => {
|
||||
// Update the head since it's likely this block will become the new
|
||||
// head.
|
||||
chain
|
||||
.fork_choice()
|
||||
.map_err(warp_utils::reject::beacon_chain_error)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
let msg = format!("{:?}", e);
|
||||
|
||||
Err(warp_utils::reject::broadcast_without_import(msg))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err(warp_utils::reject::custom_server_error(
|
||||
"no execution layer found".to_string(),
|
||||
))
|
||||
}
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
let block_id_or_err = warp::path::param::<BlockId>().or_else(|_| async {
|
||||
Err(warp_utils::reject::custom_bad_request(
|
||||
"Invalid block ID".to_string(),
|
||||
@@ -1899,7 +2010,69 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
};
|
||||
|
||||
let (block, _) = chain
|
||||
.produce_block_with_verification(
|
||||
.produce_block_with_verification::<FullPayload<T::EthSpec>>(
|
||||
randao_reveal,
|
||||
slot,
|
||||
query.graffiti.map(Into::into),
|
||||
randao_verification,
|
||||
)
|
||||
.map_err(warp_utils::reject::block_production_error)?;
|
||||
let fork_name = block
|
||||
.to_ref()
|
||||
.fork_name(&chain.spec)
|
||||
.map_err(inconsistent_fork_rejection)?;
|
||||
fork_versioned_response(endpoint_version, fork_name, block)
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
// GET validator/blinded_blocks/{slot}
|
||||
let get_validator_blinded_blocks = any_version
|
||||
.and(warp::path("validator"))
|
||||
.and(warp::path("blinded_blocks"))
|
||||
.and(warp::path::param::<Slot>().or_else(|_| async {
|
||||
Err(warp_utils::reject::custom_bad_request(
|
||||
"Invalid slot".to_string(),
|
||||
))
|
||||
}))
|
||||
.and(warp::path::end())
|
||||
.and(not_while_syncing_filter.clone())
|
||||
.and(warp::query::<api_types::ValidatorBlocksQuery>())
|
||||
.and(chain_filter.clone())
|
||||
.and_then(
|
||||
|endpoint_version: EndpointVersion,
|
||||
slot: Slot,
|
||||
query: api_types::ValidatorBlocksQuery,
|
||||
chain: Arc<BeaconChain<T>>| {
|
||||
blocking_json_task(move || {
|
||||
let randao_reveal = query.randao_reveal.as_ref().map_or_else(
|
||||
|| {
|
||||
if query.verify_randao {
|
||||
Err(warp_utils::reject::custom_bad_request(
|
||||
"randao_reveal is mandatory unless verify_randao=false".into(),
|
||||
))
|
||||
} else {
|
||||
Ok(Signature::empty())
|
||||
}
|
||||
},
|
||||
|sig_bytes| {
|
||||
sig_bytes.try_into().map_err(|e| {
|
||||
warp_utils::reject::custom_bad_request(format!(
|
||||
"randao reveal is not a valid BLS signature: {:?}",
|
||||
e
|
||||
))
|
||||
})
|
||||
},
|
||||
)?;
|
||||
|
||||
let randao_verification = if query.verify_randao {
|
||||
ProduceBlockVerification::VerifyRandao
|
||||
} else {
|
||||
ProduceBlockVerification::NoVerification
|
||||
};
|
||||
|
||||
let (block, _) = chain
|
||||
.produce_block_with_verification::<BlindedPayload<T::EthSpec>>(
|
||||
randao_reveal,
|
||||
slot,
|
||||
query.graffiti.map(Into::into),
|
||||
@@ -2766,6 +2939,7 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
.or(get_node_peer_count.boxed())
|
||||
.or(get_validator_duties_proposer.boxed())
|
||||
.or(get_validator_blocks.boxed())
|
||||
.or(get_validator_blinded_blocks.boxed())
|
||||
.or(get_validator_attestation_data.boxed())
|
||||
.or(get_validator_aggregate_attestation.boxed())
|
||||
.or(get_validator_sync_committee_contribution.boxed())
|
||||
@@ -2791,6 +2965,7 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
.or(warp::post().and(
|
||||
post_beacon_blocks
|
||||
.boxed()
|
||||
.or(post_beacon_blinded_blocks.boxed())
|
||||
.or(post_beacon_pool_attestations.boxed())
|
||||
.or(post_beacon_pool_attester_slashings.boxed())
|
||||
.or(post_beacon_pool_proposer_slashings.boxed())
|
||||
|
||||
Reference in New Issue
Block a user