From 3ea8476315bf8745dacabe59dbca1f7179328490 Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Sun, 25 Feb 2024 14:53:04 +0200 Subject: [PATCH 1/9] default vc to block v3 endpoint and deprecate block-v3 flag --- book/src/help_vc.md | 4 +- lighthouse/tests/validator_client.rs | 14 - validator_client/src/block_service.rs | 280 ++----------------- validator_client/src/cli.rs | 5 +- validator_client/src/config.rs | 7 - validator_client/src/http_metrics/metrics.rs | 1 - validator_client/src/validator_store.rs | 6 - 7 files changed, 29 insertions(+), 288 deletions(-) diff --git a/book/src/help_vc.md b/book/src/help_vc.md index 3d2519aac57..45a8f008335 100644 --- a/book/src/help_vc.md +++ b/book/src/help_vc.md @@ -68,9 +68,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 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. diff --git a/lighthouse/tests/validator_client.rs b/lighthouse/tests/validator_client.rs index 764fd87ccdf..65ffc4f005f 100644 --- a/lighthouse/tests/validator_client.rs +++ b/lighthouse/tests/validator_client.rs @@ -421,20 +421,6 @@ 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)); -} #[test] fn no_gas_limit_flag() { diff --git a/validator_client/src/block_service.rs b/validator_client/src/block_service.rs index 445d4f1a5d9..0d49f966ae0 100644 --- a/validator_client/src/block_service.rs +++ b/validator_client/src/block_service.rs @@ -323,105 +323,32 @@ impl BlockService { ) } - 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(()) } @@ -513,7 +440,7 @@ impl BlockService { Ok(()) } - async fn publish_block_v3( + async fn publish_block( self, slot: Slot, validator_pubkey: PublicKeyBytes, @@ -584,7 +511,7 @@ impl BlockService { &metrics::BLOCK_SERVICE_TIMES, &[metrics::BEACON_BLOCK_HTTP_GET], ); - let block_response = Self::get_validator_block_v3( + let block_response = Self::get_validator_block( beacon_node, slot, randao_reveal_ref, @@ -619,100 +546,6 @@ impl BlockService { 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?; - - self_ref - .sign_and_publish_block( - proposer_fallback, - slot, - graffiti, - &validator_pubkey, - unsigned_block, - ) - .await?; - - Ok(()) - } - async fn publish_signed_block_contents( &self, signed_block: &SignedBlock, @@ -745,7 +578,7 @@ impl BlockService { Ok::<_, BlockError>(()) } - async fn get_validator_block_v3( + async fn get_validator_block( beacon_node: &BeaconNodeHttpClient, slot: Slot, randao_reveal_ref: &SignatureBytes, @@ -788,65 +621,6 @@ impl BlockService { Ok::<_, BlockError>(unsigned_block) } - async fn get_validator_block( - beacon_node: &BeaconNodeHttpClient, - slot: Slot, - randao_reveal_ref: &SignatureBytes, - graffiti: Option, - proposer_index: Option, - builder_proposal: bool, - log: &Logger, - ) -> Result, 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::(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::(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: /// diff --git a/validator_client/src/cli.rs b/validator_client/src/cli.rs index 16a265212e5..982db381db0 100644 --- a/validator_client/src/cli.rs +++ b/validator_client/src/cli.rs @@ -139,10 +139,7 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .arg( Arg::with_name("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.") .takes_value(false) ) .arg( diff --git a/validator_client/src/config.rs b/validator_client/src/config.rs index ae59829a3e6..68244513d04 100644 --- a/validator_client/src/config.rs +++ b/validator_client/src/config.rs @@ -78,8 +78,6 @@ pub struct Config { pub validator_registration_batch_size: usize, /// Enable slashing protection even while using web3signer keys. pub enable_web3signer_slashing_protection: bool, - /// Enables block production via the block v3 endpoint. This configuration option can be removed post deneb. - pub produce_block_v3: bool, /// Specifies the boost factor, a percentage multiplier to apply to the builder's payload value. pub builder_boost_factor: Option, /// If true, Lighthouse will prefer builder proposals, if available. @@ -129,7 +127,6 @@ impl Default for Config { enable_latency_measurement_service: true, validator_registration_batch_size: 500, enable_web3signer_slashing_protection: true, - produce_block_v3: false, builder_boost_factor: None, prefer_builder_proposals: false, distributed: false, @@ -379,10 +376,6 @@ impl Config { config.builder_proposals = true; } - if cli_args.is_present("produce-block-v3") { - config.produce_block_v3 = true; - } - if cli_args.is_present("prefer-builder-proposals") { config.prefer_builder_proposals = true; } diff --git a/validator_client/src/http_metrics/metrics.rs b/validator_client/src/http_metrics/metrics.rs index 52b52126bd6..234c242fdf0 100644 --- a/validator_client/src/http_metrics/metrics.rs +++ b/validator_client/src/http_metrics/metrics.rs @@ -11,7 +11,6 @@ pub const UNREGISTERED: &str = "unregistered"; pub const FULL_UPDATE: &str = "full_update"; pub const BEACON_BLOCK: &str = "beacon_block"; pub const BEACON_BLOCK_HTTP_GET: &str = "beacon_block_http_get"; -pub const BLINDED_BEACON_BLOCK_HTTP_GET: &str = "blinded_beacon_block_http_get"; pub const BEACON_BLOCK_HTTP_POST: &str = "beacon_block_http_post"; pub const BLINDED_BEACON_BLOCK_HTTP_POST: &str = "blinded_beacon_block_http_post"; pub const ATTESTATIONS: &str = "attestations"; diff --git a/validator_client/src/validator_store.rs b/validator_client/src/validator_store.rs index b8c11a79bc0..006633e9d94 100644 --- a/validator_client/src/validator_store.rs +++ b/validator_client/src/validator_store.rs @@ -98,7 +98,6 @@ pub struct ValidatorStore { gas_limit: Option, builder_proposals: bool, enable_web3signer_slashing_protection: bool, - produce_block_v3: bool, prefer_builder_proposals: bool, builder_boost_factor: Option, task_executor: TaskExecutor, @@ -133,7 +132,6 @@ impl ValidatorStore { gas_limit: config.gas_limit, builder_proposals: config.builder_proposals, enable_web3signer_slashing_protection: config.enable_web3signer_slashing_protection, - produce_block_v3: config.produce_block_v3, prefer_builder_proposals: config.prefer_builder_proposals, builder_boost_factor: config.builder_boost_factor, task_executor, @@ -348,10 +346,6 @@ impl ValidatorStore { self.spec.fork_at_epoch(epoch) } - pub fn produce_block_v3(&self) -> bool { - self.produce_block_v3 - } - /// Returns a `SigningMethod` for `validator_pubkey` *only if* that validator is considered safe /// by doppelganger protection. fn doppelganger_checked_signing_method( From 0273c0587a13bfc54aa8c4f7751dccdc0b1c1ff1 Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Tue, 27 Feb 2024 18:31:28 +0200 Subject: [PATCH 2/9] add proposer and attester event variants --- beacon_node/beacon_chain/src/events.rs | 14 ++++++++++++++ common/eth2/src/types.rs | 17 +++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/beacon_node/beacon_chain/src/events.rs b/beacon_node/beacon_chain/src/events.rs index 0e5dfc80596..5c21372686a 100644 --- a/beacon_node/beacon_chain/src/events.rs +++ b/beacon_node/beacon_chain/src/events.rs @@ -20,6 +20,8 @@ pub struct ServerSentEventHandler { light_client_finality_update_tx: Sender>, light_client_optimistic_update_tx: Sender>, block_reward_tx: Sender>, + proposer_slashing_tx: Sender>, + attester_slashing_tx: Sender>, log: Logger, } @@ -45,6 +47,8 @@ impl ServerSentEventHandler { let (light_client_finality_update_tx, _) = broadcast::channel(capacity); let (light_client_optimistic_update_tx, _) = broadcast::channel(capacity); let (block_reward_tx, _) = broadcast::channel(capacity); + let (proposer_slashing_tx, _) = broadcast::channel(capacity); + let (attester_slashing_tx, _) = broadcast::channel(capacity); Self { attestation_tx, @@ -60,6 +64,8 @@ impl ServerSentEventHandler { light_client_finality_update_tx, light_client_optimistic_update_tx, block_reward_tx, + proposer_slashing_tx, + attester_slashing_tx, log, } } @@ -126,6 +132,14 @@ impl ServerSentEventHandler { .block_reward_tx .send(kind) .map(|count| log_count("block reward", count)), + EventKind::ProposerSlashing(_) => self + .proposer_slashing_tx + .send(kind) + .map(|count| log_count("proposer slashing", count)), + EventKind::AttesterSlashing(_) => self + .attester_slashing_tx + .send(kind) + .map(|count| log_count("attester slashing", count)), }; if let Err(SendError(event)) = result { trace!(self.log, "No receivers registered to listen for event"; "event" => ?event); diff --git a/common/eth2/src/types.rs b/common/eth2/src/types.rs index a301055f34c..5cfff58fc64 100644 --- a/common/eth2/src/types.rs +++ b/common/eth2/src/types.rs @@ -983,6 +983,19 @@ pub struct SseLateHead { pub execution_optimistic: bool, } +#[derive(PartialEq, Debug, Serialize, Deserialize, Clone)] +pub struct SseProposerSlashing { + pub signed_header_1: SignedBeaconBlockHeader, + pub signed_header_2: SignedBeaconBlockHeader, +} + +#[derive(PartialEq, Debug, Serialize, Deserialize, Clone)] +#[serde(bound = "E: EthSpec")] +pub struct SseAttesterSlashing { + pub attestation_1: Attestation, + pub attestation_2: Attestation, +} + #[superstruct( variants(V1, V2, V3), variant_attributes(derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)) @@ -1078,6 +1091,8 @@ pub enum EventKind { #[cfg(feature = "lighthouse")] BlockReward(BlockReward), PayloadAttributes(VersionedSsePayloadAttributes), + ProposerSlashing(SseProposerSlashing), + AttesterSlashing(SseAttesterSlashing), } impl EventKind { @@ -1097,6 +1112,8 @@ impl EventKind { EventKind::LightClientOptimisticUpdate(_) => "light_client_optimistic_update", #[cfg(feature = "lighthouse")] EventKind::BlockReward(_) => "block_reward", + EventKind::ProposerSlashing(_) => "proposer_slashing", + EventKind::AttesterSlashing(_) => "attester_slashing", } } From da00e0e433a773e0f40971a6415f3604736e0bac Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Tue, 27 Feb 2024 18:36:43 +0200 Subject: [PATCH 3/9] add TOOOs --- beacon_node/beacon_chain/src/test_utils.rs | 1 + beacon_node/beacon_chain/src/validator_monitor.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/beacon_node/beacon_chain/src/test_utils.rs b/beacon_node/beacon_chain/src/test_utils.rs index 6b85c8e4931..e9e816e809a 100644 --- a/beacon_node/beacon_chain/src/test_utils.rs +++ b/beacon_node/beacon_chain/src/test_utils.rs @@ -1654,6 +1654,7 @@ where { self.chain .import_attester_slashing(verified_attester_slashing); + // TODO add attester SSE Ok(()) } else { Err("should observe new attester slashing".to_string()) diff --git a/beacon_node/beacon_chain/src/validator_monitor.rs b/beacon_node/beacon_chain/src/validator_monitor.rs index 49a555816b8..807941047ba 100644 --- a/beacon_node/beacon_chain/src/validator_monitor.rs +++ b/beacon_node/beacon_chain/src/validator_monitor.rs @@ -1751,6 +1751,7 @@ impl ValidatorMonitor { } fn register_proposer_slashing(&self, src: &str, slashing: &ProposerSlashing) { + // TODO add proposer slashing SSE event let proposer = slashing.signed_header_1.message.proposer_index; let slot = slashing.signed_header_1.message.slot; let epoch = slot.epoch(T::slots_per_epoch()); @@ -1837,6 +1838,7 @@ impl ValidatorMonitor { validator.with_epoch_summary(epoch, |summary| summary.register_attester_slashing()); }) + // TODO add attester slashing event } /// Scrape `self` for metrics. From c1bacad45b5d33fb94ca822d59bc054fe7b20020 Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Wed, 28 Feb 2024 15:55:35 +0200 Subject: [PATCH 4/9] add tests, event triggers --- beacon_node/beacon_chain/src/beacon_chain.rs | 34 +++++++++++++++++ beacon_node/beacon_chain/src/builder.rs | 2 +- beacon_node/beacon_chain/src/events.rs | 16 ++++++++ beacon_node/http_api/src/lib.rs | 6 +++ beacon_node/http_api/tests/tests.rs | 40 ++++++++++++++++++++ common/eth2/src/types.rs | 34 +++++++++-------- 6 files changed, 116 insertions(+), 16 deletions(-) diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index 20a93e31e8d..e52bb2908b2 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -2440,6 +2440,15 @@ impl BeaconChain { proposer_slashing: ProposerSlashing, ) -> Result, Error> { let wall_clock_state = self.wall_clock_state()?; + + if let Some(event_handler) = self.event_handler.as_ref() { + if event_handler.has_proposer_slashing_subscribers() { + event_handler.register(EventKind::ProposerSlashing(Box::new( + proposer_slashing.clone(), + ))); + } + } + Ok(self.observed_proposer_slashings.lock().verify_and_observe( proposer_slashing, &wall_clock_state, @@ -2452,6 +2461,14 @@ impl BeaconChain { &self, proposer_slashing: SigVerifiedOp, ) { + if let Some(event_handler) = self.event_handler.as_ref() { + if event_handler.has_proposer_slashing_subscribers() { + event_handler.register(EventKind::ProposerSlashing(Box::new( + proposer_slashing.clone().into_inner(), + ))); + } + } + if self.eth1_chain.is_some() { self.op_pool.insert_proposer_slashing(proposer_slashing) } @@ -2463,6 +2480,15 @@ impl BeaconChain { attester_slashing: AttesterSlashing, ) -> Result, T::EthSpec>, Error> { let wall_clock_state = self.wall_clock_state()?; + + if let Some(event_handler) = self.event_handler.as_ref() { + if event_handler.has_attester_slashing_subscribers() { + event_handler.register(EventKind::AttesterSlashing(Box::new( + attester_slashing.clone(), + ))); + } + } + Ok(self.observed_attester_slashings.lock().verify_and_observe( attester_slashing, &wall_clock_state, @@ -2483,6 +2509,14 @@ impl BeaconChain { .fork_choice_write_lock() .on_attester_slashing(attester_slashing.as_inner()); + if let Some(event_handler) = self.event_handler.as_ref() { + if event_handler.has_attester_slashing_subscribers() { + event_handler.register(EventKind::AttesterSlashing(Box::new( + attester_slashing.clone().into_inner(), + ))); + } + } + // Add to the op pool (if we have the ability to propose blocks). if self.eth1_chain.is_some() { self.op_pool.insert_attester_slashing(attester_slashing) diff --git a/beacon_node/beacon_chain/src/builder.rs b/beacon_node/beacon_chain/src/builder.rs index dd4b612f60b..fbabac024d2 100644 --- a/beacon_node/beacon_chain/src/builder.rs +++ b/beacon_node/beacon_chain/src/builder.rs @@ -706,8 +706,8 @@ where .ok_or("Cannot build without a genesis state root")?; let validator_monitor_config = self.validator_monitor_config.unwrap_or_default(); let head_tracker = Arc::new(self.head_tracker.unwrap_or_default()); - let beacon_proposer_cache: Arc> = <_>::default(); + let mut validator_monitor = ValidatorMonitor::new( validator_monitor_config, beacon_proposer_cache.clone(), diff --git a/beacon_node/beacon_chain/src/events.rs b/beacon_node/beacon_chain/src/events.rs index 5c21372686a..6064335a3f7 100644 --- a/beacon_node/beacon_chain/src/events.rs +++ b/beacon_node/beacon_chain/src/events.rs @@ -198,6 +198,14 @@ impl ServerSentEventHandler { self.block_reward_tx.subscribe() } + pub fn subscribe_attester_slashing(&self) -> Receiver> { + self.attester_slashing_tx.subscribe() + } + + pub fn subscribe_proposer_slashing(&self) -> Receiver> { + self.proposer_slashing_tx.subscribe() + } + pub fn has_attestation_subscribers(&self) -> bool { self.attestation_tx.receiver_count() > 0 } @@ -241,4 +249,12 @@ impl ServerSentEventHandler { pub fn has_block_reward_subscribers(&self) -> bool { self.block_reward_tx.receiver_count() > 0 } + + pub fn has_proposer_slashing_subscribers(&self) -> bool { + self.proposer_slashing_tx.receiver_count() > 0 + } + + pub fn has_attester_slashing_subscribers(&self) -> bool { + self.attester_slashing_tx.receiver_count() > 0 + } } diff --git a/beacon_node/http_api/src/lib.rs b/beacon_node/http_api/src/lib.rs index a9b245e7987..26ec7dbf7e6 100644 --- a/beacon_node/http_api/src/lib.rs +++ b/beacon_node/http_api/src/lib.rs @@ -4348,6 +4348,12 @@ pub fn serve( api_types::EventTopic::BlockReward => { event_handler.subscribe_block_reward() } + api_types::EventTopic::AttesterSlashing => { + event_handler.subscribe_attester_slashing() + } + api_types::EventTopic::ProposerSlashing => { + event_handler.subscribe_proposer_slashing() + } }; receivers.push( diff --git a/beacon_node/http_api/tests/tests.rs b/beacon_node/http_api/tests/tests.rs index a7ba2c1ab86..5e4f6f78aab 100644 --- a/beacon_node/http_api/tests/tests.rs +++ b/beacon_node/http_api/tests/tests.rs @@ -5168,6 +5168,8 @@ impl ApiTester { EventTopic::Block, EventTopic::Head, EventTopic::FinalizedCheckpoint, + EventTopic::AttesterSlashing, + EventTopic::ProposerSlashing, ]; let mut events_future = self .client @@ -5307,6 +5309,44 @@ impl ApiTester { .await; assert_eq!(reorg_event.as_slice(), &[expected_reorg]); + let validator_indices = self.interesting_validator_indices(); + + // Test attester slashing event + let mut attester_slashing_event_future = self + .client + .get_events::(&[EventTopic::AttesterSlashing]) + .await + .unwrap(); + + self.harness.add_attester_slashing(vec![1, 2, 3]).unwrap(); + + let attester_slashing_event = poll_events( + &mut attester_slashing_event_future, + 1, + Duration::from_millis(10000), + ) + .await; + + assert!(attester_slashing_event.len() > 0); + + // Test proposer slashing event + let mut proposer_slashing_event_future = self + .client + .get_events::(&[EventTopic::ProposerSlashing]) + .await + .unwrap(); + + self.harness.add_proposer_slashing(1).unwrap(); + + let proposer_slashing_event = poll_events( + &mut proposer_slashing_event_future, + 1, + Duration::from_millis(10000), + ) + .await; + + assert!(proposer_slashing_event.len() > 0); + self } diff --git a/common/eth2/src/types.rs b/common/eth2/src/types.rs index 5cfff58fc64..679e735cbaf 100644 --- a/common/eth2/src/types.rs +++ b/common/eth2/src/types.rs @@ -983,19 +983,6 @@ pub struct SseLateHead { pub execution_optimistic: bool, } -#[derive(PartialEq, Debug, Serialize, Deserialize, Clone)] -pub struct SseProposerSlashing { - pub signed_header_1: SignedBeaconBlockHeader, - pub signed_header_2: SignedBeaconBlockHeader, -} - -#[derive(PartialEq, Debug, Serialize, Deserialize, Clone)] -#[serde(bound = "E: EthSpec")] -pub struct SseAttesterSlashing { - pub attestation_1: Attestation, - pub attestation_2: Attestation, -} - #[superstruct( variants(V1, V2, V3), variant_attributes(derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)) @@ -1091,8 +1078,8 @@ pub enum EventKind { #[cfg(feature = "lighthouse")] BlockReward(BlockReward), PayloadAttributes(VersionedSsePayloadAttributes), - ProposerSlashing(SseProposerSlashing), - AttesterSlashing(SseAttesterSlashing), + ProposerSlashing(Box), + AttesterSlashing(Box>), } impl EventKind { @@ -1125,6 +1112,7 @@ impl EventKind { let event = split .next() .ok_or_else(|| { + println!("{}", s); ServerError::InvalidServerSentEvent("Could not parse event tag".to_string()) })? .trim_start_matches("event:"); @@ -1194,6 +1182,16 @@ impl EventKind { "block_reward" => Ok(EventKind::BlockReward(serde_json::from_str(data).map_err( |e| ServerError::InvalidServerSentEvent(format!("Block Reward: {:?}", e)), )?)), + "attester_slashing" => Ok(EventKind::AttesterSlashing( + serde_json::from_str(data).map_err(|e| { + ServerError::InvalidServerSentEvent(format!("Attester Slashing: {:?}", e)) + })?, + )), + "proposer_slashing" => Ok(EventKind::ProposerSlashing( + serde_json::from_str(data).map_err(|e| { + ServerError::InvalidServerSentEvent(format!("Proposer Slashing: {:?}", e)) + })?, + )), _ => Err(ServerError::InvalidServerSentEvent( "Could not parse event tag".to_string(), )), @@ -1225,6 +1223,8 @@ pub enum EventTopic { LightClientOptimisticUpdate, #[cfg(feature = "lighthouse")] BlockReward, + AttesterSlashing, + ProposerSlashing, } impl FromStr for EventTopic { @@ -1246,6 +1246,8 @@ impl FromStr for EventTopic { "light_client_optimistic_update" => Ok(EventTopic::LightClientOptimisticUpdate), #[cfg(feature = "lighthouse")] "block_reward" => Ok(EventTopic::BlockReward), + "attester_slashing" => Ok(EventTopic::AttesterSlashing), + "proposer_slashing" => Ok(EventTopic::ProposerSlashing), _ => Err("event topic cannot be parsed.".to_string()), } } @@ -1268,6 +1270,8 @@ impl fmt::Display for EventTopic { EventTopic::LightClientOptimisticUpdate => write!(f, "light_client_optimistic_update"), #[cfg(feature = "lighthouse")] EventTopic::BlockReward => write!(f, "block_reward"), + EventTopic::AttesterSlashing => write!(f, "attester_slashing"), + EventTopic::ProposerSlashing => write!(f, "proposer_slashing"), } } } From d0f0f828eedb0167a2f98653d5a4837fbbca7abd Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Wed, 28 Feb 2024 16:07:29 +0200 Subject: [PATCH 5/9] revert --- .../beacon_chain/src/validator_monitor.rs | 2 - validator_client/src/block_service.rs | 280 ++++++++++++++++-- validator_client/src/cli.rs | 5 +- validator_client/src/config.rs | 7 + validator_client/src/http_metrics/metrics.rs | 1 + validator_client/src/validator_store.rs | 6 + 6 files changed, 271 insertions(+), 30 deletions(-) diff --git a/beacon_node/beacon_chain/src/validator_monitor.rs b/beacon_node/beacon_chain/src/validator_monitor.rs index 807941047ba..49a555816b8 100644 --- a/beacon_node/beacon_chain/src/validator_monitor.rs +++ b/beacon_node/beacon_chain/src/validator_monitor.rs @@ -1751,7 +1751,6 @@ impl ValidatorMonitor { } fn register_proposer_slashing(&self, src: &str, slashing: &ProposerSlashing) { - // TODO add proposer slashing SSE event let proposer = slashing.signed_header_1.message.proposer_index; let slot = slashing.signed_header_1.message.slot; let epoch = slot.epoch(T::slots_per_epoch()); @@ -1838,7 +1837,6 @@ impl ValidatorMonitor { validator.with_epoch_summary(epoch, |summary| summary.register_attester_slashing()); }) - // TODO add attester slashing event } /// Scrape `self` for metrics. diff --git a/validator_client/src/block_service.rs b/validator_client/src/block_service.rs index 0d49f966ae0..445d4f1a5d9 100644 --- a/validator_client/src/block_service.rs +++ b/validator_client/src/block_service.rs @@ -323,32 +323,105 @@ impl BlockService { ) } - 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" - ); + 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" + ); + } } - } - }, - "block service", - ) + }, + "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", + ) + } } + Ok(()) } @@ -440,7 +513,7 @@ impl BlockService { Ok(()) } - async fn publish_block( + async fn publish_block_v3( self, slot: Slot, validator_pubkey: PublicKeyBytes, @@ -511,7 +584,7 @@ impl BlockService { &metrics::BLOCK_SERVICE_TIMES, &[metrics::BEACON_BLOCK_HTTP_GET], ); - let block_response = Self::get_validator_block( + let block_response = Self::get_validator_block_v3( beacon_node, slot, randao_reveal_ref, @@ -546,6 +619,100 @@ impl BlockService { 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?; + + self_ref + .sign_and_publish_block( + proposer_fallback, + slot, + graffiti, + &validator_pubkey, + unsigned_block, + ) + .await?; + + Ok(()) + } + async fn publish_signed_block_contents( &self, signed_block: &SignedBlock, @@ -578,7 +745,7 @@ impl BlockService { Ok::<_, BlockError>(()) } - async fn get_validator_block( + async fn get_validator_block_v3( beacon_node: &BeaconNodeHttpClient, slot: Slot, randao_reveal_ref: &SignatureBytes, @@ -621,6 +788,65 @@ impl BlockService { Ok::<_, BlockError>(unsigned_block) } + async fn get_validator_block( + beacon_node: &BeaconNodeHttpClient, + slot: Slot, + randao_reveal_ref: &SignatureBytes, + graffiti: Option, + proposer_index: Option, + builder_proposal: bool, + log: &Logger, + ) -> Result, 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::(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::(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: /// diff --git a/validator_client/src/cli.rs b/validator_client/src/cli.rs index 982db381db0..16a265212e5 100644 --- a/validator_client/src/cli.rs +++ b/validator_client/src/cli.rs @@ -139,7 +139,10 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .arg( Arg::with_name("produce-block-v3") .long("produce-block-v3") - .help("This flag is deprecated and is no longer in use.") + .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.") .takes_value(false) ) .arg( diff --git a/validator_client/src/config.rs b/validator_client/src/config.rs index 68244513d04..ae59829a3e6 100644 --- a/validator_client/src/config.rs +++ b/validator_client/src/config.rs @@ -78,6 +78,8 @@ pub struct Config { pub validator_registration_batch_size: usize, /// Enable slashing protection even while using web3signer keys. pub enable_web3signer_slashing_protection: bool, + /// Enables block production via the block v3 endpoint. This configuration option can be removed post deneb. + pub produce_block_v3: bool, /// Specifies the boost factor, a percentage multiplier to apply to the builder's payload value. pub builder_boost_factor: Option, /// If true, Lighthouse will prefer builder proposals, if available. @@ -127,6 +129,7 @@ impl Default for Config { enable_latency_measurement_service: true, validator_registration_batch_size: 500, enable_web3signer_slashing_protection: true, + produce_block_v3: false, builder_boost_factor: None, prefer_builder_proposals: false, distributed: false, @@ -376,6 +379,10 @@ impl Config { config.builder_proposals = true; } + if cli_args.is_present("produce-block-v3") { + config.produce_block_v3 = true; + } + if cli_args.is_present("prefer-builder-proposals") { config.prefer_builder_proposals = true; } diff --git a/validator_client/src/http_metrics/metrics.rs b/validator_client/src/http_metrics/metrics.rs index 234c242fdf0..52b52126bd6 100644 --- a/validator_client/src/http_metrics/metrics.rs +++ b/validator_client/src/http_metrics/metrics.rs @@ -11,6 +11,7 @@ pub const UNREGISTERED: &str = "unregistered"; pub const FULL_UPDATE: &str = "full_update"; pub const BEACON_BLOCK: &str = "beacon_block"; pub const BEACON_BLOCK_HTTP_GET: &str = "beacon_block_http_get"; +pub const BLINDED_BEACON_BLOCK_HTTP_GET: &str = "blinded_beacon_block_http_get"; pub const BEACON_BLOCK_HTTP_POST: &str = "beacon_block_http_post"; pub const BLINDED_BEACON_BLOCK_HTTP_POST: &str = "blinded_beacon_block_http_post"; pub const ATTESTATIONS: &str = "attestations"; diff --git a/validator_client/src/validator_store.rs b/validator_client/src/validator_store.rs index 006633e9d94..b8c11a79bc0 100644 --- a/validator_client/src/validator_store.rs +++ b/validator_client/src/validator_store.rs @@ -98,6 +98,7 @@ pub struct ValidatorStore { gas_limit: Option, builder_proposals: bool, enable_web3signer_slashing_protection: bool, + produce_block_v3: bool, prefer_builder_proposals: bool, builder_boost_factor: Option, task_executor: TaskExecutor, @@ -132,6 +133,7 @@ impl ValidatorStore { gas_limit: config.gas_limit, builder_proposals: config.builder_proposals, enable_web3signer_slashing_protection: config.enable_web3signer_slashing_protection, + produce_block_v3: config.produce_block_v3, prefer_builder_proposals: config.prefer_builder_proposals, builder_boost_factor: config.builder_boost_factor, task_executor, @@ -346,6 +348,10 @@ impl ValidatorStore { self.spec.fork_at_epoch(epoch) } + pub fn produce_block_v3(&self) -> bool { + self.produce_block_v3 + } + /// Returns a `SigningMethod` for `validator_pubkey` *only if* that validator is considered safe /// by doppelganger protection. fn doppelganger_checked_signing_method( From 504635d800cc49a2806b73b5163a3b881bf39c85 Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Wed, 28 Feb 2024 16:09:25 +0200 Subject: [PATCH 6/9] revert --- book/src/help_vc.md | 4 +++- lighthouse/tests/validator_client.rs | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/book/src/help_vc.md b/book/src/help_vc.md index 45a8f008335..3d2519aac57 100644 --- a/book/src/help_vc.md +++ b/book/src/help_vc.md @@ -68,7 +68,9 @@ FLAGS: If this flag is set, Lighthouse will always prefer blocks constructed by builders, regardless of payload value. --produce-block-v3 - This flag is deprecated and no longer in use. + 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. --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. diff --git a/lighthouse/tests/validator_client.rs b/lighthouse/tests/validator_client.rs index 65ffc4f005f..764fd87ccdf 100644 --- a/lighthouse/tests/validator_client.rs +++ b/lighthouse/tests/validator_client.rs @@ -421,6 +421,20 @@ 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)); +} #[test] fn no_gas_limit_flag() { From a3e42d31e1a75d050544502d658543ef6d7c6d97 Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Tue, 12 Mar 2024 17:10:47 +0200 Subject: [PATCH 7/9] remove double event tracking --- beacon_node/beacon_chain/src/beacon_chain.rs | 16 ---------------- beacon_node/http_api/tests/tests.rs | 2 -- 2 files changed, 18 deletions(-) diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index e52bb2908b2..f32961ae254 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -2441,14 +2441,6 @@ impl BeaconChain { ) -> Result, Error> { let wall_clock_state = self.wall_clock_state()?; - if let Some(event_handler) = self.event_handler.as_ref() { - if event_handler.has_proposer_slashing_subscribers() { - event_handler.register(EventKind::ProposerSlashing(Box::new( - proposer_slashing.clone(), - ))); - } - } - Ok(self.observed_proposer_slashings.lock().verify_and_observe( proposer_slashing, &wall_clock_state, @@ -2481,14 +2473,6 @@ impl BeaconChain { ) -> Result, T::EthSpec>, Error> { let wall_clock_state = self.wall_clock_state()?; - if let Some(event_handler) = self.event_handler.as_ref() { - if event_handler.has_attester_slashing_subscribers() { - event_handler.register(EventKind::AttesterSlashing(Box::new( - attester_slashing.clone(), - ))); - } - } - Ok(self.observed_attester_slashings.lock().verify_and_observe( attester_slashing, &wall_clock_state, diff --git a/beacon_node/http_api/tests/tests.rs b/beacon_node/http_api/tests/tests.rs index 5e4f6f78aab..d57a7b2ab4a 100644 --- a/beacon_node/http_api/tests/tests.rs +++ b/beacon_node/http_api/tests/tests.rs @@ -5309,8 +5309,6 @@ impl ApiTester { .await; assert_eq!(reorg_event.as_slice(), &[expected_reorg]); - let validator_indices = self.interesting_validator_indices(); - // Test attester slashing event let mut attester_slashing_event_future = self .client From e2fdbc36c61894d520fcb636e1ba12ab56346c93 Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Wed, 3 Apr 2024 23:52:46 +0300 Subject: [PATCH 8/9] remove todo, fix test --- beacon_node/beacon_chain/src/test_utils.rs | 1 - beacon_node/http_api/tests/tests.rs | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/beacon_node/beacon_chain/src/test_utils.rs b/beacon_node/beacon_chain/src/test_utils.rs index e9e816e809a..6b85c8e4931 100644 --- a/beacon_node/beacon_chain/src/test_utils.rs +++ b/beacon_node/beacon_chain/src/test_utils.rs @@ -1654,7 +1654,6 @@ where { self.chain .import_attester_slashing(verified_attester_slashing); - // TODO add attester SSE Ok(()) } else { Err("should observe new attester slashing".to_string()) diff --git a/beacon_node/http_api/tests/tests.rs b/beacon_node/http_api/tests/tests.rs index d57a7b2ab4a..061b80f5a07 100644 --- a/beacon_node/http_api/tests/tests.rs +++ b/beacon_node/http_api/tests/tests.rs @@ -5325,7 +5325,7 @@ impl ApiTester { ) .await; - assert!(attester_slashing_event.len() > 0); + assert!(attester_slashing_event.len() == 1); // Test proposer slashing event let mut proposer_slashing_event_future = self @@ -5343,7 +5343,7 @@ impl ApiTester { ) .await; - assert!(proposer_slashing_event.len() > 0); + assert!(proposer_slashing_event.len() == 1); self } From e1a641414a4646c673e00701e39e6f18c89d1623 Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Thu, 4 Apr 2024 00:29:50 +0300 Subject: [PATCH 9/9] leftover debugging --- common/eth2/src/types.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/common/eth2/src/types.rs b/common/eth2/src/types.rs index 3d8dccbdf1c..773bfdbf740 100644 --- a/common/eth2/src/types.rs +++ b/common/eth2/src/types.rs @@ -1114,7 +1114,6 @@ impl EventKind { let event = split .next() .ok_or_else(|| { - println!("{}", s); ServerError::InvalidServerSentEvent("Could not parse event tag".to_string()) })? .trim_start_matches("event:");