Block v3 builder boost factor (#5035)

* builder boost factor

* default boost factor

* revert

* deprecate always_prefer_builder_payload, builder-profit-threshold, ignore_builder_override_suggestion_threshold and builder_comparison_factor flags

* revert

* set deprecated flags to no op, revert should_override_builder

* fix test, calc boosted relay value correctly, dont calculate if none

* Add deprecation warnings and restore CLI docs
This commit is contained in:
Eitan Seri-Levi
2024-01-08 11:10:32 +11:00
committed by GitHub
parent 0c97762032
commit 9c1505d082
20 changed files with 201 additions and 437 deletions
@@ -4021,6 +4021,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
slot: Slot,
validator_graffiti: Option<Graffiti>,
verification: ProduceBlockVerification,
builder_boost_factor: Option<u64>,
block_production_version: BlockProductionVersion,
) -> Result<BeaconBlockResponseWrapper<T::EthSpec>, BlockProductionError> {
metrics::inc_counter(&metrics::BLOCK_PRODUCTION_REQUESTS);
@@ -4049,6 +4050,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
randao_reveal,
validator_graffiti,
verification,
builder_boost_factor,
block_production_version,
)
.await
@@ -4652,6 +4654,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
randao_reveal: Signature,
validator_graffiti: Option<Graffiti>,
verification: ProduceBlockVerification,
builder_boost_factor: Option<u64>,
block_production_version: BlockProductionVersion,
) -> Result<BeaconBlockResponseWrapper<T::EthSpec>, BlockProductionError> {
// Part 1/3 (blocking)
@@ -4668,6 +4671,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
produce_at_slot,
randao_reveal,
validator_graffiti,
builder_boost_factor,
block_production_version,
)
},
@@ -4757,6 +4761,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
}
}
#[allow(clippy::too_many_arguments)]
fn produce_partial_beacon_block(
self: &Arc<Self>,
mut state: BeaconState<T::EthSpec>,
@@ -4764,6 +4769,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
produce_at_slot: Slot,
randao_reveal: Signature,
validator_graffiti: Option<Graffiti>,
builder_boost_factor: Option<u64>,
block_production_version: BlockProductionVersion,
) -> Result<PartialBeaconBlock<T::EthSpec>, BlockProductionError> {
let eth1_chain = self
@@ -4825,6 +4831,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
parent_root,
proposer_index,
builder_params,
builder_boost_factor,
block_production_version,
)?;
Some(prepare_payload_handle)
@@ -405,6 +405,7 @@ pub fn get_execution_payload<T: BeaconChainTypes>(
parent_block_root: Hash256,
proposer_index: u64,
builder_params: BuilderParams,
builder_boost_factor: Option<u64>,
block_production_version: BlockProductionVersion,
) -> Result<PreparePayloadHandle<T::EthSpec>, BlockProductionError> {
// Compute all required values from the `state` now to avoid needing to pass it into a spawned
@@ -449,6 +450,7 @@ pub fn get_execution_payload<T: BeaconChainTypes>(
builder_params,
withdrawals,
parent_beacon_block_root,
builder_boost_factor,
block_production_version,
)
.await
@@ -485,6 +487,7 @@ pub async fn prepare_execution_payload<T>(
builder_params: BuilderParams,
withdrawals: Option<Vec<Withdrawal>>,
parent_beacon_block_root: Option<Hash256>,
builder_boost_factor: Option<u64>,
block_production_version: BlockProductionVersion,
) -> Result<BlockProposalContentsType<T::EthSpec>, BlockProductionError>
where
@@ -575,6 +578,7 @@ where
builder_params,
fork,
&chain.spec,
builder_boost_factor,
block_production_version,
)
.await
+4 -5
View File
@@ -464,14 +464,13 @@ where
}
pub fn mock_execution_layer(self) -> Self {
self.mock_execution_layer_with_config(None)
self.mock_execution_layer_with_config()
}
pub fn mock_execution_layer_with_config(mut self, builder_threshold: Option<u128>) -> Self {
pub fn mock_execution_layer_with_config(mut self) -> Self {
let mock = mock_execution_layer_from_parts::<E>(
self.spec.as_ref().expect("cannot build without spec"),
self.runtime.task_executor.clone(),
builder_threshold,
);
self.execution_layer = Some(mock.el.clone());
self.mock_execution_layer = Some(mock);
@@ -574,7 +573,6 @@ where
pub fn mock_execution_layer_from_parts<T: EthSpec>(
spec: &ChainSpec,
task_executor: TaskExecutor,
builder_threshold: Option<u128>,
) -> MockExecutionLayer<T> {
let shanghai_time = spec.capella_fork_epoch.map(|epoch| {
HARNESS_GENESIS_TIME + spec.seconds_per_slot * T::slots_per_epoch() * epoch.as_u64()
@@ -593,7 +591,6 @@ pub fn mock_execution_layer_from_parts<T: EthSpec>(
DEFAULT_TERMINAL_BLOCK,
shanghai_time,
cancun_time,
builder_threshold,
Some(JwtKey::from_slice(&DEFAULT_JWT_SECRET).unwrap()),
spec.clone(),
Some(kzg),
@@ -860,6 +857,7 @@ where
randao_reveal,
Some(graffiti),
ProduceBlockVerification::VerifyRandao,
None,
BlockProductionVersion::FullV2,
)
.await
@@ -921,6 +919,7 @@ where
randao_reveal,
Some(graffiti),
ProduceBlockVerification::VerifyRandao,
None,
BlockProductionVersion::FullV2,
)
.await
@@ -2421,7 +2421,7 @@ async fn weak_subjectivity_sync_test(slots: Vec<Slot>, checkpoint_slot: Slot) {
.unwrap();
let mock =
mock_execution_layer_from_parts(&harness.spec, harness.runtime.task_executor.clone(), None);
mock_execution_layer_from_parts(&harness.spec, harness.runtime.task_executor.clone());
// Initialise a new beacon chain from the finalized checkpoint.
// The slot clock must be set to a time ahead of the checkpoint state.
+31 -124
View File
@@ -335,10 +335,7 @@ struct Inner<E: EthSpec> {
proposers: RwLock<HashMap<ProposerKey, Proposer>>,
executor: TaskExecutor,
payload_cache: PayloadCache<E>,
builder_profit_threshold: Uint256,
log: Logger,
always_prefer_builder_payload: bool,
ignore_builder_override_suggestion_threshold: f32,
/// Track whether the last `newPayload` call errored.
///
/// This is used *only* in the informational sync status endpoint, so that a VC using this
@@ -365,11 +362,7 @@ pub struct Config {
pub jwt_version: Option<String>,
/// Default directory for the jwt secret if not provided through cli.
pub default_datadir: PathBuf,
/// The minimum value of an external payload for it to be considered in a proposal.
pub builder_profit_threshold: u128,
pub execution_timeout_multiplier: Option<u32>,
pub always_prefer_builder_payload: bool,
pub ignore_builder_override_suggestion_threshold: f32,
}
/// Provides access to one execution engine and provides a neat interface for consumption by the
@@ -379,40 +372,6 @@ pub struct ExecutionLayer<T: EthSpec> {
inner: Arc<Inner<T>>,
}
/// This function will return the percentage difference between 2 U256 values, using `base_value`
/// as the denominator. It is accurate to 7 decimal places which is about the precision of
/// an f32.
///
/// If some error is encountered in the calculation, None will be returned.
fn percentage_difference_u256(base_value: Uint256, comparison_value: Uint256) -> Option<f32> {
if base_value == Uint256::zero() {
return None;
}
// this is the total supply of ETH in WEI
let max_value = Uint256::from(12u8) * Uint256::exp10(25);
if base_value > max_value || comparison_value > max_value {
return None;
}
// Now we should be able to calculate the difference without division by zero or overflow
const PRECISION: usize = 7;
let precision_factor = Uint256::exp10(PRECISION);
let scaled_difference = if base_value <= comparison_value {
(comparison_value - base_value) * precision_factor
} else {
(base_value - comparison_value) * precision_factor
};
let scaled_proportion = scaled_difference / base_value;
// max value of scaled difference is 1.2 * 10^33, well below the max value of a u128 / f64 / f32
let percentage =
100.0f64 * scaled_proportion.low_u128() as f64 / precision_factor.low_u128() as f64;
if base_value <= comparison_value {
Some(percentage as f32)
} else {
Some(-percentage as f32)
}
}
impl<T: EthSpec> ExecutionLayer<T> {
/// Instantiate `Self` with an Execution engine specified in `Config`, using JSON-RPC via HTTP.
pub fn from_config(config: Config, executor: TaskExecutor, log: Logger) -> Result<Self, Error> {
@@ -425,10 +384,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
jwt_id,
jwt_version,
default_datadir,
builder_profit_threshold,
execution_timeout_multiplier,
always_prefer_builder_payload,
ignore_builder_override_suggestion_threshold,
} = config;
if urls.len() > 1 {
@@ -489,10 +445,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
execution_blocks: Mutex::new(LruCache::new(EXECUTION_BLOCKS_LRU_CACHE_SIZE)),
executor,
payload_cache: PayloadCache::default(),
builder_profit_threshold: Uint256::from(builder_profit_threshold),
log,
always_prefer_builder_payload,
ignore_builder_override_suggestion_threshold,
last_new_payload_errored: RwLock::new(false),
};
@@ -530,7 +483,6 @@ impl<T: EthSpec> ExecutionLayer<T> {
self.log(),
"Using external block builder";
"builder_url" => ?builder_url,
"builder_profit_threshold" => self.inner.builder_profit_threshold.as_u128(),
"local_user_agent" => builder_client.get_user_agent(),
);
self.inner.builder.swap(Some(Arc::new(builder_client)));
@@ -836,6 +788,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
builder_params: BuilderParams,
current_fork: ForkName,
spec: &ChainSpec,
builder_boost_factor: Option<u64>,
block_production_version: BlockProductionVersion,
) -> Result<BlockProposalContentsType<T>, Error> {
let payload_result_type = match block_production_version {
@@ -846,6 +799,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
forkchoice_update_params,
builder_params,
current_fork,
builder_boost_factor,
spec,
)
.await
@@ -870,6 +824,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
forkchoice_update_params,
builder_params,
current_fork,
None,
spec,
)
.await?
@@ -990,6 +945,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
(relay_result, local_result)
}
#[allow(clippy::too_many_arguments)]
async fn determine_and_fetch_payload(
&self,
parent_hash: ExecutionBlockHash,
@@ -997,6 +953,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
forkchoice_update_params: ForkchoiceUpdateParameters,
builder_params: BuilderParams,
current_fork: ForkName,
builder_boost_factor: Option<u64>,
spec: &ChainSpec,
) -> Result<ProvenancedPayload<BlockProposalContentsType<T>>, Error> {
let Some(builder) = self.builder() else {
@@ -1148,18 +1105,36 @@ impl<T: EthSpec> ExecutionLayer<T> {
)));
}
if self.inner.always_prefer_builder_payload {
return ProvenancedPayload::try_from(relay.data.message);
}
let relay_value = *relay.data.message.value();
let boosted_relay_value = match builder_boost_factor {
Some(builder_boost_factor) => {
(relay_value / 100).saturating_mul(builder_boost_factor.into())
}
None => relay_value,
};
let local_value = *local.block_value();
if local_value >= relay_value {
if local_value >= boosted_relay_value {
info!(
self.log(),
"Local block is more profitable than relay block";
"local_block_value" => %local_value,
"relay_value" => %relay_value,
"boosted_relay_value" => %boosted_relay_value,
"builder_boost_factor" => ?builder_boost_factor,
);
return Ok(ProvenancedPayload::Local(BlockProposalContentsType::Full(
local.try_into()?,
)));
}
if local.should_override_builder().unwrap_or(false) {
info!(
self.log(),
"Using local payload because execution engine suggested we ignore builder payload";
"local_block_value" => %local_value,
"relay_value" => %relay_value
);
return Ok(ProvenancedPayload::Local(BlockProposalContentsType::Full(
@@ -1167,43 +1142,13 @@ impl<T: EthSpec> ExecutionLayer<T> {
)));
}
if relay_value < self.inner.builder_profit_threshold {
info!(
self.log(),
"Builder payload ignored";
"info" => "using local payload",
"reason" => format!("payload value of {} does not meet user-configured profit-threshold of {}", relay_value, self.inner.builder_profit_threshold),
"relay_block_hash" => ?header.block_hash(),
"parent_hash" => ?parent_hash,
);
return Ok(ProvenancedPayload::Local(BlockProposalContentsType::Full(
local.try_into()?,
)));
}
if local.should_override_builder().unwrap_or(false) {
let percentage_difference =
percentage_difference_u256(local_value, relay_value);
if percentage_difference.map_or(false, |percentage| {
percentage < self.inner.ignore_builder_override_suggestion_threshold
}) {
info!(
self.log(),
"Using local payload because execution engine suggested we ignore builder payload";
"local_block_value" => %local_value,
"relay_value" => %relay_value
);
return Ok(ProvenancedPayload::Local(BlockProposalContentsType::Full(
local.try_into()?,
)));
}
}
info!(
self.log(),
"Relay block is more profitable than local block";
"local_block_value" => %local_value,
"relay_value" => %relay_value
"relay_value" => %relay_value,
"boosted_relay_value" => %boosted_relay_value,
"builder_boost_factor" => ?builder_boost_factor
);
Ok(ProvenancedPayload::try_from(relay.data.message)?)
@@ -2374,42 +2319,4 @@ mod test {
})
.await;
}
#[tokio::test]
async fn percentage_difference_u256_tests() {
// ensure function returns `None` when base value is zero
assert_eq!(percentage_difference_u256(0.into(), 1.into()), None);
// ensure function returns `None` when either value is greater than 120 Million ETH
let max_value = Uint256::from(12u8) * Uint256::exp10(25);
assert_eq!(
percentage_difference_u256(1u8.into(), max_value + Uint256::from(1u8)),
None
);
assert_eq!(
percentage_difference_u256(max_value + Uint256::from(1u8), 1u8.into()),
None
);
// it should work up to max value
assert_eq!(
percentage_difference_u256(max_value, max_value / Uint256::from(2u8)),
Some(-50f32)
);
// should work when base value is greater than comparison value
assert_eq!(
percentage_difference_u256(4u8.into(), 3u8.into()),
Some(-25f32)
);
// should work when comparison value is greater than base value
assert_eq!(
percentage_difference_u256(4u8.into(), 5u8.into()),
Some(25f32)
);
// should be accurate to 7 decimal places
let result =
percentage_difference_u256(Uint256::from(31415926u64), Uint256::from(13371337u64))
.expect("should get percentage");
// result = -57.4377116
assert!(result > -57.43772);
assert!(result <= -57.43771);
}
}
@@ -1,7 +1,6 @@
use crate::{
test_utils::{
MockServer, DEFAULT_BUILDER_THRESHOLD_WEI, DEFAULT_JWT_SECRET, DEFAULT_TERMINAL_BLOCK,
DEFAULT_TERMINAL_DIFFICULTY,
MockServer, DEFAULT_JWT_SECRET, DEFAULT_TERMINAL_BLOCK, DEFAULT_TERMINAL_DIFFICULTY,
},
Config, *,
};
@@ -30,7 +29,6 @@ impl<T: EthSpec> MockExecutionLayer<T> {
DEFAULT_TERMINAL_BLOCK,
None,
None,
None,
Some(JwtKey::from_slice(&DEFAULT_JWT_SECRET).unwrap()),
spec,
None,
@@ -43,7 +41,6 @@ impl<T: EthSpec> MockExecutionLayer<T> {
terminal_block: u64,
shanghai_time: Option<u64>,
cancun_time: Option<u64>,
builder_threshold: Option<u128>,
jwt_key: Option<JwtKey>,
spec: ChainSpec,
kzg: Option<Kzg>,
@@ -72,7 +69,6 @@ impl<T: EthSpec> MockExecutionLayer<T> {
execution_endpoints: vec![url],
secret_files: vec![path],
suggested_fee_recipient: Some(Address::repeat_byte(42)),
builder_profit_threshold: builder_threshold.unwrap_or(DEFAULT_BUILDER_THRESHOLD_WEI),
..Default::default()
};
let el =
@@ -143,6 +139,7 @@ impl<T: EthSpec> MockExecutionLayer<T> {
builder_params,
ForkName::Merge,
&self.spec,
None,
BlockProductionVersion::FullV2,
)
.await
@@ -182,6 +179,7 @@ impl<T: EthSpec> MockExecutionLayer<T> {
builder_params,
ForkName::Merge,
&self.spec,
None,
BlockProductionVersion::BlindedV2,
)
.await
@@ -35,7 +35,6 @@ pub use mock_execution_layer::MockExecutionLayer;
pub const DEFAULT_TERMINAL_DIFFICULTY: u64 = 6400;
pub const DEFAULT_TERMINAL_BLOCK: u64 = 64;
pub const DEFAULT_JWT_SECRET: [u8; 32] = [42; 32];
pub const DEFAULT_BUILDER_THRESHOLD_WEI: u128 = 1_000_000_000_000_000_000;
pub const DEFAULT_MOCK_EL_PAYLOAD_VALUE_WEI: u128 = 10_000_000_000_000_000;
pub const DEFAULT_BUILDER_PAYLOAD_VALUE_WEI: u128 = 20_000_000_000_000_000;
pub const DEFAULT_ENGINE_CAPABILITIES: EngineCapabilities = EngineCapabilities {
@@ -60,6 +60,7 @@ pub async fn produce_block_v3<T: BeaconChainTypes>(
slot,
query.graffiti.map(Into::into),
randao_verification,
query.builder_boost_factor,
BlockProductionVersion::V3,
)
.await
@@ -140,6 +141,7 @@ pub async fn produce_blinded_block_v2<T: BeaconChainTypes>(
slot,
query.graffiti.map(Into::into),
randao_verification,
None,
BlockProductionVersion::BlindedV2,
)
.await
@@ -170,6 +172,7 @@ pub async fn produce_block_v2<T: BeaconChainTypes>(
slot,
query.graffiti.map(Into::into),
randao_verification,
None,
BlockProductionVersion::FullV2,
)
.await
@@ -620,7 +620,7 @@ pub async fn proposer_boost_re_org_test(
.into();
let (unsigned_block_type, _) = tester
.client
.get_validator_blocks_v3::<E>(slot_c, &randao_reveal, None)
.get_validator_blocks_v3::<E>(slot_c, &randao_reveal, None, None)
.await
.unwrap();
+94 -118
View File
@@ -13,8 +13,7 @@ use eth2::{
BeaconNodeHttpClient, Error, StatusCode, Timeouts,
};
use execution_layer::test_utils::{
MockBuilder, Operation, DEFAULT_BUILDER_PAYLOAD_VALUE_WEI, DEFAULT_BUILDER_THRESHOLD_WEI,
DEFAULT_MOCK_EL_PAYLOAD_VALUE_WEI,
MockBuilder, Operation, DEFAULT_BUILDER_PAYLOAD_VALUE_WEI, DEFAULT_MOCK_EL_PAYLOAD_VALUE_WEI,
};
use futures::stream::{Stream, StreamExt};
use futures::FutureExt;
@@ -80,7 +79,6 @@ struct ApiTester {
struct ApiTesterConfig {
spec: ChainSpec,
retain_historic_states: bool,
builder_threshold: Option<u128>,
}
impl Default for ApiTesterConfig {
@@ -90,7 +88,6 @@ impl Default for ApiTesterConfig {
Self {
spec,
retain_historic_states: false,
builder_threshold: None,
}
}
}
@@ -132,7 +129,7 @@ impl ApiTester {
.logger(logging::test_logger())
.deterministic_keypairs(VALIDATOR_COUNT)
.fresh_ephemeral_store()
.mock_execution_layer_with_config(config.builder_threshold)
.mock_execution_layer_with_config()
.build();
harness
@@ -391,19 +388,12 @@ impl ApiTester {
.test_post_validator_register_validator()
.await;
// Make sure bids always meet the minimum threshold.
tester
.mock_builder
.as_ref()
.unwrap()
.add_operation(Operation::Value(Uint256::from(
DEFAULT_BUILDER_THRESHOLD_WEI,
)));
tester.mock_builder.as_ref().unwrap();
tester
}
pub async fn new_mev_tester_no_builder_threshold() -> Self {
pub async fn new_mev_tester_default_payload_value() -> Self {
let mut config = ApiTesterConfig {
builder_threshold: Some(0),
retain_historic_states: false,
spec: E::default_spec(),
};
@@ -2730,7 +2720,7 @@ impl ApiTester {
let (response, metadata) = self
.client
.get_validator_blocks_v3_ssz::<E>(slot, &randao_reveal, None)
.get_validator_blocks_v3_ssz::<E>(slot, &randao_reveal, None, None)
.await
.unwrap();
@@ -3553,7 +3543,59 @@ impl ApiTester {
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None)
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None, None)
.await
.unwrap();
let payload: BlindedPayload<E> = match payload_type.data {
ProduceBlockV3Response::Blinded(payload) => {
payload.body().execution_payload().unwrap().into()
}
ProduceBlockV3Response::Full(_) => panic!("Expecting a blinded payload"),
};
let expected_fee_recipient = Address::from_low_u64_be(proposer_index as u64);
assert_eq!(payload.fee_recipient(), expected_fee_recipient);
assert_eq!(payload.gas_limit(), 11_111_111);
self
}
pub async fn test_payload_v3_zero_builder_boost_factor(self) -> Self {
let slot = self.chain.slot().unwrap();
let epoch = self.chain.epoch().unwrap();
let (proposer_index, randao_reveal) = self.get_test_randao(slot, epoch).await;
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None, Some(0))
.await
.unwrap();
let payload: FullPayload<E> = match payload_type.data {
ProduceBlockV3Response::Full(payload) => {
payload.block().body().execution_payload().unwrap().into()
}
ProduceBlockV3Response::Blinded(_) => panic!("Expecting a full payload"),
};
let expected_fee_recipient = Address::from_low_u64_be(proposer_index as u64);
assert_eq!(payload.fee_recipient(), expected_fee_recipient);
assert_eq!(payload.gas_limit(), 16_384);
self
}
pub async fn test_payload_v3_max_builder_boost_factor(self) -> Self {
let slot = self.chain.slot().unwrap();
let epoch = self.chain.epoch().unwrap();
let (proposer_index, randao_reveal) = self.get_test_randao(slot, epoch).await;
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None, Some(u64::MAX))
.await
.unwrap();
@@ -3657,7 +3699,7 @@ impl ApiTester {
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None)
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None, None)
.await
.unwrap();
@@ -3733,7 +3775,7 @@ impl ApiTester {
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None)
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None, None)
.await
.unwrap();
@@ -3823,7 +3865,7 @@ impl ApiTester {
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None)
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None, None)
.await
.unwrap();
@@ -3909,7 +3951,7 @@ impl ApiTester {
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None)
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None, None)
.await
.unwrap();
@@ -3995,7 +4037,7 @@ impl ApiTester {
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None)
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None, None)
.await
.unwrap();
@@ -4079,7 +4121,7 @@ impl ApiTester {
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None)
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None, None)
.await
.unwrap();
@@ -4135,7 +4177,7 @@ impl ApiTester {
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None)
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None, None)
.await
.unwrap();
@@ -4201,7 +4243,7 @@ impl ApiTester {
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None)
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None, None)
.await
.unwrap();
@@ -4309,7 +4351,7 @@ impl ApiTester {
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(next_slot, &randao_reveal, None)
.get_validator_blocks_v3::<E>(next_slot, &randao_reveal, None, None)
.await
.unwrap();
@@ -4329,7 +4371,7 @@ impl ApiTester {
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(next_slot, &randao_reveal, None)
.get_validator_blocks_v3::<E>(next_slot, &randao_reveal, None, None)
.await
.unwrap();
@@ -4457,7 +4499,7 @@ impl ApiTester {
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(next_slot, &randao_reveal, None)
.get_validator_blocks_v3::<E>(next_slot, &randao_reveal, None, None)
.await
.unwrap();
@@ -4487,7 +4529,7 @@ impl ApiTester {
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(next_slot, &randao_reveal, None)
.get_validator_blocks_v3::<E>(next_slot, &randao_reveal, None, None)
.await
.unwrap();
@@ -4567,7 +4609,7 @@ impl ApiTester {
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None)
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None, None)
.await
.unwrap();
@@ -4584,70 +4626,6 @@ impl ApiTester {
self
}
pub async fn test_payload_rejects_inadequate_builder_threshold(self) -> Self {
// Mutate value.
self.mock_builder
.as_ref()
.unwrap()
.add_operation(Operation::Value(Uint256::from(
DEFAULT_BUILDER_THRESHOLD_WEI - 1,
)));
let slot = self.chain.slot().unwrap();
let epoch = self.chain.epoch().unwrap();
let (_, randao_reveal) = self.get_test_randao(slot, epoch).await;
let payload: BlindedPayload<E> = self
.client
.get_validator_blinded_blocks::<E>(slot, &randao_reveal, None)
.await
.unwrap()
.data
.body()
.execution_payload()
.unwrap()
.into();
// If this cache is populated, it indicates fallback to the local EE was correctly used.
assert!(self
.chain
.execution_layer
.as_ref()
.unwrap()
.get_payload_by_root(&payload.tree_hash_root())
.is_some());
self
}
pub async fn test_payload_v3_rejects_inadequate_builder_threshold(self) -> Self {
// Mutate value.
self.mock_builder
.as_ref()
.unwrap()
.add_operation(Operation::Value(Uint256::from(
DEFAULT_BUILDER_THRESHOLD_WEI - 1,
)));
let slot = self.chain.slot().unwrap();
let epoch = self.chain.epoch().unwrap();
let (_, randao_reveal) = self.get_test_randao(slot, epoch).await;
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None)
.await
.unwrap();
match payload_type.data {
ProduceBlockV3Response::Full(_) => (),
ProduceBlockV3Response::Blinded(_) => panic!("Expecting a full payload"),
};
self
}
pub async fn test_builder_payload_chosen_when_more_profitable(self) -> Self {
// Mutate value.
self.mock_builder
@@ -4700,7 +4678,7 @@ impl ApiTester {
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None)
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None, None)
.await
.unwrap();
@@ -4764,7 +4742,7 @@ impl ApiTester {
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None)
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None, None)
.await
.unwrap();
@@ -4828,7 +4806,7 @@ impl ApiTester {
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None)
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None, None)
.await
.unwrap();
@@ -4890,7 +4868,7 @@ impl ApiTester {
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None)
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None, None)
.await
.unwrap();
@@ -4962,7 +4940,7 @@ impl ApiTester {
let (payload_type, _) = self
.client
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None)
.get_validator_blocks_v3::<E>(slot, &randao_reveal, None, None)
.await
.unwrap();
@@ -6048,6 +6026,22 @@ async fn post_validator_register_valid() {
.await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn post_validator_zero_builder_boost_factor() {
ApiTester::new_mev_tester()
.await
.test_payload_v3_zero_builder_boost_factor()
.await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn post_validator_max_builder_boost_factor() {
ApiTester::new_mev_tester()
.await
.test_payload_v3_max_builder_boost_factor()
.await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn post_validator_register_valid_v3() {
ApiTester::new_mev_tester()
@@ -6232,25 +6226,9 @@ async fn builder_chain_health_optimistic_head_v3() {
.await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn builder_inadequate_builder_threshold() {
ApiTester::new_mev_tester()
.await
.test_payload_rejects_inadequate_builder_threshold()
.await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn builder_inadequate_builder_threshold_v3() {
ApiTester::new_mev_tester()
.await
.test_payload_v3_rejects_inadequate_builder_threshold()
.await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn builder_payload_chosen_by_profit() {
ApiTester::new_mev_tester_no_builder_threshold()
ApiTester::new_mev_tester_default_payload_value()
.await
.test_builder_payload_chosen_when_more_profitable()
.await
@@ -6262,7 +6240,7 @@ async fn builder_payload_chosen_by_profit() {
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn builder_payload_chosen_by_profit_v3() {
ApiTester::new_mev_tester_no_builder_threshold()
ApiTester::new_mev_tester_default_payload_value()
.await
.test_builder_payload_v3_chosen_when_more_profitable()
.await
@@ -6275,7 +6253,6 @@ async fn builder_payload_chosen_by_profit_v3() {
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn builder_works_post_capella() {
let mut config = ApiTesterConfig {
builder_threshold: Some(0),
retain_historic_states: false,
spec: E::default_spec(),
};
@@ -6296,7 +6273,6 @@ async fn builder_works_post_capella() {
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn builder_works_post_deneb() {
let mut config = ApiTesterConfig {
builder_threshold: Some(0),
retain_historic_states: false,
spec: E::default_spec(),
};
+2 -32
View File
@@ -1131,32 +1131,7 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
Arg::with_name("builder-profit-threshold")
.long("builder-profit-threshold")
.value_name("WEI_VALUE")
.help("The minimum reward in wei provided to the proposer by a block builder for \
an external payload to be considered for inclusion in a proposal. If this \
threshold is not met, the local EE's payload will be used. This is currently \
*NOT* in comparison to the value of the local EE's payload. It simply checks \
whether the total proposer reward from an external payload is equal to or \
greater than this value. In the future, a comparison to a local payload is \
likely to be added. Example: Use 250000000000000000 to set the threshold to \
0.25 ETH.")
.default_value("0")
.takes_value(true)
)
.arg(
Arg::with_name("ignore-builder-override-suggestion-threshold")
.long("ignore-builder-override-suggestion-threshold")
.value_name("PERCENTAGE")
.help("When the EE advises Lighthouse to ignore the builder payload, this flag \
specifies a percentage threshold for the difference between the reward from \
the builder payload and the local EE's payload. This threshold must be met \
for Lighthouse to consider ignoring the EE's suggestion. If the reward from \
the builder's payload doesn't exceed the local payload by at least this \
percentage, the local payload will be used. The conditions under which the \
EE may make this suggestion depend on the EE's implementation, with the \
primary intent being to safeguard against potential censorship attacks \
from builders. Setting this flag to 0 will cause Lighthouse to always \
ignore the EE's suggestion. Default: 10.0 (equivalent to 10%).")
.default_value("10.0")
.help("This flag is deprecated and has no effect.")
.takes_value(true)
)
.arg(
@@ -1208,12 +1183,7 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.arg(
Arg::with_name("always-prefer-builder-payload")
.long("always-prefer-builder-payload")
.help("If set, the beacon node always uses the payload from the builder instead of the local payload.")
// The builder profit threshold flag is used to provide preference
// to local payloads, therefore it fundamentally conflicts with
// always using the builder.
.conflicts_with("builder-profit-threshold")
.conflicts_with("ignore-builder-override-suggestion-threshold")
.help("This flag is deprecated and has no effect.")
)
.arg(
Arg::with_name("invalid-gossip-verified-blocks-path")
+15 -6
View File
@@ -309,6 +309,21 @@ pub fn get_config<E: EthSpec>(
clap_utils::parse_optional(cli_args, "builder-user-agent")?;
}
if cli_args.is_present("builder-profit-threshold") {
warn!(
log,
"Ignoring --builder-profit-threshold";
"info" => "this flag is deprecated and will be removed"
);
}
if cli_args.is_present("always-prefer-builder-payload") {
warn!(
log,
"Ignoring --always-prefer-builder-payload";
"info" => "this flag is deprecated and will be removed"
);
}
// Set config values from parse values.
el_config.secret_files = vec![secret_file.clone()];
el_config.execution_endpoints = vec![execution_endpoint.clone()];
@@ -317,12 +332,6 @@ pub fn get_config<E: EthSpec>(
el_config.jwt_id = clap_utils::parse_optional(cli_args, "execution-jwt-id")?;
el_config.jwt_version = clap_utils::parse_optional(cli_args, "execution-jwt-version")?;
el_config.default_datadir = client_config.data_dir().clone();
el_config.builder_profit_threshold =
clap_utils::parse_required(cli_args, "builder-profit-threshold")?;
el_config.always_prefer_builder_payload =
cli_args.is_present("always-prefer-builder-payload");
el_config.ignore_builder_override_suggestion_threshold =
clap_utils::parse_required(cli_args, "ignore-builder-override-suggestion-threshold")?;
let execution_timeout_multiplier =
clap_utils::parse_required(cli_args, "execution-timeout-multiplier")?;
el_config.execution_timeout_multiplier = Some(execution_timeout_multiplier);