Expose additional builder booster related flags in the vc (#5086)

* expose builder booster flags in vc, enable options in validator endpoints, update tests

* resolve failing test

* fix issues related to CreateConfig and MoveConfig

* remove unneeded val, change how boost factor flag logic in the vc, add some additional documentation

* fix typos

* fix typos

* assume builder-proosals flag if one of other two vc builder flags are present

* fmt

* typo

* typo

* Fix CLI help text

* Prioritise per validator builder boost configurations over CLI flags.

* Add http test for builder boost factor with process defaults.

* Fix issue with PATCH request

* Add prefer builder proposals

* Add more builder boost factor tests.

---------

Co-authored-by: Mac L <mjladson@pm.me>
Co-authored-by: Jimmy Chen <jchen.tc@gmail.com>
Co-authored-by: Paul Hauner <paul@paulhauner.com>
This commit is contained in:
Eitan Seri-Levi
2024-01-25 00:09:47 +02:00
committed by GitHub
parent 612eaf2d41
commit f9e36c94ed
28 changed files with 715 additions and 21 deletions

View File

@@ -325,14 +325,7 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockService<T, E> {
if self.validator_store.produce_block_v3() {
for validator_pubkey in proposers {
let builder_proposals = self
.validator_store
.get_builder_proposals(&validator_pubkey);
// Translate `builder_proposals` to a boost factor. Builder proposals set to `true`
// requires no boost factor, it just means "use a builder proposal if the BN returns
// one". On the contrary, `builder_proposals: false` indicates a preference for
// local payloads, so we set the builder boost factor to 0.
let builder_boost_factor = if !builder_proposals { Some(0) } else { None };
let builder_boost_factor = self.get_builder_boost_factor(&validator_pubkey);
let service = self.clone();
let log = log.clone();
self.inner.context.executor.spawn(
@@ -853,6 +846,36 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockService<T, E> {
Ok::<_, BlockError>(unsigned_block)
}
/// Returns the builder boost factor of the given public key.
/// The priority order for fetching this value is:
///
/// 1. validator_definitions.yml
/// 2. process level flag
fn get_builder_boost_factor(&self, validator_pubkey: &PublicKeyBytes) -> Option<u64> {
// Apply per validator configuration first.
let validator_builder_boost_factor = self
.validator_store
.determine_validator_builder_boost_factor(validator_pubkey);
// Fallback to process-wide configuration if needed.
let maybe_builder_boost_factor = validator_builder_boost_factor.or_else(|| {
self.validator_store
.determine_default_builder_boost_factor()
});
if let Some(builder_boost_factor) = maybe_builder_boost_factor {
// if builder boost factor is set to 100 it should be treated
// as None to prevent unnecessary calculations that could
// lead to loss of information.
if builder_boost_factor == 100 {
return None;
}
return Some(builder_boost_factor);
}
None
}
}
pub enum UnsignedBlock<E: EthSpec> {

View File

@@ -349,4 +349,22 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.default_value("500")
.takes_value(true),
)
.arg(
Arg::with_name("builder-boost-factor")
.long("builder-boost-factor")
.value_name("UINT64")
.help("Defines the boost factor, \
a percentage multiplier to apply to the builder's payload value \
when choosing between a builder payload header and payload from \
the local execution node.")
.conflicts_with("prefer-builder-proposals")
.takes_value(true),
)
.arg(
Arg::with_name("prefer-builder-proposals")
.long("prefer-builder-proposals")
.help("If this flag is set, Lighthouse will always prefer blocks \
constructed by builders, regardless of payload value.")
.takes_value(false),
)
}

View File

@@ -77,6 +77,10 @@ pub struct Config {
pub validator_registration_batch_size: usize,
/// Enables block production via the block v3 endpoint. This configuration option can be removed post deneb.
pub produce_block_v3: bool,
/// Specifies the boost factor, a percentage multiplier to apply to the builder's payload value.
pub builder_boost_factor: Option<u64>,
/// If true, Lighthouse will prefer builder proposals, if available.
pub prefer_builder_proposals: bool,
}
impl Default for Config {
@@ -118,6 +122,8 @@ impl Default for Config {
enable_latency_measurement_service: true,
validator_registration_batch_size: 500,
produce_block_v3: false,
builder_boost_factor: None,
prefer_builder_proposals: false,
}
}
}
@@ -346,6 +352,10 @@ impl Config {
config.produce_block_v3 = true;
}
if cli_args.is_present("prefer-builder-proposals") {
config.prefer_builder_proposals = true;
}
config.gas_limit = cli_args
.value_of("gas-limit")
.map(|gas_limit| {
@@ -365,6 +375,8 @@ impl Config {
);
}
config.builder_boost_factor = parse_optional(cli_args, "builder-boost-factor")?;
config.enable_latency_measurement_service =
parse_optional(cli_args, "latency-measurement-service")?.unwrap_or(true);

View File

@@ -148,6 +148,8 @@ pub async fn create_validators_mnemonic<P: AsRef<Path>, T: 'static + SlotClock,
request.suggested_fee_recipient,
request.gas_limit,
request.builder_proposals,
request.builder_boost_factor,
request.prefer_builder_proposals,
)
.await
.map_err(|e| {

View File

@@ -224,6 +224,8 @@ fn import_single_keystore<T: SlotClock + 'static, E: EthSpec>(
None,
None,
None,
None,
None,
))
.map_err(|e| format!("failed to initialize validator: {:?}", e))?;

View File

@@ -565,6 +565,8 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
let suggested_fee_recipient = body.suggested_fee_recipient;
let gas_limit = body.gas_limit;
let builder_proposals = body.builder_proposals;
let builder_boost_factor = body.builder_boost_factor;
let prefer_builder_proposals = body.prefer_builder_proposals;
let validator_def = {
if let Some(handle) = task_executor.handle() {
@@ -577,6 +579,8 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
suggested_fee_recipient,
gas_limit,
builder_proposals,
builder_boost_factor,
prefer_builder_proposals,
))
.map_err(|e| {
warp_utils::reject::custom_server_error(format!(
@@ -625,6 +629,8 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
suggested_fee_recipient: web3signer.suggested_fee_recipient,
gas_limit: web3signer.gas_limit,
builder_proposals: web3signer.builder_proposals,
builder_boost_factor: web3signer.builder_boost_factor,
prefer_builder_proposals: web3signer.prefer_builder_proposals,
description: web3signer.description,
signing_definition: SigningDefinition::Web3Signer(
Web3SignerDefinition {
@@ -691,8 +697,12 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
(Some(is_enabled), Some(initialized_validator))
if Some(is_enabled) == body.enabled
&& initialized_validator.get_gas_limit() == body.gas_limit
&& initialized_validator.get_builder_boost_factor()
== body.builder_boost_factor
&& initialized_validator.get_builder_proposals()
== body.builder_proposals
&& initialized_validator.get_prefer_builder_proposals()
== body.prefer_builder_proposals
&& initialized_validator.get_graffiti() == maybe_graffiti =>
{
Ok(())
@@ -706,6 +716,8 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
body.enabled,
body.gas_limit,
body.builder_proposals,
body.builder_boost_factor,
body.prefer_builder_proposals,
body.graffiti,
),
)

View File

@@ -125,6 +125,8 @@ fn import_single_remotekey<T: SlotClock + 'static, E: EthSpec>(
suggested_fee_recipient: None,
gas_limit: None,
builder_proposals: None,
builder_boost_factor: None,
prefer_builder_proposals: None,
description: String::from("Added by remotekey API"),
signing_definition: SigningDefinition::Web3Signer(Web3SignerDefinition {
url,

View File

@@ -315,6 +315,8 @@ impl ApiTester {
suggested_fee_recipient: None,
gas_limit: None,
builder_proposals: None,
builder_boost_factor: None,
prefer_builder_proposals: None,
deposit_gwei: E::default_spec().max_effective_balance,
})
.collect::<Vec<_>>();
@@ -447,6 +449,8 @@ impl ApiTester {
suggested_fee_recipient: None,
gas_limit: None,
builder_proposals: None,
builder_boost_factor: None,
prefer_builder_proposals: None,
};
self.client
@@ -467,6 +471,8 @@ impl ApiTester {
suggested_fee_recipient: None,
gas_limit: None,
builder_proposals: None,
builder_boost_factor: None,
prefer_builder_proposals: None,
};
let response = self
@@ -511,6 +517,8 @@ impl ApiTester {
request_timeout_ms: None,
client_identity_path: None,
client_identity_password: None,
builder_boost_factor: None,
prefer_builder_proposals: None,
}
})
.collect();
@@ -534,7 +542,15 @@ impl ApiTester {
let validator = &self.client.get_lighthouse_validators().await.unwrap().data[index];
self.client
.patch_lighthouse_validators(&validator.voting_pubkey, Some(enabled), None, None, None)
.patch_lighthouse_validators(
&validator.voting_pubkey,
Some(enabled),
None,
None,
None,
None,
None,
)
.await
.unwrap();
@@ -582,6 +598,8 @@ impl ApiTester {
Some(gas_limit),
None,
None,
None,
None,
)
.await
.unwrap();
@@ -610,6 +628,8 @@ impl ApiTester {
None,
Some(builder_proposals),
None,
None,
None,
)
.await
.unwrap();

View File

@@ -52,6 +52,12 @@ struct ApiTester {
impl ApiTester {
pub async fn new() -> Self {
let mut config = Config::default();
config.fee_recipient = Some(TEST_DEFAULT_FEE_RECIPIENT);
Self::new_with_config(config).await
}
pub async fn new_with_config(mut config: Config) -> Self {
let log = test_logger();
let validator_dir = tempdir().unwrap();
@@ -70,10 +76,8 @@ impl ApiTester {
let api_secret = ApiSecret::create_or_open(validator_dir.path()).unwrap();
let api_pubkey = api_secret.api_token();
let mut config = Config::default();
config.validator_dir = validator_dir.path().into();
config.secrets_dir = secrets_dir.path().into();
config.fee_recipient = Some(TEST_DEFAULT_FEE_RECIPIENT);
let spec = E::default_spec();
@@ -271,6 +275,8 @@ impl ApiTester {
suggested_fee_recipient: None,
gas_limit: None,
builder_proposals: None,
builder_boost_factor: None,
prefer_builder_proposals: None,
deposit_gwei: E::default_spec().max_effective_balance,
})
.collect::<Vec<_>>();
@@ -404,6 +410,8 @@ impl ApiTester {
suggested_fee_recipient: None,
gas_limit: None,
builder_proposals: None,
builder_boost_factor: None,
prefer_builder_proposals: None,
};
self.client
@@ -424,6 +432,8 @@ impl ApiTester {
suggested_fee_recipient: None,
gas_limit: None,
builder_proposals: None,
builder_boost_factor: None,
prefer_builder_proposals: None,
};
let response = self
@@ -462,6 +472,8 @@ impl ApiTester {
suggested_fee_recipient: None,
gas_limit: None,
builder_proposals: None,
builder_boost_factor: None,
prefer_builder_proposals: None,
voting_public_key: kp.pk,
url: format!("http://signer_{}.com/", i),
root_certificate_path: None,
@@ -518,7 +530,15 @@ impl ApiTester {
let validator = &self.client.get_lighthouse_validators().await.unwrap().data[index];
self.client
.patch_lighthouse_validators(&validator.voting_pubkey, Some(enabled), None, None, None)
.patch_lighthouse_validators(
&validator.voting_pubkey,
Some(enabled),
None,
None,
None,
None,
None,
)
.await
.unwrap();
@@ -566,6 +586,8 @@ impl ApiTester {
Some(gas_limit),
None,
None,
None,
None,
)
.await
.unwrap();
@@ -594,6 +616,50 @@ impl ApiTester {
None,
Some(builder_proposals),
None,
None,
None,
)
.await
.unwrap();
self
}
pub async fn set_builder_boost_factor(self, index: usize, builder_boost_factor: u64) -> Self {
let validator = &self.client.get_lighthouse_validators().await.unwrap().data[index];
self.client
.patch_lighthouse_validators(
&validator.voting_pubkey,
None,
None,
None,
Some(builder_boost_factor),
None,
None,
)
.await
.unwrap();
self
}
pub async fn set_prefer_builder_proposals(
self,
index: usize,
prefer_builder_proposals: bool,
) -> Self {
let validator = &self.client.get_lighthouse_validators().await.unwrap().data[index];
self.client
.patch_lighthouse_validators(
&validator.voting_pubkey,
None,
None,
None,
None,
Some(prefer_builder_proposals),
None,
)
.await
.unwrap();
@@ -613,6 +679,64 @@ impl ApiTester {
self
}
pub async fn assert_builder_boost_factor(
self,
index: usize,
builder_boost_factor: Option<u64>,
) -> Self {
let validator = &self.client.get_lighthouse_validators().await.unwrap().data[index];
assert_eq!(
self.validator_store
.get_builder_boost_factor(&validator.voting_pubkey),
builder_boost_factor
);
self
}
pub async fn assert_validator_derived_builder_boost_factor(
self,
index: usize,
builder_boost_factor: Option<u64>,
) -> Self {
let validator = &self.client.get_lighthouse_validators().await.unwrap().data[index];
assert_eq!(
self.validator_store
.determine_validator_builder_boost_factor(&validator.voting_pubkey),
builder_boost_factor
);
self
}
pub fn assert_default_builder_boost_factor(self, builder_boost_factor: Option<u64>) -> Self {
assert_eq!(
self.validator_store
.determine_default_builder_boost_factor(),
builder_boost_factor
);
self
}
pub async fn assert_prefer_builder_proposals(
self,
index: usize,
prefer_builder_proposals: bool,
) -> Self {
let validator = &self.client.get_lighthouse_validators().await.unwrap().data[index];
assert_eq!(
self.validator_store
.get_prefer_builder_proposals(&validator.voting_pubkey),
prefer_builder_proposals
);
self
}
pub async fn set_graffiti(self, index: usize, graffiti: &str) -> Self {
let validator = &self.client.get_lighthouse_validators().await.unwrap().data[index];
let graffiti_str = GraffitiString::from_str(graffiti).unwrap();
@@ -622,6 +746,8 @@ impl ApiTester {
None,
None,
None,
None,
None,
Some(graffiti_str),
)
.await
@@ -741,6 +867,8 @@ async fn routes_with_invalid_auth() {
gas_limit: <_>::default(),
builder_proposals: <_>::default(),
deposit_gwei: <_>::default(),
builder_boost_factor: <_>::default(),
prefer_builder_proposals: <_>::default(),
}])
.await
})
@@ -771,6 +899,8 @@ async fn routes_with_invalid_auth() {
suggested_fee_recipient: <_>::default(),
gas_limit: <_>::default(),
builder_proposals: <_>::default(),
builder_boost_factor: <_>::default(),
prefer_builder_proposals: <_>::default(),
})
.await
})
@@ -783,6 +913,8 @@ async fn routes_with_invalid_auth() {
None,
None,
None,
None,
None,
)
.await
})
@@ -980,6 +1112,100 @@ async fn validator_builder_proposals() {
.await;
}
#[tokio::test]
async fn validator_builder_boost_factor() {
ApiTester::new()
.await
.create_hd_validators(HdValidatorScenario {
count: 2,
specify_mnemonic: false,
key_derivation_path_offset: 0,
disabled: vec![],
})
.await
.assert_enabled_validators_count(2)
.assert_validators_count(2)
.set_builder_boost_factor(0, 120)
.await
// Test setting builder proposals while the validator is disabled
.set_validator_enabled(0, false)
.await
.assert_enabled_validators_count(1)
.assert_validators_count(2)
.set_builder_boost_factor(0, 80)
.await
.set_validator_enabled(0, true)
.await
.assert_enabled_validators_count(2)
.assert_builder_boost_factor(0, Some(80))
.await;
}
/// Verifies the builder boost factors translated from the `builder_proposals`,
/// `prefer_builder_proposals` and `builder_boost_factor` values.
#[tokio::test]
async fn validator_derived_builder_boost_factor_with_process_defaults() {
let config = Config {
builder_proposals: true,
prefer_builder_proposals: false,
builder_boost_factor: Some(80),
..Config::default()
};
ApiTester::new_with_config(config)
.await
.create_hd_validators(HdValidatorScenario {
count: 3,
specify_mnemonic: false,
key_derivation_path_offset: 0,
disabled: vec![],
})
.await
.assert_default_builder_boost_factor(Some(80))
.assert_validator_derived_builder_boost_factor(0, None)
.await
.set_builder_proposals(0, false)
.await
.assert_validator_derived_builder_boost_factor(0, Some(0))
.await
.set_builder_boost_factor(1, 120)
.await
.assert_validator_derived_builder_boost_factor(1, Some(120))
.await
.set_prefer_builder_proposals(2, true)
.await
.assert_validator_derived_builder_boost_factor(2, Some(u64::MAX))
.await;
}
#[tokio::test]
async fn prefer_builder_proposals_validator() {
ApiTester::new()
.await
.create_hd_validators(HdValidatorScenario {
count: 2,
specify_mnemonic: false,
key_derivation_path_offset: 0,
disabled: vec![],
})
.await
.assert_enabled_validators_count(2)
.assert_validators_count(2)
.set_prefer_builder_proposals(0, false)
.await
// Test setting builder proposals while the validator is disabled
.set_validator_enabled(0, false)
.await
.assert_enabled_validators_count(1)
.assert_validators_count(2)
.set_prefer_builder_proposals(0, true)
.await
.set_validator_enabled(0, true)
.await
.assert_enabled_validators_count(2)
.assert_prefer_builder_proposals(0, true)
.await;
}
#[tokio::test]
async fn validator_graffiti() {
ApiTester::new()

View File

@@ -43,6 +43,8 @@ fn web3signer_validator_with_pubkey(pubkey: PublicKey) -> Web3SignerValidatorReq
suggested_fee_recipient: None,
gas_limit: None,
builder_proposals: None,
builder_boost_factor: None,
prefer_builder_proposals: None,
voting_public_key: pubkey,
url: web3_signer_url(),
root_certificate_path: None,
@@ -468,7 +470,7 @@ async fn import_and_delete_conflicting_web3_signer_keystores() {
for pubkey in &pubkeys {
tester
.client
.patch_lighthouse_validators(pubkey, Some(false), None, None, None)
.patch_lighthouse_validators(pubkey, Some(false), None, None, None, None, None)
.await
.unwrap();
}

View File

@@ -131,6 +131,8 @@ pub struct InitializedValidator {
suggested_fee_recipient: Option<Address>,
gas_limit: Option<u64>,
builder_proposals: Option<bool>,
builder_boost_factor: Option<u64>,
prefer_builder_proposals: Option<bool>,
/// The validators index in `state.validators`, to be updated by an external service.
index: Option<u64>,
}
@@ -159,6 +161,14 @@ impl InitializedValidator {
self.gas_limit
}
pub fn get_builder_boost_factor(&self) -> Option<u64> {
self.builder_boost_factor
}
pub fn get_prefer_builder_proposals(&self) -> Option<bool> {
self.prefer_builder_proposals
}
pub fn get_builder_proposals(&self) -> Option<bool> {
self.builder_proposals
}
@@ -335,6 +345,8 @@ impl InitializedValidator {
suggested_fee_recipient: def.suggested_fee_recipient,
gas_limit: def.gas_limit,
builder_proposals: def.builder_proposals,
builder_boost_factor: def.builder_boost_factor,
prefer_builder_proposals: def.prefer_builder_proposals,
index: None,
})
}
@@ -815,6 +827,22 @@ impl InitializedValidators {
.and_then(|v| v.builder_proposals)
}
/// Returns the `builder_boost_factor` for a given public key specified in the
/// `ValidatorDefinitions`.
pub fn builder_boost_factor(&self, public_key: &PublicKeyBytes) -> Option<u64> {
self.validators
.get(public_key)
.and_then(|v| v.builder_boost_factor)
}
/// Returns the `prefer_builder_proposals` for a given public key specified in the
/// `ValidatorDefinitions`.
pub fn prefer_builder_proposals(&self, public_key: &PublicKeyBytes) -> Option<bool> {
self.validators
.get(public_key)
.and_then(|v| v.prefer_builder_proposals)
}
/// Returns an `Option` of a reference to an `InitializedValidator` for a given public key specified in the
/// `ValidatorDefinitions`.
pub fn validator(&self, public_key: &PublicKeyBytes) -> Option<&InitializedValidator> {
@@ -835,12 +863,15 @@ impl InitializedValidators {
/// or `InitializedValidator`. The same logic applies to `builder_proposals` and `graffiti`.
///
/// Saves the `ValidatorDefinitions` to file, even if no definitions were changed.
#[allow(clippy::too_many_arguments)]
pub async fn set_validator_definition_fields(
&mut self,
voting_public_key: &PublicKey,
enabled: Option<bool>,
gas_limit: Option<u64>,
builder_proposals: Option<bool>,
builder_boost_factor: Option<u64>,
prefer_builder_proposals: Option<bool>,
graffiti: Option<GraffitiString>,
) -> Result<(), Error> {
if let Some(def) = self
@@ -862,6 +893,12 @@ impl InitializedValidators {
if let Some(graffiti) = graffiti.clone() {
def.graffiti = Some(graffiti);
}
if let Some(builder_boost_factor) = builder_boost_factor {
def.builder_boost_factor = Some(builder_boost_factor);
}
if let Some(prefer_builder_proposals) = prefer_builder_proposals {
def.prefer_builder_proposals = Some(prefer_builder_proposals);
}
}
self.update_validators().await?;
@@ -880,6 +917,12 @@ impl InitializedValidators {
if let Some(graffiti) = graffiti {
val.graffiti = Some(graffiti.into());
}
if let Some(builder_boost_factor) = builder_boost_factor {
val.builder_boost_factor = Some(builder_boost_factor);
}
if let Some(prefer_builder_proposals) = prefer_builder_proposals {
val.prefer_builder_proposals = Some(prefer_builder_proposals);
}
}
self.definitions

View File

@@ -98,6 +98,8 @@ pub struct ValidatorStore<T, E: EthSpec> {
gas_limit: Option<u64>,
builder_proposals: bool,
produce_block_v3: bool,
prefer_builder_proposals: bool,
builder_boost_factor: Option<u64>,
task_executor: TaskExecutor,
_phantom: PhantomData<E>,
}
@@ -130,6 +132,8 @@ impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore<T, E> {
gas_limit: config.gas_limit,
builder_proposals: config.builder_proposals,
produce_block_v3: config.produce_block_v3,
prefer_builder_proposals: config.prefer_builder_proposals,
builder_boost_factor: config.builder_boost_factor,
task_executor,
_phantom: PhantomData,
}
@@ -178,6 +182,8 @@ impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore<T, E> {
suggested_fee_recipient: Option<Address>,
gas_limit: Option<u64>,
builder_proposals: Option<bool>,
builder_boost_factor: Option<u64>,
prefer_builder_proposals: Option<bool>,
) -> Result<ValidatorDefinition, String> {
let mut validator_def = ValidatorDefinition::new_keystore_with_password(
voting_keystore_path,
@@ -186,6 +192,8 @@ impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore<T, E> {
suggested_fee_recipient,
gas_limit,
builder_proposals,
builder_boost_factor,
prefer_builder_proposals,
)
.map_err(|e| format!("failed to create validator definitions: {:?}", e))?;
@@ -474,7 +482,7 @@ impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore<T, E> {
.unwrap_or(DEFAULT_GAS_LIMIT)
}
/// Returns a `bool` for the given public key that denotes whther this validator should use the
/// Returns a `bool` for the given public key that denotes whether this validator should use the
/// builder API. The priority order for fetching this value is:
///
/// 1. validator_definitions.yml
@@ -487,12 +495,91 @@ impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore<T, E> {
)
}
/// Returns a `u64` for the given public key that denotes the builder boost factor. The priority order for fetching this value is:
///
/// 1. validator_definitions.yml
/// 2. process level flag
pub fn get_builder_boost_factor(&self, validator_pubkey: &PublicKeyBytes) -> Option<u64> {
self.validators
.read()
.builder_boost_factor(validator_pubkey)
.or(self.builder_boost_factor)
}
/// Returns a `bool` for the given public key that denotes whether this validator should prefer a
/// builder payload. The priority order for fetching this value is:
///
/// 1. validator_definitions.yml
/// 2. process level flag
pub fn get_prefer_builder_proposals(&self, validator_pubkey: &PublicKeyBytes) -> bool {
self.validators
.read()
.prefer_builder_proposals(validator_pubkey)
.unwrap_or(self.prefer_builder_proposals)
}
fn get_builder_proposals_defaulting(&self, builder_proposals: Option<bool>) -> bool {
builder_proposals
// If there's nothing in the file, try the process-level default value.
.unwrap_or(self.builder_proposals)
}
/// Translate the per validator `builder_proposals`, `builder_boost_factor` and
/// `prefer_builder_proposals` to a boost factor, if available.
/// - If `prefer_builder_proposals` is true, set boost factor to `u64::MAX` to indicate a
/// preference for builder payloads.
/// - If `builder_boost_factor` is a value other than None, return its value as the boost factor.
/// - If `builder_proposals` is set to false, set boost factor to 0 to indicate a preference for
/// local payloads.
/// - Else return `None` to indicate no preference between builder and local payloads.
pub fn determine_validator_builder_boost_factor(
&self,
validator_pubkey: &PublicKeyBytes,
) -> Option<u64> {
let validator_prefer_builder_proposals = self
.validators
.read()
.prefer_builder_proposals(validator_pubkey);
if matches!(validator_prefer_builder_proposals, Some(true)) {
return Some(u64::MAX);
}
self.validators
.read()
.builder_boost_factor(validator_pubkey)
.or_else(|| {
if matches!(
self.validators.read().builder_proposals(validator_pubkey),
Some(false)
) {
return Some(0);
}
None
})
}
/// Translate the process-wide `builder_proposals`, `builder_boost_factor` and
/// `prefer_builder_proposals` configurations to a boost factor.
/// - If `prefer_builder_proposals` is true, set boost factor to `u64::MAX` to indicate a
/// preference for builder payloads.
/// - If `builder_boost_factor` is a value other than None, return its value as the boost factor.
/// - If `builder_proposals` is set to false, set boost factor to 0 to indicate a preference for
/// local payloads.
/// - Else return `None` to indicate no preference between builder and local payloads.
pub fn determine_default_builder_boost_factor(&self) -> Option<u64> {
if self.prefer_builder_proposals {
return Some(u64::MAX);
}
self.builder_boost_factor.or({
if self.builder_proposals {
Some(0)
} else {
None
}
})
}
pub async fn sign_block<Payload: AbstractExecPayload<E>>(
&self,
validator_pubkey: PublicKeyBytes,