Exemplo n.º 1
0
def process_final_updates(state: BeaconState,
                          config: Eth2Config) -> BeaconState:
    new_eth1_data_votes = _determine_next_eth1_votes(state, config)
    new_validators = _update_effective_balances(state, config)
    new_start_shard = _compute_next_start_shard(state, config)
    new_active_index_roots = _compute_next_active_index_roots(state, config)
    new_compact_committees_roots = _compute_next_compact_committees_roots(
        state.copy(validators=new_validators, start_shard=new_start_shard),
        config)
    new_slashings = _compute_next_slashings(state, config)
    new_randao_mixes = _compute_next_randao_mixes(state, config)
    new_historical_roots = _compute_next_historical_roots(state, config)

    return state.copy(
        eth1_data_votes=new_eth1_data_votes,
        validators=new_validators,
        start_shard=new_start_shard,
        active_index_roots=new_active_index_roots,
        compact_committees_roots=new_compact_committees_roots,
        slashings=new_slashings,
        randao_mixes=new_randao_mixes,
        historical_roots=new_historical_roots,
        previous_epoch_attestations=state.current_epoch_attestations,
        current_epoch_attestations=tuple(),
    )
Exemplo n.º 2
0
def exit_validator(state: BeaconState, index: ValidatorIndex,
                   epoch_length: int, entry_exit_delay: int) -> BeaconState:
    """
    Exit the validator with the given ``index``.
    Return the updated state (immutable).
    """
    validator = state.validator_registry[index]

    entry_exit_effect_epoch = get_entry_exit_effect_epoch(
        state.current_epoch(epoch_length),
        entry_exit_delay,
    )

    # The following updates only occur if not previous exited
    if validator.exit_epoch <= entry_exit_effect_epoch:
        return state

    # Update state.validator_registry_exit_count
    state = state.copy(
        validator_registry_exit_count=state.validator_registry_exit_count +
        1, )

    # Update validator.exit_epoch and exit_epoch.exit_count
    validator = validator.copy(
        exit_epoch=state.current_epoch(epoch_length) + entry_exit_delay,
        exit_count=state.validator_registry_exit_count,
    )
    state = state.update_validator_registry(index, validator)

    return state
Exemplo n.º 3
0
def _determine_new_justified_epoch_and_bitfield(
        state: BeaconState, config: Eth2Config) -> Tuple[Epoch, Bitfield]:
    genesis_epoch = config.GENESIS_EPOCH
    previous_epoch = state.previous_epoch(config.SLOTS_PER_EPOCH,
                                          genesis_epoch)
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)

    previous_epoch_justifiable = _is_epoch_justifiable(state, previous_epoch,
                                                       config)
    current_epoch_justifiable = _is_epoch_justifiable(state, current_epoch,
                                                      config)

    (
        new_current_justified_epoch,
        justification_bits,
    ) = _determine_updated_justifications(
        previous_epoch_justifiable,
        previous_epoch,
        current_epoch_justifiable,
        current_epoch,
        state.current_justified_checkpoint.epoch,
        (False, ) + state.justification_bits[:-1],
    )

    return (new_current_justified_epoch, justification_bits)
Exemplo n.º 4
0
def process_randao(state: BeaconState, block: BaseBeaconBlock,
                   config: Eth2Config) -> BeaconState:
    proposer_index = get_beacon_proposer_index(
        state=state, committee_config=CommitteeConfig(config))

    epoch = state.current_epoch(config.SLOTS_PER_EPOCH)

    validate_randao_reveal(
        state=state,
        proposer_index=proposer_index,
        epoch=epoch,
        randao_reveal=block.body.randao_reveal,
        slots_per_epoch=config.SLOTS_PER_EPOCH,
    )

    randao_mix_index = epoch % config.EPOCHS_PER_HISTORICAL_VECTOR
    new_randao_mix = bitwise_xor(
        get_randao_mix(
            state=state,
            epoch=epoch,
            epochs_per_historical_vector=config.EPOCHS_PER_HISTORICAL_VECTOR,
        ),
        hash_eth2(block.body.randao_reveal),
    )

    return state.copy(randao_mixes=update_tuple_item(
        state.randao_mixes, randao_mix_index, new_randao_mix))
