Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

default vc to block v3 endpoint and deprecate block-v3 flag #5292

Merged
merged 15 commits into from
Jul 26, 2024
Merged
5 changes: 1 addition & 4 deletions book/src/help_vc.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,7 @@ Flags:
If this flag is set, Lighthouse will always prefer blocks constructed
by builders, regardless of payload value.
--produce-block-v3
Enable block production via the block v3 endpoint for this validator
client. This should only be enabled when paired with a beacon node
that has this endpoint implemented. This flag will be enabled by
default in future.
This flag is deprecated and is no longer in use.
--unencrypted-http-transport
This is a safety flag to ensure that the user is aware that the http
transport is unencrypted and using a custom HTTP address is unsafe.
Expand Down
15 changes: 4 additions & 11 deletions lighthouse/tests/validator_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,19 +423,12 @@ fn no_doppelganger_protection_flag() {
.run()
.with_config(|config| assert!(!config.enable_doppelganger_protection));
}
#[test]
fn produce_block_v3_flag() {
CommandLineTest::new()
.flag("produce-block-v3", None)
.run()
.with_config(|config| assert!(config.produce_block_v3));
}

#[test]
fn no_produce_block_v3_flag() {
CommandLineTest::new()
.run()
.with_config(|config| assert!(!config.produce_block_v3));
fn produce_block_v3_flag() {
// The flag is DEPRECATED but providing it should not trigger an error.
// We can delete this test when deleting the flag entirely.
CommandLineTest::new().flag("produce-block-v3", None).run();
}

#[test]
Expand Down
1 change: 0 additions & 1 deletion testing/simulator/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ pub fn cli_app() -> Command {
)
.arg(
Arg::new("vc-count")
.short('c')
jimmygchen marked this conversation as resolved.
Show resolved Hide resolved
.long("vc-count")
.action(ArgAction::Set)
.default_value("3")
Expand Down
284 changes: 28 additions & 256 deletions validator_client/src/block_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,105 +323,32 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockService<T, E> {
)
}

if self.validator_store.produce_block_v3() {
for validator_pubkey in proposers {
let builder_boost_factor = self.get_builder_boost_factor(&validator_pubkey);
let service = self.clone();
let log = log.clone();
self.inner.context.executor.spawn(
async move {
let result = service
.publish_block_v3(slot, validator_pubkey, builder_boost_factor)
.await;

match result {
Ok(_) => {}
Err(BlockError::Recoverable(e)) | Err(BlockError::Irrecoverable(e)) => {
error!(
log,
"Error whilst producing block";
"error" => ?e,
"block_slot" => ?slot,
"info" => "block v3 proposal failed, this error may or may not result in a missed block"
);
}
for validator_pubkey in proposers {
let builder_boost_factor = self.get_builder_boost_factor(&validator_pubkey);
let service = self.clone();
let log = log.clone();
self.inner.context.executor.spawn(
async move {
let result = service
.publish_block(slot, validator_pubkey, builder_boost_factor)
.await;

match result {
Ok(_) => {}
Err(BlockError::Recoverable(e)) | Err(BlockError::Irrecoverable(e)) => {
error!(
log,
"Error whilst producing block";
"error" => ?e,
"block_slot" => ?slot,
"info" => "block v3 proposal failed, this error may or may not result in a missed block"
);
}
},
"block service",
)
}
} else {
for validator_pubkey in proposers {
let builder_proposals = self
.validator_store
.get_builder_proposals(&validator_pubkey);
let service = self.clone();
let log = log.clone();
self.inner.context.executor.spawn(
async move {
if builder_proposals {
let result = service
.publish_block(slot, validator_pubkey, true)
.await;

match result {
Err(BlockError::Recoverable(e)) => {
error!(
log,
"Error whilst producing block";
"error" => ?e,
"block_slot" => ?slot,
"info" => "blinded proposal failed, attempting full block"
);
if let Err(e) = service
.publish_block(slot, validator_pubkey, false)
.await
{
// Log a `crit` since a full block
// (non-builder) proposal failed.
crit!(
log,
"Error whilst producing block";
"error" => ?e,
"block_slot" => ?slot,
"info" => "full block attempted after a blinded failure",
);
}
}
Err(BlockError::Irrecoverable(e)) => {
// Only log an `error` since it's common for
// builders to timeout on their response, only
// to publish the block successfully themselves.
error!(
log,
"Error whilst producing block";
"error" => ?e,
"block_slot" => ?slot,
"info" => "this error may or may not result in a missed block",
)
}
Ok(_) => {}
};
} else if let Err(e) = service
.publish_block(slot, validator_pubkey, false)
.await
{
// Log a `crit` since a full block (non-builder)
// proposal failed.
crit!(
log,
"Error whilst producing block";
"message" => ?e,
"block_slot" => ?slot,
"info" => "proposal did not use a builder",
);
}
},
"block service",
)
}
}
},
"block service",
)
}

Ok(())
}

Expand Down Expand Up @@ -513,7 +440,7 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockService<T, E> {
Ok(())
}

async fn publish_block_v3(
async fn publish_block(
self,
slot: Slot,
validator_pubkey: PublicKeyBytes,
Expand Down Expand Up @@ -584,7 +511,7 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockService<T, E> {
&metrics::BLOCK_SERVICE_TIMES,
&[metrics::BEACON_BLOCK_HTTP_GET],
);
let block_response = Self::get_validator_block_v3(
Self::get_validator_block(
beacon_node,
slot,
randao_reveal_ref,
Expand All @@ -599,103 +526,7 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockService<T, E> {
"Error from beacon node when producing block: {:?}",
e
))
});

Ok::<_, BlockError>(block_response)
},
)
.await??;

self_ref
.sign_and_publish_block(
proposer_fallback,
slot,
graffiti,
&validator_pubkey,
unsigned_block,
)
.await?;

Ok(())
}

