From c7ef72d01e7ed6c32da6defbebe8818c47de0e44 Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Mon, 6 Jan 2025 16:30:58 +0700 Subject: [PATCH] Added more test coverage, simplified Attestation conversion, and other minor refactors --- .../src/attestation_verification.rs | 12 +- beacon_node/beacon_chain/src/beacon_chain.rs | 10 +- beacon_node/beacon_chain/src/test_utils.rs | 38 ++++--- beacon_node/http_api/src/lib.rs | 16 ++- .../http_api/src/publish_attestations.rs | 19 +++- .../http_api/tests/interactive_tests.rs | 104 +++++++----------- beacon_node/http_api/tests/tests.rs | 41 +++++-- .../src/network_beacon_processor/mod.rs | 8 +- common/eth2/src/lib.rs | 4 +- consensus/types/src/attestation.rs | 103 +++++++---------- .../src/attestation_tests.rs | 1 - .../src/attestation_service.rs | 13 ++- 12 files changed, 181 insertions(+), 188 deletions(-) diff --git a/beacon_node/beacon_chain/src/attestation_verification.rs b/beacon_node/beacon_chain/src/attestation_verification.rs index e0d99a7a90..cd284f557e 100644 --- a/beacon_node/beacon_chain/src/attestation_verification.rs +++ b/beacon_node/beacon_chain/src/attestation_verification.rs @@ -325,14 +325,16 @@ impl VerifiedUnaggregatedAttestation<'_, T> { self.indexed_attestation } - pub fn single_attestation(&self) -> SingleAttestation { - // TODO(single-attestation) unwrap - SingleAttestation { - committee_index: self.attestation.committee_index().unwrap_or(0) as usize, + pub fn single_attestation(&self) -> Option { + let Some(committee_index) = self.attestation.committee_index() else { + return None; + }; + Some(SingleAttestation { + committee_index: committee_index as usize, attester_index: self.validator_index, data: self.attestation.data().clone(), signature: self.attestation.signature().clone(), - } + }) } } diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index bafa911572..cb131c019c 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -2038,9 +2038,13 @@ impl BeaconChain { .spec .fork_name_at_slot::(v.attestation().data().slot); if current_fork.electra_enabled() { - event_handler.register(EventKind::SingleAttestation(Box::new( - v.single_attestation(), - ))); + // I don't see a situation where this could return None. The upstream unaggregated attestation checks + // should have already verified that this is an attestation with a single committee bit set. + if let Some(single_attestation) = v.single_attestation() { + event_handler.register(EventKind::SingleAttestation(Box::new( + single_attestation, + ))); + } } else { event_handler.register(EventKind::Attestation(Box::new( v.attestation().clone_as_attestation(), diff --git a/beacon_node/beacon_chain/src/test_utils.rs b/beacon_node/beacon_chain/src/test_utils.rs index 072d671284..de0e677528 100644 --- a/beacon_node/beacon_chain/src/test_utils.rs +++ b/beacon_node/beacon_chain/src/test_utils.rs @@ -668,8 +668,10 @@ pub type CommitteeAttestations = Vec<(Attestation, SubnetId)>; pub type HarnessAttestations = Vec<(CommitteeAttestations, Option>)>; -pub type HarnessSingleAttestations = - Vec<(CommitteeSingleAttestations, Option>)>; +pub type HarnessSingleAttestations = Vec<( + CommitteeSingleAttestations, + Option>, +)>; pub type HarnessSyncContributions = Vec<( Vec<(SyncCommitteeMessage, usize)>, @@ -1028,6 +1030,7 @@ where ) } + #[allow(clippy::too_many_arguments)] pub fn produce_single_attestation_for_block( &self, slot: Slot, @@ -1038,7 +1041,6 @@ where aggregation_bit_index: usize, validator_index: usize, ) -> Result { - let epoch = slot.epoch(E::slots_per_epoch()); if state.slot() > slot { @@ -1063,7 +1065,7 @@ where *state.get_block_root(target_slot)? }; - let mut attestation: Attestation = Attestation::empty_for_signing( + let attestation: Attestation = Attestation::empty_for_signing( index, committee_len, slot, @@ -1078,29 +1080,29 @@ where let attestation = match attestation { Attestation::Electra(mut attn) => { - attn.aggregation_bits.set(aggregation_bit_index, true).unwrap(); + attn.aggregation_bits + .set(aggregation_bit_index, true) + .unwrap(); attn - }, + } Attestation::Base(_) => panic!("MUST BE AN ELECTRA ATTESTATION"), }; - let committee = state.get_beacon_committee(slot, index)?; + let committee = state.get_beacon_committee(slot, index).unwrap(); - // let committees = state.get_beacon_committees_at_epoch(RelativeEpoch::Current)?; + let single_attestation = attestation.to_single_attestation(Some(committee.clone()))?; - let single_attestation = attestation.to_single_attestation( - &vec![committee.clone()] - )?; + let attestation: Attestation = single_attestation.to_attestation(Some(committee))?; - let attestation: Attestation = single_attestation.to_attestation(&vec![committee])?; - - assert_eq!(single_attestation.committee_index, attestation.committee_index().unwrap() as usize); + assert_eq!( + single_attestation.committee_index, + attestation.committee_index().unwrap() as usize + ); assert_eq!(single_attestation.attester_index, validator_index); // assert_eq!(single_attestation.attester_index, attestation.attester_index()); Ok(single_attestation) } - /// Produces an "unaggregated" attestation for the given `slot` and `index` that attests to /// `beacon_block_root`. The provided `state` should match the `block.state_root` for the /// `block` identified by `beacon_block_root`. @@ -1158,7 +1160,7 @@ where )?) } - /// A list of attestations for each committee for the given slot. + /// A list of attestations for each committee for the given slot. /// /// The first layer of the Vec is organised per committee. For example, if the return value is /// called `all_attestations`, then all attestations in `all_attestations[0]` will be for @@ -1255,7 +1257,7 @@ where Cow::Borrowed(state), state_root, i, - *validator_index + *validator_index, ) .unwrap(); @@ -1485,7 +1487,7 @@ where ) } - /// A list of attestations for each committee for the given slot. + /// A list of attestations for each committee for the given slot. /// /// The first layer of the Vec is organised per committee. For example, if the return value is /// called `all_attestations`, then all attestations in `all_attestations[0]` will be for diff --git a/beacon_node/http_api/src/lib.rs b/beacon_node/http_api/src/lib.rs index 7ce356e921..eb27cac4da 100644 --- a/beacon_node/http_api/src/lib.rs +++ b/beacon_node/http_api/src/lib.rs @@ -81,12 +81,13 @@ use tokio_stream::{ StreamExt, }; use types::{ - fork_versioned_response::EmptyMetadata, Attestation, AttestationData, AttestationShufflingId, - AttesterSlashing, BeaconStateError, CommitteeCache, ConfigAndPreset, Epoch, EthSpec, ForkName, - ForkVersionedResponse, Hash256, ProposerPreparationData, ProposerSlashing, RelativeEpoch, - SignedAggregateAndProof, SignedBlindedBeaconBlock, SignedBlsToExecutionChange, - SignedContributionAndProof, SignedValidatorRegistrationData, SignedVoluntaryExit, Slot, - SyncCommitteeMessage, SyncContributionData, attestation::SingleAttestation + attestation::SingleAttestation, fork_versioned_response::EmptyMetadata, Attestation, + AttestationData, AttestationShufflingId, AttesterSlashing, BeaconStateError, CommitteeCache, + ConfigAndPreset, Epoch, EthSpec, ForkName, ForkVersionedResponse, Hash256, + ProposerPreparationData, ProposerSlashing, RelativeEpoch, SignedAggregateAndProof, + SignedBlindedBeaconBlock, SignedBlsToExecutionChange, SignedContributionAndProof, + SignedValidatorRegistrationData, SignedVoluntaryExit, Slot, SyncCommitteeMessage, + SyncContributionData, }; use validator::pubkey_to_validator_index; use version::{ @@ -1879,9 +1880,6 @@ pub fn serve( .and(reprocess_send_filter) .and(log_filter.clone()) .then( - // V1 and V2 are identical except V2 has a consensus version header in the request. - // We only require this header for SSZ deserialization, which isn't supported for - // this endpoint presently. |task_spawner: TaskSpawner, chain: Arc>, attestations: Vec, diff --git a/beacon_node/http_api/src/publish_attestations.rs b/beacon_node/http_api/src/publish_attestations.rs index 5decbebbeb..2067ee66e5 100644 --- a/beacon_node/http_api/src/publish_attestations.rs +++ b/beacon_node/http_api/src/publish_attestations.rs @@ -100,10 +100,14 @@ fn verify_and_publish_attestation( attn.data.target.root, attn.data.slot.epoch(T::EthSpec::slots_per_epoch()), |committee_cache, _| { - let committees = - committee_cache.get_beacon_committees_at_slot(attn.data.slot)?; + let committee_index = attn + .committee_index() + .ok_or(BeaconChainError::AttestationCommitteeIndexNotSet)?; - let single_attestation = attn.to_single_attestation(&committees)?; + let committee = + committee_cache.get_beacon_committee(attn.data.slot, committee_index); + + let single_attestation = attn.to_single_attestation(committee)?; network_tx .send(NetworkMessage::Publish { @@ -166,6 +170,7 @@ pub async fn publish_single_attestations( log: Logger, ) -> Result<(), warp::Rejection> { let mut attestations = vec![]; + for single_attestation in single_attestations { let attestation = chain.with_committee_cache( single_attestation.data.target.root, @@ -174,10 +179,12 @@ pub async fn publish_single_attestations( .slot .epoch(T::EthSpec::slots_per_epoch()), |committee_cache, _| { - let committees = - committee_cache.get_beacon_committees_at_slot(single_attestation.data.slot)?; + let committee = committee_cache.get_beacon_committee( + single_attestation.data.slot, + single_attestation.committee_index as u64, + ); - let attestation = single_attestation.to_attestation::(&committees)?; + let attestation = single_attestation.to_attestation::(committee)?; Ok(attestation) }, diff --git a/beacon_node/http_api/tests/interactive_tests.rs b/beacon_node/http_api/tests/interactive_tests.rs index 2406458a1f..c174fa3509 100644 --- a/beacon_node/http_api/tests/interactive_tests.rs +++ b/beacon_node/http_api/tests/interactive_tests.rs @@ -858,53 +858,6 @@ pub async fn fork_choice_before_proposal() { assert_eq!(block_d.parent_root(), Hash256::from(block_root_b)); } -// Test that attestations to unknown blocks are requeued and processed when their block arrives. -#[tokio::test(flavor = "multi_thread", worker_threads = 1)] -async fn valid_single_attestation() { - let validator_count = 128; - let all_validators = (0..validator_count).collect::>(); - - let tester = InteractiveTester::::new(None, validator_count).await; - let harness = &tester.harness; - let client = tester.client.clone(); - - let num_initial = 5; - - // Slot of the block attested to. - let attestation_slot = Slot::new(num_initial) + 1; - - // Make some initial blocks. - harness.advance_slot(); - harness - .extend_chain( - num_initial as usize, - BlockStrategy::OnCanonicalHead, - AttestationStrategy::AllValidators, - ) - .await; - - harness.advance_slot(); - assert_eq!(harness.get_current_slot(), attestation_slot); - - // Make the attested-to block without applying it. - let pre_state = harness.get_current_state(); - let (block, post_state) = harness.make_block(pre_state, attestation_slot).await; - let block_root = block.0.canonical_root(); - - // Make attestations to the block and POST them to the beacon node on a background thread. - let attestations = harness - .make_single_attestations( - &all_validators, - &post_state, - block.0.state_root(), - block_root.into(), - attestation_slot, - ) - .into_iter() - .flat_map(|attestations| attestations.into_iter().map(|(att, _subnet)| att)) - .collect::>(); -} - // Test that attestations to unknown blocks are requeued and processed when their block arrives. #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn queue_attestations_from_http() { @@ -937,27 +890,48 @@ async fn queue_attestations_from_http() { let pre_state = harness.get_current_state(); let (block, post_state) = harness.make_block(pre_state, attestation_slot).await; let block_root = block.0.canonical_root(); + let fork_name = tester.harness.spec.fork_name_at_slot::(attestation_slot); // Make attestations to the block and POST them to the beacon node on a background thread. - let attestations = harness - .make_unaggregated_attestations( - &all_validators, - &post_state, - block.0.state_root(), - block_root.into(), - attestation_slot, - ) - .into_iter() - .flat_map(|attestations| attestations.into_iter().map(|(att, _subnet)| att)) - .collect::>(); + let attestation_future = if fork_name.electra_enabled() { + let single_attestations = harness + .make_single_attestations( + &all_validators, + &post_state, + block.0.state_root(), + block_root.into(), + attestation_slot, + ) + .into_iter() + .flat_map(|attestations| attestations.into_iter().map(|(att, _subnet)| att)) + .collect::>(); - let fork_name = tester.harness.spec.fork_name_at_slot::(attestation_slot); - let attestation_future = tokio::spawn(async move { - client - .post_beacon_pool_attestations_v1(&attestations) - .await - .expect("attestations should be processed successfully") - }); + tokio::spawn(async move { + client + .post_beacon_pool_attestations_v2(&single_attestations, fork_name) + .await + .expect("attestations should be processed successfully") + }) + } else { + let attestations = harness + .make_unaggregated_attestations( + &all_validators, + &post_state, + block.0.state_root(), + block_root.into(), + attestation_slot, + ) + .into_iter() + .flat_map(|attestations| attestations.into_iter().map(|(att, _subnet)| att)) + .collect::>(); + + tokio::spawn(async move { + client + .post_beacon_pool_attestations_v1(&attestations) + .await + .expect("attestations should be processed successfully") + }) + }; // In parallel, apply the block. We need to manually notify the reprocess queue, because the // `beacon_chain` does not know about the queue and will not update it for us. diff --git a/beacon_node/http_api/tests/tests.rs b/beacon_node/http_api/tests/tests.rs index 5dd997f176..a4f29c6f44 100644 --- a/beacon_node/http_api/tests/tests.rs +++ b/beacon_node/http_api/tests/tests.rs @@ -39,8 +39,9 @@ use tokio::time::Duration; use tree_hash::TreeHash; use types::application_domain::ApplicationDomain; use types::{ - attestation::AttestationBase, AggregateSignature, BitList, Domain, EthSpec, ExecutionBlockHash, - Hash256, Keypair, MainnetEthSpec, RelativeEpoch, SelectionProof, SignedRoot, Slot, + attestation::AttestationBase, attestation::SingleAttestation, AggregateSignature, BitList, + Domain, EthSpec, ExecutionBlockHash, Hash256, Keypair, MainnetEthSpec, RelativeEpoch, + SelectionProof, SignedRoot, Slot, }; type E = MainnetEthSpec; @@ -71,6 +72,7 @@ struct ApiTester { next_block: PublishBlockRequest, reorg_block: PublishBlockRequest, attestations: Vec>, + single_attestations: Vec, contribution_and_proofs: Vec>, attester_slashing: AttesterSlashing, proposer_slashing: ProposerSlashing, @@ -203,6 +205,27 @@ impl ApiTester { "precondition: attestations for testing" ); + let fork_name = harness + .chain + .spec + .fork_name_at_slot::(harness.chain.slot().unwrap()); + + let single_attestations = if fork_name.electra_enabled() { + harness + .get_single_attestations( + &AttestationStrategy::AllValidators, + &head.beacon_state, + head_state_root, + head.beacon_block_root, + harness.chain.slot().unwrap(), + ) + .into_iter() + .flat_map(|vec| vec.into_iter().map(|(attestation, _subnet_id)| attestation)) + .collect::>() + } else { + vec![] + }; + let current_epoch = harness .chain .slot() @@ -294,6 +317,7 @@ impl ApiTester { next_block, reorg_block, attestations, + single_attestations, contribution_and_proofs, attester_slashing, proposer_slashing, @@ -381,6 +405,7 @@ impl ApiTester { next_block, reorg_block, attestations, + single_attestations: vec![], contribution_and_proofs: vec![], attester_slashing, proposer_slashing, @@ -1801,12 +1826,12 @@ impl ApiTester { pub async fn test_post_beacon_pool_attestations_valid_v2(mut self) -> Self { let fork_name = self - .attestations + .single_attestations .first() - .map(|att| self.chain.spec.fork_name_at_slot::(att.data().slot)) + .map(|att| self.chain.spec.fork_name_at_slot::(att.data.slot)) .unwrap(); self.client - .post_beacon_pool_attestations_v1(self.attestations.as_slice()) + .post_beacon_pool_attestations_v2(self.single_attestations.as_slice(), fork_name) .await .unwrap(); assert!( @@ -1855,9 +1880,9 @@ impl ApiTester { } pub async fn test_post_beacon_pool_attestations_invalid_v2(mut self) -> Self { let mut attestations = Vec::new(); - for attestation in &self.attestations { + for attestation in &self.single_attestations { let mut invalid_attestation = attestation.clone(); - invalid_attestation.data_mut().slot += 1; + invalid_attestation.data.slot += 1; // add both to ensure we only fail on invalid attestations attestations.push(attestation.clone()); @@ -1872,7 +1897,7 @@ impl ApiTester { let err_v2 = self .client - .post_beacon_pool_attestations_v1(attestations.as_slice()) + .post_beacon_pool_attestations_v2(attestations.as_slice(), fork_name) .await .unwrap_err(); diff --git a/beacon_node/network/src/network_beacon_processor/mod.rs b/beacon_node/network/src/network_beacon_processor/mod.rs index cd32ac9ad2..6f53bed6c2 100644 --- a/beacon_node/network/src/network_beacon_processor/mod.rs +++ b/beacon_node/network/src/network_beacon_processor/mod.rs @@ -103,10 +103,12 @@ impl NetworkBeaconProcessor { .slot .epoch(T::EthSpec::slots_per_epoch()), |committee_cache, _| { - let committees = - committee_cache.get_beacon_committees_at_slot(single_attestation.data.slot)?; + let committee = committee_cache.get_beacon_committee( + single_attestation.data.slot, + single_attestation.committee_index as u64, + ); - let attestation = single_attestation.to_attestation(&committees)?; + let attestation = single_attestation.to_attestation(committee)?; Ok(self.send_unaggregated_attestation( message_id.clone(), diff --git a/common/eth2/src/lib.rs b/common/eth2/src/lib.rs index 3c76c35e1b..7cf644d92f 100644 --- a/common/eth2/src/lib.rs +++ b/common/eth2/src/lib.rs @@ -31,12 +31,12 @@ use reqwest_eventsource::{Event, EventSource}; pub use sensitive_url::{SensitiveError, SensitiveUrl}; use serde::{de::DeserializeOwned, Serialize}; use ssz::Encode; -use types::attestation::SingleAttestation; use std::fmt; use std::future::Future; use std::path::PathBuf; use std::time::Duration; use store::fork_versioned_response::ExecutionOptimisticFinalizedForkVersionedResponse; +use types::attestation::SingleAttestation; pub const V1: EndpointVersion = EndpointVersion(1); pub const V2: EndpointVersion = EndpointVersion(2); @@ -1325,7 +1325,7 @@ impl BeaconNodeHttpClient { } /// `POST v2/beacon/pool/attestations` - pub async fn post_beacon_pool_attestations_v2( + pub async fn post_beacon_pool_attestations_v2( &self, attestations: &[SingleAttestation], fork_name: ForkName, diff --git a/consensus/types/src/attestation.rs b/consensus/types/src/attestation.rs index a7ede26083..20bcedd350 100644 --- a/consensus/types/src/attestation.rs +++ b/consensus/types/src/attestation.rs @@ -25,6 +25,7 @@ pub enum Error { InvalidCommitteeLength, InvalidCommitteeIndex, InvalidAggregationBit, + InvalidCommittee, } impl From for Error { @@ -233,10 +234,13 @@ impl Attestation { } } - pub fn to_single_attestation_with_attester_index(&self, attester_index: usize) -> Result { + pub fn to_single_attestation_with_attester_index( + &self, + attester_index: usize, + ) -> Result { match self { Self::Base(_) => Err(Error::IncorrectStateVariant), - Self::Electra(attn) => attn.to_single_attestation_with_attester_index(attester_index) + Self::Electra(attn) => attn.to_single_attestation_with_attester_index(attester_index), } } } @@ -369,35 +373,30 @@ impl AttestationElectra { pub fn to_single_attestation_with_attester_index( &self, - attester_index: usize + attester_index: usize, ) -> Result { - let committee_indices = self.get_committee_indices(); - - if committee_indices.len() != 1 { - return Err(Error::InvalidCommitteeLength); - } - - let committee_index = *committee_indices - .first() - .ok_or(Error::InvalidCommitteeIndex)?; + let Some(committee_index) = self.committee_index() else { + return Err(Error::InvalidCommitteeIndex); + }; Ok(SingleAttestation { committee_index: committee_index as usize, attester_index, data: self.data.clone(), - signature: self.signature.clone() + signature: self.signature.clone(), }) } pub fn to_single_attestation( &self, - committees: &[BeaconCommittee], + committee: Option, ) -> Result { - let committee_indices = self.get_committee_indices(); - - if committee_indices.len() != 1 { - return Err(Error::InvalidCommitteeLength); - } + let Some(committee) = committee else { + return Err(Error::InvalidCommittee); + }; + let Some(committee_index) = self.committee_index() else { + return Err(Error::InvalidCommitteeIndex); + }; let aggregation_bits = self.get_aggregation_bits(); @@ -405,41 +404,22 @@ impl AttestationElectra { return Err(Error::InvalidAggregationBit); } - let committee_index = *committee_indices - .first() - .ok_or(Error::InvalidCommitteeIndex)?; - let aggregation_bit = *aggregation_bits .first() .ok_or(Error::InvalidAggregationBit)?; - println!("committees! {:?}", committees); - - let beacon_committee = committees - .get(committee_index as usize) - .ok_or(Error::InvalidCommitteeIndex)?; - - println!("agg bit {} committee index {}", aggregation_bit, committee_index); - - - println!("agg bit {}", aggregation_bit); - println!("agg bit {} committees {:?}", aggregation_bit, beacon_committee.committee); - let attester_index = beacon_committee + let attester_index = committee .committee .iter() .enumerate() .find_map(|(i, &index)| { - println!("agg bit {} val index {}", aggregation_bit, index); - println!("agg bit {} ith {}", aggregation_bit, i); if aggregation_bit as usize == i { - println!("agg bit {} RETURNED INDEX {}", aggregation_bit, index); return Some(index); } None }); - let attester_index = attester_index - .ok_or(Error::InvalidAggregationBit)?; + let attester_index = attester_index.ok_or(Error::InvalidAggregationBit)?; Ok(SingleAttestation { committee_index: committee_index as usize, @@ -647,7 +627,6 @@ pub struct SingleAttestation { impl SingleAttestation { /// Produces a `SingleAttestation` with empty signature and empty attester index. - /// ONLY USE IN ELECTRA pub fn empty_for_signing( committee_index: usize, slot: Slot, @@ -676,38 +655,34 @@ impl SingleAttestation { pub fn to_attestation( &self, - committees: &[BeaconCommittee], + committee: Option, ) -> Result, Error> { + let Some(committee) = committee else { + return Err(Error::InvalidCommittee); + }; - let mut committee_offset = 0; - let mut aggregation_bit: Option = None; - for beacon_committee in committees { - if beacon_committee.index == self.committee_index as u64 { - aggregation_bit = beacon_committee - .committee - .iter() - .enumerate() - .find_map(|(i, &validator_index)| { - if self.attester_index == validator_index { - return Some(i + committee_offset); - } - None - }); - committee_offset += beacon_committee.committee.len(); - break; - } else { - committee_offset += beacon_committee.committee.len(); - } + if committee.index != self.committee_index as u64 { + return Err(Error::InvalidCommittee); } - - let aggregation_bit = aggregation_bit.ok_or(Error::InvalidAggregationBit)?; + + let aggregation_bit = committee + .committee + .iter() + .enumerate() + .find_map(|(i, &validator_index)| { + if self.attester_index == validator_index { + return Some(i); + } + None + }) + .ok_or(Error::InvalidAggregationBit)?; let mut committee_bits: BitVector = BitVector::default(); committee_bits .set(self.committee_index, true) .map_err(|_| Error::InvalidCommitteeIndex)?; - let mut aggregation_bits = BitList::with_capacity(committee_offset) + let mut aggregation_bits = BitList::with_capacity(committee.committee.len()) .map_err(|_| Error::InvalidCommitteeLength)?; aggregation_bits.set(aggregation_bit, true)?; diff --git a/validator_client/slashing_protection/src/attestation_tests.rs b/validator_client/slashing_protection/src/attestation_tests.rs index 3f3782950c..b577ccd9d8 100644 --- a/validator_client/slashing_protection/src/attestation_tests.rs +++ b/validator_client/slashing_protection/src/attestation_tests.rs @@ -31,7 +31,6 @@ fn signed_att(attestation: &AttestationData) -> SignedAttestation { SignedAttestation::from_attestation(attestation, DEFAULT_DOMAIN) } - #[test] fn valid_empty_history() { StreamTest { diff --git a/validator_client/validator_services/src/attestation_service.rs b/validator_client/validator_services/src/attestation_service.rs index b8b33416c7..a40c10fd46 100644 --- a/validator_client/validator_services/src/attestation_service.rs +++ b/validator_client/validator_services/src/attestation_service.rs @@ -457,11 +457,16 @@ impl AttestationService { &[validator_metrics::ATTESTATIONS_HTTP_POST], ); if fork_name.electra_enabled() { - let single_attestations = attestations.iter().zip(validator_indices).filter_map(|(a, i)| { - a.to_single_attestation_with_attester_index(*i as usize).ok() - }).collect::>(); + let single_attestations = attestations + .iter() + .zip(validator_indices) + .filter_map(|(a, i)| { + a.to_single_attestation_with_attester_index(*i as usize) + .ok() + }) + .collect::>(); beacon_node - .post_beacon_pool_attestations_v2::(&single_attestations, fork_name) + .post_beacon_pool_attestations_v2(&single_attestations, fork_name) .await } else { beacon_node