pub fn shuffling_is_compatible(
        &self,
        block_root: &Hash256,
        target_epoch: Epoch,
        state: &BeaconState<T::EthSpec>,
    ) -> bool {
        let slots_per_epoch = T::EthSpec::slots_per_epoch();
        let shuffling_lookahead = 1 + self.spec.min_seed_lookahead.as_u64();

        // Shuffling can't have changed if we're in the first few epochs
        if state.current_epoch() < shuffling_lookahead {
            return true;
        }

        // Otherwise the shuffling is determined by the block at the end of the target epoch
        // minus the shuffling lookahead (usually 2). We call this the "pivot".
        let pivot_slot =
            if target_epoch == state.previous_epoch() || target_epoch == state.current_epoch() {
                (target_epoch - shuffling_lookahead).end_slot(slots_per_epoch)
            } else {
                return false;
            };

        let state_pivot_block_root = match state.get_block_root(pivot_slot) {
            Ok(root) => *root,
            Err(e) => {
                warn!(
                    &self.log,
                    "Missing pivot block root for attestation";
                    "slot" => pivot_slot,
                    "error" => ?e,
                );
                return false;
            }
        };

        // Use fork choice's view of the block DAG to quickly evaluate whether the attestation's
        // pivot block is the same as the current state's pivot block. If it is, then the
        // attestation's shuffling is the same as the current state's.
        // To account for skipped slots, find the first block at *or before* the pivot slot.
        let fork_choice_lock = self.fork_choice.read();
        let pivot_block_root = fork_choice_lock
            .proto_array()
            .core_proto_array()
            .iter_block_roots(block_root)
            .find(|(_, slot)| *slot <= pivot_slot)
            .map(|(block_root, _)| block_root);
        drop(fork_choice_lock);

        match pivot_block_root {
            Some(root) => root == state_pivot_block_root,
            None => {
                debug!(
                    &self.log,
                    "Discarding attestation because of missing ancestor";
                    "pivot_slot" => pivot_slot.as_u64(),
                    "block_root" => ?block_root,
                );
                false
            }
        }
    }
/// Check that the shuffling at `block_root` is equal to one of the shufflings of `state`.
///
/// The `target_epoch` argument determines which shuffling to check compatibility with, it
/// should be equal to the current or previous epoch of `state`, or else `false` will be
/// returned.
///
/// The compatibility check is designed to be fast: we check that the block that
/// determined the RANDAO mix for the `target_epoch` matches the ancestor of the block
/// identified by `block_root` (at that slot).
Check that the shuffling at `block_root` is equal to one of the shufflings of `state`.

The compatibility check is designed to be fast: we check that the block that
determined the RANDAO mix for the `target_epoch` matches the ancestor of the block
identified by `block_root` (at that slot).
Check that the shuffling at ` block_root ` is equal to one of the shufflings of ` state ` . The compatibility check is designed to be fast : we check that the block that determined the RANDAO mix for the ` target_epoch ` matches the ancestor of the block identified by ` block_root ` ( at that slot ) .
pub fn shuffling_is_compatible(
        &self,
        block_root: &Hash256,
        target_epoch: Epoch,
        state: &BeaconState<T::EthSpec>,
    ) -> bool {
        let slots_per_epoch = T::EthSpec::slots_per_epoch();
        let shuffling_lookahead = 1 + self.spec.min_seed_lookahead.as_u64();
        // Shuffling can't have changed if we're in the first few epochs
        if state.current_epoch() < shuffling_lookahead {
            return true;
        }
        // Otherwise the shuffling is determined by the block at the end of the target epoch
        // minus the shuffling lookahead (usually 2). We call this the "pivot".
        let pivot_slot =
            if target_epoch == state.previous_epoch() || target_epoch == state.current_epoch() {
                (target_epoch - shuffling_lookahead).end_slot(slots_per_epoch)
            } else {
                return false;
            };
        let state_pivot_block_root = match state.get_block_root(pivot_slot) {
            Ok(root) => *root,
            Err(e) => {
                warn!(
                    &self.log,
                    "Missing pivot block root for attestation";
                    "slot" => pivot_slot,
                    "error" => ?e,
                );
                return false;
            }
        };
        // Use fork choice's view of the block DAG to quickly evaluate whether the attestation's
        // pivot block is the same as the current state's pivot block. If it is, then the
        // attestation's shuffling is the same as the current state's.
        // To account for skipped slots, find the first block at *or before* the pivot slot.
        let fork_choice_lock = self.fork_choice.read();
        let pivot_block_root = fork_choice_lock
            .proto_array()
            .core_proto_array()
            .iter_block_roots(block_root)
            .find(|(_, slot)| *slot <= pivot_slot)
            .map(|(block_root, _)| block_root);
        drop(fork_choice_lock);
        match pivot_block_root {
            Some(root) => root == state_pivot_block_root,
            None => {
                debug!(
                    &self.log,
                    "Discarding attestation because of missing ancestor";
                    "pivot_slot" => pivot_slot.as_u64(),
                    "block_root" => ?block_root,
                );
                false
            }
        }
    }
pub fn shuffling_is_compatible ( & self , block_root : & Hash256 , target_epoch : Epoch , state : & BeaconState < T :: EthSpec > , ) -> bool { let slots_per_epoch = T :: EthSpec :: slots_per_epoch ( ) ; let shuffling_lookahead = 1 + self . spec . min_seed_lookahead . as_u64 ( ) ; // Shuffling can't have changed if we're in the first few epochs if state . current_epoch ( ) < shuffling_lookahead { return true ; } // Otherwise the shuffling is determined by the block at the end of the target epoch // minus the shuffling lookahead (usually 2). We call this the "pivot". let pivot_slot = if target_epoch == state . previous_epoch ( ) || target_epoch == state . current_epoch ( ) { ( target_epoch - shuffling_lookahead ) . end_slot ( slots_per_epoch ) } else { return false ; } ; let state_pivot_block_root = match state . get_block_root ( pivot_slot ) { Ok ( root ) => * root , Err ( e ) => { warn ! ( self log " " " " pivot_slot " " e ) ; return false ; } } ; // Use fork choice's view of the block DAG to quickly evaluate whether the attestation's // pivot block is the same as the current state's pivot block. If it is, then the // attestation's shuffling is the same as the current state's. // To account for skipped slots, find the first block at *or before* the pivot slot. let fork_choice_lock = self . fork_choice . read ( ) ; let pivot_block_root = fork_choice_lock . proto_array ( ) . core_proto_array ( ) . iter_block_roots ( block_root ) . find ( | ( _ , slot ) | * slot <= pivot_slot ) . map ( | ( block_root , _ ) | block_root ) ; drop ( fork_choice_lock ) ; match pivot_block_root { Some ( root ) => root == state_pivot_block_root , None => { debug ! ( self log " " " " pivot_slot as_u64 ( ) " " block_root ) ; false } } }
Check that the shuffling at `block_root` is equal to one of the shufflings of `state`.
Check that the shuffling at ` block_root ` is equal to one of the shufflings of ` state ` .
&self
block_root
&Hash256
target_epoch
Epoch
state
&BeaconState<T::EthSpec>