def test_incorrect_head_and_target_min_inclusion_delay(spec, state):
    attestation = get_valid_attestation(spec, state, signed=False)
    next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)

    attestation.data.beacon_block_root = b'\x42' * 32
    attestation.data.target.root = b'\x42' * 32
    sign_attestation(spec, state, attestation)

    yield from run_attestation_processing(spec, state, attestation)
def test_bad_source_root(spec, state):
    attestation = get_valid_attestation(spec, state)
    next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)

    attestation.data.source.root = b'\x42' * 32

    sign_attestation(spec, state, attestation)

    yield from run_attestation_processing(spec, state, attestation, False)
def test_new_source_epoch(spec, state):
    attestation = get_valid_attestation(spec, state)
    next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)

    attestation.data.source.epoch += 1

    sign_attestation(spec, state, attestation)

    yield from run_attestation_processing(spec, state, attestation, False)
def test_process_light_client_update_timeout(spec, state):
    store = initialize_light_client_store(spec, state)

    # Forward to next sync committee period
    next_slots(spec, state, spec.UPDATE_TIMEOUT)
    snapshot_period = spec.compute_sync_committee_period(
        spec.compute_epoch_at_slot(store.optimistic_header.slot))
    update_period = spec.compute_sync_committee_period(
        spec.compute_epoch_at_slot(state.slot))
    assert snapshot_period + 1 == update_period

    block = build_empty_block_for_next_slot(spec, state)
    signed_block = state_transition_and_sign_block(spec, state, block)
    block_header = spec.BeaconBlockHeader(
        slot=signed_block.message.slot,
        proposer_index=signed_block.message.proposer_index,
        parent_root=signed_block.message.parent_root,
        state_root=signed_block.message.state_root,
        body_root=signed_block.message.body.hash_tree_root(),
    )

    # Sync committee signing the finalized_block_header
    sync_aggregate = get_sync_aggregate(spec,
                                        state,
                                        block_header,
                                        block_root=spec.Root(
                                            block_header.hash_tree_root()))

    # Sync committee is updated
    next_sync_committee_branch = build_proof(state.get_backing(),
                                             spec.NEXT_SYNC_COMMITTEE_INDEX)
    # Finality is unchanged
    finality_header = spec.BeaconBlockHeader()
    finality_branch = [
        spec.Bytes32()
        for _ in range(spec.floorlog2(spec.FINALIZED_ROOT_INDEX))
    ]

    update = spec.LightClientUpdate(
        attested_header=block_header,
        next_sync_committee=state.next_sync_committee,
        next_sync_committee_branch=next_sync_committee_branch,
        finalized_header=finality_header,
        finality_branch=finality_branch,
        sync_aggregate=sync_aggregate,
        fork_version=state.fork.current_version,
    )

    pre_store = deepcopy(store)

    spec.process_light_client_update(store, update, state.slot,
                                     state.genesis_validators_root)

    assert store.current_max_active_participants > 0
    assert store.optimistic_header == update.attested_header
    assert store.best_valid_update == update
    assert store.finalized_header == pre_store.finalized_header
Example #5
0
def test_incorrect_head_and_target_after_epoch_delay(spec, state):
    attestation = get_valid_attestation(spec, state, signed=False)
    # increment past latest inclusion slot
    next_slots(spec, state, spec.SLOTS_PER_EPOCH + 1)

    attestation.data.beacon_block_root = b'\x42' * 32
    attestation.data.target.root = b'\x42' * 32
    sign_attestation(spec, state, attestation)

    yield from run_attestation_processing(spec, state, attestation, False)
Example #6
0
def test_correct_after_epoch_delay(spec, state):
    attestation = get_valid_attestation(spec,
                                        state,
                                        signed=True,
                                        on_time=False)

    # increment past latest inclusion slot
    next_slots(spec, state, spec.SLOTS_PER_EPOCH + 1)

    yield from run_attestation_processing(spec, state, attestation, False)
Example #7
0
def test_wrong_index_for_slot_0(spec, state):
    reduce_state_committee_count_from_max(spec, state)

    attestation = get_valid_attestation(spec, state)
    next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)

    # Invalid index: current committees per slot is less than the max
    attestation.data.index = spec.MAX_COMMITTEES_PER_SLOT - 1

    yield from run_attestation_processing(spec, state, attestation, False)
Example #8
0
def test_incorrect_target_epoch_delay(spec, state):
    attestation = get_valid_attestation(spec,
                                        state,
                                        signed=False,
                                        on_time=False)
    next_slots(spec, state, spec.SLOTS_PER_EPOCH)

    attestation.data.target.root = b'\x42' * 32
    sign_attestation(spec, state, attestation)

    yield from run_attestation_processing(spec, state, attestation)