Exemplo n.º 5
0
def _validate_attestation_data(state: BeaconState, data: AttestationData,
                               config: Eth2Config) -> None:
    slots_per_epoch = config.SLOTS_PER_EPOCH
    current_epoch = state.current_epoch(slots_per_epoch)
    previous_epoch = state.previous_epoch(slots_per_epoch,
                                          config.GENESIS_EPOCH)

    attestation_slot = data.slot

    if data.target.epoch == current_epoch:
        expected_checkpoint = state.current_justified_checkpoint
    else:
        expected_checkpoint = state.previous_justified_checkpoint

    _validate_eligible_committee_index(
        state,
        attestation_slot,
        data.index,
        config.MAX_COMMITTEES_PER_SLOT,
        config.SLOTS_PER_EPOCH,
        config.TARGET_COMMITTEE_SIZE,
    )

    _validate_eligible_target_epoch(data.target.epoch, current_epoch,
                                    previous_epoch)
    _validate_slot_matches_target_epoch(data.target.epoch, attestation_slot,
                                        slots_per_epoch)
    validate_attestation_slot(
        attestation_slot,
        state.slot,
        slots_per_epoch,
        config.MIN_ATTESTATION_INCLUSION_DELAY,
    )
    _validate_checkpoint(data.source, expected_checkpoint)
Exemplo n.º 6
0
def process_cache_state(state: BeaconState, config: Eth2Config) -> BeaconState:
    slots_per_historical_root = config.SLOTS_PER_HISTORICAL_ROOT

    # Update state.latest_state_roots
    latest_state_root = state.root
    updated_latest_state_roots = _update_historical_root(
        state.latest_state_roots,
        state.slot,
        slots_per_historical_root,
        latest_state_root,
    )

    if state.latest_block_header.state_root == ZERO_HASH32:
        latest_block_header = state.latest_block_header
        state = state.copy(
            latest_block_header=latest_block_header.copy(
                state_root=latest_state_root,
            ),
        )

    # Update state.latest_block_roots
    updated_latest_block_roots = _update_historical_root(
        state.latest_block_roots,
        state.slot,
        slots_per_historical_root,
        state.latest_block_header.signing_root,
    )

    state = state.copy(
        latest_block_roots=updated_latest_block_roots,
        latest_state_roots=updated_latest_state_roots,
    )

    return state
Exemplo n.º 7
0
def create_mock_attester_slashing_is_surround_vote(
    state: BeaconState,
    config: Eth2Config,
    keymap: Dict[BLSPubkey, int],
    attestation_epoch: Epoch,
) -> AttesterSlashing:
    # target_epoch_2 < target_epoch_1
    attestation_slot_2 = compute_start_slot_at_epoch(attestation_epoch,
                                                     config.SLOTS_PER_EPOCH)
    attestation_slot_1 = Slot(attestation_slot_2 + config.SLOTS_PER_EPOCH)

    slashable_attestation_1 = create_mock_slashable_attestation(
        state.copy(slot=attestation_slot_1,
                   current_justified_epoch=config.GENESIS_EPOCH),
        config,
        keymap,
        attestation_slot_1,
    )
    slashable_attestation_2 = create_mock_slashable_attestation(
        state.copy(
            slot=attestation_slot_1,
            current_justified_epoch=config.GENESIS_EPOCH +
            1,  # source_epoch_1 < source_epoch_2
        ),
        config,
        keymap,
        attestation_slot_2,
    )

    return AttesterSlashing(attestation_1=slashable_attestation_1,
                            attestation_2=slashable_attestation_2)
Exemplo n.º 8
0
def process_final_updates(state: BeaconState,
                          config: Eth2Config) -> BeaconState:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    next_epoch = state.next_epoch(config.SLOTS_PER_EPOCH)

    state = _update_latest_active_index_roots(state, CommitteeConfig(config))

    state = state.copy(
        latest_slashed_balances=update_tuple_item(
            state.latest_slashed_balances,
            next_epoch % config.LATEST_SLASHED_EXIT_LENGTH,
            state.latest_slashed_balances[current_epoch %
                                          config.LATEST_SLASHED_EXIT_LENGTH],
        ),
        latest_randao_mixes=update_tuple_item(
            state.latest_randao_mixes,
            next_epoch % config.LATEST_RANDAO_MIXES_LENGTH,
            get_randao_mix(
                state=state,
                epoch=current_epoch,
                slots_per_epoch=config.SLOTS_PER_EPOCH,
                latest_randao_mixes_length=config.LATEST_RANDAO_MIXES_LENGTH,
            ),
        ),
    )

    state = _update_historical_roots(state, next_epoch, config)

    # Rotate current/previous epoch attestations
    state = state.copy(
        previous_epoch_attestations=state.current_epoch_attestations,
        current_epoch_attestations=(),
    )

    return state
