コード例 #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
コード例 #2
0
def decrease_balance(state: BeaconState, index: ValidatorIndex,
                     delta: Gwei) -> BeaconState:
    return state.copy(balances=update_tuple_item_with_fn(
        state.balances,
        index,
        lambda balance, *_: Gwei(0)
        if delta > balance else Gwei(balance - delta),
    ))
コード例 #3
0
def get_crosslink_deltas(
        state: BeaconState,
        config: Eth2Config) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
    rewards = tuple(0 for _ in range(len(state.validators)))
    penalties = tuple(0 for _ in range(len(state.validators)))
    epoch = state.previous_epoch(config.SLOTS_PER_EPOCH, config.GENESIS_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),
            ))
        _, attesting_indices = get_winning_crosslink_and_attesting_indices(
            state=state,
            epoch=epoch,
            shard=shard,
            config=config,
        )
        total_attesting_balance = get_total_balance(
            state,
            attesting_indices,
        )
        total_committee_balance = get_total_balance(
            state,
            crosslink_committee,
        )
        for index in crosslink_committee:
            base_reward = get_base_reward(state, index, config)
            if index in attesting_indices:
                rewards = update_tuple_item_with_fn(
                    rewards, index, lambda balance, delta: balance + delta,
                    base_reward * total_attesting_balance //
                    total_committee_balance)
            else:
                penalties = update_tuple_item_with_fn(
                    penalties,
                    index,
                    lambda balance, delta: balance + delta,
                    base_reward,
                )
    return tuple(Gwei(reward) for reward in rewards), tuple(
        Gwei(penalty) for penalty in penalties)