Example #9
0
def test_incorrect_head_sqrt_epoch_delay(spec, state):
    attestation = get_valid_attestation(spec,
                                        state,
                                        signed=False,
                                        on_time=False)
    next_slots(spec, state, spec.integer_squareroot(spec.SLOTS_PER_EPOCH))

    attestation.data.beacon_block_root = b'\x42' * 32
    sign_attestation(spec, state, attestation)

    yield from run_attestation_processing(spec, state, attestation)
Example #10
0
def test_old_target_epoch(spec, state):
    assert spec.MIN_ATTESTATION_INCLUSION_DELAY < spec.SLOTS_PER_EPOCH * 2

    attestation = get_valid_attestation(spec,
                                        state,
                                        signed=True,
                                        on_time=False)

    next_slots(spec, state, spec.SLOTS_PER_EPOCH *
               2)  # target epoch will be too old to handle

    yield from run_attestation_processing(spec, state, attestation, False)
Example #11
0
def test_wrong_index_for_slot_1(spec, state):
    reduce_state_committee_count_from_max(spec, state)

    current_epoch = spec.get_current_epoch(state)
    committee_count = spec.get_committee_count_per_slot(state, current_epoch)

    attestation = get_valid_attestation(spec, state, index=0)
    next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)

    # Invalid index: off by one
    attestation.data.index = committee_count

    yield from run_attestation_processing(spec, state, attestation, False)
Example #12
0
def test_too_few_aggregation_bits(spec, state):
    attestation = get_valid_attestation(spec, state)
    next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)

    attestation.aggregation_bits = Bitlist[spec.MAX_VALIDATORS_PER_COMMITTEE](
        *([0b1] + [0b0] * (len(attestation.aggregation_bits) - 1)))

    sign_attestation(spec, state, attestation)

    # one too few bits
    attestation.aggregation_bits = attestation.aggregation_bits[:-1]

    yield from run_attestation_processing(spec, state, attestation, False)
def test_wrong_index_for_slot(spec, state):
    while spec.get_committee_count_at_slot(state, state.slot) >= spec.MAX_COMMITTEES_PER_SLOT:
        state.validators = state.validators[:len(state.validators) // 2]
        state.balances = state.balances[:len(state.balances) // 2]

    index = spec.MAX_COMMITTEES_PER_SLOT - 1

    attestation = get_valid_attestation(spec, state)
    next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)

    attestation.data.index = index

    yield from run_attestation_processing(spec, state, attestation, False)
def test_old_source_epoch(spec, state):
    next_slots(spec, state, spec.SLOTS_PER_EPOCH * 5)
    state.finalized_checkpoint.epoch = 2
    state.previous_justified_checkpoint.epoch = 3
    state.current_justified_checkpoint.epoch = 4
    attestation = get_valid_attestation(spec, state, slot=(spec.SLOTS_PER_EPOCH * 3) + 1)

    # test logic sanity check: make sure the attestation is pointing to oldest known source epoch
    assert attestation.data.source.epoch == state.previous_justified_checkpoint.epoch

    # Now go beyond that, it will be invalid
    attestation.data.source.epoch -= 1

    sign_attestation(spec, state, attestation)

    yield from run_attestation_processing(spec, state, attestation, False)
Example #15
0
def test_on_block_finalized_skip_slots_not_in_skip_chain(spec, state):
    """
    Test case was originally from https://github.com/ethereum/consensus-specs/pull/1579
    And then rewrote largely.
    """
    test_steps = []
    # Initialization
    store, anchor_block = get_genesis_forkchoice_store_and_block(spec, state)
    yield 'anchor_state', state
    yield 'anchor_block', anchor_block
    current_time = state.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time
    on_tick_and_append_step(spec, store, current_time, test_steps)
    assert store.time == current_time

    # Fill epoch 0 and the first slot of epoch 1
    state, store, _ = yield from apply_next_slots_with_attestations(
        spec, state, store, spec.SLOTS_PER_EPOCH, True, False, test_steps)

    # Skip the rest slots of epoch 1 and the first slot of epoch 2
    next_slots(spec, state, spec.SLOTS_PER_EPOCH)

    # Fill epoch 3 and 4
    for _ in range(2):
        state, store, _ = yield from apply_next_epoch_with_attestations(
            spec, state, store, True, True, test_steps=test_steps)

    # Now we get finalized epoch 2, where `compute_start_slot_at_epoch(2)` is a skipped slot
    assert state.finalized_checkpoint.epoch == store.finalized_checkpoint.epoch == 2
    assert store.finalized_checkpoint.root == spec.get_block_root(
        state, 1) == spec.get_block_root(state, 2)
    assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3
    assert store.justified_checkpoint == state.current_justified_checkpoint

    # Now build a block after the block of the finalized **root**
    # Includes finalized block in chain, but does not include finalized skipped slots
    another_state = store.block_states[store.finalized_checkpoint.root].copy()
    assert another_state.slot == spec.compute_start_slot_at_epoch(
        store.finalized_checkpoint.epoch - 1)
    block = build_empty_block_for_next_slot(spec, another_state)
    signed_block = state_transition_and_sign_block(spec, another_state, block)
    yield from tick_and_add_block(spec,
                                  store,
                                  signed_block,
                                  test_steps,
                                  valid=False)

    yield 'steps', test_steps
Example #16
0
def test_future_target_epoch(spec, state):
    assert spec.MIN_ATTESTATION_INCLUSION_DELAY < spec.SLOTS_PER_EPOCH * 2

    attestation = get_valid_attestation(spec, state)

    participants = spec.get_attesting_indices(state, attestation.data,
                                              attestation.aggregation_bits)
    attestation.data.target.epoch = spec.get_current_epoch(
        state) + 1  # target epoch will be too new to handle

    # manually add signature for correct participants
    attestation.signature = sign_aggregate_attestation(spec, state,
                                                       attestation.data,
                                                       participants)

    next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)

    yield from run_attestation_processing(spec, state, attestation, False)
