def generate_seed(state: 'BeaconState', epoch: EpochNumber, epoch_length: int, seed_lookahead: int, entry_exit_delay: int, latest_index_roots_length: int, latest_randao_mixes_length: int) -> Hash32: """ Generate a seed for the given ``epoch``. """ randao_mix = get_randao_mix( state=state, epoch=EpochNumber(epoch - seed_lookahead), epoch_length=epoch_length, latest_randao_mixes_length=latest_randao_mixes_length, ) active_index_root = get_active_index_root( state=state, epoch=epoch, epoch_length=epoch_length, entry_exit_delay=entry_exit_delay, latest_index_roots_length=latest_index_roots_length, ) epoch_as_bytes = epoch.to_bytes(32, byteorder="little") return hash_eth2(randao_mix + active_index_root + epoch_as_bytes)
def _update_latest_index_roots(state: BeaconState, committee_config: CommitteeConfig) -> BeaconState: """ Return the BeaconState with updated `latest_index_roots`. """ next_epoch = state.next_epoch(committee_config.EPOCH_LENGTH) # TODO: chanege to hash_tree_root active_validator_indices = get_active_validator_indices( state.validator_registry, EpochNumber(next_epoch + committee_config.ENTRY_EXIT_DELAY), ) index_root = hash_eth2( b''.join( [ index.to_bytes(32, 'big') for index in active_validator_indices ] ) ) latest_index_roots = update_tuple_item( state.latest_index_roots, ( (next_epoch + committee_config.ENTRY_EXIT_DELAY) % committee_config.LATEST_INDEX_ROOTS_LENGTH ), index_root, ) return state.copy( latest_index_roots=latest_index_roots, )
def get_entry_exit_effect_epoch(epoch: EpochNumber, entry_exit_delay: int) -> EpochNumber: """ An entry or exit triggered in the ``epoch`` given by the input takes effect at the epoch given by the output. """ return EpochNumber(epoch + 1 + entry_exit_delay)
def get_shuffling(*, seed: Hash32, validators: Sequence['ValidatorRecord'], epoch: EpochNumber, epoch_length: int, target_committee_size: int, shard_count: int) -> Tuple[Iterable[ValidatorIndex], ...]: """ Shuffle ``validators`` into crosslink committees seeded by ``seed`` and ``epoch``. Return a list of ``committee_per_epoch`` committees where each committee is itself a list of validator indices. If ``get_shuffling(seed, validators, epoch)`` returns some value ``x`` for some ``epoch <= get_current_epoch(state) + ENTRY_EXIT_DELAY``, it should return the same value ``x`` for the same ``seed`` and ``epoch`` and possible future modifications of ``validators`` forever in phase 0, and until the ~1 year deletion delay in phase 2 and in the future. """ active_validator_indices = get_active_validator_indices(validators, epoch) committees_per_epoch = get_epoch_committee_count( len(active_validator_indices), shard_count, epoch_length, target_committee_size, ) # Shuffle seed = bitwise_xor(seed, Hash32(epoch.to_bytes(32, byteorder="big"))) shuffled_active_validator_indices = shuffle(active_validator_indices, seed) # Split the shuffled list into committees_per_epoch pieces return tuple( split( shuffled_active_validator_indices, committees_per_epoch, ))
def validate_randao_reveal(randao_reveal: BLSSignature, proposer_pubkey: BLSPubkey, epoch: EpochNumber, fork: Fork) -> None: message = epoch.to_bytes(32, byteorder="big") domain = get_domain(fork, epoch, SignatureDomain.DOMAIN_RANDAO) is_randao_reveal_valid = bls.verify( pubkey=proposer_pubkey, message=message, signature=randao_reveal, domain=domain, ) if not is_randao_reveal_valid: raise ValidationError( f"RANDAO reveal is invalid. " f"reveal={randao_reveal}, proposer_pubkey={proposer_pubkey}, message={message}, " f"domain={domain}")
from eth.constants import ( ZERO_HASH32, ) from eth2.beacon.typing import (BLSSignature, EpochNumber) # # shuffle function # # The size of 3 bytes in integer # sample_range = 2 ** (3 * 8) = 2 ** 24 = 16777216 # sample_range = 16777216 # Entropy is consumed from the seed in 3-byte (24 bit) chunks. RAND_BYTES = 3 # The highest possible result of the RNG. RAND_MAX = 2**(RAND_BYTES * 8) - 1 EMPTY_SIGNATURE = BLSSignature(b'\x00' * 96) GWEI_PER_ETH = 10**9 FAR_FUTURE_EPOCH = EpochNumber(2**64 - 1) GENESIS_PARENT_ROOT = ZERO_HASH32
def slot_to_epoch(slot: SlotNumber, epoch_length: int) -> EpochNumber: return EpochNumber(slot // epoch_length)
def next_epoch(self, epoch_length: int) -> EpochNumber: return EpochNumber(self.current_epoch(epoch_length) + 1)
def previous_epoch(self, epoch_length: int, genesis_epoch: int) -> EpochNumber: current_epoch: EpochNumber = self.current_epoch(epoch_length) return EpochNumber(current_epoch - 1) if current_epoch > genesis_epoch else current_epoch