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:
realbigsean
2022-03-31 07:52:23 +00:00
parent 83234ee4ce
commit ea783360d3
48 changed files with 1628 additions and 644 deletions

View File

@@ -80,6 +80,7 @@ use std::cmp::Ordering;
use std::collections::HashMap;
use std::collections::HashSet;
use std::io::prelude::*;
use std::marker::PhantomData;
use std::sync::Arc;
use std::time::{Duration, Instant};
use store::iter::{BlockRootsIterator, ParentRootBlockIterator, StateRootsIterator};
@@ -370,7 +371,7 @@ pub struct BeaconChain<T: BeaconChainTypes> {
pub validator_monitor: RwLock<ValidatorMonitor<T::EthSpec>>,
}
type BeaconBlockAndState<T> = (BeaconBlock<T>, BeaconState<T>);
type BeaconBlockAndState<T, Payload> = (BeaconBlock<T, Payload>, BeaconState<T>);
impl<T: BeaconChainTypes> BeaconChain<T> {
/// Persists the head tracker and fork choice.
@@ -1151,7 +1152,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.body()
.execution_payload()
.ok()
.map(|ep| ep.block_hash),
.map(|ep| ep.block_hash()),
random,
})
})
@@ -2892,12 +2893,12 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
///
/// The produced block will not be inherently valid, it must be signed by a block producer.
/// Block signing is out of the scope of this function and should be done by a separate program.
pub fn produce_block(
pub fn produce_block<Payload: ExecPayload<T::EthSpec>>(
&self,
randao_reveal: Signature,
slot: Slot,
validator_graffiti: Option<Graffiti>,
) -> Result<BeaconBlockAndState<T::EthSpec>, BlockProductionError> {
) -> Result<BeaconBlockAndState<T::EthSpec, Payload>, BlockProductionError> {
self.produce_block_with_verification(
randao_reveal,
slot,
@@ -2907,13 +2908,13 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
}
/// Same as `produce_block` but allowing for configuration of RANDAO-verification.
pub fn produce_block_with_verification(
pub fn produce_block_with_verification<Payload: ExecPayload<T::EthSpec>>(
&self,
randao_reveal: Signature,
slot: Slot,
validator_graffiti: Option<Graffiti>,
verification: ProduceBlockVerification,
) -> Result<BeaconBlockAndState<T::EthSpec>, BlockProductionError> {
) -> Result<BeaconBlockAndState<T::EthSpec, Payload>, BlockProductionError> {
metrics::inc_counter(&metrics::BLOCK_PRODUCTION_REQUESTS);
let _complete_timer = metrics::start_timer(&metrics::BLOCK_PRODUCTION_TIMES);
@@ -2964,7 +2965,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
};
drop(state_load_timer);
self.produce_block_on_state(
self.produce_block_on_state::<Payload>(
state,
state_root_opt,
slot,
@@ -2986,7 +2987,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
/// The provided `state_root_opt` should only ever be set to `Some` if the contained value is
/// equal to the root of `state`. Providing this value will serve as an optimization to avoid
/// performing a tree hash in some scenarios.
pub fn produce_block_on_state(
pub fn produce_block_on_state<Payload: ExecPayload<T::EthSpec>>(
&self,
mut state: BeaconState<T::EthSpec>,
state_root_opt: Option<Hash256>,
@@ -2994,7 +2995,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
randao_reveal: Signature,
validator_graffiti: Option<Graffiti>,
verification: ProduceBlockVerification,
) -> Result<BeaconBlockAndState<T::EthSpec>, BlockProductionError> {
) -> Result<BeaconBlockAndState<T::EthSpec, Payload>, BlockProductionError> {
let eth1_chain = self
.eth1_chain
.as_ref()
@@ -3118,6 +3119,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
attestations,
deposits,
voluntary_exits: voluntary_exits.into(),
_phantom: PhantomData,
},
}),
BeaconState::Altair(_) => {
@@ -3137,12 +3139,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
deposits,
voluntary_exits: voluntary_exits.into(),
sync_aggregate,
_phantom: PhantomData,
},
})
}
BeaconState::Merge(_) => {
let sync_aggregate = get_sync_aggregate()?;
let execution_payload = get_execution_payload(self, &state, proposer_index)?;
let execution_payload =
get_execution_payload::<T, Payload>(self, &state, proposer_index)?;
BeaconBlock::Merge(BeaconBlockMerge {
slot,
proposer_index,

View File

@@ -75,6 +75,7 @@ use std::io::Write;
use std::time::Duration;
use store::{Error as DBError, HotColdDB, HotStateSummary, KeyValueStore, StoreOp};
use tree_hash::TreeHash;
use types::ExecPayload;
use types::{
BeaconBlockRef, BeaconState, BeaconStateError, ChainSpec, CloneConfig, Epoch, EthSpec,
ExecutionBlockHash, Hash256, InconsistentFork, PublicKey, PublicKeyBytes, RelativeEpoch,
@@ -1295,9 +1296,9 @@ impl<'a, T: BeaconChainTypes> FullyVerifiedBlock<'a, T> {
if valid_merge_transition_block {
info!(chain.log, "{}", POS_PANDA_BANNER);
info!(chain.log, "Proof of Stake Activated"; "slot" => block.slot());
info!(chain.log, ""; "Terminal POW Block Hash" => ?block.message().execution_payload()?.parent_hash.into_root());
info!(chain.log, ""; "Terminal POW Block Hash" => ?block.message().execution_payload()?.parent_hash().into_root());
info!(chain.log, ""; "Merge Transition Block Root" => ?block.message().tree_hash_root());
info!(chain.log, ""; "Merge Transition Execution Hash" => ?block.message().execution_payload()?.block_hash.into_root());
info!(chain.log, ""; "Merge Transition Execution Hash" => ?block.message().execution_payload()?.block_hash().into_root());
}
Ok(Self {

View File

@@ -53,8 +53,9 @@ pub fn notify_new_payload<T: BeaconChainTypes>(
.execution_layer
.as_ref()
.ok_or(ExecutionPayloadError::NoExecutionConnection)?;
let new_payload_response = execution_layer
.block_on(|execution_layer| execution_layer.notify_new_payload(execution_payload));
let new_payload_response = execution_layer.block_on(|execution_layer| {
execution_layer.notify_new_payload(&execution_payload.execution_payload)
});
match new_payload_response {
Ok(status) => match status {
@@ -118,10 +119,10 @@ pub fn validate_merge_block<T: BeaconChainTypes>(
.into());
}
if execution_payload.parent_hash != spec.terminal_block_hash {
if execution_payload.parent_hash() != spec.terminal_block_hash {
return Err(ExecutionPayloadError::InvalidTerminalBlockHash {
terminal_block_hash: spec.terminal_block_hash,
payload_parent_hash: execution_payload.parent_hash,
payload_parent_hash: execution_payload.parent_hash(),
}
.into());
}
@@ -136,14 +137,14 @@ pub fn validate_merge_block<T: BeaconChainTypes>(
let is_valid_terminal_pow_block = execution_layer
.block_on(|execution_layer| {
execution_layer.is_valid_terminal_pow_block_hash(execution_payload.parent_hash, spec)
execution_layer.is_valid_terminal_pow_block_hash(execution_payload.parent_hash(), spec)
})
.map_err(ExecutionPayloadError::from)?;
match is_valid_terminal_pow_block {
Some(true) => Ok(()),
Some(false) => Err(ExecutionPayloadError::InvalidTerminalPoWBlock {
parent_hash: execution_payload.parent_hash,
parent_hash: execution_payload.parent_hash(),
}
.into()),
None => {
@@ -167,7 +168,7 @@ pub fn validate_merge_block<T: BeaconChainTypes>(
debug!(
chain.log,
"Optimistically accepting terminal block";
"block_hash" => ?execution_payload.parent_hash,
"block_hash" => ?execution_payload.parent_hash(),
"msg" => "the terminal block/parent was unavailable"
);
Ok(())
@@ -215,11 +216,11 @@ pub fn validate_execution_payload_for_gossip<T: BeaconChainTypes>(
))?;
// The block's execution payload timestamp is correct with respect to the slot
if execution_payload.timestamp != expected_timestamp {
if execution_payload.timestamp() != expected_timestamp {
return Err(BlockError::ExecutionPayloadError(
ExecutionPayloadError::InvalidPayloadTimestamp {
expected: expected_timestamp,
found: execution_payload.timestamp,
found: execution_payload.timestamp(),
},
));
}
@@ -241,20 +242,23 @@ pub fn validate_execution_payload_for_gossip<T: BeaconChainTypes>(
/// Equivalent to the `get_execution_payload` function in the Validator Guide:
///
/// https://github.com/ethereum/consensus-specs/blob/v1.1.5/specs/merge/validator.md#block-proposal
pub fn get_execution_payload<T: BeaconChainTypes>(
pub fn get_execution_payload<T: BeaconChainTypes, Payload: ExecPayload<T::EthSpec>>(
chain: &BeaconChain<T>,
state: &BeaconState<T::EthSpec>,
proposer_index: u64,
) -> Result<ExecutionPayload<T::EthSpec>, BlockProductionError> {
Ok(prepare_execution_payload_blocking(chain, state, proposer_index)?.unwrap_or_default())
) -> Result<Payload, BlockProductionError> {
Ok(
prepare_execution_payload_blocking::<T, Payload>(chain, state, proposer_index)?
.unwrap_or_default(),
)
}
/// Wraps the async `prepare_execution_payload` function as a blocking task.
pub fn prepare_execution_payload_blocking<T: BeaconChainTypes>(
pub fn prepare_execution_payload_blocking<T: BeaconChainTypes, Payload: ExecPayload<T::EthSpec>>(
chain: &BeaconChain<T>,
state: &BeaconState<T::EthSpec>,
proposer_index: u64,
) -> Result<Option<ExecutionPayload<T::EthSpec>>, BlockProductionError> {
) -> Result<Option<Payload>, BlockProductionError> {
let execution_layer = chain
.execution_layer
.as_ref()
@@ -262,7 +266,7 @@ pub fn prepare_execution_payload_blocking<T: BeaconChainTypes>(
execution_layer
.block_on_generic(|_| async {
prepare_execution_payload(chain, state, proposer_index).await
prepare_execution_payload::<T, Payload>(chain, state, proposer_index).await
})
.map_err(BlockProductionError::BlockingFailed)?
}
@@ -281,11 +285,11 @@ pub fn prepare_execution_payload_blocking<T: BeaconChainTypes>(
/// Equivalent to the `prepare_execution_payload` function in the Validator Guide:
///
/// https://github.com/ethereum/consensus-specs/blob/v1.1.5/specs/merge/validator.md#block-proposal
pub async fn prepare_execution_payload<T: BeaconChainTypes>(
pub async fn prepare_execution_payload<T: BeaconChainTypes, Payload: ExecPayload<T::EthSpec>>(
chain: &BeaconChain<T>,
state: &BeaconState<T::EthSpec>,
proposer_index: u64,
) -> Result<Option<ExecutionPayload<T::EthSpec>>, BlockProductionError> {
) -> Result<Option<Payload>, BlockProductionError> {
let spec = &chain.spec;
let execution_layer = chain
.execution_layer
@@ -335,12 +339,12 @@ pub async fn prepare_execution_payload<T: BeaconChainTypes>(
.body()
.execution_payload()
.ok()
.map(|ep| ep.block_hash)
.map(|ep| ep.block_hash())
};
// Note: the suggested_fee_recipient is stored in the `execution_layer`, it will add this parameter.
let execution_payload = execution_layer
.get_payload(
.get_payload::<T::EthSpec, Payload>(
parent_hash,
timestamp,
random,