Exemple #1
0
def sample_beacon_state_params(
    config,
    genesis_slot,
    genesis_epoch,
    sample_fork_params,
    sample_eth1_data_params,
    sample_block_header_params,
    sample_crosslink_record_params,
):
    return {
        # Versioning
        "genesis_time":
        0,
        "slot":
        genesis_slot + 100,
        "fork":
        Fork(**sample_fork_params),
        # History
        "latest_block_header":
        BeaconBlockHeader(**sample_block_header_params),
        "block_roots": (ZERO_HASH32, ) * config.SLOTS_PER_HISTORICAL_ROOT,
        "state_roots": (ZERO_HASH32, ) * config.SLOTS_PER_HISTORICAL_ROOT,
        "historical_roots": (),
        # Eth1
        "eth1_data":
        Eth1Data(**sample_eth1_data_params),
        "eth1_data_votes": (),
        "eth1_deposit_index":
        0,
        # Registry
        "validators": (),
        "balances": (),
        # Shuffling
        "start_shard":
        1,
        "randao_mixes": (ZERO_HASH32, ) * config.EPOCHS_PER_HISTORICAL_VECTOR,
        "active_index_roots":
        (ZERO_HASH32, ) * config.EPOCHS_PER_HISTORICAL_VECTOR,
        "compact_committees_roots":
        (ZERO_HASH32, ) * config.EPOCHS_PER_HISTORICAL_VECTOR,
        # Slashings
        "slashings": (0, ) * config.EPOCHS_PER_SLASHINGS_VECTOR,
        # Attestations
        "previous_epoch_attestations": (),
        "current_epoch_attestations": (),
        # Crosslinks
        "previous_crosslinks":
        ((Crosslink(**sample_crosslink_record_params), ) * config.SHARD_COUNT),
        "current_crosslinks":
        ((Crosslink(**sample_crosslink_record_params), ) * config.SHARD_COUNT),
        # Justification
        "justification_bits": (False, ) * JUSTIFICATION_BITS_LENGTH,
        "previous_justified_checkpoint":
        Checkpoint(epoch=0, root=b"\x99" * 32),
        "current_justified_checkpoint":
        Checkpoint(epoch=0, root=b"\x55" * 32),
        # Finality
        "finalized_checkpoint":
        Checkpoint(epoch=0, root=b"\x33" * 32),
    }
Exemple #2
0
def sample_beacon_state_params(config, genesis_slot, genesis_epoch,
                               sample_fork_params, sample_eth1_data_params,
                               sample_block_header_params,
                               sample_crosslink_record_params):
    return {
        # Versioning
        'genesis_time':
        0,
        'slot':
        genesis_slot + 100,
        'fork':
        Fork(**sample_fork_params),
        # History
        'latest_block_header':
        BeaconBlockHeader(**sample_block_header_params),
        'block_roots': (ZERO_HASH32, ) * config.SLOTS_PER_HISTORICAL_ROOT,
        'state_roots': (ZERO_HASH32, ) * config.SLOTS_PER_HISTORICAL_ROOT,
        'historical_roots': (),
        # Eth1
        'eth1_data':
        Eth1Data(**sample_eth1_data_params),
        'eth1_data_votes': (),
        'eth1_deposit_index':
        0,
        # Registry
        'validators': (),
        'balances': (),
        # Shuffling
        'start_shard':
        1,
        'randao_mixes': (ZERO_HASH32, ) * config.EPOCHS_PER_HISTORICAL_VECTOR,
        'active_index_roots':
        (ZERO_HASH32, ) * config.EPOCHS_PER_HISTORICAL_VECTOR,
        # Slashings
        'slashed_balances': (0, ) * config.EPOCHS_PER_SLASHED_BALANCES_VECTOR,
        # Attestations
        'previous_epoch_attestations': (),
        'current_epoch_attestations': (),
        # Crosslinks
        'previous_crosslinks':
        ((Crosslink(**sample_crosslink_record_params), ) * config.SHARD_COUNT),
        'current_crosslinks':
        ((Crosslink(**sample_crosslink_record_params), ) * config.SHARD_COUNT),
        # Justification
        'previous_justified_epoch':
        0,
        'previous_justified_root':
        b'\x99' * 32,
        'current_justified_epoch':
        0,
        'current_justified_root':
        b'\x55' * 32,
        'justification_bitfield':
        0,
        # Finality
        'finalized_epoch':
        0,
        'finalized_root':
        b'\x33' * 32,
    }