/// Produce a block at the given slot for validator_pubkey
async fn publish_block(
&self,
slot: Slot,
validator_pubkey: PublicKeyBytes,
builder_proposal: bool,
) -> Result<(), BlockError> {
let log = self.context.log();
let _timer =
metrics::start_timer_vec(&metrics::BLOCK_SERVICE_TIMES, &[metrics::BEACON_BLOCK]);

let randao_reveal = match self
.validator_store
.randao_reveal(validator_pubkey, slot.epoch(E::slots_per_epoch()))
.await
{
Ok(signature) => signature.into(),
Err(ValidatorStoreError::UnknownPubkey(pubkey)) => {
// A pubkey can be missing when a validator was recently removed
// via the API.
warn!(
log,
"Missing pubkey for block";
"info" => "a validator may have recently been removed from this VC",
"pubkey" => ?pubkey,
"slot" => ?slot
);
return Ok(());
}
Err(e) => {
return Err(BlockError::Recoverable(format!(
"Unable to sign block: {:?}",
e
)))
}
};

let graffiti = determine_graffiti(
&validator_pubkey,
log,
self.graffiti_file.clone(),
self.validator_store.graffiti(&validator_pubkey),
self.graffiti,
);

let randao_reveal_ref = &randao_reveal;
let self_ref = &self;
let proposer_index = self.validator_store.validator_index(&validator_pubkey);
let proposer_fallback = ProposerFallback {
beacon_nodes: self.beacon_nodes.clone(),
proposer_nodes: self.proposer_nodes.clone(),
};

info!(
log,
"Requesting unsigned block";
"slot" => slot.as_u64(),
);

// Request block from first responsive beacon node.
//
// Try the proposer nodes last, since it's likely that they don't have a
// great view of attestations on the network.
let unsigned_block = proposer_fallback
.request_proposers_last(
RequireSynced::No,
OfflineOnFailure::Yes,
move |beacon_node| {
Self::get_validator_block(
beacon_node,
slot,
randao_reveal_ref,
graffiti,
proposer_index,
builder_proposal,
log,
)
})
},
)
.await?;
Expand Down Expand Up @@ -745,7 +576,7 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockService<T, E> {
Ok::<_, BlockError>(())
}

async fn get_validator_block_v3(
async fn get_validator_block(
beacon_node: &BeaconNodeHttpClient,
slot: Slot,
randao_reveal_ref: &SignatureBytes,
Expand Down Expand Up @@ -788,65 +619,6 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockService<T, E> {
Ok::<_, BlockError>(unsigned_block)
}

async fn get_validator_block(
beacon_node: &BeaconNodeHttpClient,
slot: Slot,
randao_reveal_ref: &SignatureBytes,
graffiti: Option<Graffiti>,
proposer_index: Option<u64>,
builder_proposal: bool,
log: &Logger,
) -> Result<UnsignedBlock<E>, BlockError> {
let unsigned_block = if !builder_proposal {
let _get_timer = metrics::start_timer_vec(
&metrics::BLOCK_SERVICE_TIMES,
&[metrics::BEACON_BLOCK_HTTP_GET],
);
UnsignedBlock::Full(
beacon_node
.get_validator_blocks::<E>(slot, randao_reveal_ref, graffiti.as_ref())
.await
.map_err(|e| {
BlockError::Recoverable(format!(
"Error from beacon node when producing block: {:?}",
e
))
})?
.data,
)
} else {
let _get_timer = metrics::start_timer_vec(
&metrics::BLOCK_SERVICE_TIMES,
&[metrics::BLINDED_BEACON_BLOCK_HTTP_GET],
);
UnsignedBlock::Blinded(
beacon_node
.get_validator_blinded_blocks::<E>(slot, randao_reveal_ref, graffiti.as_ref())
.await
.map_err(|e| {
BlockError::Recoverable(format!(
"Error from beacon node when producing block: {:?}",
e
))
})?
.data,
)
};

info!(
log,
"Received unsigned block";
"slot" => slot.as_u64(),
);
if proposer_index != Some(unsigned_block.proposer_index()) {
return Err(BlockError::Recoverable(
"Proposer index does not match block proposer. Beacon chain re-orged".to_string(),
));
}

Ok::<_, BlockError>(unsigned_block)
}

/// Returns the builder boost factor of the given public key.
/// The priority order for fetching this value is:
///
Expand Down
5 changes: 1 addition & 4 deletions validator_client/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,7 @@ pub fn cli_app() -> Command {
.arg(
Arg::new("produce-block-v3")
.long("produce-block-v3")
.help("Enable block production via the block v3 endpoint for this validator client. \
This should only be enabled when paired with a beacon node \
that has this endpoint implemented. This flag will be enabled by default in \
future.")
.help("This flag is deprecated and is no longer in use.")
.action(ArgAction::SetTrue)
.help_heading(FLAG_HEADER)
.display_order(0)
Expand Down
Loading
Loading