Optimise no-op PATCH ops in VC HTTP API (#5064)

* Optimise no-op changes in VC API

* Handle another no-op case

* Merge remote-tracking branch 'origin/unstable' into opt-vc-patch-api
This commit is contained in:
Michael Sproul 2024-02-29 12:51:07 +11:00 committed by GitHub
parent 64e563f5e9
commit 88b37a10df
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -685,7 +685,16 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
let maybe_graffiti = body.graffiti.clone().map(Into::into); let maybe_graffiti = body.graffiti.clone().map(Into::into);
let initialized_validators_rw_lock = validator_store.initialized_validators(); let initialized_validators_rw_lock = validator_store.initialized_validators();
let mut initialized_validators = initialized_validators_rw_lock.write(); let initialized_validators = initialized_validators_rw_lock.upgradable_read();
// Do not make any changes if all fields are identical or unchanged.
fn equal_or_none<T: PartialEq>(
current_value: Option<T>,
new_value: Option<T>,
) -> bool {
new_value.is_none() || current_value == new_value
}
match ( match (
initialized_validators.is_enabled(&validator_pubkey), initialized_validators.is_enabled(&validator_pubkey),
initialized_validators.validator(&validator_pubkey.compress()), initialized_validators.validator(&validator_pubkey.compress()),
@ -694,32 +703,65 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
"no validator for {:?}", "no validator for {:?}",
validator_pubkey validator_pubkey
))), ))),
// If all specified parameters match their existing settings, then this
// change is a no-op.
(Some(is_enabled), Some(initialized_validator)) (Some(is_enabled), Some(initialized_validator))
if Some(is_enabled) == body.enabled if equal_or_none(Some(is_enabled), body.enabled)
&& initialized_validator.get_gas_limit() == body.gas_limit && equal_or_none(
&& initialized_validator.get_builder_boost_factor() initialized_validator.get_gas_limit(),
== body.builder_boost_factor body.gas_limit,
&& initialized_validator.get_builder_proposals() )
== body.builder_proposals && equal_or_none(
&& initialized_validator.get_prefer_builder_proposals() initialized_validator.get_builder_boost_factor(),
== body.prefer_builder_proposals body.builder_boost_factor,
&& initialized_validator.get_graffiti() == maybe_graffiti => )
&& equal_or_none(
initialized_validator.get_builder_proposals(),
body.builder_proposals,
)
&& equal_or_none(
initialized_validator.get_prefer_builder_proposals(),
body.prefer_builder_proposals,
)
&& equal_or_none(
initialized_validator.get_graffiti(),
maybe_graffiti,
) =>
{
Ok(())
}
// Disabling an already disabled validator *with no other changes* is a
// no-op.
(Some(false), None)
if body.enabled.map_or(true, |enabled| !enabled)
&& body.gas_limit.is_none()
&& body.builder_boost_factor.is_none()
&& body.builder_proposals.is_none()
&& body.prefer_builder_proposals.is_none()
&& maybe_graffiti.is_none() =>
{ {
Ok(()) Ok(())
} }
(Some(_), _) => { (Some(_), _) => {
// Upgrade read lock only in the case where a write is actually
// required.
let mut initialized_validators_write =
parking_lot::RwLockUpgradableReadGuard::upgrade(
initialized_validators,
);
if let Some(handle) = task_executor.handle() { if let Some(handle) = task_executor.handle() {
handle handle
.block_on( .block_on(
initialized_validators.set_validator_definition_fields( initialized_validators_write
&validator_pubkey, .set_validator_definition_fields(
body.enabled, &validator_pubkey,
body.gas_limit, body.enabled,
body.builder_proposals, body.gas_limit,
body.builder_boost_factor, body.builder_proposals,
body.prefer_builder_proposals, body.builder_boost_factor,
body.graffiti, body.prefer_builder_proposals,
), body.graffiti,
),
) )
.map_err(|e| { .map_err(|e| {
warp_utils::reject::custom_server_error(format!( warp_utils::reject::custom_server_error(format!(