Exemple #3
0
def test_find_winning_crosslink_and_attesting_indices_from_candidates(
        genesis_state, number_of_candidates, config):
    some_epoch = config.GENESIS_EPOCH + 20
    some_shard = 3

    state = genesis_state.copy(
        slot=compute_start_slot_of_epoch(some_epoch, config.SLOTS_PER_EPOCH),
        start_shard=some_shard,
        current_crosslinks=tuple(
            Crosslink(shard=i, data_root=(i).to_bytes(32, "little"))
            for i in range(config.SHARD_COUNT)),
    )

    full_committee = get_crosslink_committee(state, some_epoch, some_shard,
                                             CommitteeConfig(config))

    # break the committees up into different subsets to simulate different
    # attestations for the same crosslink
    committees = tuple(
        random_sample(
            len(full_committee) // number_of_candidates, full_committee)
        for _ in range(number_of_candidates))
    seen = set()
    filtered_committees = tuple()
    for committee in committees:
        deduplicated_committee = tuple()
        for index in committee:
            if index in seen:
                pass
            else:
                seen.add(index)
                deduplicated_committee += (index, )
        filtered_committees += (deduplicated_committee, )

    candidates = tuple(
        mk_pending_attestation_from_committee(
            state.current_crosslinks[some_shard],
            len(full_committee),
            some_shard,
            target_epoch=some_epoch,
        ) for committee in filtered_committees)

    if number_of_candidates == 0:
        expected_result = (Crosslink(), set())
    else:
        expected_result = (candidates[0].data.crosslink,
                           set(sorted(full_committee)))

    result = _find_winning_crosslink_and_attesting_indices_from_candidates(
        state, candidates, config)
    assert result == expected_result
Exemple #4
0
def _find_winning_crosslink_and_attesting_indices_from_candidates(
        state: BeaconState,
        candidate_attestations: Sequence[PendingAttestation],
        config: Eth2Config) -> Tuple[Crosslink, Tuple[ValidatorIndex, ...]]:
    if not candidate_attestations:
        return (Crosslink(), tuple())

    attestations_by_crosslink = groupby(
        lambda a: a.data.crosslink,
        candidate_attestations,
    )

    winning_crosslink, winning_attestations = max(
        attestations_by_crosslink.items(),
        key=lambda pair: _score_crosslink(
            state,
            pair[0],  # crosslink
            pair[1],  # attestations
            config,
        ),
    )

    return (
        winning_crosslink,
        get_unslashed_attesting_indices(
            state,
            winning_attestations,
            CommitteeConfig(config),
        ),
    )
Exemple #5
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)
Exemple #6
0
async def test_send_multiple_attestations(request, event_loop):
    alice, msg_buffer = await get_command_setup(request, event_loop)

    attestations = tuple(
        Attestation(
            aggregation_bitfield=b"\x00\x00\x00",
            data=AttestationData(
                slot=0,
                beacon_block_root=ZERO_HASH32,
                source_epoch=SERENITY_CONFIG.GENESIS_EPOCH,
                target_root=ZERO_HASH32,
                source_root=ZERO_HASH32,
                shard=shard,
                previous_crosslink=Crosslink(SERENITY_CONFIG.GENESIS_EPOCH,
                                             ZERO_HASH32),
                crosslink_data_root=ZERO_HASH32,
            ),
            custody_bitfield=b"\x00\x00\x00",
        ) for shard in range(10))

    alice.sub_proto.send_attestation_records(attestations)

    message = await msg_buffer.msg_queue.get()
    assert isinstance(message.command, Attestations)
    assert message.payload == tuple(
        ssz.encode(attestation) for attestation in attestations)
def validate_attestation_previous_crosslink_or_root(attestation_data: AttestationData,
                                                    state_latest_crosslink: Crosslink,
                                                    slots_per_epoch: int) -> None:
    """
    Validate that either the attestation ``previous_crosslink`` or ``crosslink_data_root``
    field of ``attestation_data`` is the provided ``latest_crosslink``.
    Raise ``ValidationError`` if it's invalid.
    """
    attestation_creating_crosslink = Crosslink(
        epoch=slot_to_epoch(attestation_data.slot, slots_per_epoch),
        crosslink_data_root=attestation_data.crosslink_data_root,
    )
    acceptable_crosslink_data = {
        # Case 1: Latest crosslink matches the one in the state
        attestation_data.previous_crosslink,
        # Case 2: State has already been updated, state's latest crosslink matches the crosslink
        # the attestation is trying to create
        attestation_creating_crosslink,
    }
    if state_latest_crosslink not in acceptable_crosslink_data:
        raise ValidationError(
            f"State's latests crosslink ({state_latest_crosslink}) doesn't match "
            " case 1: the `attestation_data.previous_crosslink` "
            f"({attestation_data.previous_crosslink.root}) or "
            "`case 2: the crosslink the attestation is trying to create "
            f"({attestation_creating_crosslink})"
        )
