@@ -685,7 +685,16 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
685
685
686
686
let maybe_graffiti = body. graffiti . clone ( ) . map ( Into :: into) ;
687
687
let initialized_validators_rw_lock = validator_store. initialized_validators ( ) ;
688
- let mut initialized_validators = initialized_validators_rw_lock. write ( ) ;
688
+ let initialized_validators = initialized_validators_rw_lock. upgradable_read ( ) ;
689
+
690
+ // Do not make any changes if all fields are identical or unchanged.
691
+ fn equal_or_none < T : PartialEq > (
692
+ current_value : Option < T > ,
693
+ new_value : Option < T > ,
694
+ ) -> bool {
695
+ new_value. is_none ( ) || current_value == new_value
696
+ }
697
+
689
698
match (
690
699
initialized_validators. is_enabled ( & validator_pubkey) ,
691
700
initialized_validators. validator ( & validator_pubkey. compress ( ) ) ,
@@ -694,32 +703,65 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
694
703
"no validator for {:?}" ,
695
704
validator_pubkey
696
705
) ) ) ,
706
+ // If all specified parameters match their existing settings, then this
707
+ // change is a no-op.
697
708
( Some ( is_enabled) , Some ( initialized_validator) )
698
- if Some ( is_enabled) == body. enabled
699
- && initialized_validator. get_gas_limit ( ) == body. gas_limit
700
- && initialized_validator. get_builder_boost_factor ( )
701
- == body. builder_boost_factor
702
- && initialized_validator. get_builder_proposals ( )
703
- == body. builder_proposals
704
- && initialized_validator. get_prefer_builder_proposals ( )
705
- == body. prefer_builder_proposals
706
- && initialized_validator. get_graffiti ( ) == maybe_graffiti =>
709
+ if equal_or_none ( Some ( is_enabled) , body. enabled )
710
+ && equal_or_none (
711
+ initialized_validator. get_gas_limit ( ) ,
712
+ body. gas_limit ,
713
+ )
714
+ && equal_or_none (
715
+ initialized_validator. get_builder_boost_factor ( ) ,
716
+ body. builder_boost_factor ,
717
+ )
718
+ && equal_or_none (
719
+ initialized_validator. get_builder_proposals ( ) ,
720
+ body. builder_proposals ,
721
+ )
722
+ && equal_or_none (
723
+ initialized_validator. get_prefer_builder_proposals ( ) ,
724
+ body. prefer_builder_proposals ,
725
+ )
726
+ && equal_or_none (
727
+ initialized_validator. get_graffiti ( ) ,
728
+ maybe_graffiti,
729
+ ) =>
730
+ {
731
+ Ok ( ( ) )
732
+ }
733
+ // Disabling an already disabled validator *with no other changes* is a
734
+ // no-op.
735
+ ( Some ( false ) , None )
736
+ if body. enabled . map_or ( true , |enabled| !enabled)
737
+ && body. gas_limit . is_none ( )
738
+ && body. builder_boost_factor . is_none ( )
739
+ && body. builder_proposals . is_none ( )
740
+ && body. prefer_builder_proposals . is_none ( )
741
+ && maybe_graffiti. is_none ( ) =>
707
742
{
708
743
Ok ( ( ) )
709
744
}
710
745
( Some ( _) , _) => {
746
+ // Upgrade read lock only in the case where a write is actually
747
+ // required.
748
+ let mut initialized_validators_write =
749
+ parking_lot:: RwLockUpgradableReadGuard :: upgrade (
750
+ initialized_validators,
751
+ ) ;
711
752
if let Some ( handle) = task_executor. handle ( ) {
712
753
handle
713
754
. block_on (
714
- initialized_validators. set_validator_definition_fields (
715
- & validator_pubkey,
716
- body. enabled ,
717
- body. gas_limit ,
718
- body. builder_proposals ,
719
- body. builder_boost_factor ,
720
- body. prefer_builder_proposals ,
721
- body. graffiti ,
722
- ) ,
755
+ initialized_validators_write
756
+ . set_validator_definition_fields (
757
+ & validator_pubkey,
758
+ body. enabled ,
759
+ body. gas_limit ,
760
+ body. builder_proposals ,
761
+ body. builder_boost_factor ,
762
+ body. prefer_builder_proposals ,
763
+ body. graffiti ,
764
+ ) ,
723
765
)
724
766
. map_err ( |e| {
725
767
warp_utils:: reject:: custom_server_error ( format ! (
0 commit comments