Exemplo n.º 9
0
def process_randao(state: BeaconState, block: BaseBeaconBlock,
                   config: Eth2Config) -> BeaconState:
    proposer_index = get_beacon_proposer_index(
        state=state,
        slot=state.slot,
        committee_config=CommitteeConfig(config),
    )
    proposer = state.validator_registry[proposer_index]

    epoch = state.current_epoch(config.SLOTS_PER_EPOCH)

    validate_randao_reveal(
        randao_reveal=block.body.randao_reveal,
        proposer_index=proposer_index,
        proposer_pubkey=proposer.pubkey,
        epoch=epoch,
        fork=state.fork,
    )

    randao_mix_index = epoch % config.LATEST_RANDAO_MIXES_LENGTH
    new_randao_mix = bitwise_xor(
        get_randao_mix(
            state=state,
            epoch=epoch,
            slots_per_epoch=config.SLOTS_PER_EPOCH,
            latest_randao_mixes_length=config.LATEST_RANDAO_MIXES_LENGTH,
        ),
        hash_eth2(block.body.randao_reveal),
    )

    return state.copy(latest_randao_mixes=update_tuple_item(
        state.latest_randao_mixes,
        randao_mix_index,
        new_randao_mix,
    ), )
Exemplo n.º 10
0
def process_slot_transition(state: BeaconState,
                            config: Eth2Config,
                            previous_block_root: Hash32) -> BeaconState:
    slots_per_historical_root = config.SLOTS_PER_HISTORICAL_ROOT

    # Update state.latest_state_roots
    # TODO ensure this becomes the `hash_tree_root` of the `state`
    latest_state_root = state.root
    updated_latest_state_roots = _update_historical_root(
        state.latest_state_roots,
        state.slot,
        slots_per_historical_root,
        latest_state_root,
    )

    # Update state.slot
    state = state.copy(
        slot=state.slot + 1
    )

    # Update state.latest_block_roots
    updated_latest_block_roots = _update_historical_root(
        state.latest_block_roots,
        state.slot - 1,
        slots_per_historical_root,
        previous_block_root,
    )

    state = state.copy(
        latest_block_roots=updated_latest_block_roots,
        latest_state_roots=updated_latest_state_roots,
    )

    return state
Exemplo n.º 11
0
def process_justification_and_finalization(state: BeaconState,
                                           config: Eth2Config) -> BeaconState:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)

    if current_epoch <= GENESIS_EPOCH + 1:
        return state

    (
        new_current_justified_checkpoint,
        justification_bits,
    ) = _determine_new_justified_checkpoint_and_bitfield(state, config)

    new_finalized_checkpoint = _determine_new_finalized_checkpoint(
        state, justification_bits, config)

    return state.mset(
        "justification_bits",
        justification_bits,
        "previous_justified_checkpoint",
        state.current_justified_checkpoint,
        "current_justified_checkpoint",
        new_current_justified_checkpoint,
        "finalized_checkpoint",
        new_finalized_checkpoint,
    )
Exemplo n.º 12
0
def process_final_updates(state: BeaconState,
                          config: BeaconConfig) -> BeaconState:
    current_epoch = state.current_epoch(config.EPOCH_LENGTH)
    next_epoch = state.next_epoch(config.EPOCH_LENGTH)

    state = state.copy(
        latest_penalized_balances=update_tuple_item(
            state.latest_penalized_balances,
            next_epoch % config.LATEST_PENALIZED_EXIT_LENGTH,
            state.latest_penalized_balances[
                current_epoch % config.LATEST_PENALIZED_EXIT_LENGTH],
        ),
        latest_randao_mixes=update_tuple_item(
            state.latest_randao_mixes,
            next_epoch % config.LATEST_PENALIZED_EXIT_LENGTH,
            get_randao_mix(
                state=state,
                epoch=current_epoch,
                epoch_length=config.EPOCH_LENGTH,
                latest_randao_mixes_length=config.LATEST_RANDAO_MIXES_LENGTH,
            ),
        ),
    )

    latest_attestations = tuple(
        filter(
            lambda attestation: (slot_to_epoch(attestation.data.slot, config.
                                               EPOCH_LENGTH) >= current_epoch),
            state.latest_attestations))
    state = state.copy(latest_attestations=latest_attestations, )

    return state
Exemplo n.º 13
0
def _update_shuffling_epoch(state: BeaconState,
                            slots_per_epoch: int) -> BeaconState:
    """
    Updates the ``current_shuffling_epoch`` to the ``state``'s next epoch.
    """
    return state.copy(
        current_shuffling_epoch=state.next_epoch(slots_per_epoch), )