コード例 #4
0
def get_base_reward(*, state: 'BeaconState', index: ValidatorIndex,
                    base_reward_quotient: int, previous_total_balance: Gwei,
                    max_deposit_amount: Gwei) -> Gwei:
    if previous_total_balance == 0:
        return Gwei(0)
    adjusted_quotient = (integer_squareroot(previous_total_balance) //
                         base_reward_quotient)
    return Gwei(
        get_effective_balance(
            state.validator_balances,
            index,
            max_deposit_amount,
        ) // adjusted_quotient // 5)
コード例 #5
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
コード例 #6
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
コード例 #7
0
def get_total_attesting_balance(
        *,
        state: 'BeaconState',
        shard: ShardNumber,
        shard_block_root: Hash32,
        attestations: Sequence[PendingAttestationRecord],
        genesis_epoch: EpochNumber,
        epoch_length: int,
        max_deposit_amount: Gwei,
        target_committee_size: int,
        shard_count: int) -> Gwei:
    return Gwei(
        sum(
            get_effective_balance(state.validator_balances, i, max_deposit_amount)
            for i in get_attesting_validator_indices(
                state=state,
                attestations=attestations,
                shard=shard,
                shard_block_root=shard_block_root,
                genesis_epoch=genesis_epoch,
                epoch_length=epoch_length,
                target_committee_size=target_committee_size,
                shard_count=shard_count,
            )
        )
    )
コード例 #8
0
ファイル: conftest.py プロジェクト: s0b0lev/trinity
def sample_deposit_data_params(sample_signature):
    return {
        'pubkey': BLSPubkey(b'\x67' * 48),
        'withdrawal_credentials': b'\11' * 32,
        'amount': Gwei(56),
        'signature': sample_signature,
    }
コード例 #9
0
 def create_pending_validator(cls,
                              pubkey: BLSPubkey,
                              withdrawal_credentials: Hash32,
                              amount: Gwei,
                              config: Eth2Config) -> 'Validator':
     """
     Return a new pending ``Validator`` with the given fields.
     """
     return cls(
         pubkey=pubkey,
         withdrawal_credentials=withdrawal_credentials,
         effective_balance=Gwei(
             min(
                 _round_down_to_previous_multiple(
                     amount,
                     config.EFFECTIVE_BALANCE_INCREMENT,
                 ),
                 config.MAX_EFFECTIVE_BALANCE,
             )
         ),
         activation_eligibility_epoch=FAR_FUTURE_EPOCH,
         activation_epoch=FAR_FUTURE_EPOCH,
         exit_epoch=FAR_FUTURE_EPOCH,
         withdrawable_epoch=FAR_FUTURE_EPOCH,
     )
コード例 #10
0
ファイル: helpers.py プロジェクト: Agreene/trinity
def get_effective_balance(validator_balances: Sequence[Gwei],
                          index: ValidatorIndex, max_deposit: Ether) -> Gwei:
    """
    Return the effective balance (also known as "balance at stake") for a
    ``validator`` with the given ``index``.
    """
    return min(validator_balances[index], Gwei(max_deposit * GWEI_PER_ETH))
コード例 #11
0
def get_winning_root(
        *,
        state: 'BeaconState',
        shard: ShardNumber,
        attestations: Sequence[PendingAttestationRecord],
        max_deposit_amount: Gwei,
        committee_config: CommitteeConfig) -> Tuple[Hash32, Gwei]:
    winning_root = None
    winning_root_balance: Gwei = Gwei(0)
    shard_block_roots = set(
        [
            a.data.shard_block_root for a in attestations
            if a.data.shard == shard
        ]
    )
    for shard_block_root in shard_block_roots:
        total_attesting_balance = get_total_attesting_balance(
            state=state,
            shard=shard,
            shard_block_root=shard_block_root,
            attestations=attestations,
            max_deposit_amount=max_deposit_amount,
            committee_config=committee_config,
        )
        if total_attesting_balance > winning_root_balance:
            winning_root = shard_block_root
            winning_root_balance = total_attesting_balance
        elif total_attesting_balance == winning_root_balance and winning_root_balance > 0:
            if shard_block_root < winning_root:
                winning_root = shard_block_root

    if winning_root is None:
        raise NoWinningRootError
    return (winning_root, winning_root_balance)
コード例 #12
0
def calculate_effective_balance(amount: Gwei, config: Eth2Config) -> Gwei:
    return Gwei(
        min(
            _round_down_to_previous_multiple(
                amount, config.EFFECTIVE_BALANCE_INCREMENT),
            config.MAX_EFFECTIVE_BALANCE,
        ))
コード例 #13
0
ファイル: conftest.py プロジェクト: nondejus/trinity
def sample_deposit_data_params(sample_signature):
    return {
        "pubkey": BLSPubkey(b"\x67" * 48),
        "withdrawal_credentials": b"\11" * 32,
        "amount": Gwei(56),
        "signature": sample_signature,
    }
コード例 #14
0
def get_winning_root(*, state: 'BeaconState', shard: ShardNumber,
                     attestations: Sequence[PendingAttestationRecord],
                     genesis_epoch: EpochNumber, epoch_length: int,
                     max_deposit_amount: Gwei, target_committee_size: int,
                     shard_count: int) -> Tuple[Hash32, Gwei]:
    winning_root = None
    winning_root_balance: Gwei = Gwei(0)
    shard_block_roots = set([
        a.data.shard_block_root for a in attestations if a.data.shard == shard
    ])
    for shard_block_root in shard_block_roots:
        total_attesting_balance = get_total_attesting_balance(
            state=state,
            shard=shard,
            shard_block_root=shard_block_root,
            attestations=attestations,
            genesis_epoch=genesis_epoch,
            epoch_length=epoch_length,
            max_deposit_amount=max_deposit_amount,
            target_committee_size=target_committee_size,
            shard_count=shard_count,
        )
        if total_attesting_balance > winning_root_balance:
            winning_root = shard_block_root
            winning_root_balance = total_attesting_balance
        elif total_attesting_balance == winning_root_balance and winning_root_balance > 0:
            if shard_block_root < winning_root:
                winning_root = shard_block_root

    if winning_root is None:
        raise NoWinningRootError
    return (winning_root, winning_root_balance)
コード例 #15
0
def get_winning_root(*, state: 'BeaconState', shard: Shard,
                     attestations: Sequence[PendingAttestationRecord],
                     max_deposit_amount: Gwei,
                     committee_config: CommitteeConfig) -> Tuple[Hash32, Gwei]:
    winning_root = None
    winning_root_balance: Gwei = Gwei(0)
    crosslink_data_roots = set([
        a.data.crosslink_data_root for a in attestations
        if a.data.shard == shard
    ])
    for crosslink_data_root in crosslink_data_roots:
        attesting_validator_indices = get_attester_indices_from_attesttion(
            state=state,
            attestations=[
                a for a in attestations if a.data.shard == shard
                and a.data.crosslink_data_root == crosslink_data_root
            ],
            committee_config=committee_config,
        )
        total_attesting_balance = get_total_balance(
            state.validator_balances,
            attesting_validator_indices,
            max_deposit_amount,
        )
        if total_attesting_balance > winning_root_balance:
            winning_root = crosslink_data_root
            winning_root_balance = total_attesting_balance
        elif total_attesting_balance == winning_root_balance and winning_root_balance > 0:
            if crosslink_data_root < winning_root:
                winning_root = crosslink_data_root

    if winning_root is None:
        raise NoWinningRootError
    return (winning_root, winning_root_balance)
コード例 #16
0
 def get_logs(self, block_number: BlockNumber) -> Tuple[DepositLog, ...]:
     block_hash = block_number.to_bytes(32, byteorder='big')
     if block_number == self.start_block_number:
         logs = (
             DepositLog(
                 block_hash=Hash32(block_hash),
                 pubkey=deposit.pubkey,
                 withdrawal_credentials=deposit.withdrawal_credentials,
                 signature=deposit.signature,
                 amount=deposit.amount,
             )
             for deposit in self.deposits
         )
         return tuple(logs)
     else:
         logs = (
             DepositLog(
                 block_hash=Hash32(block_hash),
                 pubkey=BLSPubkey(b'\x12' * 48),
                 withdrawal_credentials=Hash32(b'\x23' * 32),
                 signature=BLSSignature(b'\x34' * 96),
                 amount=Gwei(32 * GWEI_PER_ETH),
             )
             for _ in range(self.num_deposits_per_block)
         )
         return tuple(logs)
コード例 #17
0
def _compute_next_slashings(state: BeaconState,
                            config: Eth2Config) -> Tuple[Gwei, ...]:
    next_epoch = state.next_epoch(config.SLOTS_PER_EPOCH)
    return update_tuple_item(
        state.slashings,
        next_epoch % config.EPOCHS_PER_SLASHINGS_VECTOR,
        Gwei(0),
    )
コード例 #18
0
def get_total_balance(state: 'BeaconState',
                      validator_indices: Sequence[ValidatorIndex]) -> Gwei:
    """
    Return the combined effective balance of an array of validators.
    """
    return Gwei(
        max(
            sum(state.validators[index].effective_balance
                for index in validator_indices), 1))
コード例 #19
0
def get_base_reward(*, state: 'BeaconState', index: ValidatorIndex,
                    base_reward_quotient: int,
                    max_deposit_amount: Gwei) -> Gwei:
    return Gwei(
        get_effective_balance(
            state.validator_balances,
            index,
            max_deposit_amount,
        ) // base_reward_quotient // 5)
コード例 #20
0
 def from_contract_log_dict(cls, log: Dict[Any, Any]) -> "DepositLog":
     log_args = log["args"]
     return cls(
         block_hash=log["blockHash"],
         pubkey=log_args["pubkey"],
         withdrawal_credentials=log_args["withdrawal_credentials"],
         amount=Gwei(int.from_bytes(log_args["amount"], "little")),
         signature=log_args["signature"],
     )
コード例 #21
0
def test_process_registry_updates(validator_count, genesis_state, config,
                                  slots_per_epoch):
    eligible_index = len(genesis_state.validators)
    activation_index = len(genesis_state.validators) + 1
    exiting_index = len(genesis_state.validators) - 1

    eligible_validator = Validator.create_pending_validator(
        pubkey=b"\x10" * 48,
        withdrawal_credentials=b"\x11" * 32,
        amount=Gwei(32 * GWEI_PER_ETH),
        config=config,
    )
    activating_validator = eligible_validator.set(
        "activation_eligibility_epoch",
        genesis_state.finalized_checkpoint.epoch)

    state = genesis_state.mset(
        "validators",
        genesis_state.validators[:exiting_index] +
        (genesis_state.validators[exiting_index].set(
            "effective_balance", config.EJECTION_BALANCE - 1), ) +
        (eligible_validator, activating_validator),
        "balances",
        genesis_state.balances +
        (config.MAX_EFFECTIVE_BALANCE, config.MAX_EFFECTIVE_BALANCE),
    )

    # handles activations
    post_state = process_registry_updates(state, config)

    # Check if the eligible_validator is eligible
    pre_eligible_validator = state.validators[eligible_index]
    post_eligible_validator = post_state.validators[eligible_index]
    assert pre_eligible_validator.activation_eligibility_epoch == FAR_FUTURE_EPOCH
    assert pre_eligible_validator.activation_epoch == FAR_FUTURE_EPOCH
    assert (post_eligible_validator.activation_eligibility_epoch ==
            state.current_epoch(slots_per_epoch) + 1)

    # Check if the activating_validator is activated
    pre_activation_validator = state.validators[activation_index]
    post_activation_validator = post_state.validators[activation_index]
    assert pre_activation_validator.activation_epoch == FAR_FUTURE_EPOCH
    assert post_activation_validator.activation_eligibility_epoch != FAR_FUTURE_EPOCH
    activation_epoch = compute_activation_exit_epoch(
        state.current_epoch(config.SLOTS_PER_EPOCH), config.MAX_SEED_LOOKAHEAD)
    assert post_activation_validator.is_active(activation_epoch)

    # Check if the exiting_validator is exited
    pre_exiting_validator = state.validators[exiting_index]
    post_exiting_validator = post_state.validators[exiting_index]
    assert pre_exiting_validator.exit_epoch == FAR_FUTURE_EPOCH
    assert pre_exiting_validator.withdrawable_epoch == FAR_FUTURE_EPOCH
    assert state.validators[
        exiting_index].effective_balance <= config.EJECTION_BALANCE
    assert post_exiting_validator.exit_epoch != FAR_FUTURE_EPOCH
    assert post_exiting_validator.withdrawable_epoch != FAR_FUTURE_EPOCH
    assert post_exiting_validator.withdrawable_epoch > post_exiting_validator.exit_epoch
コード例 #22
0
def _update_rewards_or_penalies(
    index: ValidatorIndex, amount: Gwei,
    rewards_or_penalties: Dict[ValidatorIndex, Gwei]
) -> Iterable[Tuple[ValidatorIndex, Gwei]]:
    for i in rewards_or_penalties:
        if i == index:
            yield i, Gwei(rewards_or_penalties[i] + amount)
        else:
            yield i, rewards_or_penalties[i]
コード例 #23
0
def get_total_balance_from_effective_balances(
        effective_balances: Dict[ValidatorIndex, Gwei],
        validator_indices: Sequence[ValidatorIndex]) -> Gwei:
    return Gwei(
        sum(
            effective_balances[index]
            for index in validator_indices
        )
    )
コード例 #24
0
def _compute_total_penalties(state: BeaconState, config: BeaconConfig,
                             current_epoch: Epoch) -> Gwei:
    epoch_index = current_epoch % config.LATEST_SLASHED_EXIT_LENGTH
    start_index_in_latest_slashed_balances = (
        (epoch_index + 1) % config.LATEST_SLASHED_EXIT_LENGTH)
    total_at_start = state.latest_slashed_balances[
        start_index_in_latest_slashed_balances]
    total_at_end = state.latest_slashed_balances[epoch_index]
    return Gwei(total_at_end - total_at_start)
コード例 #25
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)
コード例 #26
0
def get_inactivity_penalty(
        *,
        base_reward: Gwei,
        effective_balance: Gwei,
        epochs_since_finality: int,
        inactivity_penalty_quotient: int) -> Gwei:
    return Gwei(
        base_reward +
        effective_balance * epochs_since_finality // inactivity_penalty_quotient // 2
    )
コード例 #27
0
ファイル: helpers.py プロジェクト: manimech315/trinity
def get_total_balance(validator_balances: Sequence[Gwei],
                      validator_indices: Sequence[ValidatorIndex],
                      max_deposit_amount: Gwei) -> Gwei:
    """
    Return the combined effective balance of an array of validators.
    """
    return Gwei(sum(
        get_effective_balance(validator_balances, index, max_deposit_amount)
        for index in validator_indices
    ))
コード例 #28
0
ファイル: conftest.py プロジェクト: s0b0lev/trinity
def sample_validator_record_params():
    return {
        'pubkey': b'\x67' * 48,
        'withdrawal_credentials': b'\x01' * 32,
        'effective_balance': Gwei(32 * GWEI_PER_ETH),
        'slashed': False,
        'activation_eligibility_epoch': FAR_FUTURE_EPOCH,
        'activation_epoch': FAR_FUTURE_EPOCH,
        'exit_epoch': FAR_FUTURE_EPOCH,
        'withdrawable_epoch': FAR_FUTURE_EPOCH,
    }
コード例 #29
0
ファイル: conftest.py プロジェクト: nondejus/trinity
def sample_validator_record_params():
    return {
        "pubkey": b"\x67" * 48,
        "withdrawal_credentials": b"\x01" * 32,
        "effective_balance": Gwei(32 * GWEI_PER_ETH),
        "slashed": False,
        "activation_eligibility_epoch": FAR_FUTURE_EPOCH,
        "activation_epoch": FAR_FUTURE_EPOCH,
        "exit_epoch": FAR_FUTURE_EPOCH,
        "withdrawable_epoch": FAR_FUTURE_EPOCH,
    }
コード例 #30
0
def _determine_slashing_penalty(total_penalties: Gwei,
                                total_balance: Gwei,
                                balance: Gwei,
                                min_slashing_penalty_quotient: int) -> Gwei:
    collective_penalty = min(total_penalties * 3, total_balance) // total_balance
    return Gwei(
        max(
            balance * collective_penalty,
            balance // min_slashing_penalty_quotient
        )
    )