def test_invalid_signature_past_block(spec, state):
    committee_indices = compute_committee_indices(spec, state)

    for _ in range(2):
        # NOTE: need to transition twice to move beyond the degenerate case at genesis
        block = build_empty_block_for_next_slot(spec, state)
        # Valid sync committee signature here...
        block.body.sync_aggregate = spec.SyncAggregate(
            sync_committee_bits=[True] * len(committee_indices),
            sync_committee_signature=compute_aggregate_sync_committee_signature(
                spec,
                state,
                block.slot - 1,
                committee_indices,
                block_root=block.parent_root,
            )
        )

        state_transition_and_sign_block(spec, state, block)

    invalid_block = build_empty_block_for_next_slot(spec, state)
    # Invalid signature from a slot other than the previous
    invalid_block.body.sync_aggregate = spec.SyncAggregate(
        sync_committee_bits=[True] * len(committee_indices),
        sync_committee_signature=compute_aggregate_sync_committee_signature(
            spec,
            state,
            invalid_block.slot - 2,
            committee_indices,
        )
    )

    yield from run_sync_committee_processing(spec, state, invalid_block, expect_exception=True)
def test_sync_committee_with_participating_withdrawable_member(spec, state):
    # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
    state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH

    # move forward via some blocks
    for _ in range(3):
        next_epoch_via_block(spec, state)

    committee_indices = compute_committee_indices(spec, state)
    rng = random.Random(1010)

    exited_index = _exit_validator_from_committee_and_transition_state(
        spec,
        state,
        committee_indices,
        rng,
        lambda v: v.withdrawable_epoch + 1,
    )

    current_epoch = spec.get_current_epoch(state)
    assert current_epoch > state.validators[exited_index].withdrawable_epoch

    block = build_empty_block_for_next_slot(spec, state)
    block.body.sync_aggregate = spec.SyncAggregate(
        sync_committee_bits=[True] * len(committee_indices),
        sync_committee_signature=compute_aggregate_sync_committee_signature(
            spec,
            state,
            block.slot - 1,
            committee_indices,  # full committee signs
            block_root=block.parent_root,
        )
    )
    yield from run_sync_committee_processing(spec, state, block)
def test_proposer_in_committee_with_participation(spec, state):
    committee_indices = compute_committee_indices(spec, state, state.current_sync_committee)
    participation = [True for _ in committee_indices]

    # NOTE: seem to reliably be getting a matching proposer in the first epoch w/ ``MINIMAL`` preset.
    for _ in range(spec.SLOTS_PER_EPOCH):
        block = build_empty_block_for_next_slot(spec, state)
        proposer_index = block.proposer_index
        proposer_pubkey = state.validators[proposer_index].pubkey
        proposer_is_in_sync_committee = proposer_pubkey in state.current_sync_committee.pubkeys

        # Valid sync committee signature here...
        block.body.sync_aggregate = spec.SyncAggregate(
            sync_committee_bits=participation,
            sync_committee_signature=compute_aggregate_sync_committee_signature(
                spec,
                state,
                block.slot - 1,
                committee_indices,
                block_root=block.parent_root,
            )
        )

        if proposer_is_in_sync_committee:
            assert state.validators[block.proposer_index].pubkey in state.current_sync_committee.pubkeys
            yield from run_sync_committee_processing(spec, state, block)
            return
        else:
            state_transition_and_sign_block(spec, state, block)
    raise AssertionError("failed to find a proposer in the sync committee set; check test setup")
def test_invalid_signature_previous_committee(spec, state):
    # NOTE: the `state` provided is at genesis and the process to select
    # sync committees currently returns the same committee for the first and second
    # periods at genesis.
    # To get a distinct committee so we can generate an "old" signature, we need to advance
    # 2 EPOCHS_PER_SYNC_COMMITTEE_PERIOD periods.
    current_epoch = spec.get_current_epoch(state)
    old_sync_committee = state.next_sync_committee

    epoch_in_future_sync_commitee_period = current_epoch + 2 * spec.EPOCHS_PER_SYNC_COMMITTEE_PERIOD
    slot_in_future_sync_committee_period = epoch_in_future_sync_commitee_period * spec.SLOTS_PER_EPOCH
    transition_to(spec, state, slot_in_future_sync_committee_period)

    # Use the previous sync committee to produce the signature.
    # Ensure that the pubkey sets are different.
    assert set(old_sync_committee.pubkeys) != set(state.current_sync_committee.pubkeys)
    committee_indices = compute_committee_indices(spec, state, old_sync_committee)

    block = build_empty_block_for_next_slot(spec, state)
    block.body.sync_aggregate = spec.SyncAggregate(
        sync_committee_bits=[True] * len(committee_indices),
        sync_committee_signature=compute_aggregate_sync_committee_signature(
            spec,
            state,
            block.slot - 1,
            committee_indices,
            block_root=block.parent_root,
        )
    )

    yield from run_sync_committee_processing(spec, state, block, expect_exception=True)