def test_invalid_current_source_root(spec, state):
    next_slots(spec, state, spec.SLOTS_PER_EPOCH * 5)

    state.finalized_checkpoint.epoch = 2

    state.previous_justified_checkpoint = spec.Checkpoint(epoch=3, root=b'\x01' * 32)
    state.current_justified_checkpoint = spec.Checkpoint(epoch=4, root=b'\x32' * 32)

    attestation = get_valid_attestation(spec, state, slot=(spec.SLOTS_PER_EPOCH * 3) + 1, on_time=False)
    next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)

    # Test logic sanity checks:
    assert state.current_justified_checkpoint.root != state.previous_justified_checkpoint.root
    assert attestation.data.source.root == state.previous_justified_checkpoint.root

    # Make attestation source root invalid: should be previous justified, not current one
    attestation.data.source.root = state.current_justified_checkpoint.root

    sign_attestation(spec, state, attestation)

    yield from run_attestation_processing(spec, state, attestation, False)
Example #18
0
def test_on_block_outside_safe_slots_but_finality(spec, state):
    """
    Test `should_update_justified_checkpoint` case
    - compute_slots_since_epoch_start(get_current_slot(store)) > SAFE_SLOTS_TO_UPDATE_JUSTIFIED
    - new_justified_checkpoint and store.justified_checkpoint.root are NOT conflicting

    Thus should_update_justified_checkpoint returns True.

    Part of this script is similar to `test_new_justified_is_later_than_store_justified`.
    """
    test_steps = []
    # Initialization
    store, anchor_block = get_genesis_forkchoice_store_and_block(spec, state)
    yield 'anchor_state', state
    yield 'anchor_block', anchor_block
    current_time = state.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time
    on_tick_and_append_step(spec, store, current_time, test_steps)
    assert store.time == current_time

    # Skip epoch 0
    next_epoch(spec, state)
    # Fill epoch 1 to 3, attest current epoch
    for _ in range(3):
        state, store, _ = yield from apply_next_epoch_with_attestations(
            spec, state, store, True, False, test_steps=test_steps)
    assert state.finalized_checkpoint.epoch == store.finalized_checkpoint.epoch == 2
    assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3

    # Skip epoch 4-6
    for _ in range(3):
        next_epoch(spec, state)

    # epoch 7
    state, store, _ = yield from apply_next_epoch_with_attestations(
        spec, state, store, True, True, test_steps=test_steps)
    assert state.finalized_checkpoint.epoch == 2
    assert state.current_justified_checkpoint.epoch == 7

    # epoch 8, attest the first 5 blocks
    state, store, _ = yield from apply_next_slots_with_attestations(
        spec, state, store, 5, True, True, test_steps)
    assert state.finalized_checkpoint.epoch == store.finalized_checkpoint.epoch == 2
    assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 7

    # Propose a block at epoch 9, 5th slot
    next_epoch(spec, state)
    next_slots(spec, state, 4)
    signed_block = state_transition_with_full_attestations_block(
        spec, state, True, True)
    yield from tick_and_add_block(spec, store, signed_block, test_steps)
    assert state.finalized_checkpoint.epoch == store.finalized_checkpoint.epoch == 2
    assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 7

    # Propose an empty block at epoch 10, SAFE_SLOTS_TO_UPDATE_JUSTIFIED + 2 slot
    # This block would trigger justification and finality updates on store
    next_epoch(spec, state)
    next_slots(spec, state, 4)
    block = build_empty_block_for_next_slot(spec, state)
    signed_block = state_transition_and_sign_block(spec, state, block)
    assert state.finalized_checkpoint.epoch == 7
    assert state.current_justified_checkpoint.epoch == 8
    # Step time past safe slots and run on_block
    if store.time < spec.compute_time_at_slot(state,
                                              signed_block.message.slot):
        time = store.genesis_time + signed_block.message.slot * spec.config.SECONDS_PER_SLOT
        on_tick_and_append_step(spec, store, time, test_steps)
    assert spec.get_current_slot(
        store) % spec.SLOTS_PER_EPOCH >= spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED
    yield from add_block(spec, store, signed_block, test_steps)

    # Ensure justified_checkpoint finality has been changed
    assert store.finalized_checkpoint.epoch == 7
    assert store.finalized_checkpoint == state.finalized_checkpoint
    assert store.justified_checkpoint.epoch == 8
    assert store.justified_checkpoint == state.current_justified_checkpoint

    yield 'steps', test_steps
