<commit_before>use super::attestation_parent_hashes::{attestation_parent_hashes, ParentHashesError};
use super::db::stores::{BeaconBlockAtSlotError, BeaconBlockStore, ValidatorStore};
use super::db::{ClientDB, DBError};
use super::message_generation::generate_signed_message;
use super::signature_verification::{
    verify_aggregate_signature_for_indices, SignatureVerificationError,
};
use super::types::Hash256;
use super::types::{AttestationRecord, AttesterMap};
use std::collections::HashSet;
use std::sync::Arc;

#[derive(Debug, PartialEq)]
pub enum AttestationValidationError {
    ParentSlotTooHigh,
    ParentSlotTooLow,
    BlockSlotTooHigh,
    BlockSlotTooLow,
    JustifiedSlotIncorrect,
    InvalidJustifiedBlockHash,
    TooManyObliqueHashes,
    BadCurrentHashes,
    BadObliqueHashes,
    BadAttesterMap,
    IntWrapping,
    PublicKeyCorrupt,
    NoPublicKeyForValidator,
    BadBitfieldLength,
    InvalidBitfield,
    InvalidBitfieldEndBits,
    NoSignatures,
    NonZeroTrailingBits,
    BadAggregateSignature,
    DBError(String),
    OutOfBoundsBitfieldIndex,
}

/// The context against which some attestation should be validated.
pub struct AttestationValidationContext<T>
where
    T: ClientDB + Sized,
{
    /// The slot as determined by the system time.
    pub block_slot: u64,
    /// The slot of the parent of the block that contained this attestation.
    pub parent_block_slot: u64,
    /// The cycle_length as determined by the chain configuration.
    pub cycle_length: u8,
    /// The last justified slot as per the client's view of the canonical chain.
    pub last_justified_slot: u64,
    /// A vec of the hashes of the blocks preceeding the present slot.
    pub recent_block_hashes: Arc<Vec<Hash256>>,
    /// The store containing block information.
    pub block_store: Arc<BeaconBlockStore<T>>,
    /// The store containing validator information.
    pub validator_store: Arc<ValidatorStore<T>>,
    /// A map of (slot, shard_id) to the attestation set of validation indices.
    pub attester_map: Arc<AttesterMap>,
}

impl<T> AttestationValidationContext<T>
where
    T: ClientDB,
{
    /// Validate a (fully deserialized) AttestationRecord against this context.
    ///
    /// The function will return a HashSet of validator indices (canonical validator indices not
    /// attestation indices) if the validation passed successfully, or an error otherwise.
    ///
    /// The attestation's aggregate signature will be verified, therefore the function must able to
    /// access all required validation public keys via the `validator_store`.
    pub fn validate_attestation(
        &self,
        a: &AttestationRecord,
    ) -> Result<HashSet<usize>, AttestationValidationError> {
        /*
         * The attesation slot must be less than or equal to the parent of the slot of the block
         * that contained the attestation.
         */
        if a.slot > self.parent_block_slot {
            return Err(AttestationValidationError::ParentSlotTooHigh);
        }

        /*
         * The slot of this attestation must not be more than cycle_length + 1 distance
         * from the parent_slot of block that contained it.
         */
        if a.slot < self
            .parent_block_slot
            .saturating_sub(u64::from(self.cycle_length).saturating_add(1))
        {
            return Err(AttestationValidationError::ParentSlotTooLow);<commit_msg>rustfmt edits<commit_after>use super::attestation_parent_hashes::{attestation_parent_hashes, ParentHashesError};
use super::db::stores::{BeaconBlockAtSlotError, BeaconBlockStore, ValidatorStore};
use super::db::{ClientDB, DBError};
use super::message_generation::generate_signed_message;
use super::signature_verification::{
    verify_aggregate_signature_for_indices, SignatureVerificationError,
};
use super::types::Hash256;
use super::types::{AttestationRecord, AttesterMap};
use std::collections::HashSet;
use std::sync::Arc;

#[derive(Debug, PartialEq)]
pub enum AttestationValidationError {
    ParentSlotTooHigh,
    ParentSlotTooLow,
    BlockSlotTooHigh,
    BlockSlotTooLow,
    JustifiedSlotIncorrect,
    InvalidJustifiedBlockHash,
    TooManyObliqueHashes,
    BadCurrentHashes,
    BadObliqueHashes,
    BadAttesterMap,
    IntWrapping,
    PublicKeyCorrupt,
    NoPublicKeyForValidator,
    BadBitfieldLength,
    InvalidBitfield,
    InvalidBitfieldEndBits,
    NoSignatures,
    NonZeroTrailingBits,
    BadAggregateSignature,
    DBError(String),
    OutOfBoundsBitfieldIndex,
}

/// The context against which some attestation should be validated.
pub struct AttestationValidationContext<T>
where
    T: ClientDB + Sized,
{
    /// The slot as determined by the system time.
    pub block_slot: u64,
    /// The slot of the parent of the block that contained this attestation.
    pub parent_block_slot: u64,
    /// The cycle_length as determined by the chain configuration.
    pub cycle_length: u8,
    /// The last justified slot as per the client's view of the canonical chain.
    pub last_justified_slot: u64,
    /// A vec of the hashes of the blocks preceeding the present slot.
    pub recent_block_hashes: Arc<Vec<Hash256>>,
    /// The store containing block information.
    pub block_store: Arc<BeaconBlockStore<T>>,
    /// The store containing validator information.
    pub validator_store: Arc<ValidatorStore<T>>,
    /// A map of (slot, shard_id) to the attestation set of validation indices.
    pub attester_map: Arc<AttesterMap>,
}

impl<T> AttestationValidationContext<T>
where
    T: ClientDB,
{
    /// Validate a (fully deserialized) AttestationRecord against this context.
    ///
    /// The function will return a HashSet of validator indices (canonical validator indices not
    /// attestation indices) if the validation passed successfully, or an error otherwise.
    ///
    /// The attestation's aggregate signature will be verified, therefore the function must able to
    /// access all required validation public keys via the `validator_store`.
    pub fn validate_attestation(
        &self,
        a: &AttestationRecord,
    ) -> Result<HashSet<usize>, AttestationValidationError> {
        /*
         * The attesation slot must be less than or equal to the parent of the slot of the block
         * that contained the attestation.
         */
        if a.slot > self.parent_block_slot {
            return Err(AttestationValidationError::ParentSlotTooHigh);
        }

        /*
         * The slot of this attestation must not be more than cycle_length + 1 distance
         * from the parent_slot of block that contained it.
         */
        if a.slot
            < self
                .parent_block_slot
                .saturating_sub(u64::from(self.cycle_length).saturating_add(1))
        {
            return Err(AttestationValidationError::ParentSlotTooLow);
{'fraction_non_alphanumeric': 0.08033888401986561, 'fraction_numerical': 0.004966403739409875, 'mean_word_length': 3.4003856041131106, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2008942', 'n_tokens_mistral': 1948, 'n_tokens_neox': 1893, 'n_words': 576}