Exemplo n.º 14
0
def process_crosslinks(state: BeaconState, config: Eth2Config) -> BeaconState:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    previous_epoch = state.previous_epoch(config.SLOTS_PER_EPOCH,
                                          config.GENESIS_EPOCH)

    new_current_crosslinks = state.current_crosslinks

    for epoch in (previous_epoch, current_epoch):
        active_validators_indices = get_active_validator_indices(
            state.validators, epoch)
        epoch_committee_count = get_committee_count(
            len(active_validators_indices),
            config.SHARD_COUNT,
            config.SLOTS_PER_EPOCH,
            config.TARGET_COMMITTEE_SIZE,
        )
        epoch_start_shard = get_start_shard(
            state,
            epoch,
            CommitteeConfig(config),
        )
        for shard_offset in range(epoch_committee_count):
            shard = Shard(
                (epoch_start_shard + shard_offset) % config.SHARD_COUNT)
            crosslink_committee = set(
                get_crosslink_committee(
                    state,
                    epoch,
                    shard,
                    CommitteeConfig(config),
                ))

            if not crosslink_committee:
                # empty crosslink committee this epoch
                continue

            winning_crosslink, attesting_indices = get_winning_crosslink_and_attesting_indices(
                state=state,
                epoch=epoch,
                shard=shard,
                config=config,
            )
            threshold_met = _is_threshold_met_against_committee(
                state,
                attesting_indices,
                crosslink_committee,
            )
            if threshold_met:
                new_current_crosslinks = update_tuple_item(
                    new_current_crosslinks,
                    shard,
                    winning_crosslink,
                )

    return state.copy(
        previous_crosslinks=state.current_crosslinks,
        current_crosslinks=new_current_crosslinks,
    )
Exemplo n.º 15
0
def process_deposit(state: BeaconState, deposit: Deposit, slots_per_epoch: int,
                    deposit_contract_tree_depth: int) -> BeaconState:
    """
    Process a deposit from Ethereum 1.0.
    """
    validate_deposit(state, deposit, deposit_contract_tree_depth)

    # Increment the next deposit index we are expecting. Note that this
    # needs to be done here because while the deposit contract will never
    # create an invalid Merkle branch, it may admit an invalid deposit
    # object, and we need to be able to skip over it
    state = state.copy(deposit_index=state.deposit_index + 1, )

    validator_pubkeys = tuple(v.pubkey for v in state.validator_registry)
    deposit_input = deposit.deposit_data.deposit_input
    pubkey = deposit_input.pubkey
    amount = deposit.deposit_data.amount
    withdrawal_credentials = deposit_input.withdrawal_credentials

    if pubkey not in validator_pubkeys:
        # Verify the proof of possession
        proof_is_valid = bls.verify(
            pubkey=pubkey,
            message_hash=deposit_input.signing_root,
            signature=deposit_input.signature,
            domain=get_domain(
                state.fork,
                state.current_epoch(slots_per_epoch),
                SignatureDomain.DOMAIN_DEPOSIT,
            ),
        )
        if not proof_is_valid:
            return state

        validator = Validator.create_pending_validator(
            pubkey=pubkey,
            withdrawal_credentials=withdrawal_credentials,
        )

        # Note: In phase 2 registry indices that has been withdrawn for a long time
        # will be recycled.
        state = add_pending_validator(
            state,
            validator,
            amount,
        )
    else:
        # Top-up - increase balance by deposit
        index = ValidatorIndex(validator_pubkeys.index(pubkey))
        validator = state.validator_registry[index]

        # Update validator's balance and state
        state = state.update_validator_balance(
            validator_index=index,
            balance=state.validator_balances[index] + amount,
        )

    return state
def get_matching_source_attestations(
        state: BeaconState, epoch: Epoch,
        config: Eth2Config) -> Tuple[PendingAttestation, ...]:
    if epoch == state.current_epoch(config.SLOTS_PER_EPOCH):
        return state.current_epoch_attestations
    elif epoch == state.previous_epoch(config.SLOTS_PER_EPOCH):
        return state.previous_epoch_attestations
    else:
        raise InvalidEpochError
Exemplo n.º 17
0
def _compute_next_randao_mixes(state: BeaconState,
                               config: Eth2Config) -> Tuple[Hash32, ...]:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    next_epoch = state.next_epoch(config.SLOTS_PER_EPOCH)
    return state.randao_mixes.set(
        next_epoch % config.EPOCHS_PER_HISTORICAL_VECTOR,
        get_randao_mix(state, current_epoch,
                       config.EPOCHS_PER_HISTORICAL_VECTOR),
    )