Example #19
0
def test_success_multi_proposer_index_iterations(spec, state):
    next_slots(spec, state, spec.SLOTS_PER_EPOCH * 2)
    attestation = get_valid_attestation(spec, state, signed=True)
    next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)

    yield from run_attestation_processing(spec, state, attestation)
Example #20
0
def test_correct_min_inclusion_delay(spec, state):
    attestation = get_valid_attestation(spec, state, signed=True)
    next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)

    yield from run_attestation_processing(spec, state, attestation)
def test_process_light_client_update_finality_updated(spec, state):
    pre_snapshot = spec.LightClientSnapshot(
        header=spec.BeaconBlockHeader(),
        current_sync_committee=state.current_sync_committee,
        next_sync_committee=state.next_sync_committee,
    )
    store = spec.LightClientStore(snapshot=pre_snapshot, valid_updates=[])

    # Change finality
    blocks = []
    next_slots(spec, state, spec.SLOTS_PER_EPOCH * 2)
    for epoch in range(3):
        prev_state, new_blocks, state = next_epoch_with_attestations(
            spec, state, True, True)
        blocks += new_blocks
    # Ensure that finality checkpoint has changed
    assert state.finalized_checkpoint.epoch == 3
    # Ensure that it's same period
    snapshot_period = spec.compute_epoch_at_slot(
        pre_snapshot.header.slot) // spec.EPOCHS_PER_SYNC_COMMITTEE_PERIOD
    update_period = spec.compute_epoch_at_slot(
        state.slot) // spec.EPOCHS_PER_SYNC_COMMITTEE_PERIOD
    assert snapshot_period == update_period

    # Updated sync_committee and finality
    next_sync_committee_branch = [
        spec.Bytes32()
        for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))
    ]
    finalized_block_header = blocks[spec.SLOTS_PER_EPOCH - 1].message
    assert finalized_block_header.slot == spec.compute_start_slot_at_epoch(
        state.finalized_checkpoint.epoch)
    assert finalized_block_header.hash_tree_root(
    ) == state.finalized_checkpoint.root
    finality_branch = build_proof(state.get_backing(),
                                  spec.FINALIZED_ROOT_INDEX)

    # Build block header
    block = build_empty_block(spec, state)
    block_header = spec.BeaconBlockHeader(
        slot=block.slot,
        proposer_index=block.proposer_index,
        parent_root=block.parent_root,
        state_root=state.hash_tree_root(),
        body_root=block.body.hash_tree_root(),
    )

    # Sync committee signing the finalized_block_header
    committee = spec.get_sync_committee_indices(state,
                                                spec.get_current_epoch(state))
    sync_committee_bits = [True] * len(committee)
    sync_committee_signature = compute_aggregate_sync_committee_signature(
        spec,
        state,
        block_header.slot,
        committee,
        block_root=spec.Root(block_header.hash_tree_root()),
    )

    update = spec.LightClientUpdate(
        header=finalized_block_header,
        next_sync_committee=state.next_sync_committee,
        next_sync_committee_branch=next_sync_committee_branch,
        finality_header=block_header,  # block_header is the signed header
        finality_branch=finality_branch,
        sync_committee_bits=sync_committee_bits,
        sync_committee_signature=sync_committee_signature,
        fork_version=state.fork.current_version,
    )

    spec.process_light_client_update(store, update, state.slot,
                                     state.genesis_validators_root)

    # snapshot has been updated
    assert len(store.valid_updates) == 0
    assert store.snapshot.header == update.header
Example #22
0
def test_success(spec, state):
    attestation = get_valid_attestation(spec, state, signed=True)
    next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)

    yield from run_attestation_processing(spec, state, attestation)
