Esempio n. 1
0
def test_get_committee_assignment(genesis_state, slots_per_epoch, shard_count,
                                  config, num_validators, state_epoch, epoch,
                                  registry_change):
    state_slot = get_epoch_start_slot(state_epoch, slots_per_epoch)
    state = genesis_state.copy(slot=state_slot, )
    proposer_count = 0
    shard_validator_count = [0 for _ in range(shard_count)]
    slots = []

    epoch_start_slot = get_epoch_start_slot(epoch, slots_per_epoch)

    for validator_index in range(num_validators):
        assignment = get_committee_assignment(
            state,
            config,
            epoch,
            validator_index,
            registry_change,
        )
        assert assignment.slot >= epoch_start_slot
        assert assignment.slot < epoch_start_slot + slots_per_epoch
        if assignment.is_proposer:
            proposer_count += 1

        shard_validator_count[assignment.shard] += 1
        slots.append(assignment.slot)

    assert proposer_count == slots_per_epoch
    assert sum(shard_validator_count) == num_validators
def test_get_previous_epoch_matching_head_attestations(
        random, sample_state, genesis_epoch, slots_per_epoch,
        slots_per_historical_root, sample_attestation_data_params,
        sample_attestation_params):
    previous_epoch = 9
    current_epoch = previous_epoch + 1
    current_slot = get_epoch_start_slot(current_epoch + 1, slots_per_epoch) - 1
    latest_block_roots = [
        hash_eth2(b'block_root' + i.to_bytes(1, 'little'))
        for i in range(slots_per_historical_root)
    ]

    num_previous_epoch_attestation = random.sample(range(slots_per_epoch),
                                                   1)[0]
    previous_epoch_attestion_slots = random.sample(
        range(
            get_epoch_start_slot(previous_epoch, slots_per_epoch),
            get_epoch_start_slot(current_epoch, slots_per_epoch),
        ),
        num_previous_epoch_attestation,
    )
    num_previous_epoch_head_attestation = random.sample(
        range(num_previous_epoch_attestation), 1)[0]
    previous_epoch_head_attestion_slots = random.sample(
        previous_epoch_attestion_slots,
        num_previous_epoch_head_attestation,
    )
    previous_epoch_not_head_attestion_slots = set(
        previous_epoch_attestion_slots).difference(
            set(previous_epoch_head_attestion_slots))

    previous_epoch_head_attestations = []
    for slot in previous_epoch_head_attestion_slots:
        previous_epoch_head_attestations.append(
            Attestation(**sample_attestation_params).copy(
                data=AttestationData(**sample_attestation_data_params).copy(
                    slot=slot,
                    beacon_block_root=latest_block_roots[
                        slot % slots_per_historical_root],
                ), ))
    previous_epoch_not_head_attestations = []
    for slot in previous_epoch_not_head_attestion_slots:
        previous_epoch_not_head_attestations.append(
            Attestation(**sample_attestation_params).copy(data=AttestationData(
                **sample_attestation_data_params).copy(slot=slot, ), ))

    state = sample_state.copy(
        slot=current_slot,
        latest_block_roots=latest_block_roots,
        previous_epoch_attestations=(previous_epoch_head_attestations +
                                     previous_epoch_not_head_attestations),
    )

    result = get_previous_epoch_matching_head_attestations(
        state,
        slots_per_epoch,
        genesis_epoch,
        slots_per_historical_root,
    )
    assert set(previous_epoch_head_attestations) == set(result)