Ejemplo n.º 5
0
def get_random_sync_aggregate(spec,
                              state,
                              slot,
                              block_root=None,
                              fraction_participated=1.0,
                              rng=Random(2099)):
    committee_indices = compute_committee_indices(spec, state,
                                                  state.current_sync_committee)
    participant_count = int(len(committee_indices) * fraction_participated)
    participant_indices = rng.sample(range(len(committee_indices)),
                                     participant_count)
    participants = [committee_indices[index] for index in participant_indices]
    signature = compute_aggregate_sync_committee_signature(
        spec,
        state,
        slot,
        participants,
        block_root=block_root,
    )
    return spec.SyncAggregate(
        sync_committee_bits=[
            index in participant_indices
            for index in range(len(committee_indices))
        ],
        sync_committee_signature=signature,
    )
Ejemplo n.º 6
0
def check_proposer_slashing_effect(spec,
                                   pre_state,
                                   state,
                                   slashed_index,
                                   block=None):
    slashed_validator = state.validators[slashed_index]
    assert slashed_validator.slashed
    assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
    assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH

    proposer_index = spec.get_beacon_proposer_index(state)
    slash_penalty = state.validators[
        slashed_index].effective_balance // get_min_slashing_penalty_quotient(
            spec)
    whistleblower_reward = state.validators[
        slashed_index].effective_balance // spec.WHISTLEBLOWER_REWARD_QUOTIENT

    # Altair introduces sync committee (SC) reward and penalty
    sc_reward_for_slashed = sc_penalty_for_slashed = sc_reward_for_proposer = sc_penalty_for_proposer = 0
    if is_post_altair(spec) and block is not None:
        committee_indices = compute_committee_indices(
            spec, state, state.current_sync_committee)
        committee_bits = block.body.sync_aggregate.sync_committee_bits
        sc_reward_for_slashed, sc_penalty_for_slashed = compute_sync_committee_participant_reward_and_penalty(
            spec,
            pre_state,
            slashed_index,
            committee_indices,
            committee_bits,
        )
        sc_reward_for_proposer, sc_penalty_for_proposer = compute_sync_committee_participant_reward_and_penalty(
            spec,
            pre_state,
            proposer_index,
            committee_indices,
            committee_bits,
        )

    if proposer_index != slashed_index:
        # slashed validator lost initial slash penalty
        assert (get_balance(
            state, slashed_index) == get_balance(pre_state, slashed_index) -
                slash_penalty + sc_reward_for_slashed - sc_penalty_for_slashed)
        # block proposer gained whistleblower reward
        # >= because proposer could have reported multiple
        assert (
            get_balance(state, proposer_index) >=
            (get_balance(pre_state, proposer_index) + whistleblower_reward +
             sc_reward_for_proposer - sc_penalty_for_proposer))
    else:
        # proposer reported themself so get penalty and reward
        # >= because proposer could have reported multiple
        assert (get_balance(state, slashed_index) >=
                (get_balance(pre_state, slashed_index) - slash_penalty +
                 whistleblower_reward + sc_reward_for_slashed -
                 sc_penalty_for_slashed))
def test_sync_committee_rewards_duplicate_committee_full_participation(spec, state):
    committee_indices = compute_committee_indices(spec, state)
    committee_size = len(committee_indices)
    committee_bits = [True] * committee_size
    active_validator_count = len(spec.get_active_validator_indices(state, spec.get_current_epoch(state)))

    # Preconditions of this test case
    assert active_validator_count < spec.SYNC_COMMITTEE_SIZE
    assert committee_size > len(set(committee_indices))

    yield from run_successful_sync_committee_test(spec, state, committee_indices, committee_bits)
def test_invalid_signature_bad_domain(spec, state):
    committee_indices = compute_committee_indices(spec, state)

    block = build_empty_block_for_next_slot(spec, state)
    block.body.sync_aggregate = spec.SyncAggregate(
        sync_committee_bits=[True] * len(committee_indices),
        sync_committee_signature=compute_aggregate_sync_committee_signature(
            spec,
            state,
            block.slot - 1,
            committee_indices,  # full committee signs
            block_root=block.parent_root,
            domain_type=spec.DOMAIN_BEACON_ATTESTER,  # Incorrect domain
        )
    )
    yield from run_sync_committee_processing(spec, state, block, expect_exception=True)
def test_invalid_signature_missing_participant(spec, state):
    committee_indices = compute_committee_indices(spec, state)
    rng = random.Random(2020)
    random_participant = rng.choice(committee_indices)

    block = build_empty_block_for_next_slot(spec, state)
    # Exclude one participant whose signature was included.
    block.body.sync_aggregate = spec.SyncAggregate(
        sync_committee_bits=[index != random_participant for index in committee_indices],
        sync_committee_signature=compute_aggregate_sync_committee_signature(
            spec,
            state,
            block.slot - 1,
            committee_indices,  # full committee signs
            block_root=block.parent_root,
        )
    )
    yield from run_sync_committee_processing(spec, state, block, expect_exception=True)