def test_process_light_client_update_timeout(spec, state):
    pre_snapshot = spec.LightClientSnapshot(
        header=spec.BeaconBlockHeader(),
        current_sync_committee=state.current_sync_committee,
        next_sync_committee=state.next_sync_committee,
    )
    store = spec.LightClientStore(snapshot=pre_snapshot, valid_updates=[])

    # Forward to next sync committee period
    next_slots(spec, state,
               spec.SLOTS_PER_EPOCH * (spec.EPOCHS_PER_SYNC_COMMITTEE_PERIOD))
    snapshot_period = spec.compute_epoch_at_slot(
        pre_snapshot.header.slot) // spec.EPOCHS_PER_SYNC_COMMITTEE_PERIOD
    update_period = spec.compute_epoch_at_slot(
        state.slot) // spec.EPOCHS_PER_SYNC_COMMITTEE_PERIOD
    assert snapshot_period + 1 == update_period

    block = build_empty_block_for_next_slot(spec, state)
    signed_block = state_transition_and_sign_block(spec, state, block)
    block_header = spec.BeaconBlockHeader(
        slot=signed_block.message.slot,
        proposer_index=signed_block.message.proposer_index,
        parent_root=signed_block.message.parent_root,
        state_root=signed_block.message.state_root,
        body_root=signed_block.message.body.hash_tree_root(),
    )

    # Sync committee signing the finalized_block_header
    committee = spec.get_sync_committee_indices(state,
                                                spec.get_current_epoch(state))
    sync_committee_bits = [True] * len(committee)
    sync_committee_signature = compute_aggregate_sync_committee_signature(
        spec,
        state,
        block_header.slot,
        committee,
        block_root=spec.Root(block_header.hash_tree_root()),
    )

    # Sync committee is updated
    next_sync_committee_branch = build_proof(state.get_backing(),
                                             spec.NEXT_SYNC_COMMITTEE_INDEX)
    # Finality is unchanged
    finality_header = spec.BeaconBlockHeader()
    finality_branch = [
        spec.Bytes32()
        for _ in range(spec.floorlog2(spec.FINALIZED_ROOT_INDEX))
    ]

    update = spec.LightClientUpdate(
        header=block_header,
        next_sync_committee=state.next_sync_committee,
        next_sync_committee_branch=next_sync_committee_branch,
        finality_header=finality_header,
        finality_branch=finality_branch,
        sync_committee_bits=sync_committee_bits,
        sync_committee_signature=sync_committee_signature,
        fork_version=state.fork.current_version,
    )

    spec.process_light_client_update(store, update, state.slot,
                                     state.genesis_validators_root)

    # snapshot has been updated
    assert len(store.valid_updates) == 0
    assert store.snapshot.header == update.header
Example #24
0
def test_correct_epoch_delay(spec, state):
    attestation = get_valid_attestation(spec, state, signed=True)
    next_slots(spec, state, spec.SLOTS_PER_EPOCH)

    yield from run_attestation_processing(spec, state, attestation)
Example #25
0
def test_proposer_boost_correct_head(spec, state):
    test_steps = []
    genesis_state = state.copy()

    # Initialization
    store, anchor_block = get_genesis_forkchoice_store_and_block(spec, state)
    yield 'anchor_state', state
    yield 'anchor_block', anchor_block
    anchor_root = get_anchor_root(spec, state)
    assert spec.get_head(store) == anchor_root
    test_steps.append(
        {'checks': {
            'head': get_formatted_head_output(spec, store),
        }})

    # Build block that serves as head ONLY on timely arrival, and ONLY in that slot
    state_1 = genesis_state.copy()
    next_slots(spec, state_1, 3)
    block_1 = build_empty_block_for_next_slot(spec, state_1)
    signed_block_1 = state_transition_and_sign_block(spec, state_1, block_1)

    # Build block that serves as current head, and remains the head after block_1.slot
    state_2 = genesis_state.copy()
    next_slots(spec, state_2, 2)
    block_2 = build_empty_block_for_next_slot(spec, state_2)
    signed_block_2 = state_transition_and_sign_block(spec, state_2.copy(),
                                                     block_2)
    while spec.hash_tree_root(block_1) >= spec.hash_tree_root(block_2):
        block_2.body.graffiti = spec.Bytes32(
            hex(rng.getrandbits(8 * 32))[2:].zfill(64))
        signed_block_2 = state_transition_and_sign_block(
            spec, state_2.copy(), block_2)
    assert spec.hash_tree_root(block_1) < spec.hash_tree_root(block_2)

    # Tick to block_1 slot time
    time = store.genesis_time + block_1.slot * spec.config.SECONDS_PER_SLOT
    on_tick_and_append_step(spec, store, time, test_steps)

    # Process block_2
    yield from add_block(spec, store, signed_block_2, test_steps)
    assert store.proposer_boost_root == spec.Root()
    assert spec.get_head(store) == spec.hash_tree_root(block_2)

    # Process block_1 on timely arrival
    # The head should temporarily change to block_1
    yield from add_block(spec, store, signed_block_1, test_steps)
    assert store.proposer_boost_root == spec.hash_tree_root(block_1)
    assert spec.get_head(store) == spec.hash_tree_root(block_1)

    # After block_1.slot, the head should revert to block_2
    time = store.genesis_time + (block_1.slot +
                                 1) * spec.config.SECONDS_PER_SLOT
    on_tick_and_append_step(spec, store, time, test_steps)
    assert store.proposer_boost_root == spec.Root()
    assert spec.get_head(store) == spec.hash_tree_root(block_2)

    test_steps.append(
        {'checks': {
            'head': get_formatted_head_output(spec, store),
        }})

    yield 'steps', test_steps