Exemplo n.º 18
0
def _process_rewards_and_penalties_for_crosslinks(
    state: BeaconState, config: Eth2Config,
    effective_balances: Dict[ValidatorIndex,
                             Gwei], base_rewards: Dict[ValidatorIndex, Gwei]
) -> Tuple[Dict[ValidatorIndex, Gwei], Dict[ValidatorIndex,
                                            Gwei]]:  # noqa: E501
    previous_epoch_start_slot = get_epoch_start_slot(
        state.previous_epoch(config.SLOTS_PER_EPOCH),
        config.SLOTS_PER_EPOCH,
    )
    current_epoch_start_slot = get_epoch_start_slot(
        state.current_epoch(config.SLOTS_PER_EPOCH),
        config.SLOTS_PER_EPOCH,
    )
    rewards_received = {
        ValidatorIndex(index): Gwei(0)
        for index in range(len(state.validator_registry))
    }
    penalties_received = rewards_received.copy()
    for slot in range(previous_epoch_start_slot, current_epoch_start_slot):
        crosslink_committees_at_slot = get_crosslink_committees_at_slot(
            state,
            slot,
            CommitteeConfig(config),
        )
        for crosslink_committee, shard in crosslink_committees_at_slot:
            winning_root, attesting_validator_indices = get_winning_root_and_participants(
                state=state,
                shard=shard,
                effective_balances=effective_balances,
                committee_config=CommitteeConfig(config),
            )
            total_attesting_balance = get_total_balance(
                state.validator_balances,
                attesting_validator_indices,
                config.MAX_DEPOSIT_AMOUNT,
            )
            total_balance = get_total_balance_from_effective_balances(
                effective_balances,
                crosslink_committee,
            )
            for index in attesting_validator_indices:
                rewards_received = _update_rewards_or_penalies(
                    index,
                    base_rewards[index] * total_attesting_balance //
                    total_balance,
                    rewards_received,
                )
            for index in set(crosslink_committee).difference(
                    attesting_validator_indices):
                penalties_received = _update_rewards_or_penalies(
                    index,
                    base_rewards[index],
                    penalties_received,
                )
    return (rewards_received, penalties_received)