Esempio n. 3
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)
def get_epoch_boundary_attesting_balances(
        current_epoch: Epoch, previous_epoch: Epoch, state: 'BeaconState',
        config: 'BeaconConfig') -> Tuple[Gwei, Gwei]:

    current_epoch_attestations = get_current_epoch_attestations(
        state, config.SLOTS_PER_EPOCH)
    previous_epoch_attestations = get_previous_epoch_attestations(
        state,
        config.SLOTS_PER_EPOCH,
        config.GENESIS_EPOCH,
    )

    previous_epoch_boundary_root = get_block_root(
        state,
        get_epoch_start_slot(previous_epoch, config.SLOTS_PER_EPOCH),
        config.LATEST_BLOCK_ROOTS_LENGTH,
    )

    previous_epoch_boundary_attester_indices = get_epoch_boundary_attester_indices(
        state,
        current_epoch_attestations + previous_epoch_attestations,
        state.previous_justified_epoch,
        previous_epoch_boundary_root,
        CommitteeConfig(config),
    )

    previous_epoch_boundary_attesting_balance = get_total_balance(
        state.validator_balances,
        previous_epoch_boundary_attester_indices,
        config.MAX_DEPOSIT_AMOUNT,
    )

    current_epoch_boundary_root = get_block_root(
        state,
        get_epoch_start_slot(current_epoch, config.SLOTS_PER_EPOCH),
        config.LATEST_BLOCK_ROOTS_LENGTH,
    )

    current_epoch_boundary_attester_indices = get_epoch_boundary_attester_indices(
        state,
        current_epoch_attestations,
        state.justified_epoch,
        current_epoch_boundary_root,
        CommitteeConfig(config),
    )

    current_epoch_boundary_attesting_balance = get_total_balance(
        state.validator_balances,
        current_epoch_boundary_attester_indices,
        config.MAX_DEPOSIT_AMOUNT,
    )
    return previous_epoch_boundary_attesting_balance, current_epoch_boundary_attesting_balance
def test_process_ejections(genesis_state, config, activation_exit_delay):
    current_epoch = 8
    state = genesis_state.copy(
        slot=get_epoch_start_slot(current_epoch, config.SLOTS_PER_EPOCH),
    )
    delayed_activation_exit_epoch = get_delayed_activation_exit_epoch(
        current_epoch,
        activation_exit_delay,
    )

    ejecting_validator_index = 0
    validator = state.validator_registry[ejecting_validator_index]
    assert validator.is_active(current_epoch)
    assert validator.exit_epoch > delayed_activation_exit_epoch

    state = state.update_validator_balance(
        validator_index=ejecting_validator_index,
        balance=config.EJECTION_BALANCE - 1,
    )
    result_state = process_ejections(state, config)
    result_validator = result_state.validator_registry[ejecting_validator_index]
    assert result_validator.is_active(current_epoch)
    assert result_validator.exit_epoch == delayed_activation_exit_epoch
    # The ejecting validator will be inactive at the exit_epoch
    assert not result_validator.is_active(result_validator.exit_epoch)
    # Other validators are not ejected
    assert (
        result_state.validator_registry[ejecting_validator_index + 1].exit_epoch ==
        FAR_FUTURE_EPOCH
    )
def test_process_exit_queue_eligible(genesis_state,
                                     config,
                                     current_epoch,
                                     min_validator_withdrawability_delay,
                                     withdrawable_epoch,
                                     exit_epoch,
                                     is_eligible):
    state = genesis_state.copy(
        slot=get_epoch_start_slot(current_epoch, config.SLOTS_PER_EPOCH)
    )
    validator_index = 0

    # Set eligible validators
    state = state.update_validator_registry(
        validator_index,
        state.validator_registry[validator_index].copy(
            withdrawable_epoch=withdrawable_epoch,
            exit_epoch=exit_epoch,
        )
    )

    result_state = process_exit_queue(state, config)

    if is_eligible:
        # Check if they got prepared for withdrawal
        assert (
            result_state.validator_registry[validator_index].withdrawable_epoch ==
            current_epoch + min_validator_withdrawability_delay
        )
    else:
        assert (
            result_state.validator_registry[validator_index].withdrawable_epoch ==
            state.validator_registry[validator_index].withdrawable_epoch
        )
def test_validate_voluntary_validator_exit_epoch(genesis_state, current_epoch,
                                                 validator_exit_epoch,
                                                 slots_per_epoch,
                                                 activation_exit_delay,
                                                 success):
    state = genesis_state.copy(slot=get_epoch_start_slot(
        current_epoch, slots_per_epoch), )

    validator_index = 0

    validator = state.validator_registry[validator_index].copy(
        exit_epoch=validator_exit_epoch, )

    if success:
        validate_voluntary_exit_validator_exit_epoch(
            state,
            validator,
            current_epoch,
            slots_per_epoch,
            activation_exit_delay,
        )
    else:
        with pytest.raises(ValidationError):
            validate_voluntary_exit_validator_exit_epoch(
                state,
                validator,
                current_epoch,
                slots_per_epoch,
                activation_exit_delay,
            )