def test_process_light_client_update_finality_updated(spec, state):
    store = initialize_light_client_store(spec, state)

    # Change finality
    blocks = []
    next_slots(spec, state, spec.SLOTS_PER_EPOCH * 2)
    for epoch in range(3):
        prev_state, new_blocks, state = next_epoch_with_attestations(
            spec, state, True, True)
        blocks += new_blocks
    # Ensure that finality checkpoint has changed
    assert state.finalized_checkpoint.epoch == 3
    # Ensure that it's same period
    snapshot_period = spec.compute_sync_committee_period(
        spec.compute_epoch_at_slot(store.optimistic_header.slot))
    update_period = spec.compute_sync_committee_period(
        spec.compute_epoch_at_slot(state.slot))
    assert snapshot_period == update_period

    # Updated sync_committee and finality
    next_sync_committee_branch = [
        spec.Bytes32()
        for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))
    ]
    finalized_block_header = blocks[spec.SLOTS_PER_EPOCH - 1].message
    assert finalized_block_header.slot == spec.compute_start_slot_at_epoch(
        state.finalized_checkpoint.epoch)
    assert finalized_block_header.hash_tree_root(
    ) == state.finalized_checkpoint.root
    finality_branch = build_proof(state.get_backing(),
                                  spec.FINALIZED_ROOT_INDEX)

    # Build block header
    block = build_empty_block(spec, state)
    block_header = spec.BeaconBlockHeader(
        slot=block.slot,
        proposer_index=block.proposer_index,
        parent_root=block.parent_root,
        state_root=state.hash_tree_root(),
        body_root=block.body.hash_tree_root(),
    )

    # Sync committee signing the finalized_block_header
    sync_aggregate = get_sync_aggregate(spec,
                                        state,
                                        block_header,
                                        block_root=spec.Root(
                                            block_header.hash_tree_root()))

    update = spec.LightClientUpdate(
        attested_header=block_header,
        next_sync_committee=state.next_sync_committee,
        next_sync_committee_branch=next_sync_committee_branch,
        finalized_header=finalized_block_header,
        finality_branch=finality_branch,
        sync_aggregate=sync_aggregate,
        fork_version=state.fork.current_version,
    )

    spec.process_light_client_update(store, update, state.slot,
                                     state.genesis_validators_root)

    assert store.current_max_active_participants > 0
    assert store.optimistic_header == update.attested_header
    assert store.finalized_header == update.finalized_header
    assert store.best_valid_update is None
Example #27
0
def test_invalid_attestation_signature(spec, state):
    attestation = get_valid_attestation(spec, state)
    next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)

    yield from run_attestation_processing(spec, state, attestation, False)
