Skip to content

Commit

Permalink
Move function into test harness
Browse files Browse the repository at this point in the history
  • Loading branch information
paulhauner committed Apr 5, 2022
1 parent a119c77 commit 8be59d6
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 105 deletions.
72 changes: 0 additions & 72 deletions beacon_node/beacon_chain/src/beacon_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ use state_processing::{
state_advance::{complete_state_advance, partial_state_advance},
BlockSignatureStrategy, SigVerifiedOp, VerifyBlockRoot,
};
use std::borrow::Cow;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::collections::HashSet;
Expand Down Expand Up @@ -1711,77 +1710,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
})
}

/// 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`.
///
/// The attestation doesn't _really_ have anything about it that makes it unaggregated per say,
/// however this function is only required in the context of forming an unaggregated
/// attestation. It would be an (undetectable) violation of the protocol to create a
/// `SignedAggregateAndProof` based upon the output of this function.
pub fn produce_unaggregated_attestation_for_block(
&self,
slot: Slot,
index: CommitteeIndex,
beacon_block_root: Hash256,
mut state: Cow<BeaconState<T::EthSpec>>,
state_root: Hash256,
) -> Result<Attestation<T::EthSpec>, Error> {
// Only attest to a block if it is fully verified (i.e. not optimistic).
//
// If the head *is* optimistic, return an error without producing an attestation.
if self
.fork_choice
.read()
.get_block_execution_status(&beacon_block_root)
.ok_or(Error::HeadMissingFromForkChoice(beacon_block_root))?
.is_not_verified()
{
return Err(Error::CannotAttestToOptimisticHead { beacon_block_root });
}

let epoch = slot.epoch(T::EthSpec::slots_per_epoch());

if state.slot() > slot {
return Err(Error::CannotAttestToFutureState);
} else if state.current_epoch() < epoch {
let mut_state = state.to_mut();
// Only perform a "partial" state advance since we do not require the state roots to be
// accurate.
partial_state_advance(
mut_state,
Some(state_root),
epoch.start_slot(T::EthSpec::slots_per_epoch()),
&self.spec,
)?;
mut_state.build_committee_cache(RelativeEpoch::Current, &self.spec)?;
}

let committee_len = state.get_beacon_committee(slot, index)?.committee.len();

let target_slot = epoch.start_slot(T::EthSpec::slots_per_epoch());
let target_root = if state.slot() <= target_slot {
beacon_block_root
} else {
*state.get_block_root(target_slot)?
};

Ok(Attestation {
aggregation_bits: BitList::with_capacity(committee_len)?,
data: AttestationData {
slot,
index,
beacon_block_root,
source: state.current_justified_checkpoint(),
target: Checkpoint {
epoch,
root: target_root,
},
},
signature: AggregateSignature::empty(),
})
}

/// Performs the same validation as `Self::verify_unaggregated_attestation_for_gossip`, but for
/// multiple attestations using batch BLS verification. Batch verification can provide
/// significant CPU-time savings compared to individual verification.
Expand Down
77 changes: 66 additions & 11 deletions beacon_node/beacon_chain/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ use rayon::prelude::*;
use sensitive_url::SensitiveUrl;
use slog::Logger;
use slot_clock::TestingSlotClock;
use state_processing::{state_advance::complete_state_advance, StateRootStrategy};
use state_processing::{
state_advance::{complete_state_advance, partial_state_advance},
StateRootStrategy,
};
use std::borrow::Cow;
use std::collections::{HashMap, HashSet};
use std::str::FromStr;
Expand All @@ -42,15 +45,7 @@ use task_executor::ShutdownReason;
use tree_hash::TreeHash;
use types::sync_selection_proof::SyncSelectionProof;
pub use types::test_utils::generate_deterministic_keypairs;
use types::{
typenum::U4294967296, Address, AggregateSignature, Attestation, AttestationData,
AttesterSlashing, BeaconBlock, BeaconState, BeaconStateHash, ChainSpec, Checkpoint, Deposit,
DepositData, Domain, Epoch, EthSpec, ForkName, Graffiti, Hash256, IndexedAttestation, Keypair,
ProposerSlashing, PublicKeyBytes, SelectionProof, SignatureBytes, SignedAggregateAndProof,
SignedBeaconBlock, SignedBeaconBlockHash, SignedContributionAndProof, SignedRoot,
SignedVoluntaryExit, Slot, SubnetId, SyncCommittee, SyncCommitteeContribution,
SyncCommitteeMessage, VariableList, VoluntaryExit,
};
use types::{typenum::U4294967296, *};