Exemplo n.º 19
0
def _settle_penality_to_validator_and_whistleblower(
        *, state: BeaconState, validator_index: ValidatorIndex,
        latest_penalized_exit_length: int, whistleblower_reward_quotient: int,
        epoch_length: int, max_deposit: Ether) -> BeaconState:
    """
    Apply penality/reward to validator and whistleblower and update the meta data

    More intuitive pseudo-code:
    current_epoch_penalization_index = (state.slot // EPOCH_LENGTH) % LATEST_PENALIZED_EXIT_LENGTH
    state.latest_penalized_exit_balances[current_epoch_penalization_index] += (
        get_effective_balance(state, index)
    )
    whistleblower_index = get_beacon_proposer_index(state, state.slot)
    whistleblower_reward = get_effective_balance(state, index) // WHISTLEBLOWER_REWARD_QUOTIENT
    state.validator_balances[whistleblower_index] += whistleblower_reward
    state.validator_balances[index] -= whistleblower_reward
    validator.penalized_slot = state.slot
    """
    # Update `state.latest_penalized_exit_balances`
    current_epoch_penalization_index = (
        state.slot // epoch_length) % latest_penalized_exit_length
    effective_balance = get_effective_balance(
        state.validator_balances,
        validator_index,
        max_deposit,
    )
    penalized_exit_balance = (
        state.latest_penalized_exit_balances[current_epoch_penalization_index]
        + effective_balance)
    latest_penalized_exit_balances = update_tuple_item(
        tuple_data=state.latest_penalized_exit_balances,
        index=current_epoch_penalization_index,
        new_value=penalized_exit_balance,
    )
    state = state.copy(
        latest_penalized_exit_balances=latest_penalized_exit_balances, )

    # Update whistleblower's balance
    whistleblower_reward = (effective_balance // whistleblower_reward_quotient)
    whistleblower_index = get_beacon_proposer_index(state, state.slot,
                                                    epoch_length)
    state = state.update_validator_balance(
        whistleblower_index,
        state.validator_balances[whistleblower_index] + whistleblower_reward,
    )

    # Update validator's balance and `penalized_slot` field
    validator = state.validator_registry[validator_index]
    validator = validator.copy(penalized_slot=state.slot, )
    state = state.update_validator(
        validator_index,
        validator,
        state.validator_balances[validator_index] - whistleblower_reward,
    )

    return state
Exemplo n.º 20
0
def _compute_next_slashed_balances(state: BeaconState, config: Eth2Config) -> Tuple[Gwei, ...]:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    next_epoch = state.next_epoch(config.SLOTS_PER_EPOCH)
    return update_tuple_item(
        state.slashed_balances,
        next_epoch % config.EPOCHS_PER_SLASHED_BALANCES_VECTOR,
        state.slashed_balances[
            current_epoch % config.EPOCHS_PER_SLASHED_BALANCES_VECTOR
        ],
    )
Exemplo n.º 21
0
def process_deposit(state: BeaconState,
                    deposit: Deposit,
                    config: Eth2Config) -> BeaconState:
    """
    Process a deposit from Ethereum 1.0.
    """
    validate_deposit_proof(state, deposit, DEPOSIT_CONTRACT_TREE_DEPTH)

    # Increment the next deposit index we are expecting. Note that this
    # needs to be done here because while the deposit contract will never
    # create an invalid Merkle branch, it may admit an invalid deposit
    # object, and we need to be able to skip over it
    state = state.copy(
        eth1_deposit_index=state.eth1_deposit_index + 1,
    )

    pubkey = deposit.data.pubkey
    amount = deposit.data.amount
    validator_pubkeys = tuple(v.pubkey for v in state.validators)
    if pubkey not in validator_pubkeys:
        # Verify the deposit signature (proof of possession) for new validators.
        # Note: The deposit contract does not check signatures.
        # Note: Deposits are valid across forks, thus the deposit domain
        # is retrieved directly from `compute_domain`.
        is_valid_proof_of_possession = bls.verify(
            message_hash=deposit.data.signing_root,
            pubkey=pubkey,
            signature=deposit.data.signature,
            domain=compute_domain(
                SignatureDomain.DOMAIN_DEPOSIT,
            ),
        )
        if not is_valid_proof_of_possession:
            return state

        withdrawal_credentials = deposit.data.withdrawal_credentials
        validator = Validator.create_pending_validator(
            pubkey,
            withdrawal_credentials,
            amount,
            config,
        )

        return state.copy(
            validators=state.validators + (validator,),
            balances=state.balances + (amount, ),
        )
    else:
        index = ValidatorIndex(validator_pubkeys.index(pubkey))
        return increase_balance(
            state,
            index,
            amount,
        )
Exemplo n.º 22
0
def get_committee_assignment(
        state: BeaconState,
        config: BeaconConfig,
        epoch: Epoch,
        validator_index: ValidatorIndex,
        registry_change: bool = False) -> CommitteeAssignment:
    """
    Return the ``CommitteeAssignment`` in the ``epoch`` for ``validator_index``
    and ``registry_change``.
    ``CommitteeAssignment.committee`` is the tuple array of validators in the committee
    ``CommitteeAssignment.shard`` is the shard to which the committee is assigned
    ``CommitteeAssignment.slot`` is the slot at which the committee is assigned
    ``CommitteeAssignment.is_proposer`` is a bool signalling if the validator is expected to
        propose a beacon block at the assigned slot.
    """
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    previous_epoch = state.previous_epoch(config.SLOTS_PER_EPOCH,
                                          config.GENESIS_EPOCH)
    next_epoch = Epoch(current_epoch + 1)

    validate_epoch_within_previous_and_next(epoch, previous_epoch, next_epoch)

    epoch_start_slot = get_epoch_start_slot(epoch, config.SLOTS_PER_EPOCH)

    committee_config = CommitteeConfig(config)

    for slot in range(epoch_start_slot,
                      epoch_start_slot + config.SLOTS_PER_EPOCH):
        crosslink_committees = get_crosslink_committees_at_slot(
            state,
            slot,
            committee_config,
            registry_change=registry_change,
        )
        selected_committees = [
            committee for committee in crosslink_committees
            if validator_index in committee[0]
        ]
        if len(selected_committees) > 0:
            validators = selected_committees[0][0]
            shard = selected_committees[0][1]
            is_proposer = validator_index == get_beacon_proposer_index(
                state,
                Slot(slot),
                committee_config,
                registry_change=registry_change,
            )

            return CommitteeAssignment(validators, shard, Slot(slot),
                                       is_proposer)

    raise NoCommitteeAssignment
Exemplo n.º 23
0
def prepare_validator_for_withdrawal(
        state: BeaconState, index: ValidatorIndex, slots_per_epoch: int,
        min_validator_withdrawability_delay: int) -> BeaconState:
    """
    Set the validator with the given ``index`` as withdrawable
    ``MIN_VALIDATOR_WITHDRAWABILITY_DELAY`` after the current epoch.
    """
    validator = state.validator_registry[index].copy(
        withdrawable_epoch=(state.current_epoch(slots_per_epoch) +
                            min_validator_withdrawability_delay))
    state = state.update_validator_registry(index, validator)

    return state
Exemplo n.º 24
0
def slash_validator(state: BeaconState,
                    index: ValidatorIndex,
                    config: Eth2Config,
                    whistleblower_index: ValidatorIndex = None) -> BeaconState:
    """
    Slash the validator with index ``index``.

    Exit the validator, penalize the validator, and reward the whistleblower.
    """
    # NOTE: remove in phase 1
    assert whistleblower_index is None

    slots_per_epoch = config.SLOTS_PER_EPOCH

    current_epoch = state.current_epoch(slots_per_epoch)

    state = initiate_validator_exit(state, index, config)
    state = state.update_validator_with_fn(
        index,
        _set_validator_slashed,
        current_epoch,
        config.EPOCHS_PER_SLASHINGS_VECTOR,
    )

    slashed_balance = state.validators[index].effective_balance
    slashed_epoch = current_epoch % config.EPOCHS_PER_SLASHINGS_VECTOR
    state = state.copy(slashings=update_tuple_item_with_fn(
        state.slashings,
        slashed_epoch,
        lambda balance, slashed_balance: Gwei(balance + slashed_balance),
        slashed_balance,
    ))
    state = decrease_balance(
        state, index, slashed_balance // config.MIN_SLASHING_PENALTY_QUOTIENT)

    proposer_index = get_beacon_proposer_index(state, CommitteeConfig(config))
    if whistleblower_index is None:
        whistleblower_index = proposer_index
    whistleblower_reward = Gwei(slashed_balance //
                                config.WHISTLEBLOWER_REWARD_QUOTIENT)
    proposer_reward = Gwei(whistleblower_reward //
                           config.PROPOSER_REWARD_QUOTIENT)
    state = increase_balance(state, proposer_index, proposer_reward)
    state = increase_balance(
        state,
        whistleblower_index,
        Gwei(whistleblower_reward - proposer_reward),
    )

    return state
Exemplo n.º 25
0
def get_committee_assignment(
    state: BeaconState,
    config: Eth2Config,
    epoch: Epoch,
    validator_index: ValidatorIndex,
) -> CommitteeAssignment:
    """
    Return the ``CommitteeAssignment`` in the ``epoch`` for ``validator_index``.
    ``CommitteeAssignment.committee`` is the tuple array of validators in the committee
    ``CommitteeAssignment.shard`` is the shard to which the committee is assigned
    ``CommitteeAssignment.slot`` is the slot at which the committee is assigned
    ``CommitteeAssignment.is_proposer`` is a bool signalling if the validator is expected to
        propose a beacon block at the assigned slot.
    """
    next_epoch = state.next_epoch(config.SLOTS_PER_EPOCH)
    if epoch > next_epoch:
        raise ValidationError(
            f"Epoch for committee assignment ({epoch}) must not be after next epoch {next_epoch}."
        )

    active_validators = get_active_validator_indices(state.validators, epoch)
    committees_per_slot = (
        get_committee_count(
            len(active_validators),
            config.SHARD_COUNT,
            config.SLOTS_PER_EPOCH,
            config.TARGET_COMMITTEE_SIZE,
        )
        // config.SLOTS_PER_EPOCH
    )
    epoch_start_slot = compute_start_slot_of_epoch(epoch, config.SLOTS_PER_EPOCH)
    epoch_start_shard = get_start_shard(state, epoch, CommitteeConfig(config))

    for slot in range(epoch_start_slot, epoch_start_slot + config.SLOTS_PER_EPOCH):
        offset = committees_per_slot * (slot % config.SLOTS_PER_EPOCH)
        slot_start_shard = (epoch_start_shard + offset) % config.SHARD_COUNT
        for i in range(committees_per_slot):
            shard = Shard((slot_start_shard + i) % config.SHARD_COUNT)
            committee = get_crosslink_committee(
                state, epoch, shard, CommitteeConfig(config)
            )
            if validator_index in committee:
                is_proposer = validator_index == get_beacon_proposer_index(
                    state.copy(slot=slot), CommitteeConfig(config)
                )
                return CommitteeAssignment(
                    committee, Shard(shard), Slot(slot), is_proposer
                )

    raise NoCommitteeAssignment
Exemplo n.º 26
0
def _process_activation_eligibility_or_ejections(
        state: BeaconState, index: ValidatorIndex,
        config: Eth2Config) -> BeaconState:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    validator = state.validators[index]

    if validator.is_eligible_for_activation_queue(config):
        validator = validator.set("activation_eligibility_epoch",
                                  current_epoch + 1)

    if (validator.is_active(current_epoch)
            and validator.effective_balance <= config.EJECTION_BALANCE):
        validator = initiate_exit_for_validator(validator, state, config)

    return state.transform(("validators", index), validator)
Exemplo n.º 27
0
def get_start_shard(state: BeaconState, epoch: Epoch,
                    config: CommitteeConfig) -> Shard:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    next_epoch = state.next_epoch(config.SLOTS_PER_EPOCH)
    if epoch > next_epoch:
        raise ValidationError("Asking for start shard for an epoch after next")

    check_epoch = int(next_epoch)
    shard = (state.start_shard + get_shard_delta(state, current_epoch,
                                                 config)) % config.SHARD_COUNT
    while check_epoch > epoch:
        check_epoch -= 1
        shard = (shard + config.SHARD_COUNT - get_shard_delta(
            state, Epoch(check_epoch), config)) % config.SHARD_COUNT
    return shard
Exemplo n.º 28
0
def slash_validator(
    state: BeaconState,
    index: ValidatorIndex,
    config: Eth2Config,
    whistleblower_index: ValidatorIndex = None,
) -> BeaconState:
    """
    Slash the validator with index ``index``.

    Exit the validator, penalize the validator, and reward the whistleblower.
    """
    # NOTE: remove in phase 1
    assert whistleblower_index is None

    slots_per_epoch = config.SLOTS_PER_EPOCH

    current_epoch = state.current_epoch(slots_per_epoch)

    state = initiate_validator_exit(state, index, config)

    state = state.transform(
        ("validators", index),
        partial(
            _set_validator_slashed,
            current_epoch=current_epoch,
            epochs_per_slashings_vector=config.EPOCHS_PER_SLASHINGS_VECTOR,
        ),
    )

    slashed_balance = state.validators[index].effective_balance
    slashed_epoch = current_epoch % config.EPOCHS_PER_SLASHINGS_VECTOR
    state = state.transform(("slashings", slashed_epoch),
                            lambda balance: Gwei(balance + slashed_balance))
    state = decrease_balance(
        state, index, slashed_balance // config.MIN_SLASHING_PENALTY_QUOTIENT)

    proposer_index = get_beacon_proposer_index(state, config)
    if whistleblower_index is None:
        whistleblower_index = proposer_index
    whistleblower_reward = Gwei(slashed_balance //
                                config.WHISTLEBLOWER_REWARD_QUOTIENT)
    proposer_reward = Gwei(whistleblower_reward //
                           config.PROPOSER_REWARD_QUOTIENT)
    state = increase_balance(state, proposer_index, proposer_reward)
    state = increase_balance(state, whistleblower_index,
                             Gwei(whistleblower_reward - proposer_reward))

    return state
Exemplo n.º 29
0
def create_mock_deposit(
    state: BeaconState,
    pubkey: BLSPubkey,
    keymap: Dict[BLSPubkey, int],
    withdrawal_credentials: Hash32,
    config: Eth2Config,
    leaves: Sequence[Hash32] = None,
) -> Tuple[BeaconState, Deposit]:
    deposits, root = create_mock_deposits_and_root(
        (pubkey, ),
        keymap,
        config,
        withdrawal_credentials=(withdrawal_credentials, ),
        leaves=leaves,
    )
    # sanity check
    assert len(deposits) == 1
    deposit = deposits[0]

    state = state.copy(
        eth1_data=state.eth1_data.copy(
            deposit_root=root,
            deposit_count=state.eth1_data.deposit_count + len(deposits),
        ),
        eth1_deposit_index=0 if not leaves else len(leaves),
    )

    return state, deposit
Exemplo n.º 30
0
def _validate_sender_eligibility(state: BeaconState, transfer: Transfer,
                                 config: Eth2Config) -> None:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    sender = state.validators[transfer.sender]
    sender_balance = state.balances[transfer.sender]

    eligible_for_activation = sender.activation_eligibility_epoch != FAR_FUTURE_EPOCH
    is_withdrawable = current_epoch >= sender.withdrawable_epoch
    is_transfer_total_allowed = (
        transfer.amount + transfer.fee + config.MAX_EFFECTIVE_BALANCE <=
        sender_balance)

    if (not eligible_for_activation
        ) or is_withdrawable or is_transfer_total_allowed:
        return

    if eligible_for_activation:
        raise ValidationError(
            f"Sender in transfer {transfer} is eligible for activation.")

    if not is_withdrawable:
        raise ValidationError(
            f"Sender in transfer {transfer} is not withdrawable.")

    if not is_transfer_total_allowed:
        raise ValidationError(
            f"Sender does not have sufficient funds in transfer {transfer}.")