From 03cba8290fe98f63751ab424e334f12a9fcdf545 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Wed, 6 Dec 2023 11:56:01 +1100 Subject: [PATCH 01/12] Optional slashing protection for remote keys --- validator_client/src/cli.rs | 8 +++++ validator_client/src/config.rs | 6 ++++ validator_client/src/signing_method.rs | 14 +++++++++ validator_client/src/validator_store.rs | 41 +++++++++++++++++-------- 4 files changed, 57 insertions(+), 12 deletions(-) diff --git a/validator_client/src/cli.rs b/validator_client/src/cli.rs index 6957934fb8d..6fc40892714 100644 --- a/validator_client/src/cli.rs +++ b/validator_client/src/cli.rs @@ -340,4 +340,12 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .default_value("500") .takes_value(true), ) + .arg( + Arg::with_name("disable-slashing-protection-web3signer") + .long("disable-slashing-protection-web3signer") + .help("Disable Lighthouse's slashing protection for all web3signer keys. This can \ + reduce the I/O burden on the VC and is safe as long as the remote signer \ + implements slashing protection correctly.") + .takes_value(false), + ) } diff --git a/validator_client/src/config.rs b/validator_client/src/config.rs index 95d42d6d83a..ffcb4398b52 100644 --- a/validator_client/src/config.rs +++ b/validator_client/src/config.rs @@ -75,6 +75,8 @@ pub struct Config { pub enable_latency_measurement_service: bool, /// Defines the number of validators per `validator/register_validator` request sent to the BN. pub validator_registration_batch_size: usize, + /// Enable slashing protection even while using web3signer keys. + pub enable_web3signer_slashing_protection: bool, } impl Default for Config { @@ -115,6 +117,7 @@ impl Default for Config { broadcast_topics: vec![ApiTopic::Subscriptions], enable_latency_measurement_service: true, validator_registration_batch_size: 500, + enable_web3signer_slashing_protection: true, } } } @@ -367,6 +370,9 @@ impl Config { return Err("validator-registration-batch-size cannot be 0".to_string()); } + config.enable_web3signer_slashing_protection = + !cli_args.is_present("disable-slashing-protection-web3signer"); + Ok(config) } } diff --git a/validator_client/src/signing_method.rs b/validator_client/src/signing_method.rs index 0de2f2f54fa..4ead0ed3c77 100644 --- a/validator_client/src/signing_method.rs +++ b/validator_client/src/signing_method.rs @@ -117,6 +117,20 @@ impl SigningContext { } impl SigningMethod { + /// Return whether this signing method requires local slashing protection. + pub fn requires_local_slashing_protection( + &self, + enable_web3signer_slashing_protection: bool, + ) -> bool { + match self { + // Slashing protection is ALWAYS required for local keys. DO NOT TURN THIS OFF. + SigningMethod::LocalKeystore { .. } => true, + // Slashing protection is only required for remote signer keys when the configuration + // dictates that it is desired. + SigningMethod::Web3Signer { .. } => enable_web3signer_slashing_protection, + } + } + /// Return the signature of `signable_message`, with respect to the `signing_context`. pub async fn get_signature>( &self, diff --git a/validator_client/src/validator_store.rs b/validator_client/src/validator_store.rs index 60155d8efb7..34b5e4f7326 100644 --- a/validator_client/src/validator_store.rs +++ b/validator_client/src/validator_store.rs @@ -97,6 +97,7 @@ pub struct ValidatorStore { fee_recipient_process: Option
, gas_limit: Option, builder_proposals: bool, + enable_web3signer_slashing_protection: bool, task_executor: TaskExecutor, _phantom: PhantomData, } @@ -129,6 +130,7 @@ impl ValidatorStore { gas_limit: config.gas_limit, builder_proposals: config.builder_proposals, task_executor, + enable_web3signer_slashing_protection: config.enable_web3signer_slashing_protection, _phantom: PhantomData, } } @@ -511,19 +513,26 @@ impl ValidatorStore { let signing_context = self.signing_context(Domain::BeaconProposer, signing_epoch); let domain_hash = signing_context.domain_hash(&self.spec); + let signing_method = self.doppelganger_checked_signing_method(validator_pubkey)?; + // Check for slashing conditions. - let slashing_status = self.slashing_protection.check_and_insert_block_proposal( - &validator_pubkey, - &block.block_header(), - domain_hash, - ); + let slashing_status = if signing_method + .requires_local_slashing_protection(self.enable_web3signer_slashing_protection) + { + self.slashing_protection.check_and_insert_block_proposal( + &validator_pubkey, + &block.block_header(), + domain_hash, + ) + } else { + Ok(Safe::Valid) + }; match slashing_status { // We can safely sign this block without slashing. Ok(Safe::Valid) => { metrics::inc_counter_vec(&metrics::SIGNED_BLOCKS_TOTAL, &[metrics::SUCCESS]); - let signing_method = self.doppelganger_checked_signing_method(validator_pubkey)?; let signature = signing_method .get_signature::( SignableMessage::BeaconBlock(&block), @@ -579,20 +588,28 @@ impl ValidatorStore { }); } + // Get the signing method and check doppelganger protection. + let signing_method = self.doppelganger_checked_signing_method(validator_pubkey)?; + // Checking for slashing conditions. let signing_epoch = attestation.data.target.epoch; let signing_context = self.signing_context(Domain::BeaconAttester, signing_epoch); let domain_hash = signing_context.domain_hash(&self.spec); - let slashing_status = self.slashing_protection.check_and_insert_attestation( - &validator_pubkey, - &attestation.data, - domain_hash, - ); + let slashing_status = if signing_method + .requires_local_slashing_protection(self.enable_web3signer_slashing_protection) + { + self.slashing_protection.check_and_insert_attestation( + &validator_pubkey, + &attestation.data, + domain_hash, + ) + } else { + Ok(Safe::Valid) + }; match slashing_status { // We can safely sign this attestation. Ok(Safe::Valid) => { - let signing_method = self.doppelganger_checked_signing_method(validator_pubkey)?; let signature = signing_method .get_signature::>( SignableMessage::AttestationData(&attestation.data), From 39994dff185c45ca9109f52781a4db494070c961 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Thu, 18 Jan 2024 10:54:54 +1100 Subject: [PATCH 02/12] Start writing tests --- testing/web3signer_tests/src/lib.rs | 31 +++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/testing/web3signer_tests/src/lib.rs b/testing/web3signer_tests/src/lib.rs index 463de0c8b3a..90e0f196fc3 100644 --- a/testing/web3signer_tests/src/lib.rs +++ b/testing/web3signer_tests/src/lib.rs @@ -702,4 +702,35 @@ mod tests { async fn sepolia_merge_types() { test_merge_types("sepolia", 4252).await } + + async fn test_lighthouse_slashing_protection(slashing_protection_enabled: bool, port: u16) { + // Run these tests on mainnet. + let network = "mainnet"; + + let network_config = Eth2NetworkConfig::constant(network).unwrap().unwrap(); + let spec = &network_config.chain_spec::().unwrap(); + let merge_fork_slot = spec + .bellatrix_fork_epoch + .unwrap() + .start_slot(E::slots_per_epoch()); + + TestingRig::new(network, spec.clone(), listen_port) + .await + .assert_signatures_match("beacon_block_merge", |pubkey, validator_store| async move { + let mut merge_block = BeaconBlockMerge::empty(spec); + merge_block.slot = merge_fork_slot; + validator_store + .sign_block(pubkey, BeaconBlock::Merge(merge_block), merge_fork_slot) + .await + .unwrap() + }) + .await; + } + + #[tokio::test] + async fn slashing_protection_disabled_everywhere() { + test_lighthouse_slashing_protection(false, + } + + } From e544c1c4347b18a845c409f4d4d2857a7870d56a Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Fri, 26 Jan 2024 09:42:14 +1100 Subject: [PATCH 03/12] Make half-written tests compile --- testing/web3signer_tests/src/lib.rs | 10 ++++++---- validator_client/src/validator_store.rs | 1 - 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/testing/web3signer_tests/src/lib.rs b/testing/web3signer_tests/src/lib.rs index 05e59d87393..43e4dc96392 100644 --- a/testing/web3signer_tests/src/lib.rs +++ b/testing/web3signer_tests/src/lib.rs @@ -707,7 +707,11 @@ mod tests { test_merge_types("sepolia", 4252).await } - async fn test_lighthouse_slashing_protection(slashing_protection_enabled: bool, port: u16) { + // FIXME(sproul): actually write tests here + async fn test_lighthouse_slashing_protection( + _slashing_protection_enabled: bool, + listen_port: u16, + ) { // Run these tests on mainnet. let network = "mainnet"; @@ -733,8 +737,6 @@ mod tests { #[tokio::test] async fn slashing_protection_disabled_everywhere() { - test_lighthouse_slashing_protection(false, + test_lighthouse_slashing_protection(false, 4253).await } - - } diff --git a/validator_client/src/validator_store.rs b/validator_client/src/validator_store.rs index dae52fd4c7a..7fda9f0a5ec 100644 --- a/validator_client/src/validator_store.rs +++ b/validator_client/src/validator_store.rs @@ -137,7 +137,6 @@ impl ValidatorStore { prefer_builder_proposals: config.prefer_builder_proposals, builder_boost_factor: config.builder_boost_factor, task_executor, - task_executor, _phantom: PhantomData, } } From e7ee3a6f6a830780316b0b3c1e4d393ce3f12cc5 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Mon, 29 Jan 2024 11:18:25 +1100 Subject: [PATCH 04/12] Make tests work --- testing/web3signer_tests/src/lib.rs | 520 +++++++++++++++++++--------- 1 file changed, 353 insertions(+), 167 deletions(-) diff --git a/testing/web3signer_tests/src/lib.rs b/testing/web3signer_tests/src/lib.rs index 43e4dc96392..3c7bf33668a 100644 --- a/testing/web3signer_tests/src/lib.rs +++ b/testing/web3signer_tests/src/lib.rs @@ -45,7 +45,7 @@ mod tests { initialized_validators::{ load_pem_certificate, load_pkcs12_identity, InitializedValidators, }, - validator_store::ValidatorStore, + validator_store::{Error as ValidatorStoreError, ValidatorStore}, SlashingDatabase, SLASHING_PROTECTION_FILENAME, }; @@ -157,6 +157,18 @@ mod tests { } } + #[derive(Debug, Clone, Copy)] + struct SlashingProtectionConfig { + /// Whether to enable slashing protection for web3signer keys locally within Lighthouse. + local: bool, + } + + impl Default for SlashingProtectionConfig { + fn default() -> Self { + SlashingProtectionConfig { local: true } + } + } + impl Web3SignerRig { pub async fn new(network: &str, listen_address: &str, listen_port: u16) -> Self { GET_WEB3SIGNER_BIN @@ -231,6 +243,8 @@ mod tests { )) .arg("eth2") .arg(format!("--network={}", network)) + // Can't *easily* test `--slashing-protection-enabled=true` because web3signer + // requires a Postgres instance. .arg("--slashing-protection-enabled=false") .stdout(stdio()) .stderr(stdio()) @@ -294,10 +308,16 @@ mod tests { _validator_dir: TempDir, runtime: Arc, _runtime_shutdown: exit_future::Signal, + using_web3signer: bool, } impl ValidatorStoreRig { - pub async fn new(validator_definitions: Vec, spec: ChainSpec) -> Self { + pub async fn new( + validator_definitions: Vec, + slashing_protection_config: SlashingProtectionConfig, + using_web3signer: bool, + spec: ChainSpec, + ) -> Self { let log = environment::null_logger().unwrap(); let validator_dir = TempDir::new().unwrap(); @@ -331,7 +351,10 @@ mod tests { let slot_clock = TestingSlotClock::new(Slot::new(0), Duration::from_secs(0), Duration::from_secs(1)); - let config = validator_client::Config::default(); + let config = validator_client::Config { + enable_web3signer_slashing_protection: slashing_protection_config.local, + ..Default::default() + }; let validator_store = ValidatorStore::<_, E>::new( initialized_validators, @@ -350,6 +373,7 @@ mod tests { _validator_dir: validator_dir, runtime, _runtime_shutdown: runtime_shutdown, + using_web3signer, } } @@ -378,7 +402,12 @@ mod tests { } impl TestingRig { - pub async fn new(network: &str, spec: ChainSpec, listen_port: u16) -> Self { + pub async fn new( + network: &str, + slashing_protection_config: SlashingProtectionConfig, + spec: ChainSpec, + listen_port: u16, + ) -> Self { let signer_rig = Web3SignerRig::new(network, WEB3SIGNER_LISTEN_ADDRESS, listen_port).await; let validator_pubkey = signer_rig.keypair.pk.clone(); @@ -400,7 +429,13 @@ mod tests { voting_keystore_password: Some(KEYSTORE_PASSWORD.to_string().into()), }, }; - ValidatorStoreRig::new(vec![validator_definition], spec.clone()).await + ValidatorStoreRig::new( + vec![validator_definition], + slashing_protection_config, + false, + spec.clone(), + ) + .await }; let remote_signer_validator_store = { @@ -422,7 +457,13 @@ mod tests { client_identity_password: Some(client_identity_password()), }), }; - ValidatorStoreRig::new(vec![validator_definition], spec).await + ValidatorStoreRig::new( + vec![validator_definition], + slashing_protection_config, + true, + spec, + ) + .await }; Self { @@ -465,6 +506,36 @@ mod tests { assert!(prev_signature.is_some(), "sanity check"); self } + + /// Assert that a slashable message fails to be signed locally and is either signed or not + /// by the web3signer rig depending on the value of `web3signer_should_sign`. + pub async fn assert_slashable_message_should_sign( + self, + case_name: &str, + generate_sig: F, + web3signer_should_sign: bool, + ) -> Self + where + F: Fn(PublicKeyBytes, Arc>) -> R, + R: Future>, + { + for validator_rig in &self.validator_rigs { + let result = + generate_sig(self.validator_pubkey, validator_rig.validator_store.clone()) + .await; + + if !validator_rig.using_web3signer || !web3signer_should_sign { + let err = result.unwrap_err(); + assert!( + matches!(err, ValidatorStoreError::Slashable(_)), + "should not sign slashable {case_name}" + ); + } else { + assert_eq!(result, Ok(()), "should sign slashable {case_name}"); + } + } + self + } } /// Get a generic, arbitrary attestation for signing. @@ -503,155 +574,188 @@ mod tests { let network_config = Eth2NetworkConfig::constant(network).unwrap().unwrap(); let spec = &network_config.chain_spec::().unwrap(); - TestingRig::new(network, spec.clone(), listen_port) - .await - .assert_signatures_match("randao_reveal", |pubkey, validator_store| async move { + TestingRig::new( + network, + SlashingProtectionConfig::default(), + spec.clone(), + listen_port, + ) + .await + .assert_signatures_match("randao_reveal", |pubkey, validator_store| async move { + validator_store + .randao_reveal(pubkey, Epoch::new(0)) + .await + .unwrap() + }) + .await + .assert_signatures_match("beacon_block_base", |pubkey, validator_store| async move { + let block = BeaconBlock::Base(BeaconBlockBase::empty(spec)); + let block_slot = block.slot(); + validator_store + .sign_block(pubkey, block, block_slot) + .await + .unwrap() + }) + .await + .assert_signatures_match("attestation", |pubkey, validator_store| async move { + let mut attestation = get_attestation(); + validator_store + .sign_attestation(pubkey, 0, &mut attestation, Epoch::new(0)) + .await + .unwrap(); + attestation + }) + .await + .assert_signatures_match("signed_aggregate", |pubkey, validator_store| async move { + let attestation = get_attestation(); + validator_store + .produce_signed_aggregate_and_proof( + pubkey, + 0, + attestation, + SelectionProof::from(Signature::empty()), + ) + .await + .unwrap() + }) + .await + .assert_signatures_match("selection_proof", |pubkey, validator_store| async move { + validator_store + .produce_selection_proof(pubkey, Slot::new(0)) + .await + .unwrap() + }) + .await + .assert_signatures_match( + "validator_registration", + |pubkey, validator_store| async move { + let val_reg_data = get_validator_registration(pubkey); validator_store - .randao_reveal(pubkey, Epoch::new(0)) + .sign_validator_registration_data(val_reg_data) .await .unwrap() - }) - .await - .assert_signatures_match("beacon_block_base", |pubkey, validator_store| async move { - let block = BeaconBlock::Base(BeaconBlockBase::empty(spec)); - let block_slot = block.slot(); + }, + ) + .await; + } + + /// Test all the Altair types. + async fn test_altair_types(network: &str, listen_port: u16) { + let network_config = Eth2NetworkConfig::constant(network).unwrap().unwrap(); + let spec = &network_config.chain_spec::().unwrap(); + let altair_fork_slot = spec + .altair_fork_epoch + .unwrap() + .start_slot(E::slots_per_epoch()); + + TestingRig::new( + network, + SlashingProtectionConfig::default(), + spec.clone(), + listen_port, + ) + .await + .assert_signatures_match( + "beacon_block_altair", + |pubkey, validator_store| async move { + let mut altair_block = BeaconBlockAltair::empty(spec); + altair_block.slot = altair_fork_slot; validator_store - .sign_block(pubkey, block, block_slot) + .sign_block(pubkey, BeaconBlock::Altair(altair_block), altair_fork_slot) .await .unwrap() - }) - .await - .assert_signatures_match("attestation", |pubkey, validator_store| async move { - let mut attestation = get_attestation(); + }, + ) + .await + .assert_signatures_match( + "sync_selection_proof", + |pubkey, validator_store| async move { validator_store - .sign_attestation(pubkey, 0, &mut attestation, Epoch::new(0)) + .produce_sync_selection_proof(&pubkey, altair_fork_slot, SyncSubnetId::from(0)) .await - .unwrap(); - attestation - }) - .await - .assert_signatures_match("signed_aggregate", |pubkey, validator_store| async move { - let attestation = get_attestation(); + .unwrap() + }, + ) + .await + .assert_signatures_match( + "sync_committee_signature", + |pubkey, validator_store| async move { validator_store - .produce_signed_aggregate_and_proof( - pubkey, + .produce_sync_committee_signature(altair_fork_slot, Hash256::zero(), 0, &pubkey) + .await + .unwrap() + }, + ) + .await + .assert_signatures_match( + "signed_contribution_and_proof", + |pubkey, validator_store| async move { + let contribution = SyncCommitteeContribution { + slot: altair_fork_slot, + beacon_block_root: <_>::default(), + subcommittee_index: <_>::default(), + aggregation_bits: <_>::default(), + signature: AggregateSignature::empty(), + }; + validator_store + .produce_signed_contribution_and_proof( 0, - attestation, - SelectionProof::from(Signature::empty()), + pubkey, + contribution, + SyncSelectionProof::from(Signature::empty()), ) .await .unwrap() - }) - .await - .assert_signatures_match("selection_proof", |pubkey, validator_store| async move { + }, + ) + .await + .assert_signatures_match( + "validator_registration", + |pubkey, validator_store| async move { + let val_reg_data = get_validator_registration(pubkey); validator_store - .produce_selection_proof(pubkey, Slot::new(0)) + .sign_validator_registration_data(val_reg_data) .await .unwrap() - }) - .await - .assert_signatures_match( - "validator_registration", - |pubkey, validator_store| async move { - let val_reg_data = get_validator_registration(pubkey); - validator_store - .sign_validator_registration_data(val_reg_data) - .await - .unwrap() - }, - ) - .await; + }, + ) + .await; } - /// Test all the Altair types. - async fn test_altair_types(network: &str, listen_port: u16) { + /// Test all the Merge types. + async fn test_merge_types(network: &str, listen_port: u16) { let network_config = Eth2NetworkConfig::constant(network).unwrap().unwrap(); let spec = &network_config.chain_spec::().unwrap(); - let altair_fork_slot = spec - .altair_fork_epoch + let merge_fork_slot = spec + .bellatrix_fork_epoch .unwrap() .start_slot(E::slots_per_epoch()); - TestingRig::new(network, spec.clone(), listen_port) - .await - .assert_signatures_match( - "beacon_block_altair", - |pubkey, validator_store| async move { - let mut altair_block = BeaconBlockAltair::empty(spec); - altair_block.slot = altair_fork_slot; - validator_store - .sign_block(pubkey, BeaconBlock::Altair(altair_block), altair_fork_slot) - .await - .unwrap() - }, - ) - .await - .assert_signatures_match( - "sync_selection_proof", - |pubkey, validator_store| async move { - validator_store - .produce_sync_selection_proof( - &pubkey, - altair_fork_slot, - SyncSubnetId::from(0), - ) - .await - .unwrap() - }, - ) - .await - .assert_signatures_match( - "sync_committee_signature", - |pubkey, validator_store| async move { - validator_store - .produce_sync_committee_signature( - altair_fork_slot, - Hash256::zero(), - 0, - &pubkey, - ) - .await - .unwrap() - }, - ) - .await - .assert_signatures_match( - "signed_contribution_and_proof", - |pubkey, validator_store| async move { - let contribution = SyncCommitteeContribution { - slot: altair_fork_slot, - beacon_block_root: <_>::default(), - subcommittee_index: <_>::default(), - aggregation_bits: <_>::default(), - signature: AggregateSignature::empty(), - }; - validator_store - .produce_signed_contribution_and_proof( - 0, - pubkey, - contribution, - SyncSelectionProof::from(Signature::empty()), - ) - .await - .unwrap() - }, - ) - .await - .assert_signatures_match( - "validator_registration", - |pubkey, validator_store| async move { - let val_reg_data = get_validator_registration(pubkey); - validator_store - .sign_validator_registration_data(val_reg_data) - .await - .unwrap() - }, - ) - .await; + TestingRig::new( + network, + SlashingProtectionConfig::default(), + spec.clone(), + listen_port, + ) + .await + .assert_signatures_match("beacon_block_merge", |pubkey, validator_store| async move { + let mut merge_block = BeaconBlockMerge::empty(spec); + merge_block.slot = merge_fork_slot; + validator_store + .sign_block(pubkey, BeaconBlock::Merge(merge_block), merge_fork_slot) + .await + .unwrap() + }) + .await; } - /// Test all the Merge types. - async fn test_merge_types(network: &str, listen_port: u16) { + async fn test_lighthouse_slashing_protection( + slashing_protection_config: SlashingProtectionConfig, + listen_port: u16, + ) { + // Run these tests on mainnet. + let network = "mainnet"; + let network_config = Eth2NetworkConfig::constant(network).unwrap().unwrap(); let spec = &network_config.chain_spec::().unwrap(); let merge_fork_slot = spec @@ -659,17 +763,122 @@ mod tests { .unwrap() .start_slot(E::slots_per_epoch()); - TestingRig::new(network, spec.clone(), listen_port) - .await - .assert_signatures_match("beacon_block_merge", |pubkey, validator_store| async move { - let mut merge_block = BeaconBlockMerge::empty(spec); - merge_block.slot = merge_fork_slot; + // The slashable message should only be signed by the web3signer validator if slashing + // protection is disabled in Lighthouse. + let slashable_message_should_sign = !slashing_protection_config.local; + + let first_attestation = || { + let mut attestation = get_attestation(); + attestation.data.source.epoch = Epoch::new(1); + attestation.data.target.epoch = Epoch::new(4); + attestation + }; + + let double_vote_attestation = || { + let mut attestation = first_attestation(); + attestation.data.beacon_block_root = Hash256::from_low_u64_be(1); + attestation + }; + + let surrounding_attestation = || { + let mut attestation = first_attestation(); + attestation.data.source.epoch = Epoch::new(0); + attestation.data.target.epoch = Epoch::new(5); + attestation + }; + + let surrounded_attestation = || { + let mut attestation = first_attestation(); + attestation.data.source.epoch = Epoch::new(2); + attestation.data.target.epoch = Epoch::new(3); + attestation + }; + + let first_block = || { + let mut merge_block = BeaconBlockMerge::empty(spec); + merge_block.slot = merge_fork_slot; + BeaconBlock::Merge(merge_block) + }; + + let double_vote_block = || { + let mut block = first_block(); + *block.state_root_mut() = Hash256::repeat_byte(0xff); + block + }; + + let current_epoch = Epoch::new(5); + + TestingRig::new( + network, + slashing_protection_config, + spec.clone(), + listen_port, + ) + .await + .assert_signatures_match("first_attestation", |pubkey, validator_store| async move { + let mut attestation = first_attestation(); + validator_store + .sign_attestation(pubkey, 0, &mut attestation, current_epoch) + .await + .unwrap(); + attestation + }) + .await + .assert_slashable_message_should_sign( + "double_vote_attestation", + move |pubkey, validator_store| async move { + let mut attestation = double_vote_attestation(); validator_store - .sign_block(pubkey, BeaconBlock::Merge(merge_block), merge_fork_slot) + .sign_attestation(pubkey, 0, &mut attestation, current_epoch) .await - .unwrap() - }) - .await; + }, + slashable_message_should_sign, + ) + .await + .assert_slashable_message_should_sign( + "surrounding_attestation", + move |pubkey, validator_store| async move { + let mut attestation = surrounding_attestation(); + validator_store + .sign_attestation(pubkey, 0, &mut attestation, current_epoch) + .await + }, + slashable_message_should_sign, + ) + .await + .assert_slashable_message_should_sign( + "surrounded_attestation", + move |pubkey, validator_store| async move { + let mut attestation = surrounded_attestation(); + validator_store + .sign_attestation(pubkey, 0, &mut attestation, current_epoch) + .await + }, + slashable_message_should_sign, + ) + .await + .assert_signatures_match("first_block", |pubkey, validator_store| async move { + let block = first_block(); + let slot = block.slot(); + validator_store + .sign_block(pubkey, block, slot) + .await + .unwrap() + }) + .await + .assert_slashable_message_should_sign( + "double_vote_block", + move |pubkey, validator_store| async move { + let block = double_vote_block(); + let slot = block.slot(); + validator_store + .sign_block(pubkey, block, slot) + .await + .map(|_| ()) + }, + slashable_message_should_sign, + ) + .await; } #[tokio::test] @@ -707,36 +916,13 @@ mod tests { test_merge_types("sepolia", 4252).await } - // FIXME(sproul): actually write tests here - async fn test_lighthouse_slashing_protection( - _slashing_protection_enabled: bool, - listen_port: u16, - ) { - // Run these tests on mainnet. - let network = "mainnet"; - - let network_config = Eth2NetworkConfig::constant(network).unwrap().unwrap(); - let spec = &network_config.chain_spec::().unwrap(); - let merge_fork_slot = spec - .bellatrix_fork_epoch - .unwrap() - .start_slot(E::slots_per_epoch()); - - TestingRig::new(network, spec.clone(), listen_port) - .await - .assert_signatures_match("beacon_block_merge", |pubkey, validator_store| async move { - let mut merge_block = BeaconBlockMerge::empty(spec); - merge_block.slot = merge_fork_slot; - validator_store - .sign_block(pubkey, BeaconBlock::Merge(merge_block), merge_fork_slot) - .await - .unwrap() - }) - .await; + #[tokio::test] + async fn slashing_protection_disabled_locally() { + test_lighthouse_slashing_protection(SlashingProtectionConfig { local: false }, 4253).await } #[tokio::test] - async fn slashing_protection_disabled_everywhere() { - test_lighthouse_slashing_protection(false, 4253).await + async fn slashing_protection_enabled_locally() { + test_lighthouse_slashing_protection(SlashingProtectionConfig { local: true }, 4254).await } } From c5dd63407baee8321d506da3455857f3be4f1c9c Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Mon, 29 Jan 2024 11:25:58 +1100 Subject: [PATCH 05/12] Update help text --- validator_client/src/cli.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/validator_client/src/cli.rs b/validator_client/src/cli.rs index d6d5bc4fcfc..00e3a18f708 100644 --- a/validator_client/src/cli.rs +++ b/validator_client/src/cli.rs @@ -371,8 +371,8 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { Arg::with_name("disable-slashing-protection-web3signer") .long("disable-slashing-protection-web3signer") .help("Disable Lighthouse's slashing protection for all web3signer keys. This can \ - reduce the I/O burden on the VC and is safe as long as the remote signer \ - implements slashing protection correctly.") + reduce the I/O burden on the VC and is safe as long as slashing protection \ + is enabled on the remote signer and is implemented correctly.") .takes_value(true), ) } From 5e0f4854171b813f9f455565bc7f3b30c42b27b6 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Mon, 29 Jan 2024 11:30:08 +1100 Subject: [PATCH 06/12] Update book CLI text --- book/src/help_vc.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/book/src/help_vc.md b/book/src/help_vc.md index bc6deec1e99..9379789d359 100644 --- a/book/src/help_vc.md +++ b/book/src/help_vc.md @@ -96,6 +96,9 @@ OPTIONS: --debug-level Specifies the verbosity level used when emitting logs to the terminal. [default: info] [possible values: info, debug, trace, warn, error, crit] + --disable-slashing-protection-web3signer + Disable Lighthouse's slashing protection for all web3signer keys. This can reduce the I/O burden on the VC + and is safe as long as slashing protection is enabled on the remote signer and is implemented correctly. --gas-limit The gas limit to be used in all builder proposals for all validators managed by this validator client. Note this will not necessarily be used if the gas limit set here moves too far from the previous block's gas From 6bc70f5c2464b16740ea7cbc79b1b269a31885e9 Mon Sep 17 00:00:00 2001 From: Age Manning Date: Wed, 31 Jan 2024 18:44:37 +0000 Subject: [PATCH 07/12] Downgrade duplicate publish logs --- beacon_node/lighthouse_network/src/config.rs | 5 --- .../lighthouse_network/src/service/mod.rs | 35 +++++++++---------- beacon_node/src/cli.rs | 10 ------ beacon_node/src/config.rs | 3 -- book/src/help_bn.md | 5 --- book/src/redundancy.md | 4 --- lighthouse/tests/beacon_node.rs | 19 ---------- 7 files changed, 17 insertions(+), 64 deletions(-) diff --git a/beacon_node/lighthouse_network/src/config.rs b/beacon_node/lighthouse_network/src/config.rs index 86bae4331b7..93ab3d2d81b 100644 --- a/beacon_node/lighthouse_network/src/config.rs +++ b/beacon_node/lighthouse_network/src/config.rs @@ -157,10 +157,6 @@ pub struct Config { /// Configuration for the inbound rate limiter (requests received by this node). pub inbound_rate_limiter_config: Option, - - /// Whether to disable logging duplicate gossip messages as WARN. If set to true, duplicate - /// errors will be logged at DEBUG level. - pub disable_duplicate_warn_logs: bool, } impl Config { @@ -378,7 +374,6 @@ impl Default for Config { outbound_rate_limiter_config: None, invalid_block_storage: None, inbound_rate_limiter_config: None, - disable_duplicate_warn_logs: false, } } } diff --git a/beacon_node/lighthouse_network/src/service/mod.rs b/beacon_node/lighthouse_network/src/service/mod.rs index 5d35ed509db..73e414e946f 100644 --- a/beacon_node/lighthouse_network/src/service/mod.rs +++ b/beacon_node/lighthouse_network/src/service/mod.rs @@ -127,8 +127,6 @@ pub struct Network { gossip_cache: GossipCache, /// This node's PeerId. pub local_peer_id: PeerId, - /// Flag to disable warning logs for duplicate gossip messages and log at DEBUG level instead. - pub disable_duplicate_warn_logs: bool, /// Logger for behaviour actions. log: slog::Logger, } @@ -426,7 +424,6 @@ impl Network { update_gossipsub_scores, gossip_cache, local_peer_id, - disable_duplicate_warn_logs: config.disable_duplicate_warn_logs, log, }; @@ -745,21 +742,23 @@ impl Network { .gossipsub_mut() .publish(Topic::from(topic.clone()), message_data.clone()) { - if self.disable_duplicate_warn_logs && matches!(e, PublishError::Duplicate) { - debug!( - self.log, - "Could not publish message"; - "error" => ?e, - "kind" => %topic.kind(), - ); - } else { - warn!( - self.log, - "Could not publish message"; - "error" => ?e, - "kind" => %topic.kind(), - ); - }; + match e { + PublishError::Duplicate => { + debug!( + self.log, + "Attempted to publish duplicate message"; + "kind" => %topic.kind(), + ); + } + ref e => { + warn!( + self.log, + "Could not publish message"; + "error" => ?e, + "kind" => %topic.kind(), + ); + } + } // add to metrics match topic.kind() { diff --git a/beacon_node/src/cli.rs b/beacon_node/src/cli.rs index 002bb344a3e..6022eae39aa 100644 --- a/beacon_node/src/cli.rs +++ b/beacon_node/src/cli.rs @@ -1268,15 +1268,5 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .default_value("64") .takes_value(true) ) - .arg( - Arg::with_name("disable-duplicate-warn-logs") - .long("disable-duplicate-warn-logs") - .help("Disable warning logs for duplicate gossip messages. The WARN level log is \ - useful for detecting a duplicate validator key running elsewhere. However, this may \ - result in excessive warning logs if the validator is broadcasting messages to \ - multiple beacon nodes via the validator client --broadcast flag. In this case, \ - disabling these warn logs may be useful.") - .takes_value(false) - ) .group(ArgGroup::with_name("enable_http").args(&["http", "gui", "staking"]).multiple(true)) } diff --git a/beacon_node/src/config.rs b/beacon_node/src/config.rs index fff384e195f..b485775dbfe 100644 --- a/beacon_node/src/config.rs +++ b/beacon_node/src/config.rs @@ -1425,9 +1425,6 @@ pub fn set_network_config( Some(config_str.parse()?) } }; - - config.disable_duplicate_warn_logs = cli_args.is_present("disable-duplicate-warn-logs"); - Ok(()) } diff --git a/book/src/help_bn.md b/book/src/help_bn.md index dff2ab6876a..ec550a45ad5 100644 --- a/book/src/help_bn.md +++ b/book/src/help_bn.md @@ -32,11 +32,6 @@ FLAGS: --disable-deposit-contract-sync Explicitly disables syncing of deposit logs from the execution node. This overrides any previous option that depends on it. Useful if you intend to run a non-validating beacon node. - --disable-duplicate-warn-logs Disable warning logs for duplicate gossip messages. The WARN level log is - useful for detecting a duplicate validator key running elsewhere. - However, this may result in excessive warning logs if the validator is - broadcasting messages to multiple beacon nodes via the validator client - --broadcast flag. In this case, disabling these warn logs may be useful. -x, --disable-enr-auto-update Discovery automatically updates the nodes local ENR with an external IP address and port as seen by other peers on the network. This disables this feature, fixing the ENR's IP/PORT to those specified on boot. diff --git a/book/src/redundancy.md b/book/src/redundancy.md index 11b98456587..bd1976f9503 100644 --- a/book/src/redundancy.md +++ b/book/src/redundancy.md @@ -101,10 +101,6 @@ from this list: - `none`: Disable all broadcasting. This option only has an effect when provided alone, otherwise it is ignored. Not recommended except for expert tweakers. -Broadcasting attestation, blocks and sync committee messages may result in excessive warning logs in the beacon node -due to duplicate gossip messages. In this case, it may be desirable to disable warning logs for duplicates using the -beacon node `--disable-duplicate-warn-logs` flag. - The default is `--broadcast subscriptions`. To also broadcast blocks for example, use `--broadcast subscriptions,blocks`. diff --git a/lighthouse/tests/beacon_node.rs b/lighthouse/tests/beacon_node.rs index 3efcb2d0e5f..f97f17a6677 100644 --- a/lighthouse/tests/beacon_node.rs +++ b/lighthouse/tests/beacon_node.rs @@ -2584,22 +2584,3 @@ fn genesis_state_url_value() { assert_eq!(config.genesis_state_url_timeout, Duration::from_secs(42)); }); } - -#[test] -fn disable_duplicate_warn_logs_default() { - CommandLineTest::new() - .run_with_zero_port() - .with_config(|config| { - assert_eq!(config.network.disable_duplicate_warn_logs, false); - }); -} - -#[test] -fn disable_duplicate_warn_logs() { - CommandLineTest::new() - .flag("disable-duplicate-warn-logs", None) - .run_with_zero_port() - .with_config(|config| { - assert_eq!(config.network.disable_duplicate_warn_logs, true); - }); -} From 30eb70671aeb2c1969d3e831f35b1fc2a76ad5ca Mon Sep 17 00:00:00 2001 From: Jimmy Chen Date: Thu, 1 Feb 2024 10:46:12 +1100 Subject: [PATCH 08/12] Remove unused js file in Lighthouse book. --- book/src/js/deposit.js | 127 ----------------------------------------- 1 file changed, 127 deletions(-) delete mode 100644 book/src/js/deposit.js diff --git a/book/src/js/deposit.js b/book/src/js/deposit.js deleted file mode 100644 index 58895854f6a..00000000000 --- a/book/src/js/deposit.js +++ /dev/null @@ -1,127 +0,0 @@ -const NETWORK = "5"; -const NETWORK_NAME = "Goerli Test Network"; -const DEPOSIT_CONTRACT = "0x07b39F4fDE4A38bACe212b546dAc87C58DfE3fDC"; -const DEPOSIT_AMOUNT_ETH = "32"; -const GAS_LIMIT = "4000000"; -const DEPOSIT_DATA_BYTES = 420; - -let PREVIOUS_NON_ERROR_STATE = ""; - -$(document).ready(function(){ - if (typeof window.ethereum !== 'undefined') { - ethereum.on('networkChanged', function (accounts) { - checkNetwork() - }) - - PREVIOUS_NON_ERROR_STATE = "upload"; - checkNetwork() - } else { - console.error("No metamask detected!") - triggerError("Metamask is not installed.
Get Metamask.") - } - - $("#fileInput").change(function() { - openFile(this.files[0]) - }); - - $("#uploadButton").on("click", function() { - $("#fileInput").trigger("click"); - }); -}); - -function checkNetwork() { - if (window.ethereum.networkVersion === NETWORK) { - setUiState(PREVIOUS_NON_ERROR_STATE) - } else { - triggerError("Please set Metamask to use " + NETWORK_NAME + ".") - } -} - -function doDeposit(deposit_data) { - const ethereum = window.ethereum; - const utils = ethers.utils; - - let wei = utils.parseEther(DEPOSIT_AMOUNT_ETH); - let gasLimit = utils.bigNumberify(GAS_LIMIT); - - ethereum.enable() - .then(function (accounts) { - let params = [{ - "from": accounts[0], - "to": DEPOSIT_CONTRACT, - "gas": utils.hexlify(gasLimit), - "value": utils.hexlify(wei), - "data": deposit_data - }] - - ethereum.sendAsync({ - method: 'eth_sendTransaction', - params: params, - from: accounts[0], // Provide the user's account to use. - }, function (err, result) { - if (err !== null) { - triggerError("

" + err.message + "

Reload the window to try again.

") - } else { - let tx_hash = result.result; - $("#txLink").attr("href", "https://goerli.etherscan.io/tx/" + tx_hash); - setUiState("waiting"); - } - }) - }) - .catch(function (error) { - triggerError("Unable to get Metamask accounts.
Reload page to try again.") - }) - -} - -function openFile(file) { - var reader = new FileReader(); - - reader.onload = function () { - let data = reader.result; - if (data.startsWith("0x")) { - if (data.length === DEPOSIT_DATA_BYTES * 2 + 2) { - doDeposit(data) - } else { - triggerError("Invalid eth1_deposit_file. Bad length.") - } - } else { - triggerError("Invalid eth1_deposit_file. Did not start with 0x.") - } - } - - reader.readAsBinaryString(file); -} - -function triggerError(text) { - $("#errorText").html(text); - setUiState("error"); -} - -function setUiState(state) { - if (state === "upload") { - $('#uploadDiv').show(); - $('#depositDiv').hide(); - $('#waitingDiv').hide(); - $('#errorDiv').hide(); - } else if (state == "deposit") { - $('#uploadDiv').hide(); - $('#depositDiv').show(); - $('#waitingDiv').hide(); - $('#errorDiv').hide(); - } else if (state == "error") { - $('#uploadDiv').hide(); - $('#depositDiv').hide(); - $('#waitingDiv').hide(); - $('#errorDiv').show(); - } else if (state == "waiting") { - $('#uploadDiv').hide(); - $('#depositDiv').hide(); - $('#waitingDiv').show(); - $('#errorDiv').hide(); - } - - if (state !== "error") { - PREVIOUS_NON_ERROR_STATE = state; - } -} From 7e4b0e828f4c7bd24538fab0a27f0d115f799923 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Fri, 2 Feb 2024 13:32:17 +1100 Subject: [PATCH 09/12] More logging & CLI tests --- book/src/help_vc.md | 20 +++++++++++--------- lighthouse/tests/validator_client.rs | 17 +++++++++++++++++ validator_client/src/cli.rs | 7 +++++-- validator_client/src/config.rs | 12 +++++++++++- 4 files changed, 44 insertions(+), 12 deletions(-) diff --git a/book/src/help_vc.md b/book/src/help_vc.md index 2ca3f93924f..9a4e55b7455 100644 --- a/book/src/help_vc.md +++ b/book/src/help_vc.md @@ -13,7 +13,7 @@ FLAGS: --disable-auto-discover If present, do not attempt to discover new validators in the validators-dir. Validators will need to be manually added to the validator_definitions.yml file. - --disable-log-timestamp If present, do not include timestamps in logging output. + --disable-log-timestamp If present, do not include timestamps in logging output. --disable-malloc-tuning If present, do not configure the system allocator. Providing this flag will generally increase memory usage, it should only be provided when debugging specific memory allocation issues. @@ -21,6 +21,11 @@ FLAGS: DEPRECATED. Use --broadcast. By default, Lighthouse publishes attestation, sync committee subscriptions and proposer preparation messages to all beacon nodes provided in the `--beacon-nodes flag`. This option changes that behaviour such that these api calls only go out to the first available and synced beacon node + --disable-slashing-protection-web3signer + Disable Lighthouse's slashing protection for all web3signer keys. This can reduce the I/O burden on the VC + but is only safe if slashing protection is enabled on the remote signer and is implemented correctly. DO NOT + ENABLE THIS FLAG UNLESS YOU ARE CERTAIN THAT SLASHING PROTECTION IS ENABLED ON THE REMOTE SIGNER. IT IS OFF + BY DEFAULT, AND YOU WILL GET SLASHED IF YOU USE THIS FLAG WITHOUT ENABLING IT. --enable-doppelganger-protection If this flag is set, Lighthouse will delay startup for three epochs and monitor for messages on the network by any of the validators managed by this client. This will result in three (possibly four) epochs worth of @@ -32,8 +37,8 @@ FLAGS: Enable per validator metrics for > 64 validators. Note: This flag is automatically enabled for <= 64 validators. Enabling this metric for higher validator counts will lead to higher volume of prometheus metrics being collected. - -h, --help Prints help information - --http Enable the RESTful HTTP API server. Disabled by default. + -h, --help Prints help information + --http Enable the RESTful HTTP API server. Disabled by default. --http-allow-keystore-export If present, allow access to the DELETE /lighthouse/keystores HTTP API method, which allows exporting keystores and passwords to HTTP API consumers who have access to the API token. This method is useful for @@ -47,7 +52,7 @@ FLAGS: flag unless you're certain that a new slashing protection database is required. Usually, your database will have been initialized when you imported your validator keys. If you misplace your database and then run with this flag you risk being slashed. - --log-color Force outputting colors when emitting logs to the terminal. + --log-color Force outputting colors when emitting logs to the terminal. --logfile-compress If present, compress old log files. This can help reduce the space needed to store old logs. @@ -55,7 +60,7 @@ FLAGS: If present, log files will be generated as world-readable meaning they can be read by any user on the machine. Note that logs can often contain sensitive information about your validator and so this flag should be used with caution. For Windows users, the log file permissions will be inherited from the parent folder. - --metrics Enable the Prometheus metrics HTTP server. Disabled by default. + --metrics Enable the Prometheus metrics HTTP server. Disabled by default. --prefer-builder-proposals If this flag is set, Lighthouse will always prefer blocks constructed by builders, regardless of payload value. @@ -69,7 +74,7 @@ FLAGS: --use-long-timeouts If present, the validator client will use longer timeouts for requests made to the beacon node. This flag is generally not recommended, longer timeouts can cause missed duties when fallbacks are used. - -V, --version Prints version information + -V, --version Prints version information OPTIONS: --beacon-nodes @@ -96,9 +101,6 @@ OPTIONS: --debug-level Specifies the verbosity level used when emitting logs to the terminal. [default: info] [possible values: info, debug, trace, warn, error, crit] - --disable-slashing-protection-web3signer - Disable Lighthouse's slashing protection for all web3signer keys. This can reduce the I/O burden on the VC - and is safe as long as slashing protection is enabled on the remote signer and is implemented correctly. --gas-limit The gas limit to be used in all builder proposals for all validators managed by this validator client. Note this will not necessarily be used if the gas limit set here moves too far from the previous block's gas diff --git a/lighthouse/tests/validator_client.rs b/lighthouse/tests/validator_client.rs index 701aed07edc..764fd87ccdf 100644 --- a/lighthouse/tests/validator_client.rs +++ b/lighthouse/tests/validator_client.rs @@ -636,3 +636,20 @@ fn validator_registration_batch_size_zero_value() { .flag("validator-registration-batch-size", Some("0")) .run(); } + +#[test] +fn validator_disable_web3_signer_slashing_protection_default() { + CommandLineTest::new().run().with_config(|config| { + assert!(config.enable_web3signer_slashing_protection); + }); +} + +#[test] +fn validator_disable_web3_signer_slashing_protection() { + CommandLineTest::new() + .flag("disable-slashing-protection-web3signer", None) + .run() + .with_config(|config| { + assert!(!config.enable_web3signer_slashing_protection); + }); +} diff --git a/validator_client/src/cli.rs b/validator_client/src/cli.rs index 951533e4643..0951fc1c9ad 100644 --- a/validator_client/src/cli.rs +++ b/validator_client/src/cli.rs @@ -371,8 +371,11 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { Arg::with_name("disable-slashing-protection-web3signer") .long("disable-slashing-protection-web3signer") .help("Disable Lighthouse's slashing protection for all web3signer keys. This can \ - reduce the I/O burden on the VC and is safe as long as slashing protection \ - is enabled on the remote signer and is implemented correctly.") + reduce the I/O burden on the VC but is only safe if slashing protection \ + is enabled on the remote signer and is implemented correctly. DO NOT ENABLE \ + THIS FLAG UNLESS YOU ARE CERTAIN THAT SLASHING PROTECTION IS ENABLED ON \ + THE REMOTE SIGNER. IT IS OFF BY DEFAULT, AND YOU WILL GET SLASHED IF YOU \ + USE THIS FLAG WITHOUT ENABLING IT.") ) /* * Experimental/development options. diff --git a/validator_client/src/config.rs b/validator_client/src/config.rs index 7a49822fd3a..7ac9e3e3bc7 100644 --- a/validator_client/src/config.rs +++ b/validator_client/src/config.rs @@ -411,7 +411,17 @@ impl Config { } config.enable_web3signer_slashing_protection = - !cli_args.is_present("disable-slashing-protection-web3signer"); + if cli_args.is_present("disable-slashing-protection-web3signer") { + warn!( + log, + "Slashing protection for remote keys disabled"; + "info" => "ensure slashing protection on web3signer is enabled or you WILL \ + get slashed" + ); + false + } else { + true + }; Ok(config) } From afd7c74359979aac3ae2db992c517980f496e5b6 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Fri, 2 Feb 2024 15:11:51 +1100 Subject: [PATCH 10/12] CLI tweaks --- book/src/help_vc.md | 4 ++-- validator_client/src/cli.rs | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/book/src/help_vc.md b/book/src/help_vc.md index 9a4e55b7455..02819804315 100644 --- a/book/src/help_vc.md +++ b/book/src/help_vc.md @@ -24,8 +24,8 @@ FLAGS: --disable-slashing-protection-web3signer Disable Lighthouse's slashing protection for all web3signer keys. This can reduce the I/O burden on the VC but is only safe if slashing protection is enabled on the remote signer and is implemented correctly. DO NOT - ENABLE THIS FLAG UNLESS YOU ARE CERTAIN THAT SLASHING PROTECTION IS ENABLED ON THE REMOTE SIGNER. IT IS OFF - BY DEFAULT, AND YOU WILL GET SLASHED IF YOU USE THIS FLAG WITHOUT ENABLING IT. + ENABLE THIS FLAG UNLESS YOU ARE CERTAIN THAT SLASHING PROTECTION IS ENABLED ON THE REMOTE SIGNER. YOU WILL + GET SLASHED IF YOU USE THIS FLAG WITHOUT ENABLING WEB3SIGNER'S SLASHING PROTECTION. --enable-doppelganger-protection If this flag is set, Lighthouse will delay startup for three epochs and monitor for messages on the network by any of the validators managed by this client. This will result in three (possibly four) epochs worth of diff --git a/validator_client/src/cli.rs b/validator_client/src/cli.rs index 0951fc1c9ad..e4e5a2f1307 100644 --- a/validator_client/src/cli.rs +++ b/validator_client/src/cli.rs @@ -374,8 +374,9 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { reduce the I/O burden on the VC but is only safe if slashing protection \ is enabled on the remote signer and is implemented correctly. DO NOT ENABLE \ THIS FLAG UNLESS YOU ARE CERTAIN THAT SLASHING PROTECTION IS ENABLED ON \ - THE REMOTE SIGNER. IT IS OFF BY DEFAULT, AND YOU WILL GET SLASHED IF YOU \ - USE THIS FLAG WITHOUT ENABLING IT.") + THE REMOTE SIGNER. YOU WILL GET SLASHED IF YOU USE THIS FLAG WITHOUT \ + ENABLING WEB3SIGNER'S SLASHING PROTECTION.") + .takes_value(false) ) /* * Experimental/development options. From 0a947c79ba2deb72c8e0e85f267a0db588fea56d Mon Sep 17 00:00:00 2001 From: Age Manning Date: Sun, 4 Feb 2024 15:59:49 +0000 Subject: [PATCH 11/12] Maintain backwards compatiblity, deprecate flag --- beacon_node/src/cli.rs | 6 ++++++ lighthouse/tests/beacon_node.rs | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/beacon_node/src/cli.rs b/beacon_node/src/cli.rs index 6022eae39aa..4ed60d27b0f 100644 --- a/beacon_node/src/cli.rs +++ b/beacon_node/src/cli.rs @@ -1268,5 +1268,11 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .default_value("64") .takes_value(true) ) + .arg( + Arg::with_name("disable-duplicate-warn-logs") + .long("disable-duplicate-warn-logs") + .help("This flag is deprecated and has no effect.") + .takes_value(false) + ) .group(ArgGroup::with_name("enable_http").args(&["http", "gui", "staking"]).multiple(true)) } diff --git a/lighthouse/tests/beacon_node.rs b/lighthouse/tests/beacon_node.rs index f97f17a6677..3efcb2d0e5f 100644 --- a/lighthouse/tests/beacon_node.rs +++ b/lighthouse/tests/beacon_node.rs @@ -2584,3 +2584,22 @@ fn genesis_state_url_value() { assert_eq!(config.genesis_state_url_timeout, Duration::from_secs(42)); }); } + +#[test] +fn disable_duplicate_warn_logs_default() { + CommandLineTest::new() + .run_with_zero_port() + .with_config(|config| { + assert_eq!(config.network.disable_duplicate_warn_logs, false); + }); +} + +#[test] +fn disable_duplicate_warn_logs() { + CommandLineTest::new() + .flag("disable-duplicate-warn-logs", None) + .run_with_zero_port() + .with_config(|config| { + assert_eq!(config.network.disable_duplicate_warn_logs, true); + }); +} From 7c35e2a5a601bae4ffd37759af4d6905bec54b2e Mon Sep 17 00:00:00 2001 From: Age Manning Date: Mon, 5 Feb 2024 09:27:21 +0000 Subject: [PATCH 12/12] The tests had to go, because there's no config to test against --- lighthouse/tests/beacon_node.rs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/lighthouse/tests/beacon_node.rs b/lighthouse/tests/beacon_node.rs index 3efcb2d0e5f..f97f17a6677 100644 --- a/lighthouse/tests/beacon_node.rs +++ b/lighthouse/tests/beacon_node.rs @@ -2584,22 +2584,3 @@ fn genesis_state_url_value() { assert_eq!(config.genesis_state_url_timeout, Duration::from_secs(42)); }); } - -#[test] -fn disable_duplicate_warn_logs_default() { - CommandLineTest::new() - .run_with_zero_port() - .with_config(|config| { - assert_eq!(config.network.disable_duplicate_warn_logs, false); - }); -} - -#[test] -fn disable_duplicate_warn_logs() { - CommandLineTest::new() - .flag("disable-duplicate-warn-logs", None) - .run_with_zero_port() - .with_config(|config| { - assert_eq!(config.network.disable_duplicate_warn_logs, true); - }); -}