def test_invalid_signature_extra_participant(spec, state):
    committee_indices = compute_committee_indices(spec, state)
    rng = random.Random(3030)
    random_participant = rng.choice(committee_indices)

    block = build_empty_block_for_next_slot(spec, state)
    # Exclude one signature even though the block claims the entire committee participated.
    block.body.sync_aggregate = spec.SyncAggregate(
        sync_committee_bits=[True] * len(committee_indices),
        sync_committee_signature=compute_aggregate_sync_committee_signature(
            spec,
            state,
            block.slot - 1,
            [index for index in committee_indices if index != random_participant],
            block_root=block.parent_root,
        )
    )

    yield from run_sync_committee_processing(spec, state, block, expect_exception=True)
Ejemplo n.º 11
0
def test_deposit_top_up(spec, state):
    validator_index = 0
    amount = spec.MAX_EFFECTIVE_BALANCE // 4
    deposit = prepare_state_and_deposit(spec, state, validator_index, amount)

    initial_registry_len = len(state.validators)
    initial_balances_len = len(state.balances)
    validator_pre_balance = get_balance(state, validator_index)

    pre_state = state.copy()
    yield 'pre', pre_state

    block = build_empty_block_for_next_slot(spec, state)
    block.body.deposits.append(deposit)

    signed_block = state_transition_and_sign_block(spec, state, block)

    yield 'blocks', [signed_block]
    yield 'post', state

    assert len(state.validators) == initial_registry_len
    assert len(state.balances) == initial_balances_len

    # Altair introduces sync committee (sm) reward and penalty
    sync_committee_reward = sync_committee_penalty = 0
    if is_post_altair(spec):
        committee_indices = compute_committee_indices(
            spec, state, state.current_sync_committee)
        committee_bits = block.body.sync_aggregate.sync_committee_bits
        sync_committee_reward, sync_committee_penalty = compute_sync_committee_participant_reward_and_penalty(
            spec,
            pre_state,
            validator_index,
            committee_indices,
            committee_bits,
        )

    assert get_balance(state,
                       validator_index) == (validator_pre_balance + amount +
                                            sync_committee_reward -
                                            sync_committee_penalty)
def test_sync_committee_with_nonparticipating_exited_member(spec, state):
    # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit
    state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH

    # move forward via some blocks
    for _ in range(3):
        next_epoch_via_block(spec, state)

    committee_indices = compute_committee_indices(spec, state)
    rng = random.Random(1010)

    exited_index = _exit_validator_from_committee_and_transition_state(
        spec,
        state,
        committee_indices,
        rng,
        lambda v: v.exit_epoch,
    )
    exited_pubkey = state.validators[exited_index].pubkey

    current_epoch = spec.get_current_epoch(state)
    assert current_epoch < state.validators[exited_index].withdrawable_epoch

    exited_committee_index = state.current_sync_committee.pubkeys.index(exited_pubkey)
    block = build_empty_block_for_next_slot(spec, state)
    committee_bits = [i != exited_committee_index for i in committee_indices]
    committee_indices = [index for index in committee_indices if index != exited_committee_index]
    block.body.sync_aggregate = spec.SyncAggregate(
        sync_committee_bits=committee_bits,
        sync_committee_signature=compute_aggregate_sync_committee_signature(
            spec,
            state,
            block.slot - 1,
            committee_indices,  # with exited validator removed
            block_root=block.parent_root,
        )
    )
    yield from run_sync_committee_processing(spec, state, block)
def _test_harness_for_randomized_test_case(spec,
                                           state,
                                           expect_duplicates=False,
                                           participation_fn=None):
    committee_indices = compute_committee_indices(spec, state)

    if participation_fn:
        participating_indices = participation_fn(committee_indices)
    else:
        participating_indices = committee_indices

    committee_bits = [
        index in participating_indices for index in committee_indices
    ]
    committee_size = len(committee_indices)
    if expect_duplicates:
        assert committee_size > len(set(committee_indices))
    else:
        assert committee_size == len(set(committee_indices))

    yield from run_successful_sync_committee_test(spec, state,
                                                  committee_indices,
                                                  committee_bits)
def test_sync_committee_rewards_empty_participants(spec, state):
    committee_indices = compute_committee_indices(spec, state)
    committee_bits = [False for _ in committee_indices]

    yield from run_successful_sync_committee_test(spec, state, committee_indices, committee_bits)
def test_sync_committee_rewards_not_full_participants(spec, state):
    committee_indices = compute_committee_indices(spec, state)
    rng = random.Random(1010)
    committee_bits = [rng.choice([True, False]) for _ in committee_indices]

    yield from run_successful_sync_committee_test(spec, state, committee_indices, committee_bits)