Skip to content

Commit

Permalink
Add builder_boost_factor param to /eth/v3/validator/blocks{slot}
Browse files Browse the repository at this point in the history
  • Loading branch information
Tumas committed Apr 23, 2024
1 parent 8491378 commit 1c0f078
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 11 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 22 additions & 4 deletions http_api/src/standard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ use types::{
preset::Preset,
traits::{BeaconState as _, SignedBeaconBlock as _},
};
use validator::{ApiToValidator, ValidatorBlindedBlock, ValidatorConfig, ValidatorProposerData};
use validator::{
ApiToValidator, ValidatorBlindedBlock, ValidatorConfig, ValidatorProposerData,
DEFAULT_BUILDER_BOOST_FACTOR,
};

use crate::{
block_id,
Expand Down Expand Up @@ -161,7 +164,7 @@ pub struct PoolAttestationQuery {
}

#[derive(Deserialize)]
// Allow custom fields in ValidatorBlockQuery.
// Allow custom fields in `ValidatorBlockQuery`.
// This is required for Lodestar interoperability.
// #[serde(deny_unknown_fields)]
pub struct ValidatorBlockQuery {
Expand All @@ -171,6 +174,18 @@ pub struct ValidatorBlockQuery {
skip_randao_verification: bool,
}

#[derive(Deserialize)]
// Allow custom fields in `ValidatorBlockQueryV3`.
// This is required for Lodestar interoperability.
// #[serde(deny_unknown_fields)]
pub struct ValidatorBlockQueryV3 {
randao_reveal: SignatureBytes,
graffiti: Option<H256>,
#[serde(default, with = "serde_utils::bool_as_empty_string")]
skip_randao_verification: bool,
builder_boost_factor: Option<u64>,
}

#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
pub struct SyncCommitteeContributionQuery {
Expand Down Expand Up @@ -1849,6 +1864,7 @@ pub async fn validator_blinded_block<P: Preset>(
randao_reveal,
slot,
skip_randao_verification,
DEFAULT_BUILDER_BOOST_FACTOR.get(),
)
.send(&api_to_validator_tx);

Expand Down Expand Up @@ -1908,13 +1924,14 @@ pub async fn validator_block_v3<P: Preset, W: Wait>(
State(controller): State<ApiController<P, W>>,
State(api_to_validator_tx): State<UnboundedSender<ApiToValidator<P>>>,
EthPath(slot): EthPath<Slot>,
EthQuery(query): EthQuery<ValidatorBlockQuery>,
EthQuery(query): EthQuery<ValidatorBlockQueryV3>,
headers: HeaderMap,
) -> Result<EthResponse<APIBlock<ValidatorBlindedBlock<P>, P>, (), JsonOrSsz>, Error> {
let ValidatorBlockQuery {
let ValidatorBlockQueryV3 {
randao_reveal,
graffiti,
skip_randao_verification,
builder_boost_factor,
} = query;

if skip_randao_verification && !randao_reveal.is_empty() {
Expand All @@ -1930,6 +1947,7 @@ pub async fn validator_block_v3<P: Preset, W: Wait>(
randao_reveal,
slot,
skip_randao_verification,
builder_boost_factor.unwrap_or_else(|| DEFAULT_BUILDER_BOOST_FACTOR.get()),
)
.send(&api_to_validator_tx);

Expand Down
5 changes: 5 additions & 0 deletions ssz/src/uint256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,11 @@ impl Uint256 {
]))
}

#[must_use]
pub fn saturating_mul(self, rhs: Self) -> Self {
Self(self.into_raw().saturating_mul(rhs.into_raw()))
}

const fn into_raw(self) -> RawUint256 {
self.0
}
Expand Down
1 change: 1 addition & 0 deletions validator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ http_api_utils = { workspace = true }
itertools = { workspace = true }
keymanager = { workspace = true }
log = { workspace = true }
nonzero_ext = { workspace = true }
once_cell = { workspace = true }
operation_pools = { workspace = true }
p2p = { workspace = true }
Expand Down
4 changes: 3 additions & 1 deletion validator/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
pub use crate::{
api::{run_validator_api, ValidatorApiConfig},
messages::{ApiToValidator, ValidatorToApi, ValidatorToLiveness},
misc::{ProposerData as ValidatorProposerData, ValidatorBlindedBlock},
misc::{
ProposerData as ValidatorProposerData, ValidatorBlindedBlock, DEFAULT_BUILDER_BOOST_FACTOR,
},
validator::{Channels as ValidatorChannels, Validator},
validator_config::ValidatorConfig,
};
Expand Down
2 changes: 1 addition & 1 deletion validator/src/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub type BlindedBlockSender<P> =

pub enum ApiToValidator<P: Preset> {
ProduceBeaconBlock(BeaconBlockSender<P>, H256, SignatureBytes, Slot, bool),
ProduceBlindedBeaconBlock(BlindedBlockSender<P>, H256, SignatureBytes, Slot, bool),
ProduceBlindedBeaconBlock(BlindedBlockSender<P>, H256, SignatureBytes, Slot, bool, u64),
AttesterSlashing(Sender<PoolAdditionOutcome>, Box<AttesterSlashing<P>>),
ProposerSlashing(Sender<PoolAdditionOutcome>, Box<ProposerSlashing>),
PublishSignedBlindedBlock(
Expand Down
5 changes: 5 additions & 0 deletions validator/src/misc.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use core::num::NonZeroU64;

use bls::{PublicKeyBytes, SignatureBytes};
use nonzero_ext::nonzero;
use serde::{Deserialize, Serialize};
use ssz::{BitVector, Size, SszHash, SszSize, SszWrite, WriteError, H256};
use typenum::U1;
Expand All @@ -11,6 +14,8 @@ use types::{
traits::{BeaconBlock as _, PostDenebBeaconBlockBody},
};

pub const DEFAULT_BUILDER_BOOST_FACTOR: NonZeroU64 = nonzero!(100_u64);

#[allow(clippy::struct_field_names)]
pub struct Aggregator {
pub aggregator_index: ValidatorIndex,
Expand Down
42 changes: 37 additions & 5 deletions validator/src/validator.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! <https://github.com/ethereum/consensus-specs/blob/b2f42bf4d79432ee21e2f2b3912ff4bbf7898ada/specs/phase0/validator.md>
use core::ops::ControlFlow;
use core::ops::{ControlFlow, Div as _};
use std::{
collections::{BTreeMap, BTreeSet, HashMap, HashSet},
error::Error as StdError,
Expand Down Expand Up @@ -98,7 +98,9 @@ use types::{
BeaconBlock as Phase0BeaconBlock, BeaconBlockBody as Phase0BeaconBlockBody, Checkpoint,
ProposerSlashing, SignedAggregateAndProof, SignedVoluntaryExit,
},
primitives::{Epoch, ExecutionAddress, ExecutionBlockHash, Slot, ValidatorIndex, H256},
primitives::{
Epoch, ExecutionAddress, ExecutionBlockHash, Slot, Uint256, ValidatorIndex, H256,
},
},
preset::Preset,
traits::{
Expand All @@ -111,7 +113,10 @@ use crate::{
messages::{
ApiToValidator, BeaconBlockSender, BlindedBlockSender, ValidatorToApi, ValidatorToLiveness,
},
misc::{Aggregator, ProposerData, SyncCommitteeMember, ValidatorBlindedBlock},
misc::{
Aggregator, ProposerData, SyncCommitteeMember, ValidatorBlindedBlock,
DEFAULT_BUILDER_BOOST_FACTOR,
},
own_beacon_committee_members::{BeaconCommitteeMember, OwnBeaconCommitteeMembers},
own_sync_committee_subscriptions::OwnSyncCommitteeSubscriptions,
slot_head::SlotHead,
Expand Down Expand Up @@ -413,13 +418,15 @@ impl<P: Preset, W: Wait + Sync> Validator<P, W> {
randao_reveal,
slot,
skip_randao_verification,
builder_boost_factor,
) => {
self.produce_blinded_beacon_block(
sender,
graffiti,
randao_reveal,
slot,
skip_randao_verification,
builder_boost_factor,
).await
},
ApiToValidator::ProposerSlashing(sender, proposer_slashing) => {
Expand Down Expand Up @@ -955,6 +962,7 @@ impl<P: Preset, W: Wait + Sync> Validator<P, W> {
.pipe(Some)
}

#[allow(clippy::too_many_arguments)]
async fn build_blinded_beacon_block(
&mut self,
slot_head: &SlotHead<P>,
Expand All @@ -963,6 +971,7 @@ impl<P: Preset, W: Wait + Sync> Validator<P, W> {
graffiti: H256,
execution_payload_header_handle: Option<JoinHandle<Result<Option<SignedBuilderBid<P>>>>>,
skip_randao_verification: bool,
builder_boost_factor: u64,
) -> Result<Option<WithBlobsAndMev<ValidatorBlindedBlock<P>, P>>> {
let Some(beacon_block) = self
.build_beacon_block(
Expand All @@ -982,7 +991,7 @@ impl<P: Preset, W: Wait + Sync> Validator<P, W> {
match header_handle.await? {
Ok(Some(response)) => {
let blob_kzg_commitments = response.blob_kzg_commitments().cloned();
let mev = response.mev();
let builder_mev = response.mev();

if let Some(blinded_block) = self.blinded_block_from_beacon_block(
slot_head,
Expand All @@ -991,6 +1000,26 @@ impl<P: Preset, W: Wait + Sync> Validator<P, W> {
blob_kzg_commitments,
skip_randao_verification,
) {
if let Some(local_mev) = beacon_block.mev {
let builder_boost_factor = Uint256::from_u64(builder_boost_factor);

let boosted_builder_mev = builder_mev
.div(DEFAULT_BUILDER_BOOST_FACTOR)
.saturating_mul(builder_boost_factor);

if local_mev >= boosted_builder_mev {
info!(
"using more profitable local payload: \
local MEV: {local_mev}, builder MEV: {builder_mev}, \
boosted builder MEV: {boosted_builder_mev}, builder_boost_factor: {builder_boost_factor}",
);

return Ok(Some(
beacon_block.map(ValidatorBlindedBlock::BeaconBlock),
));
}
}

let block = ValidatorBlindedBlock::BlindedBeaconBlock {
blinded_block,
execution_payload: Box::new(
Expand All @@ -1005,7 +1034,7 @@ impl<P: Preset, W: Wait + Sync> Validator<P, W> {
None,
beacon_block.proofs,
beacon_block.blobs,
Some(mev),
Some(builder_mev),
)));
}
}
Expand Down Expand Up @@ -1271,6 +1300,7 @@ impl<P: Preset, W: Wait + Sync> Validator<P, W> {
randao_reveal: SignatureBytes,
slot: Slot,
skip_randao_verification: bool,
builder_boost_factor: u64,
) -> bool {
let Some(slot_head) = self.safe_slot_head(slot).await else {
return sender.send(Ok(None)).is_ok();
Expand All @@ -1294,6 +1324,7 @@ impl<P: Preset, W: Wait + Sync> Validator<P, W> {
graffiti,
execution_payload_header_handle,
skip_randao_verification,
builder_boost_factor,
)
.await;

Expand Down Expand Up @@ -1370,6 +1401,7 @@ impl<P: Preset, W: Wait + Sync> Validator<P, W> {
graffiti,
execution_payload_header_handle,
false,
DEFAULT_BUILDER_BOOST_FACTOR.get(),
)
.await?;

Expand Down

0 comments on commit 1c0f078

Please sign in to comment.