Example #1
0
def process_rewards_and_penalties(
    state: BeaconState, config: Eth2Config
) -> BeaconState:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    if current_epoch == config.GENESIS_EPOCH:
        return state

    rewards_for_attestations, penalties_for_attestations = get_attestation_deltas(
        state, config
    )
    rewards_for_crosslinks, penalties_for_crosslinks = get_crosslink_deltas(
        state, config
    )

    for index in range(len(state.validators)):
        index = ValidatorIndex(index)
        state = increase_balance(
            state,
            index,
            Gwei(rewards_for_attestations[index] + rewards_for_crosslinks[index]),
        )
        state = decrease_balance(
            state,
            index,
            Gwei(penalties_for_attestations[index] + penalties_for_crosslinks[index]),
        )

    return state
Example #2
0
def process_transfers(state: BeaconState, block: BaseBeaconBlock,
                      config: Eth2Config) -> BeaconState:
    if len(block.body.transfers) > config.MAX_TRANSFERS:
        raise ValidationError(
            f"The block ({block}) has too many transfers:\n"
            f"\tFound {len(block.body.transfers)} transfers, "
            f"maximum: {config.MAX_TRANSFERS}")

    for transfer in block.body.transfers:
        validate_transfer(
            state,
            transfer,
            config,
        )
        state = decrease_balance(
            state,
            transfer.sender,
            transfer.amount + transfer.fee,
        )
        state = increase_balance(
            state,
            transfer.recipient,
            transfer.amount,
        )
        state = increase_balance(
            state,
            get_beacon_proposer_index(
                state,
                CommitteeConfig(config),
            ),
            transfer.fee,
        )

    return state
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
Example #4
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
Example #5
0
def process_slashings(state: BeaconState, config: Eth2Config) -> BeaconState:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    total_balance = get_total_active_balance(state, config)

    slashing_period = config.EPOCHS_PER_SLASHINGS_VECTOR // 2
    for index, validator in enumerate(state.validators):
        index = ValidatorIndex(index)
        if validator.slashed and current_epoch + slashing_period == validator.withdrawable_epoch:
            penalty = _determine_slashing_penalty(
                Gwei(sum(state.slashings)),
                total_balance,
                validator.effective_balance,
                config.EFFECTIVE_BALANCE_INCREMENT,
            )
            state = decrease_balance(state, index, penalty)
    return state
Example #6
0
def process_slashings(state: BeaconState, config: Eth2Config) -> BeaconState:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    total_balance = get_total_active_balance(state, config)

    start_index = (current_epoch + 1) % config.EPOCHS_PER_SLASHED_BALANCES_VECTOR
    total_at_start = state.slashed_balances[start_index]

    end_index = current_epoch % config.EPOCHS_PER_SLASHED_BALANCES_VECTOR
    total_at_end = state.slashed_balances[end_index]

    total_penalties = total_at_end - total_at_start

    slashing_period = config.EPOCHS_PER_SLASHED_BALANCES_VECTOR // 2
    for index, validator in enumerate(state.validators):
        index = ValidatorIndex(index)
        if validator.slashed and current_epoch == validator.withdrawable_epoch - slashing_period:
            penalty = _determine_slashing_penalty(
                total_penalties,
                total_balance,
                validator.effective_balance,
                config.MIN_SLASHING_PENALTY_QUOTIENT,
            )
            state = decrease_balance(state, index, penalty)
    return state
def test_decrease_balance(genesis_state, delta):
    index = random.sample(range(len(genesis_state.validators)), 1)[0]
    prior_balance = genesis_state.balances[index]
    state = decrease_balance(genesis_state, index, delta)
    assert state.balances[index] == Gwei(max(prior_balance - delta, 0))