Exemple #8
0
def test_validate_crosslink(genesis_state,
                            mutator,
                            is_valid,
                            config):
    some_shard = 3
    parent = genesis_state.current_crosslinks[some_shard]
    target_epoch = config.GENESIS_EPOCH + 1
    valid_crosslink = Crosslink(
        shard=some_shard,
        parent_root=parent.hash_tree_root,
        start_epoch=parent.end_epoch,
        end_epoch=target_epoch,
        data_root=ZERO_HASH32,
    )

    candidate_crosslink = mutator(valid_crosslink)

    if is_valid:
        _validate_crosslink(
            candidate_crosslink,
            target_epoch,
            parent,
            config.MAX_EPOCHS_PER_CROSSLINK,
        )
    else:
        with pytest.raises(ValidationError):
            _validate_crosslink(
                candidate_crosslink,
                target_epoch,
                parent,
                config.MAX_EPOCHS_PER_CROSSLINK,
            )
Exemple #9
0
def test_get_unslashed_attesting_indices(genesis_state, config):
    state = genesis_state.copy(
        slot=compute_start_slot_of_epoch(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=Checkpoint(epoch=target_epoch),
                           crosslink=Crosslink(shard=target_shard))
    some_subset_count = random.randrange(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:
            if random.choice([True, False]):
                state = state.update_validator_with_fn(
                    index, lambda v, *_: v.copy(slashed=True))
            bitfield = set_voted(bitfield, i)

    some_subset = tuple(
        filter(lambda index: not state.validators[index].slashed, some_subset))

    indices = get_unslashed_attesting_indices(
        state,
        (PendingAttestation(data=data, aggregation_bits=bitfield), ),
        CommitteeConfig(config),
    )

    assert set(indices) == set(some_subset)
    assert len(indices) == len(some_subset)
Exemple #10
0
def sample_attestation_data_params(sample_crosslink_record_params):
    return {
        "beacon_block_root": b"\x11" * 32,
        "source": Checkpoint(epoch=11, root=b"\x22" * 32),
        "target": Checkpoint(epoch=12, root=b"\x33" * 32),
        "crosslink": Crosslink(**sample_crosslink_record_params),
    }
Exemple #11
0
def test_get_matching_head_attestations(genesis_state, config):
    some_epoch = config.GENESIS_EPOCH + 20
    some_slot = (
        compute_start_slot_of_epoch(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=Checkpoint(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=Checkpoint(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
Exemple #12
0
def create_mock_signed_attestations_at_slot(
        state: BeaconState,
        config: Eth2Config,
        state_machine: BaseBeaconStateMachine,
        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``.
    """
    crosslink_committees_at_slot = get_crosslink_committees_at_slot(
        state,
        attestation_slot,
        config,
    )

    # Get `target_root`
    target_root = _get_target_root(state, config, beacon_block_root)
    target_epoch = compute_epoch_of_slot(
        state.slot,
        config.SLOTS_PER_EPOCH,
    )

    for crosslink_committee in crosslink_committees_at_slot:
        committee, shard = crosslink_committee

        parent_crosslink = state.current_crosslinks[shard]

        attestation_data = AttestationData(
            beacon_block_root=beacon_block_root,
            source=Checkpoint(
                epoch=state.current_justified_checkpoint.epoch,
                root=state.current_justified_checkpoint.root,
            ),
            target=Checkpoint(
                root=target_root,
                epoch=target_epoch,
            ),
            crosslink=Crosslink(
                shard=shard,
                parent_root=parent_crosslink.hash_tree_root,
                start_epoch=parent_crosslink.end_epoch,
                end_epoch=min(
                    target_epoch, parent_crosslink.end_epoch +
                    config.MAX_EPOCHS_PER_CROSSLINK),
            ))

        num_voted_attesters = int(len(committee) * voted_attesters_ratio)

        yield _create_mock_signed_attestation(
            state,
            attestation_data,
            attestation_slot,
            committee,
            num_voted_attesters,
            keymap,
            config.SLOTS_PER_EPOCH,
        )
Exemple #13
0
def test_num_crosslink_records(expected, sample_crosslink_record_params,
                               filled_beacon_state):
    crosslinks = [
        Crosslink(**sample_crosslink_record_params) for i in range(expected)
    ]
    state = filled_beacon_state.copy(latest_crosslinks=crosslinks, )

    assert state.num_crosslinks == expected
Exemple #14
0
def test_validate_attestation_data(genesis_state,
                                   sample_attestation_data_params,
                                   attestation_source_epoch,
                                   attestation_target_epoch,
                                   current_epoch,
                                   previous_justified_epoch,
                                   current_justified_epoch,
                                   slots_per_epoch,
                                   config,
                                   is_valid):
    state = genesis_state.copy(
        slot=compute_start_slot_of_epoch(current_epoch, slots_per_epoch) + 5,
        previous_justified_checkpoint=Checkpoint(
            epoch=previous_justified_epoch,
        ),
        current_justified_checkpoint=Checkpoint(
            epoch=current_justified_epoch,
        ),
    )
    start_shard = get_start_shard(
        state,
        current_epoch,
        CommitteeConfig(config),
    )
    if attestation_target_epoch == current_epoch:
        crosslinks = state.current_crosslinks
    else:
        crosslinks = state.previous_crosslinks

    parent_crosslink = crosslinks[start_shard]
    attestation_data = AttestationData(**sample_attestation_data_params).copy(
        source=Checkpoint(
            epoch=attestation_source_epoch,
        ),
        target=Checkpoint(
            epoch=attestation_target_epoch,
        ),
        crosslink=Crosslink(
            start_epoch=parent_crosslink.end_epoch,
            end_epoch=attestation_target_epoch,
            parent_root=parent_crosslink.hash_tree_root,
            shard=start_shard,
        ),
    )

    if is_valid:
        _validate_attestation_data(
            state,
            attestation_data,
            config,
        )
    else:
        with pytest.raises(ValidationError):
            _validate_attestation_data(
                state,
                attestation_data,
                config,
            )
Exemple #15
0
def test_process_attestations(genesis_state, genesis_block,
                              sample_beacon_block_params,
                              sample_beacon_block_body_params, config, keymap,
                              fixture_sm_class, chaindb,
                              empty_attestation_pool, success):

    attestation_slot = 0
    current_slot = attestation_slot + config.MIN_ATTESTATION_INCLUSION_DELAY
    state = genesis_state.copy(slot=current_slot, )

    attestations = create_mock_signed_attestations_at_slot(
        state=state,
        config=config,
        state_machine=fixture_sm_class(
            chaindb,
            empty_attestation_pool,
            genesis_block.slot,
        ),
        attestation_slot=attestation_slot,
        beacon_block_root=genesis_block.signing_root,
        keymap=keymap,
        voted_attesters_ratio=1.0,
    )

    assert len(attestations) > 0

    if not success:
        # create invalid attestation by shard
        # i.e. wrong parent
        invalid_attestation_data = attestations[-1].data.copy(
            crosslink=attestations[-1].data.crosslink.copy(
                parent_root=Crosslink(shard=333, ).root, ))
        invalid_attestation = attestations[-1].copy(
            data=invalid_attestation_data, )
        attestations = attestations[:-1] + (invalid_attestation, )

    block_body = BeaconBlockBody(**sample_beacon_block_body_params).copy(
        attestations=attestations, )
    block = SerenityBeaconBlock(**sample_beacon_block_params).copy(
        slot=current_slot,
        body=block_body,
    )

    if success:
        new_state = process_attestations(
            state,
            block,
            config,
        )

        assert len(new_state.current_epoch_attestations) == len(attestations)
    else:
        with pytest.raises(ValidationError):
            process_attestations(
                state,
                block,
                config,
            )
Exemple #16
0
def sample_attestation_data_params(sample_crosslink_record_params):
    return {
        'beacon_block_root': b'\x11' * 32,
        'source_epoch': 11,
        'source_root': b'\x22' * 32,
        'target_epoch': 12,
        'target_root': b'\x33' * 32,
        'crosslink': Crosslink(**sample_crosslink_record_params),
    }
Exemple #17
0
def _mk_attestation_inputs_in_epoch(epoch, state, config):
    active_validators_indices = get_active_validator_indices(state.validators, epoch)
    epoch_committee_count = get_committee_count(
        len(active_validators_indices),
        config.SHARD_COUNT,
        config.SLOTS_PER_EPOCH,
        config.TARGET_COMMITTEE_SIZE,
    )
    epoch_start_shard = get_start_shard(
        state,
        epoch,
        CommitteeConfig(config),
    )
    for shard_offset in random.sample(range(epoch_committee_count), epoch_committee_count):
        shard = Shard((epoch_start_shard + shard_offset) % config.SHARD_COUNT)
        committee = get_crosslink_committee(
            state,
            epoch,
            shard,
            CommitteeConfig(config),
        )

        if not committee:
            # empty crosslink committee this epoch
            continue

        attestation_data = AttestationData(
            target=Checkpoint(
                epoch=epoch,
            ),
            crosslink=Crosslink(
                shard=shard,
            ),
        )
        committee_count = len(committee)
        aggregation_bits = bitfield.get_empty_bitfield(committee_count)
        for index in range(committee_count):
            aggregation_bits = bitfield.set_voted(aggregation_bits, index)

            for index in committee:
                yield (
                    index,
                    (
                        get_attestation_data_slot(
                            state,
                            attestation_data,
                            config,
                        ),
                        (
                            aggregation_bits,
                            attestation_data,
                        ),
                    ),
                )
Exemple #18
0
def create_signed_attestation_at_slot(state: BeaconState, config: Eth2Config,
                                      state_machine: BaseBeaconStateMachine,
                                      attestation_slot: Slot,
                                      beacon_block_root: Hash32,
                                      validator_privkeys: Dict[ValidatorIndex,
                                                               int],
                                      committee: Tuple[ValidatorIndex, ...],
                                      shard: Shard) -> Attestation:
    """
    Create the attestations of the given ``attestation_slot`` slot with ``validator_privkeys``.
    """
    state_transition = state_machine.state_transition
    state = state_transition.apply_state_transition(
        state,
        future_slot=attestation_slot,
    )

    target_epoch = compute_epoch_of_slot(
        attestation_slot,
        config.SLOTS_PER_EPOCH,
    )

    target_root = _get_target_root(state, config, beacon_block_root)

    parent_crosslink = state.current_crosslinks[shard]

    attestation_data = AttestationData(
        beacon_block_root=beacon_block_root,
        source=Checkpoint(
            epoch=state.current_justified_checkpoint.epoch,
            root=state.current_justified_checkpoint.root,
        ),
        target=Checkpoint(
            root=target_root,
            epoch=target_epoch,
        ),
        crosslink=Crosslink(
            shard=shard,
            parent_root=parent_crosslink.hash_tree_root,
            start_epoch=parent_crosslink.end_epoch,
            end_epoch=target_epoch,
        ))

    return _create_mock_signed_attestation(
        state,
        attestation_data,
        attestation_slot,
        committee,
        len(committee),
        keymapper(lambda index: state.validators[index].pubkey,
                  validator_privkeys),
        config.SLOTS_PER_EPOCH,
    )
Exemple #19
0
def sample_attestation_data_params(sample_crosslink_record_params):
    return {
        'beacon_block_root': b'\x11' * 32,
        'source': Checkpoint(
            epoch=11,
            root=b'\x22' * 32,
        ),
        'target': Checkpoint(
            epoch=12,
            root=b'\x33' * 32,
        ),
        'crosslink': Crosslink(**sample_crosslink_record_params),
    }
Exemple #20
0
async def test_send_single_attestation(request, event_loop):
    alice, msg_buffer = await get_command_setup(request, event_loop)

    attestation = Attestation(
        aggregation_bits=b"\x00\x00\x00",
        data=AttestationData(crosslink=Crosslink(shard=1, )),
        custody_bits=b"\x00\x00\x00",
    )

    alice.sub_proto.send_attestation_records((attestation, ))

    message = await msg_buffer.msg_queue.get()
    assert isinstance(message.command, Attestations)
    assert message.payload["encoded_attestations"] == (
        ssz.encode(attestation), )
Exemple #21
0
def _mk_attestation_for_block_with_committee(block, committee, shard, config):
    committee_count = len(committee)
    aggregation_bitfield = bitfield.get_empty_bitfield(committee_count)
    for index in range(committee_count):
        aggregation_bitfield = bitfield.set_voted(aggregation_bitfield, index)

    attestation = Attestation(
        aggregation_bitfield=aggregation_bitfield,
        data=AttestationData(
            beacon_block_root=block.signing_root,
            target_epoch=slot_to_epoch(block.slot, config.SLOTS_PER_EPOCH),
            crosslink=Crosslink(shard=shard, ),
        ),
    )
    return attestation
Exemple #22
0
async def test_send_multiple_attestations(request, event_loop):
    alice, msg_buffer = await get_command_setup(request, event_loop)

    attestations = tuple(
        Attestation(
            aggregation_bits=b"\x00\x00\x00",
            data=AttestationData(crosslink=Crosslink(shard=shard, )),
            custody_bits=b"\x00\x00\x00",
        ) for shard in range(10))

    alice.sub_proto.send_attestation_records(attestations)

    message = await msg_buffer.msg_queue.get()
    assert isinstance(message.command, Attestations)
    assert message.payload["encoded_attestations"] == tuple(
        ssz.encode(attestation) for attestation in attestations)
Exemple #23
0
def _find_collision(state, config, index, epoch):
    """
    Given a target epoch, make the attestation expected for the
    validator w/ the given index.
    """
    active_validators = get_active_validator_indices(state.validators, epoch)
    committees_per_slot = get_committee_count(
        len(active_validators),
        config.SHARD_COUNT,
        config.SLOTS_PER_EPOCH,
        config.TARGET_COMMITTEE_SIZE,
    ) // config.SLOTS_PER_EPOCH
    epoch_start_slot = compute_start_slot_of_epoch(
        epoch,
        config.SLOTS_PER_EPOCH,
    )
    epoch_start_shard = get_start_shard(state, epoch, CommitteeConfig(config))

    for slot in range(epoch_start_slot, epoch_start_slot + config.SLOTS_PER_EPOCH):
        offset = committees_per_slot * (slot % config.SLOTS_PER_EPOCH)
        slot_start_shard = (epoch_start_shard + offset) % config.SHARD_COUNT
        for i in range(committees_per_slot):
            shard = Shard((slot_start_shard + i) % config.SHARD_COUNT)
            committee = get_crosslink_committee(state, epoch, shard, CommitteeConfig(config))
            if index in committee:
                # TODO(ralexstokes) refactor w/ tools/builder
                attestation_data = AttestationData(
                    target=Checkpoint(
                        epoch=epoch,
                    ),
                    crosslink=Crosslink(
                        shard=shard,
                    ),
                )
                committee_count = len(committee)
                aggregation_bits = bitfield.get_empty_bitfield(committee_count)
                for i in range(committee_count):
                    aggregation_bits = bitfield.set_voted(aggregation_bits, i)

                return {
                    index: (
                        slot, (aggregation_bits, attestation_data)
                    )
                    for index in committee
                }
    else:
        raise Exception("should have found a duplicate validator")
Exemple #24
0
def genesis_state(filled_beacon_state, activated_genesis_validators,
                  genesis_balances, slots_per_epoch, target_committee_size,
                  genesis_epoch, shard_count, slots_per_historical_root,
                  latest_slashed_exit_length, latest_randao_mixes_length):
    return filled_beacon_state.copy(
        validator_registry=activated_genesis_validators,
        validator_balances=genesis_balances,
        latest_block_roots=tuple(ZERO_HASH32
                                 for _ in range(slots_per_historical_root)),
        latest_slashed_balances=(0, ) * latest_slashed_exit_length,
        latest_crosslinks=tuple(
            Crosslink(
                epoch=genesis_epoch,
                crosslink_data_root=ZERO_HASH32,
            ) for _ in range(shard_count)),
        latest_randao_mixes=tuple(ZERO_HASH32
                                  for _ in range(latest_randao_mixes_length)),
    )
Exemple #25
0
def mock_attestation():
    return Attestation(
        aggregation_bitfield=b'\x12' * 16,
        data=AttestationData(
            slot=XIAO_LONG_BAO_CONFIG.GENESIS_SLOT + 1,
            beacon_block_root=ZERO_HASH32,
            source_epoch=XIAO_LONG_BAO_CONFIG.GENESIS_EPOCH,
            source_root=ZERO_HASH32,
            target_root=ZERO_HASH32,
            shard=0,
            previous_crosslink=Crosslink(
                epoch=XIAO_LONG_BAO_CONFIG.GENESIS_EPOCH,
                crosslink_data_root=ZERO_HASH32,
            ),
            crosslink_data_root=ZERO_HASH32,
        ),
        custody_bitfield=b'\x34' * 16,
        aggregate_signature=b'\x56' * 96,
    )
Exemple #26
0
def _mk_pending_attestation(
        bitfield: Bitfield = default_bitfield,
        target_root: Hash32 = ZERO_HASH32,
        target_epoch: Epoch = default_epoch,
        shard: Shard = default_shard,
        start_epoch: Epoch = default_epoch,
        parent_root: Hash32 = ZERO_HASH32,
        data_root: Hash32 = ZERO_HASH32) -> PendingAttestation:
    return PendingAttestation(
        aggregation_bitfield=bitfield,
        data=AttestationData(target_epoch=target_epoch,
                             target_root=target_root,
                             crosslink=Crosslink(
                                 shard=shard,
                                 parent_root=parent_root,
                                 start_epoch=start_epoch,
                                 end_epoch=target_epoch,
                                 data_root=data_root,
                             )),
    )
Exemple #27
0
def _mk_pending_attestation(
    bitfield: Bitfield = default_bitfield,
    target_root: SigningRoot = ZERO_SIGNING_ROOT,
    target_epoch: Epoch = default_epoch,
    shard: Shard = default_shard,
    start_epoch: Epoch = default_epoch,
    parent_root: Hash32 = ZERO_HASH32,
    data_root: Hash32 = ZERO_HASH32,
) -> PendingAttestation:
    return PendingAttestation(
        aggregation_bits=bitfield,
        data=AttestationData(
            target=Checkpoint(epoch=target_epoch, root=target_root),
            crosslink=Crosslink(
                shard=shard,
                parent_root=parent_root,
                start_epoch=start_epoch,
                end_epoch=target_epoch,
                data_root=data_root,
            ),
        ),
    )
Exemple #28
0
def test_process_rewards_and_penalties_for_crosslinks(
        genesis_state, config, slots_per_epoch, target_committee_size,
        shard_count, current_slot, num_attesting_validators,
        max_effective_balance, min_attestation_inclusion_delay,
        sample_attestation_data_params,
        sample_pending_attestation_record_params):
    state = genesis_state.copy(slot=current_slot, )
    previous_epoch = state.previous_epoch(config.SLOTS_PER_EPOCH,
                                          config.GENESIS_EPOCH)

    prev_epoch_start_slot = compute_start_slot_of_epoch(
        previous_epoch, slots_per_epoch)
    prev_epoch_crosslink_committees = [
        get_crosslink_committees_at_slot(
            state,
            slot,
            CommitteeConfig(config),
        )[0] for slot in range(prev_epoch_start_slot, prev_epoch_start_slot +
                               slots_per_epoch)
    ]

    # Record which validators attest during each slot for reward collation.
    each_slot_attestion_validators_list = []

    epoch_start_shard = get_start_shard(
        state,
        previous_epoch,
        CommitteeConfig(config),
    )
    shard_delta = get_shard_delta(
        state,
        previous_epoch,
        CommitteeConfig(config),
    )

    a = epoch_start_shard
    b = epoch_start_shard + shard_delta
    if a > b:
        valid_shards_for_epoch = range(b, a)
    else:
        valid_shards_for_epoch = range(a, b)

    indices_to_check = set()

    previous_epoch_attestations = []
    for committee, shard in prev_epoch_crosslink_committees:
        if shard not in valid_shards_for_epoch:
            continue
        for index in committee:
            indices_to_check.add(index)
        # Randomly sample `num_attesting_validators` validators
        # from the committee to attest in this slot.
        crosslink_attesting_validators = random.sample(
            committee,
            num_attesting_validators,
        )
        each_slot_attestion_validators_list.append(
            crosslink_attesting_validators)
        participants_bitfield = get_empty_bitfield(len(committee))
        for index in crosslink_attesting_validators:
            participants_bitfield = set_voted(participants_bitfield,
                                              committee.index(index))
        previous_epoch_attestations.append(
            PendingAttestation(
                **sample_pending_attestation_record_params).copy(
                    aggregation_bits=participants_bitfield,
                    data=AttestationData(
                        **sample_attestation_data_params).copy(
                            target=Checkpoint(epoch=previous_epoch, ),
                            crosslink=Crosslink(
                                shard=shard,
                                parent_root=Crosslink().hash_tree_root,
                            ),
                        ),
                ))
    state = state.copy(
        previous_epoch_attestations=tuple(previous_epoch_attestations), )

    rewards_received, penalties_received = get_crosslink_deltas(
        state,
        config,
    )

    expected_rewards_received = {
        index: 0
        for index in range(len(state.validators))
    }
    validator_balance = max_effective_balance
    for i in range(slots_per_epoch):
        crosslink_committee, shard = prev_epoch_crosslink_committees[i]
        if shard not in valid_shards_for_epoch:
            continue
        attesting_validators = each_slot_attestion_validators_list[i]
        total_attesting_balance = len(attesting_validators) * validator_balance
        total_committee_balance = len(crosslink_committee) * validator_balance
        for index in crosslink_committee:
            if index in attesting_validators:
                reward = get_base_reward(
                    state=state,
                    index=index,
                    config=config,
                ) * total_attesting_balance // total_committee_balance
                expected_rewards_received[index] += reward
            else:
                penalty = get_base_reward(
                    state=state,
                    index=index,
                    config=config,
                )
                expected_rewards_received[index] -= penalty

    # Check the rewards/penalties match
    for index in range(len(state.validators)):
        if index not in indices_to_check:
            continue
        assert (rewards_received[index] -
                penalties_received[index] == expected_rewards_received[index])
Exemple #29
0
def test_get_attestation_deltas(genesis_state, config, slots_per_epoch,
                                target_committee_size, shard_count,
                                min_attestation_inclusion_delay,
                                inactivity_penalty_quotient, finalized_epoch,
                                current_slot,
                                sample_pending_attestation_record_params,
                                sample_attestation_data_params):
    state = genesis_state.copy(slot=current_slot,
                               finalized_checkpoint=Checkpoint(
                                   epoch=finalized_epoch, ))
    previous_epoch = state.previous_epoch(config.SLOTS_PER_EPOCH,
                                          config.GENESIS_EPOCH)
    epoch_start_shard = get_start_shard(
        state,
        previous_epoch,
        CommitteeConfig(config),
    )
    shard_delta = get_shard_delta(
        state,
        previous_epoch,
        CommitteeConfig(config),
    )

    a = epoch_start_shard
    b = epoch_start_shard + shard_delta
    if a > b:
        valid_shards_for_epoch = range(b, a)
    else:
        valid_shards_for_epoch = range(a, b)

    indices_to_check = set()

    prev_epoch_start_slot = compute_start_slot_of_epoch(
        previous_epoch, slots_per_epoch)
    prev_epoch_attestations = tuple()
    for slot in range(prev_epoch_start_slot,
                      prev_epoch_start_slot + slots_per_epoch):
        committee, shard = get_crosslink_committees_at_slot(
            state,
            slot,
            CommitteeConfig(config),
        )[0]
        if not committee:
            continue
        if shard not in valid_shards_for_epoch:
            continue
        participants_bitfield = get_empty_bitfield(len(committee))
        for i, index in enumerate(committee):
            indices_to_check.add(index)
            participants_bitfield = set_voted(participants_bitfield, i)
        prev_epoch_attestations += (PendingAttestation(
            **sample_pending_attestation_record_params).copy(
                aggregation_bits=participants_bitfield,
                inclusion_delay=min_attestation_inclusion_delay,
                proposer_index=get_beacon_proposer_index(
                    state.copy(slot=slot, ),
                    CommitteeConfig(config),
                ),
                data=AttestationData(**sample_attestation_data_params).copy(
                    crosslink=Crosslink(shard=shard, ),
                    target=Checkpoint(
                        epoch=previous_epoch,
                        root=get_block_root(
                            state,
                            previous_epoch,
                            config.SLOTS_PER_EPOCH,
                            config.SLOTS_PER_HISTORICAL_ROOT,
                        ),
                    ),
                    beacon_block_root=get_block_root_at_slot(
                        state,
                        slot,
                        config.SLOTS_PER_HISTORICAL_ROOT,
                    ),
                ),
            ), )
    state = state.copy(previous_epoch_attestations=prev_epoch_attestations, )

    rewards_received, penalties_received = get_attestation_deltas(
        state,
        config,
    )

    # everyone attested, no penalties
    assert (sum(penalties_received) == 0)
    the_reward = rewards_received[0]
    # everyone performed the same, equal rewards
    assert (sum(rewards_received) // len(rewards_received) == the_reward)
Exemple #30
0
def test_process_crosslinks(genesis_state, config, success_in_previous_epoch,
                            success_in_current_epoch):
    shard_count = config.SHARD_COUNT
    current_slot = config.SLOTS_PER_EPOCH * 5 - 1
    current_epoch = compute_epoch_of_slot(current_slot, config.SLOTS_PER_EPOCH)
    assert current_epoch - 4 >= 0

    previous_crosslinks = tuple(
        Crosslink(
            shard=i,
            start_epoch=current_epoch - 4,
            end_epoch=current_epoch - 3,
        ) for i in range(shard_count))
    parent_crosslinks = tuple(
        Crosslink(
            shard=i,
            parent_root=previous_crosslinks[i].hash_tree_root,
            start_epoch=current_epoch - 2,
            end_epoch=current_epoch - 1,
        ) for i in range(shard_count))
    new_crosslinks = tuple(
        Crosslink(
            shard=i,
            parent_root=parent_crosslinks[i].hash_tree_root,
            start_epoch=current_epoch - 1,
            end_epoch=current_epoch,
        ) for i in range(shard_count))

    # generate expected state for correct crosslink generation
    state = genesis_state.copy(
        slot=current_slot,
        previous_crosslinks=previous_crosslinks,
        current_crosslinks=parent_crosslinks,
    )

    previous_epoch = current_epoch - 1

    expected_success_shards = set()
    previous_epoch_attestations = tuple(
        mk_all_pending_attestations_with_some_participation_in_epoch(
            state,
            previous_epoch,
            config,
            0.7 if success_in_previous_epoch else 0,
        ))
    if success_in_previous_epoch:
        for a in previous_epoch_attestations:
            expected_success_shards.add(a.data.crosslink.shard)

    current_epoch_attestations = tuple(
        mk_all_pending_attestations_with_some_participation_in_epoch(
            state,
            current_epoch,
            config,
            0.7 if success_in_current_epoch else 0,
        ))
    if success_in_current_epoch:
        for a in current_epoch_attestations:
            expected_success_shards.add(a.data.crosslink.shard)

    state = state.copy(
        previous_epoch_attestations=previous_epoch_attestations,
        current_epoch_attestations=current_epoch_attestations,
    )

    post_state = process_crosslinks(state, config)

    assert post_state.previous_crosslinks == state.current_crosslinks

    for shard in range(shard_count):
        crosslink = post_state.current_crosslinks[shard]
        if shard in expected_success_shards:
            if success_in_current_epoch:
                expected_crosslink = new_crosslinks[shard]
            else:
                expected_crosslink = parent_crosslinks[shard]
            assert crosslink == expected_crosslink
        else:
            # no change
            assert crosslink == state.current_crosslinks[shard]