Example #28
0
def test_new_justified_is_later_than_store_justified(spec, state):
    """
    J: Justified
    F: Finalized
    fork_1_state (forked from genesis):
        epoch
        [0] <- [1] <- [2] <- [3] <- [4]
         F                    J

    fork_2_state (forked from fork_1_state's epoch 2):
        epoch
                       └──── [3] <- [4] <- [5] <- [6]
         F                           J

    fork_3_state (forked from genesis):
        [0] <- [1] <- [2] <- [3] <- [4] <- [5]
                              F      J
    """
    # The 1st fork, from genesis
    fork_1_state = state.copy()
    # The 3rd fork, from genesis
    fork_3_state = state.copy()

    test_steps = []
    # Initialization
    store, anchor_block = get_genesis_forkchoice_store_and_block(spec, state)
    yield 'anchor_state', state
    yield 'anchor_block', anchor_block
    current_time = state.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time
    on_tick_and_append_step(spec, store, current_time, test_steps)
    assert store.time == current_time

    # ----- Process fork_1_state
    # Skip epoch 0
    next_epoch(spec, fork_1_state)
    # Fill epoch 1 with previous epoch attestations
    fork_1_state, store, _ = yield from apply_next_epoch_with_attestations(
        spec, fork_1_state, store, False, True, test_steps=test_steps)

    # Fork `fork_2_state` at the start of epoch 2
    fork_2_state = fork_1_state.copy()
    assert spec.get_current_epoch(fork_2_state) == 2

    # Skip epoch 2
    next_epoch(spec, fork_1_state)
    # # Fill epoch 3 & 4 with previous epoch attestations
    for _ in range(2):
        fork_1_state, store, _ = yield from apply_next_epoch_with_attestations(
            spec, fork_1_state, store, False, True, test_steps=test_steps)

    assert fork_1_state.finalized_checkpoint.epoch == store.finalized_checkpoint.epoch == 0
    assert fork_1_state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3
    assert store.justified_checkpoint == fork_1_state.current_justified_checkpoint

    # ------ fork_2_state: Create a chain to set store.best_justified_checkpoint
    # NOTE: The goal is to make `store.best_justified_checkpoint.epoch > store.justified_checkpoint.epoch`
    all_blocks = []

    # Proposed an empty block at epoch 2, 1st slot
    block = build_empty_block_for_next_slot(spec, fork_2_state)
    signed_block = state_transition_and_sign_block(spec, fork_2_state, block)
    yield from tick_and_add_block(spec, store, signed_block, test_steps)
    assert fork_2_state.current_justified_checkpoint.epoch == 0

    # Skip to epoch 4
    for _ in range(2):
        next_epoch(spec, fork_2_state)
        assert fork_2_state.current_justified_checkpoint.epoch == 0

    # Propose a block at epoch 4, 5th slot
    # Propose a block at epoch 5, 5th slot
    for _ in range(2):
        next_epoch(spec, fork_2_state)
        next_slots(spec, fork_2_state, 4)
        signed_block = state_transition_with_full_attestations_block(
            spec, fork_2_state, True, True)
        yield from tick_and_add_block(spec, store, signed_block, test_steps)
        assert fork_2_state.current_justified_checkpoint.epoch == 0

    # Propose a block at epoch 6, SAFE_SLOTS_TO_UPDATE_JUSTIFIED + 2 slot
    next_epoch(spec, fork_2_state)
    next_slots(spec, fork_2_state, spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED + 2)
    signed_block = state_transition_with_full_attestations_block(
        spec, fork_2_state, True, True)
    assert fork_2_state.finalized_checkpoint.epoch == 0
    assert fork_2_state.current_justified_checkpoint.epoch == 5
    # Check SAFE_SLOTS_TO_UPDATE_JUSTIFIED
    time = store.genesis_time + fork_2_state.slot * spec.config.SECONDS_PER_SLOT
    on_tick_and_append_step(spec, store, time, test_steps)
    assert spec.compute_slots_since_epoch_start(
        spec.get_current_slot(store)) >= spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED
    # Run on_block
    yield from add_block(spec, store, signed_block, test_steps)
    assert store.finalized_checkpoint.epoch == 0
    assert store.justified_checkpoint.epoch == 3
    assert store.best_justified_checkpoint.epoch == 5

    # ------ fork_3_state: Create another chain to test the
    # "Update justified if new justified is later than store justified" case
    all_blocks = []
    for _ in range(3):
        next_epoch(spec, fork_3_state)

    # epoch 3
    _, signed_blocks, fork_3_state = next_epoch_with_attestations(
        spec, fork_3_state, True, True)
    all_blocks += signed_blocks
    assert fork_3_state.finalized_checkpoint.epoch == 0

    # epoch 4, attest the first 5 blocks
    _, blocks, fork_3_state = next_slots_with_attestations(
        spec, fork_3_state, 5, True, True)
    all_blocks += blocks.copy()
    assert fork_3_state.finalized_checkpoint.epoch == 0

    # Propose a block at epoch 5, 5th slot
    next_epoch(spec, fork_3_state)
    next_slots(spec, fork_3_state, 4)
    signed_block = state_transition_with_full_block(spec, fork_3_state, True,
                                                    True)
    all_blocks.append(signed_block.copy())
    assert fork_3_state.finalized_checkpoint.epoch == 0

    # Propose a block at epoch 6, 5th slot
    next_epoch(spec, fork_3_state)
    next_slots(spec, fork_3_state, 4)
    signed_block = state_transition_with_full_block(spec, fork_3_state, True,
                                                    True)
    all_blocks.append(signed_block.copy())
    assert fork_3_state.finalized_checkpoint.epoch == 3
    assert fork_3_state.current_justified_checkpoint.epoch == 4

    # Apply blocks of `fork_3_state` to `store`
    for block in all_blocks:
        if store.time < spec.compute_time_at_slot(fork_2_state,
                                                  block.message.slot):
            time = store.genesis_time + block.message.slot * spec.config.SECONDS_PER_SLOT
            on_tick_and_append_step(spec, store, time, test_steps)
        yield from add_block(spec, store, block, test_steps)

    assert store.finalized_checkpoint == fork_3_state.finalized_checkpoint
    assert store.justified_checkpoint == fork_3_state.current_justified_checkpoint
    assert store.justified_checkpoint != store.best_justified_checkpoint
    assert store.best_justified_checkpoint == fork_2_state.current_justified_checkpoint

    yield 'steps', test_steps
