Skip to content

Commit

Permalink
Kiln mev boost (sigp#3062)
Browse files Browse the repository at this point in the history
## Issue Addressed

MEV boost compatibility

## Proposed Changes

See sigp#2987

## Additional Info

This is blocked on the stabilization of a couple specs, [here](ethereum/beacon-APIs#194) and [here](flashbots/mev-boost#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 <[email protected]>
Co-authored-by: realbigsean <[email protected]>
  • Loading branch information
3 people authored and paulhauner committed Apr 4, 2022
1 parent 06f7bc8 commit 4cb763e
Show file tree
Hide file tree
Showing 48 changed files with 1,630 additions and 646 deletions.
222 changes: 104 additions & 118 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ members = [
fixed-hash = { git = "https://github.com/paritytech/parity-common", rev="df638ab0885293d21d656dc300d39236b69ce57d" }
warp = { git = "https://github.com/macladson/warp", rev ="7e75acc" }
eth2_ssz = { path = "consensus/ssz" }
eth2_ssz_derive = { path = "consensus/ssz_derive" }
eth2_ssz_types = { path = "consensus/ssz_types" }
tree_hash = { path = "consensus/tree_hash" }
tree_hash_derive = { path = "consensus/tree_hash_derive" }
eth2_serde_utils = { path = "consensus/serde_utils" }
2 changes: 1 addition & 1 deletion beacon_node/beacon_chain/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ strum = { version = "0.21.0", features = ["derive"] }
logging = { path = "../../common/logging" }
execution_layer = { path = "../execution_layer" }
sensitive_url = { path = "../../common/sensitive_url" }
superstruct = "0.4.0"
superstruct = "0.4.1"

[[test]]
name = "beacon_chain_tests"
Expand Down
24 changes: 14 additions & 10 deletions beacon_node/beacon_chain/src/beacon_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -1151,7 +1152,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.body()
.execution_payload()
.ok()
.map(|ep| ep.block_hash),
.map(|ep| ep.block_hash()),
random,
})
})
Expand Down Expand Up @@ -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,
Expand All @@ -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);

Expand Down Expand Up @@ -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,
Expand All @@ -2986,15 +2987,15 @@ 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>,
produce_at_slot: Slot,
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()
Expand Down Expand Up @@ -3118,6 +3119,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
attestations,
deposits,
voluntary_exits: voluntary_exits.into(),
_phantom: PhantomData,
},
}),
BeaconState::Altair(_) => {
Expand All @@ -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,
Expand Down
5 changes: 3 additions & 2 deletions beacon_node/beacon_chain/src/block_verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down
42 changes: 23 additions & 19 deletions beacon_node/beacon_chain/src/execution_payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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());
}
Expand All @@ -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 => {
Expand All @@ -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(())
Expand Down Expand Up @@ -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(),
},
));
}
Expand All @@ -241,28 +242,31 @@ 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()
.ok_or(BlockProductionError::ExecutionLayerMissing)?;

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)?
}
Expand All @@ -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
Expand Down Expand Up @@ -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,
Expand Down
3 changes: 3 additions & 0 deletions beacon_node/beacon_chain/tests/block_verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use state_processing::{
per_block_processing::{per_block_processing, BlockSignatureStrategy},
per_slot_processing, BlockProcessingError, VerifyBlockRoot,
};
use std::marker::PhantomData;
use std::sync::Arc;
use tempfile::tempdir;
use types::{test_utils::generate_deterministic_keypair, *};
Expand Down Expand Up @@ -962,6 +963,7 @@ fn add_base_block_to_altair_chain() {
attestations: altair_body.attestations.clone(),
deposits: altair_body.deposits.clone(),
voluntary_exits: altair_body.voluntary_exits.clone(),
_phantom: PhantomData,
},
},
signature: Signature::empty(),
Expand Down Expand Up @@ -1082,6 +1084,7 @@ fn add_altair_block_to_base_chain() {
deposits: base_body.deposits.clone(),
voluntary_exits: base_body.voluntary_exits.clone(),
sync_aggregate: SyncAggregate::empty(),
_phantom: PhantomData,
},
},
signature: Signature::empty(),
Expand Down
25 changes: 14 additions & 11 deletions beacon_node/beacon_chain/tests/merge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,20 @@ const VALIDATOR_COUNT: usize = 32;

type E = MainnetEthSpec;

fn verify_execution_payload_chain<T: EthSpec>(chain: &[ExecutionPayload<T>]) {
let mut prev_ep: Option<ExecutionPayload<T>> = None;
fn verify_execution_payload_chain<T: EthSpec>(chain: &[FullPayload<T>]) {
let mut prev_ep: Option<FullPayload<T>> = None;

for ep in chain {
assert!(*ep != ExecutionPayload::default());
assert!(ep.block_hash != ExecutionBlockHash::zero());
assert!(*ep != FullPayload::default());
assert!(ep.block_hash() != ExecutionBlockHash::zero());

// Check against previous `ExecutionPayload`.
if let Some(prev_ep) = prev_ep {
assert_eq!(prev_ep.block_hash, ep.parent_hash);
assert_eq!(prev_ep.block_number + 1, ep.block_number);
assert_eq!(prev_ep.block_hash(), ep.execution_payload.parent_hash);
assert_eq!(
prev_ep.execution_payload.block_number + 1,
ep.execution_payload.block_number
);
}
prev_ep = Some(ep.clone());
}
Expand Down Expand Up @@ -83,12 +86,12 @@ fn merge_with_terminal_block_hash_override() {

let execution_payload = block.message().body().execution_payload().unwrap().clone();
if i == 0 {
assert_eq!(execution_payload.block_hash, genesis_pow_block_hash);
assert_eq!(execution_payload.block_hash(), genesis_pow_block_hash);
}
execution_payloads.push(execution_payload);
}

verify_execution_payload_chain(&execution_payloads);
verify_execution_payload_chain(execution_payloads.as_slice());
}

#[test]
Expand Down Expand Up @@ -138,7 +141,7 @@ fn base_altair_merge_with_terminal_block_after_fork() {
assert_eq!(merge_head.slot(), merge_fork_slot);
assert_eq!(
*merge_head.message().body().execution_payload().unwrap(),
ExecutionPayload::default()
FullPayload::default()
);

/*
Expand All @@ -154,7 +157,7 @@ fn base_altair_merge_with_terminal_block_after_fork() {
.body()
.execution_payload()
.unwrap(),
ExecutionPayload::default()
FullPayload::default()
);
assert_eq!(one_after_merge_head.slot(), merge_fork_slot + 1);

Expand All @@ -178,5 +181,5 @@ fn base_altair_merge_with_terminal_block_after_fork() {
execution_payloads.push(block.message().body().execution_payload().unwrap().clone());
}

verify_execution_payload_chain(&execution_payloads);
verify_execution_payload_chain(execution_payloads.as_slice());
}
2 changes: 1 addition & 1 deletion beacon_node/beacon_chain/tests/payload_invalidation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ impl InvalidPayloadRig {
.body()
.execution_payload()
.unwrap()
.block_hash
.block_hash()
}

fn execution_status(&self, block_root: Hash256) -> ExecutionStatus {
Expand Down
Loading

0 comments on commit 4cb763e

Please sign in to comment.