// 4th September 2019
pub const HARNESS_GENESIS_TIME: u64 = 1_567_552_690;
Expand Down Expand Up @@ -685,6 +680,67 @@ where
(signed_block, pre_state)
}

/// 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`.
///
/// The attestation doesn't _really_ have anything about it that makes it unaggregated per say,
/// however this function is only required in the context of forming an unaggregated
/// attestation. It would be an (undetectable) violation of the protocol to create a
/// `SignedAggregateAndProof` based upon the output of this function.
///
/// This function will produce attestations to optimistic blocks, which is against the
/// specification but useful during testing.
pub fn produce_unaggregated_attestation_for_block(
&self,
slot: Slot,
index: CommitteeIndex,
beacon_block_root: Hash256,
mut state: Cow<BeaconState<E>>,
state_root: Hash256,
) -> Result<Attestation<E>, BeaconChainError> {
let epoch = slot.epoch(E::slots_per_epoch());

if state.slot() > slot {
return Err(BeaconChainError::CannotAttestToFutureState);
} else if state.current_epoch() < epoch {
let mut_state = state.to_mut();
// Only perform a "partial" state advance since we do not require the state roots to be
// accurate.
partial_state_advance(
mut_state,
Some(state_root),
epoch.start_slot(E::slots_per_epoch()),
&self.spec,
)?;
mut_state.build_committee_cache(RelativeEpoch::Current, &self.spec)?;
}

let committee_len = state.get_beacon_committee(slot, index)?.committee.len();

let target_slot = epoch.start_slot(E::slots_per_epoch());
let target_root = if state.slot() <= target_slot {
beacon_block_root
} else {
*state.get_block_root(target_slot)?
};

Ok(Attestation {
aggregation_bits: BitList::with_capacity(committee_len)?,
data: AttestationData {
slot,
index,
beacon_block_root,
source: state.current_justified_checkpoint(),
target: Checkpoint {
epoch,
root: target_root,
},
},
signature: AggregateSignature::empty(),
})
}

/// 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
Expand Down Expand Up @@ -716,7 +772,6 @@ where
return None;
}
let mut attestation = self
.chain
.produce_unaggregated_attestation_for_block(
attestation_slot,
bc.index,
Expand Down
22 changes: 0 additions & 22 deletions beacon_node/beacon_chain/tests/payload_invalidation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use execution_layer::{
};
use proto_array::ExecutionStatus;
use slot_clock::SlotClock;
use std::borrow::Cow;
use task_executor::ShutdownReason;
use tree_hash::TreeHash;
use types::*;
Expand Down Expand Up @@ -766,18 +765,6 @@ fn attesting_to_optimistic_head() {

let produce_unaggregated = || rig.harness.chain.produce_unaggregated_attestation(slot, 0);

let produce_unaggregated_for_block = || {
rig.harness
.chain
.produce_unaggregated_attestation_for_block(
slot,
0,
root,
Cow::Owned(head.beacon_state.clone()),
head.beacon_state_root(),
)
};

let attestation = {
let mut attestation = rig
.harness
Expand Down Expand Up @@ -826,14 +813,6 @@ fn attesting_to_optimistic_head() {
if beacon_block_root == root
));

assert!(matches!(
produce_unaggregated_for_block(),
Err(BeaconChainError::CannotAttestToOptimisticHead {
beacon_block_root
})
if beacon_block_root == root
));

assert_eq!(get_aggregated(), None);

assert_eq!(get_aggregated_by_slot_and_root(), None);
Expand All @@ -851,7 +830,6 @@ fn attesting_to_optimistic_head() {
);

produce_unaggregated().unwrap();
produce_unaggregated_for_block().unwrap();
get_aggregated().unwrap();
get_aggregated_by_slot_and_root().unwrap();
}

0 comments on commit 8be59d6

Please sign in to comment.