Example #29
0
def test_discard_equivocations(spec, state):
    test_steps = []
    genesis_state = state.copy()

    # Initialization
    store, anchor_block = get_genesis_forkchoice_store_and_block(spec, state)
    yield 'anchor_state', state
    yield 'anchor_block', anchor_block
    anchor_root = get_anchor_root(spec, state)
    assert spec.get_head(store) == anchor_root
    test_steps.append(
        {'checks': {
            'head': get_formatted_head_output(spec, store),
        }})

    # Build block that serves as head before discarding equivocations
    state_1 = genesis_state.copy()
    next_slots(spec, state_1, 3)
    block_1 = build_empty_block_for_next_slot(spec, state_1)
    signed_block_1 = state_transition_and_sign_block(spec, state_1, block_1)

    # Build equivocating attestations to feed to store
    state_eqv = state_1.copy()
    block_eqv = apply_empty_block(spec, state_eqv, state_eqv.slot + 1)
    attestation_eqv = get_valid_attestation(spec,
                                            state_eqv,
                                            slot=block_eqv.slot,
                                            signed=True)

    next_slots(spec, state_1, 1)
    attestation = get_valid_attestation(spec,
                                        state_1,
                                        slot=block_eqv.slot,
                                        signed=True)
    assert spec.is_slashable_attestation_data(attestation.data,
                                              attestation_eqv.data)

    indexed_attestation = spec.get_indexed_attestation(state_1, attestation)
    indexed_attestation_eqv = spec.get_indexed_attestation(
        state_eqv, attestation_eqv)
    attester_slashing = spec.AttesterSlashing(
        attestation_1=indexed_attestation,
        attestation_2=indexed_attestation_eqv)

    # Build block that serves as head after discarding equivocations
    state_2 = genesis_state.copy()
    next_slots(spec, state_2, 2)
    block_2 = build_empty_block_for_next_slot(spec, state_2)
    signed_block_2 = state_transition_and_sign_block(spec, state_2.copy(),
                                                     block_2)
    while spec.hash_tree_root(block_1) >= spec.hash_tree_root(block_2):
        block_2.body.graffiti = spec.Bytes32(
            hex(rng.getrandbits(8 * 32))[2:].zfill(64))
        signed_block_2 = state_transition_and_sign_block(
            spec, state_2.copy(), block_2)
    assert spec.hash_tree_root(block_1) < spec.hash_tree_root(block_2)

    # Tick to (block_eqv.slot + 2) slot time
    time = store.genesis_time + (block_eqv.slot +
                                 2) * spec.config.SECONDS_PER_SLOT
    on_tick_and_append_step(spec, store, time, test_steps)

    # Process block_2
    yield from add_block(spec, store, signed_block_2, test_steps)
    assert store.proposer_boost_root == spec.Root()
    assert spec.get_head(store) == spec.hash_tree_root(block_2)

    # Process block_1
    # The head should remain block_2
    yield from add_block(spec, store, signed_block_1, test_steps)
    assert store.proposer_boost_root == spec.Root()
    assert spec.get_head(store) == spec.hash_tree_root(block_2)

    # Process attestation
    # The head should change to block_1
    yield from add_attestation(spec, store, attestation, test_steps)
    assert spec.get_head(store) == spec.hash_tree_root(block_1)

    # Process attester_slashing
    # The head should revert to block_2
    yield from add_attester_slashing(spec, store, attester_slashing,
                                     test_steps)
    assert spec.get_head(store) == spec.hash_tree_root(block_2)

    test_steps.append(
        {'checks': {
            'head': get_formatted_head_output(spec, store),
        }})

    yield 'steps', test_steps
def test_empty_participants_zeroes_sig(spec, state):
    attestation = get_valid_attestation(spec, state, filter_participant_set=lambda comm: [])  # 0 participants
    attestation.signature = spec.BLSSignature(b'\x00' * 96)
    next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY)

    yield from run_attestation_processing(spec, state, attestation, False)