Esempio n. 8
0
def test_get_attesting_indices(genesis_state, config):
    state = genesis_state.copy(
        slot=get_epoch_start_slot(3, config.SLOTS_PER_EPOCH))
    target_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    target_shard = (state.start_shard + 3) % config.SHARD_COUNT
    some_committee = get_crosslink_committee(
        state,
        target_epoch,
        target_shard,
        CommitteeConfig(config),
    )

    data = AttestationData(
        target_epoch=target_epoch,
        crosslink=Crosslink(shard=target_shard, ),
    )
    some_subset_count = random.randint(1, len(some_committee) // 2)
    some_subset = random.sample(some_committee, some_subset_count)

    bitfield = get_empty_bitfield(len(some_committee))
    for i, index in enumerate(some_committee):
        if index in some_subset:
            bitfield = set_voted(bitfield, i)

    indices = get_attesting_indices(
        state,
        data,
        bitfield,
        CommitteeConfig(config),
    )

    assert set(indices) == set(some_subset)
    assert len(indices) == len(some_subset)
Esempio n. 9
0
def test_get_matching_head_attestations(genesis_state, config):
    some_epoch = config.GENESIS_EPOCH + 20
    some_slot = get_epoch_start_slot(
        some_epoch, config.SLOTS_PER_EPOCH) + config.SLOTS_PER_EPOCH // 4
    some_target_root = b'\x33' * 32
    target_attestations = tuple((PendingAttestation(data=AttestationData(
        beacon_block_root=some_target_root,
        target_epoch=some_epoch - 1,
        crosslink=Crosslink(shard=i, )), ) for i in range(3)))
    current_epoch_attestations = target_attestations + tuple(
        (PendingAttestation(data=AttestationData(
            beacon_block_root=b'\x44' * 32,
            target_epoch=some_epoch - 1,
        ), ) for _ in range(3)))
    state = genesis_state.copy(
        slot=some_slot - 1,
        block_roots=tuple(some_target_root
                          for _ in range(config.SLOTS_PER_HISTORICAL_ROOT)),
        current_epoch_attestations=current_epoch_attestations,
    )

    attestations = get_matching_head_attestations(
        state,
        some_epoch,
        config,
    )

    assert attestations == target_attestations
Esempio n. 10
0
def test_get_matching_target_attestations(genesis_state, config):
    some_epoch = config.GENESIS_EPOCH + 20
    some_slot = get_epoch_start_slot(some_epoch, config.SLOTS_PER_EPOCH)
    some_target_root = b'\x33' * 32
    target_attestations = tuple((PendingAttestation(data=AttestationData(
        target_root=some_target_root, ), ) for _ in range(3)))
    current_epoch_attestations = target_attestations + tuple(
        (PendingAttestation(data=AttestationData(target_root=b'\x44' * 32, ), )
         for _ in range(3)))
    state = genesis_state.copy(
        slot=some_slot + 1,
        block_roots=update_tuple_item(
            genesis_state.block_roots,
            some_slot % config.SLOTS_PER_HISTORICAL_ROOT,
            some_target_root,
        ),
        current_epoch_attestations=current_epoch_attestations,
    )

    attestations = get_matching_target_attestations(
        state,
        some_epoch,
        config,
    )

    assert attestations == target_attestations
Esempio n. 11
0
def test_get_matching_source_attestations(genesis_state, current_epoch,
                                          target_epoch, success, config):
    state = genesis_state.copy(
        slot=get_epoch_start_slot(current_epoch, config.SLOTS_PER_EPOCH),
        current_epoch_attestations=tuple(
            PendingAttestation(data=AttestationData(
                beacon_block_root=current_epoch.to_bytes(32, "little"), ))),
        previous_epoch_attestations=tuple(
            PendingAttestation(data=AttestationData(beacon_block_root=(
                current_epoch - 1).to_bytes(32, "little"), ))))

    if success:
        attestations = get_matching_source_attestations(
            state,
            target_epoch,
            config,
        )
    else:
        with pytest.raises(InvalidEpochError):
            get_matching_source_attestations(
                state,
                target_epoch,
                config,
            )
        return

    if current_epoch == target_epoch:
        assert attestations == state.current_epoch_attestations
    else:
        assert attestations == state.previous_epoch_attestations
Esempio n. 12
0
def test_get_next_epoch_committee_assignment(genesis_state, epoch_length,
                                             shard_count, config,
                                             num_validators, registry_change):
    state = genesis_state
    proposer_count = 0
    shard_validator_count = [0 for _ in range(shard_count)]
    slots = []
    next_epoch_start = get_epoch_start_slot(
        state.current_epoch(epoch_length) + 1, epoch_length)

    for validator_index in range(num_validators):
        assignment = get_next_epoch_committee_assignment(
            state,
            config,
            validator_index,
            registry_change,
        )
        assert assignment.slot >= next_epoch_start
        assert assignment.slot < next_epoch_start + epoch_length
        if assignment.is_proposer:
            proposer_count += 1

        shard_validator_count[assignment.shard] += 1
        slots.append(assignment.slot)

    assert proposer_count == epoch_length
    assert sum(shard_validator_count) == num_validators
Esempio n. 13
0
def validate_attestation_justified_epoch(attestation_data: AttestationData,
                                         current_epoch: EpochNumber,
                                         previous_justified_epoch: EpochNumber,
                                         justified_epoch: EpochNumber,
                                         epoch_length: int) -> None:
    """
    Validate ``justified_epoch`` field of ``attestation_data``.
    Raise ``ValidationError`` if it's invalid.
    """
    if attestation_data.slot >= get_epoch_start_slot(current_epoch, epoch_length):
        if attestation_data.justified_epoch != justified_epoch:
            raise ValidationError(
                "Attestation ``slot`` is after recent epoch transition but attestation"
                "``justified_epoch`` is not targeting the ``justified_epoch``:\n"
                "\tFound: %s, Expected %s" %
                (attestation_data.justified_epoch, justified_epoch)
            )
    else:
        if attestation_data.justified_epoch != previous_justified_epoch:
            raise ValidationError(
                "Attestation ``slot`` is before recent epoch transition but attestation"
                "``justified_epoch`` is not targeting the ``previous_justified_epoch:\n"
                "\tFound: %s, Expected %s" %
                (attestation_data.justified_epoch, previous_justified_epoch)
            )
Esempio n. 14
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 = get_epoch_start_slot(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,
    )
Esempio n. 15
0
def create_mock_attester_slashing_is_double_vote(
        state: BeaconState,
        config: Eth2Config,
        keymap: Dict[BLSPubkey, int],
        attestation_epoch: Epoch) -> AttesterSlashing:
    attestation_slot_1 = get_epoch_start_slot(attestation_epoch, config.SLOTS_PER_EPOCH)
    attestation_slot_2 = Slot(attestation_slot_1 + 1)

    slashable_attestation_1 = create_mock_slashable_attestation(
        state,
        config,
        keymap,
        attestation_slot_1,
    )
    slashable_attestation_2 = create_mock_slashable_attestation(
        state,
        config,
        keymap,
        attestation_slot_2,
    )

    return AttesterSlashing(
        slashable_attestation_1=slashable_attestation_1,
        slashable_attestation_2=slashable_attestation_2,
    )
Esempio n. 16
0
def test_validate_validator_minimum_lifespan(genesis_state, keymap,
                                             current_epoch, activation_epoch,
                                             slots_per_epoch,
                                             persistent_committee_period,
                                             success):
    state = genesis_state.copy(slot=get_epoch_start_slot(
        current_epoch, slots_per_epoch), )
    validator_index = 0
    validator = state.validators[validator_index].copy(
        activation_epoch=activation_epoch, )
    state = state.update_validator(validator_index, validator)

    if success:
        _validate_validator_minimum_lifespan(
            validator,
            state.current_epoch(slots_per_epoch),
            persistent_committee_period,
        )
    else:
        with pytest.raises(ValidationError):
            _validate_validator_minimum_lifespan(
                validator,
                state.current_epoch(slots_per_epoch),
                persistent_committee_period,
            )
Esempio n. 17
0
def test_validate_eligible_exit_epoch(genesis_state, keymap, current_epoch,
                                      voluntary_exit_epoch, slots_per_epoch,
                                      config, success):
    state = genesis_state.copy(slot=get_epoch_start_slot(
        current_epoch, slots_per_epoch), )

    validator_index = 0
    voluntary_exit = create_mock_voluntary_exit(
        state,
        config,
        keymap,
        validator_index,
        exit_epoch=voluntary_exit_epoch,
    )
    if success:
        _validate_eligible_exit_epoch(
            voluntary_exit.epoch,
            state.current_epoch(slots_per_epoch),
        )
    else:
        with pytest.raises(ValidationError):
            _validate_eligible_exit_epoch(
                voluntary_exit.epoch,
                state.current_epoch(slots_per_epoch),
            )
def test_validate_attestation_source_epoch_and_root(
        genesis_state, sample_attestation_data_params, attestation_slot,
        attestation_source_epoch, attestation_source_root, current_epoch,
        previous_justified_epoch, current_justified_epoch,
        previous_justified_root, current_justified_root, slots_per_epoch,
        is_valid):
    state = genesis_state.copy(
        slot=get_epoch_start_slot(current_epoch, slots_per_epoch),
        previous_justified_epoch=previous_justified_epoch,
        current_justified_epoch=current_justified_epoch,
        previous_justified_root=previous_justified_root,
        current_justified_root=current_justified_root,
    )
    attestation_data = AttestationData(**sample_attestation_data_params).copy(
        slot=attestation_slot,
        source_epoch=attestation_source_epoch,
        source_root=attestation_source_root,
    )

    if is_valid:
        validate_attestation_source_epoch_and_root(
            state,
            attestation_data,
            current_epoch,
            slots_per_epoch,
        )
    else:
        with pytest.raises(ValidationError):
            validate_attestation_source_epoch_and_root(
                state,
                attestation_data,
                current_epoch,
                slots_per_epoch,
            )
def test_validate_voluntary_exit_persistent(genesis_state, keymap,
                                            current_epoch, activation_epoch,
                                            slots_per_epoch,
                                            persistent_committee_period,
                                            success):
    state = genesis_state.copy(slot=get_epoch_start_slot(
        current_epoch, slots_per_epoch), )
    validator_index = 0
    validator = state.validator_registry[validator_index].copy(
        activation_epoch=activation_epoch, )
    state = state.update_validator_registry(validator_index, validator)

    if success:
        validate_voluntary_exit_persistent(
            validator,
            state.current_epoch(slots_per_epoch),
            persistent_committee_period,
        )
    else:
        with pytest.raises(ValidationError):
            validate_voluntary_exit_persistent(
                validator,
                state.current_epoch(slots_per_epoch),
                persistent_committee_period,
            )
Esempio n. 20
0
def test_generate_seed(genesis_state,
                       committee_config,
                       slots_per_epoch,
                       min_seed_lookahead,
                       activation_exit_delay,
                       epochs_per_historical_vector):
    def mock_get_randao_mix(state,
                            epoch,
                            slots_per_epoch,
                            epochs_per_historical_vector,
                            perform_validation=False):
        return hash_eth2(
            state.root +
            epoch.to_bytes(32, byteorder='little') +
            epochs_per_historical_vector.to_bytes(32, byteorder='little')
        )

    def mock_get_active_index_root(state,
                                   epoch,
                                   slots_per_epoch,
                                   activation_exit_delay,
                                   epochs_per_historical_vector):
        return hash_eth2(
            state.root +
            epoch.to_bytes(32, byteorder='little') +
            slots_per_epoch.to_bytes(32, byteorder='little') +
            epochs_per_historical_vector.to_bytes(32, byteorder='little')
        )

    state = genesis_state
    epoch = 1
    state = state.copy(
        slot=get_epoch_start_slot(epoch, committee_config.SLOTS_PER_EPOCH),
    )

    epoch_as_bytes = epoch.to_bytes(32, 'little')

    seed = _generate_seed(
        state=state,
        epoch=epoch,
        randao_provider=mock_get_randao_mix,
        active_index_root_provider=mock_get_active_index_root,
        epoch_provider=lambda *_: epoch_as_bytes,
        committee_config=committee_config,
    )
    assert seed == hash_eth2(
        mock_get_randao_mix(
            state=state,
            epoch=(epoch + epochs_per_historical_vector - min_seed_lookahead),
            slots_per_epoch=slots_per_epoch,
            epochs_per_historical_vector=epochs_per_historical_vector,
        ) + mock_get_active_index_root(
            state=state,
            epoch=epoch,
            slots_per_epoch=slots_per_epoch,
            activation_exit_delay=activation_exit_delay,
            epochs_per_historical_vector=epochs_per_historical_vector,
        ) + epoch_as_bytes
    )
Esempio n. 21
0
def _validate_withdrawable_epoch(state_slot: Slot,
                                 validator_withdrawable_epoch: Epoch,
                                 slots_per_epoch: int) -> None:
    if state_slot >= get_epoch_start_slot(validator_withdrawable_epoch,
                                          slots_per_epoch):
        raise ValidationError(
            f"state.slot ({state_slot}) should be less than "
            f"validator.withdrawable_epoch ({validator_withdrawable_epoch})")
Esempio n. 22
0
def create_mock_signed_attestations_at_slot(
        state: BeaconState,
        config: Eth2Config,
        attestation_slot: Slot,
        beacon_block_root: Hash32,
        keymap: Dict[BLSPubkey, int],
        voted_attesters_ratio: float=1.0) -> Iterable[Attestation]:
    """
    Create the mocking attestations of the given ``attestation_slot`` slot with ``keymap``.
    """
    slots_per_epoch = config.SLOTS_PER_EPOCH

    crosslink_committees_at_slot = get_crosslink_committees_at_slot(
        # To avoid the epoch boundary cases
        state.copy(
            slot=state.slot + 1,
        ),
        attestation_slot,
        CommitteeConfig(config),
    )

    # Get `target_root`
    target_root = _get_target_root(state, config, beacon_block_root)

    # Get `source_root`
    source_root = get_block_root(
        state,
        get_epoch_start_slot(state.justified_epoch, slots_per_epoch),
        config.SLOTS_PER_HISTORICAL_ROOT,
    )

    for crosslink_committee in crosslink_committees_at_slot:
        committee, shard = crosslink_committee

        num_voted_attesters = int(len(committee) * voted_attesters_ratio)
        previous_crosslink = state.latest_crosslinks[shard]

        attestation_data = AttestationData(
            slot=attestation_slot,
            beacon_block_root=beacon_block_root,
            source_epoch=state.justified_epoch,
            source_root=source_root,
            target_root=target_root,
            shard=shard,
            previous_crosslink=previous_crosslink,
            crosslink_data_root=ZERO_HASH32,
        )

        num_voted_attesters = int(len(committee) * voted_attesters_ratio)

        yield create_mock_signed_attestation(
            state,
            attestation_data,
            committee,
            num_voted_attesters,
            keymap,
            config.SLOTS_PER_EPOCH,
        )
Esempio n. 23
0
def test_process_voluntary_exits(genesis_state, sample_beacon_block_params,
                                 sample_beacon_block_body_params, config,
                                 keymap, success):
    state = genesis_state.copy(slot=get_epoch_start_slot(
        config.GENESIS_EPOCH + config.PERSISTENT_COMMITTEE_PERIOD,
        config.SLOTS_PER_EPOCH,
    ), )
    validator_index = 0
    validator = state.validators[validator_index].copy(
        activation_epoch=config.GENESIS_EPOCH, )
    state = state.update_validator(validator_index, validator)
    valid_voluntary_exit = create_mock_voluntary_exit(
        state,
        config,
        keymap,
        validator_index,
    )

    if success:
        block_body = BeaconBlockBody(**sample_beacon_block_body_params).copy(
            voluntary_exits=(valid_voluntary_exit, ), )
        block = SerenityBeaconBlock(**sample_beacon_block_params).copy(
            slot=state.slot,
            body=block_body,
        )

        new_state = process_voluntary_exits(
            state,
            block,
            config,
        )
        updated_validator = new_state.validators[validator_index]
        assert updated_validator.exit_epoch != FAR_FUTURE_EPOCH
        assert updated_validator.exit_epoch > state.current_epoch(
            config.SLOTS_PER_EPOCH)
        assert updated_validator.withdrawable_epoch == (
            updated_validator.exit_epoch +
            config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY)
    else:
        invalid_voluntary_exit = valid_voluntary_exit.copy(
            signature=b'\x12' * 96,  # Put wrong signature
        )
        block_body = BeaconBlockBody(**sample_beacon_block_body_params).copy(
            voluntary_exits=(invalid_voluntary_exit, ), )
        block = SerenityBeaconBlock(**sample_beacon_block_params).copy(
            slot=state.slot,
            body=block_body,
        )

        with pytest.raises(ValidationError):
            process_voluntary_exits(
                state,
                block,
                config,
            )
Esempio n. 24
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
Esempio n. 25
0
def validate_attestation(state: BeaconState,
                         attestation: Attestation,
                         genesis_epoch: EpochNumber,
                         epoch_length: int,
                         min_attestation_inclusion_delay: int,
                         latest_block_roots_length: int,
                         target_committee_size: int,
                         shard_count: int) -> None:
    """
    Validate the given ``attestation``.
    Raise ``ValidationError`` if it's invalid.
    """

    validate_attestation_slot(
        attestation.data,
        state.slot,
        epoch_length,
        min_attestation_inclusion_delay,
    )

    validate_attestation_justified_epoch(
        attestation.data,
        state.current_epoch(epoch_length),
        state.previous_justified_epoch,
        state.justified_epoch,
        epoch_length,
    )

    validate_attestation_justified_block_root(
        attestation.data,
        justified_block_root=get_block_root(
            state=state,
            slot=get_epoch_start_slot(attestation.data.justified_epoch, epoch_length),
            latest_block_roots_length=latest_block_roots_length,
        ),
    )

    validate_attestation_latest_crosslink_root(
        attestation.data,
        latest_crosslink_root=state.latest_crosslinks[attestation.data.shard].shard_block_root,
    )

    validate_attestation_shard_block_root(attestation.data)

    validate_attestation_aggregate_signature(
        state,
        attestation,
        genesis_epoch,
        epoch_length,
        target_committee_size,
        shard_count,
    )
Esempio n. 26
0
def validate_attestation(state: BeaconState, attestation: Attestation,
                         min_attestation_inclusion_delay: int,
                         slots_per_historical_root: int,
                         committee_config: CommitteeConfig) -> None:
    """
    Validate the given ``attestation``.
    Raise ``ValidationError`` if it's invalid.
    """
    slots_per_epoch = committee_config.SLOTS_PER_EPOCH

    validate_attestation_slot(
        attestation.data,
        state.slot,
        slots_per_epoch,
        min_attestation_inclusion_delay,
        committee_config.GENESIS_SLOT,
    )

    validate_attestation_source_epoch(
        attestation.data,
        state.current_epoch(slots_per_epoch),
        state.previous_justified_epoch,
        state.justified_epoch,
        slots_per_epoch,
    )

    validate_attestation_source_root(
        attestation.data,
        justified_epoch=get_block_root(
            state=state,
            slot=get_epoch_start_slot(
                attestation.data.source_epoch,
                slots_per_epoch,
            ),
            slots_per_historical_root=slots_per_historical_root,
        ),
    )

    validate_attestation_previous_crosslink_or_root(
        attestation_data=attestation.data,
        state_latest_crosslink=state.latest_crosslinks[attestation.data.shard],
        slots_per_epoch=slots_per_epoch,
    )

    validate_attestation_crosslink_data_root(attestation.data)

    validate_attestation_aggregate_signature(
        state,
        attestation,
        committee_config,
    )
Esempio n. 27
0
def _get_target_root(state: BeaconState, config: Eth2Config,
                     beacon_block_root: Hash32) -> Hash32:
    epoch_start_slot = get_epoch_start_slot(
        slot_to_epoch(state.slot, config.SLOTS_PER_EPOCH),
        config.SLOTS_PER_EPOCH,
    )
    if epoch_start_slot == state.slot:
        return beacon_block_root
    else:
        return get_block_root(
            state,
            epoch_start_slot,
            config.SLOTS_PER_HISTORICAL_ROOT,
        )
Esempio n. 28
0
def validate_attestation(state: BeaconState, attestation: Attestation,
                         min_attestation_inclusion_delay: int,
                         latest_block_roots_length: int,
                         committee_config: CommitteeConfig) -> None:
    """
    Validate the given ``attestation``.
    Raise ``ValidationError`` if it's invalid.
    """
    epoch_length = committee_config.EPOCH_LENGTH

    validate_attestation_slot(
        attestation.data,
        state.slot,
        epoch_length,
        min_attestation_inclusion_delay,
    )

    validate_attestation_justified_epoch(
        attestation.data,
        state.current_epoch(epoch_length),
        state.previous_justified_epoch,
        state.justified_epoch,
        epoch_length,
    )

    validate_attestation_justified_block_root(
        attestation.data,
        justified_block_root=get_block_root(
            state=state,
            slot=get_epoch_start_slot(
                attestation.data.justified_epoch,
                epoch_length,
            ),
            latest_block_roots_length=latest_block_roots_length,
        ),
    )

    validate_attestation_latest_crosslink_root(
        attestation.data,
        latest_crosslink_root=state.latest_crosslinks[
            attestation.data.shard].shard_block_root,
    )

    validate_attestation_shard_block_root(attestation.data)

    validate_attestation_aggregate_signature(
        state,
        attestation,
        committee_config,
    )
Esempio n. 29
0
def test_process_voluntary_exits(genesis_state, sample_beacon_block_params,
                                 sample_beacon_block_body_params, config,
                                 keymap, success):
    state = genesis_state.copy(slot=get_epoch_start_slot(
        config.GENESIS_EPOCH + config.PERSISTENT_COMMITTEE_PERIOD,
        config.SLOTS_PER_EPOCH,
    ), )
    validator_index = 0
    validator = state.validator_registry[validator_index].copy(
        activation_epoch=config.GENESIS_EPOCH, )
    state = state.update_validator_registry(validator_index, validator)
    valid_voluntary_exit = create_mock_voluntary_exit(
        state,
        config,
        keymap,
        validator_index,
    )

    if success:
        block_body = BeaconBlockBody(**sample_beacon_block_body_params).copy(
            voluntary_exits=(valid_voluntary_exit, ), )
        block = SerenityBeaconBlock(**sample_beacon_block_params).copy(
            slot=state.slot,
            body=block_body,
        )

        new_state = process_voluntary_exits(
            state,
            block,
            config,
        )
        # Check if initiated exit
        assert (new_state.validator_registry[validator_index].initiated_exit)
    else:
        invalid_voluntary_exit = valid_voluntary_exit.copy(
            signature=b'\x12' * 96,  # Put wrong signature
        )
        block_body = BeaconBlockBody(**sample_beacon_block_body_params).copy(
            voluntary_exits=(invalid_voluntary_exit, ), )
        block = SerenityBeaconBlock(**sample_beacon_block_params).copy(
            slot=state.slot,
            body=block_body,
        )

        with pytest.raises(ValidationError):
            process_voluntary_exits(
                state,
                block,
                config,
            )
Esempio n. 30
0
def _get_epoch_boundary_root(state: BeaconState, config: BeaconConfig,
                             beacon_block_root: Hash32) -> Hash32:
    epoch_start_slot = get_epoch_start_slot(
        slot_to_epoch(state.slot, config.SLOTS_PER_EPOCH),
        config.SLOTS_PER_EPOCH,
    )
    if epoch_start_slot == state.slot:
        return beacon_block_root
    else:
        return get_block_root(
            state,
            epoch_start_slot,
            config.LATEST_BLOCK_ROOTS_LENGTH,
        )