Example #1
0
 async def propose_or_skip_block(self, slot: Slot,
                                 is_second_tick: bool) -> None:
     head = self.chain.get_canonical_head()
     state_machine = self.chain.get_state_machine()
     state = state_machine.state
     self.logger.debug(
         bold_green(
             f"head: slot={head.slot}, state root={head.state_root.hex()}"))
     proposer_index = _get_proposer_index(
         state,
         slot,
         state_machine.config,
     )
     # Since it's expected to tick twice in one slot, `latest_proposed_epoch` is used to prevent
     # proposing twice in the same slot.
     has_proposed = slot_to_epoch(
         slot, self.slots_per_epoch) <= self.latest_proposed_epoch
     if not has_proposed and proposer_index in self.validator_privkeys:
         self.propose_block(
             proposer_index=proposer_index,
             slot=slot,
             state=state,
             state_machine=state_machine,
             head_block=head,
         )
         self.latest_proposed_epoch = slot_to_epoch(slot,
                                                    self.slots_per_epoch)
     # skip the block if it's second half of the slot and we are not proposing
     elif is_second_tick and proposer_index not in self.validator_privkeys:
         self.skip_block(
             slot=slot,
             state=state,
             state_machine=state_machine,
         )
Example #2
0
def _correct_slashable_attestation_params(epoch_length, num_validators, params,
                                          messages, privkeys, fork):
    valid_params = copy.deepcopy(params)

    key = "custody_bit_0_indices"
    (poc_0_indices, poc_0_signatures) = _get_indices_and_signatures(
        num_validators,
        messages[0],
        privkeys,
        fork,
        slot_to_epoch(params["data"].slot, epoch_length),
    )
    valid_params[key] = poc_0_indices

    key = "custody_bit_1_indices"
    # NOTE: does not guarantee non-empty intersection
    (poc_1_indices, poc_1_signatures) = _get_indices_and_signatures(
        num_validators,
        messages[1],
        privkeys,
        fork,
        slot_to_epoch(params["data"].slot, epoch_length),
    )
    valid_params[key] = poc_1_indices

    signatures = poc_0_signatures + poc_1_signatures
    aggregate_signature = bls.aggregate_signatures(signatures)

    valid_params["aggregate_signature"] = aggregate_signature

    return valid_params
Example #3
0
def validate_proposer_slashing_epoch(proposer_slashing: ProposerSlashing,
                                     slots_per_epoch: int) -> None:
    epoch_1 = slot_to_epoch(proposer_slashing.header_1.slot, slots_per_epoch)
    epoch_2 = slot_to_epoch(proposer_slashing.header_2.slot, slots_per_epoch)

    if epoch_1 != epoch_2:
        raise ValidationError(
            f"Epoch of proposer_slashing.proposal_1 ({epoch_1}) !="
            f" epoch of proposer_slashing.proposal_2 ({epoch_2})")
Example #4
0
def process_final_updates(state: BeaconState,
                          config: BeaconConfig) -> BeaconState:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    next_epoch = state.next_epoch(config.SLOTS_PER_EPOCH)

    state = _update_latest_active_index_roots(state, CommitteeConfig(config))

    state = state.copy(
        latest_slashed_balances=update_tuple_item(
            state.latest_slashed_balances,
            next_epoch % config.LATEST_SLASHED_EXIT_LENGTH,
            state.latest_slashed_balances[current_epoch %
                                          config.LATEST_SLASHED_EXIT_LENGTH],
        ),
        latest_randao_mixes=update_tuple_item(
            state.latest_randao_mixes,
            next_epoch % config.LATEST_SLASHED_EXIT_LENGTH,
            get_randao_mix(
                state=state,
                epoch=current_epoch,
                slots_per_epoch=config.SLOTS_PER_EPOCH,
                latest_randao_mixes_length=config.LATEST_RANDAO_MIXES_LENGTH,
            ),
        ),
    )

    latest_attestations = tuple(
        filter(
            lambda attestation:
            (slot_to_epoch(attestation.data.slot, config.SLOTS_PER_EPOCH) >=
             current_epoch), state.latest_attestations))
    state = state.copy(latest_attestations=latest_attestations, )

    return state
Example #5
0
def get_beacon_proposer_index(state: 'BeaconState',
                              slot: Slot,
                              committee_config: CommitteeConfig,
                              registry_change: bool=False) -> ValidatorIndex:
    """
    Return the beacon proposer index for the ``slot``.
    """
    epoch = slot_to_epoch(slot, committee_config.SLOTS_PER_EPOCH)
    previous_epoch = state.previous_epoch(committee_config.SLOTS_PER_EPOCH)
    next_epoch = state.next_epoch(committee_config.SLOTS_PER_EPOCH)

    validate_epoch_within_previous_and_next(epoch, previous_epoch, next_epoch)

    crosslink_committees_at_slot = get_crosslink_committees_at_slot(
        state=state,
        slot=slot,
        committee_config=committee_config,
        registry_change=registry_change,
    )
    try:
        first_crosslink_committee = crosslink_committees_at_slot[0]
    except IndexError:
        raise ValidationError("crosslink_committees should not be empty.")

    first_committee, _ = first_crosslink_committee
    if len(first_committee) <= 0:
        raise ValidationError(
            "The first committee should not be empty"
        )

    return first_committee[epoch % len(first_committee)]
Example #6
0
def process_final_updates(state: BeaconState,
                          config: BeaconConfig) -> BeaconState:
    current_epoch = state.current_epoch(config.EPOCH_LENGTH)
    next_epoch = state.next_epoch(config.EPOCH_LENGTH)

    state = state.copy(
        latest_penalized_balances=update_tuple_item(
            state.latest_penalized_balances,
            next_epoch % config.LATEST_PENALIZED_EXIT_LENGTH,
            state.latest_penalized_balances[
                current_epoch % config.LATEST_PENALIZED_EXIT_LENGTH],
        ),
        latest_randao_mixes=update_tuple_item(
            state.latest_randao_mixes,
            next_epoch % config.LATEST_PENALIZED_EXIT_LENGTH,
            get_randao_mix(
                state=state,
                epoch=current_epoch,
                epoch_length=config.EPOCH_LENGTH,
                latest_randao_mixes_length=config.LATEST_RANDAO_MIXES_LENGTH,
            ),
        ),
    )

    latest_attestations = tuple(
        filter(
            lambda attestation: (slot_to_epoch(attestation.data.slot, config.
                                               EPOCH_LENGTH) >= current_epoch),
            state.latest_attestations))
    state = state.copy(latest_attestations=latest_attestations, )

    return state
def test_update_latest_active_index_roots(genesis_state,
                                          committee_config,
                                          state_slot,
                                          slots_per_epoch,
                                          latest_active_index_roots_length,
                                          activation_exit_delay):
    state = genesis_state.copy(
        slot=state_slot,
    )

    result_state = _update_latest_active_index_roots(state, committee_config)

    # TODO: chanege to hash_tree_root
    index_root = hash_eth2(
        b''.join(
            [
                index.to_bytes(32, 'little')
                for index in get_active_validator_indices(
                    state.validator_registry,
                    # TODO: change to `per-epoch` version
                    slot_to_epoch(state.slot, slots_per_epoch),
                )
            ]
        )
    )

    target_epoch = state.next_epoch(slots_per_epoch) + activation_exit_delay
    assert result_state.latest_active_index_roots[
        target_epoch % latest_active_index_roots_length
    ] == index_root
Example #8
0
def create_block_on_state(
        *,
        state: BeaconState,
        config: BeaconConfig,
        state_machine: BaseBeaconStateMachine,
        block_class: BaseBeaconBlock,
        parent_block: BaseBeaconBlock,
        slot: SlotNumber,
        validator_index: ValidatorIndex,
        privkey: int,
        attestations: Sequence[Attestation],
        check_proposer_index: bool = True) -> BaseBeaconBlock:
    """
    Create a beacon block with the given parameters.
    """
    # Check proposer
    if check_proposer_index:
        validate_proposer_index(state, config, slot, validator_index)

    # Prepare block: slot and parent_root
    block = block_class.from_parent(
        parent_block=parent_block,
        block_params=FromBlockParams(slot=slot),
    )

    # TODO: Add more operations
    randao_reveal = ZERO_HASH32
    eth1_data = Eth1Data.create_empty_data()
    body = BeaconBlockBody.create_empty_body().copy(
        attestations=attestations, )

    block = block.copy(
        randao_reveal=randao_reveal,
        eth1_data=eth1_data,
        body=body,
    )

    # Apply state transition to get state root
    state, block = state_machine.import_block(block,
                                              check_proposer_signature=True)

    # Sign
    empty_signature_block_root = block.block_without_signature_root
    proposal_root = ProposalSignedData(
        slot,
        config.BEACON_CHAIN_SHARD_NUMBER,
        empty_signature_block_root,
    ).root
    domain = get_domain(
        state.fork,
        slot_to_epoch(slot, config.EPOCH_LENGTH),
        SignatureDomain.DOMAIN_PROPOSAL,
    )
    block = block.copy(signature=bls.sign(
        message=proposal_root,
        privkey=privkey,
        domain=domain,
    ), )

    return block
Example #9
0
async def test_validator_attest(event_loop, event_bus, monkeypatch):
    alice_indices = [i for i in range(8)]
    alice = await get_validator(event_loop=event_loop,
                                event_bus=event_bus,
                                indices=alice_indices)
    head = alice.chain.get_canonical_head()
    state_machine = alice.chain.get_state_machine()
    state = state_machine.state

    epoch = slot_to_epoch(state.slot, state_machine.config.SLOTS_PER_EPOCH)
    assignment = alice._get_this_epoch_assignment(alice_indices[0], epoch)

    attestations = await alice.attest(assignment.slot)
    assert len(attestations) == 1
    attestation = attestations[0]
    assert get_attestation_data_slot(
        state,
        attestation.data,
        state_machine.config,
    ) == assignment.slot
    assert attestation.data.beacon_block_root == head.signing_root
    assert attestation.data.crosslink.shard == assignment.shard

    # Advance the state and validate the attestation
    config = state_machine.config
    future_state = state_machine.state_transition.apply_state_transition(
        state,
        future_slot=assignment.slot + config.MIN_ATTESTATION_INCLUSION_DELAY,
    )
    validate_attestation(
        future_state,
        attestation,
        config,
    )
Example #10
0
def verify_slashable_attestation_signature(
        state: BeaconState, slashable_attestation: SlashableAttestation,
        slots_per_epoch: int) -> bool:
    """
    Ensure we have a valid aggregate signature for the ``slashable_attestation``.
    """
    all_indices = slashable_attestation.custody_bit_indices
    pubkeys: Tuple[BLSPubkey, ...] = generate_aggregate_pubkeys_from_indices(
        state.validator_registry,
        *all_indices,
    )
    message_hashes: Tuple[Hash32, ...] = slashable_attestation.message_hashes

    signature = slashable_attestation.aggregate_signature

    domain = get_domain(
        state.fork,
        slot_to_epoch(slashable_attestation.data.slot, slots_per_epoch),
        SignatureDomain.DOMAIN_ATTESTATION,
    )

    # No custody bit 1 indice votes in phase 0, so we only need to process custody bit 0
    # for efficiency.
    # TODO: to be removed in phase 1.
    if len(all_indices[1]) == 0:
        pubkeys = pubkeys[:1]
        message_hashes = message_hashes[:1]

    return bls.verify_multiple(
        pubkeys=pubkeys,
        message_hashes=message_hashes,
        signature=signature,
        domain=domain,
    )
Example #11
0
def validate_attestation_previous_crosslink_or_root(
        attestation_data: AttestationData,
        state_latest_crosslink: CrosslinkRecord, 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 = CrosslinkRecord(
        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})")
Example #12
0
 def _get_highest_justified_epoch(self, db: BaseDB) -> Epoch:
     try:
         justified_head_root = self._get_justified_head_root(db)
         slot = self.get_slot_by_root(justified_head_root)
         return slot_to_epoch(slot, self.config.SLOTS_PER_EPOCH)
     except JustifiedHeadNotFound:
         return self.config.GENESIS_EPOCH
Example #13
0
def _correct_slashable_attestation_params(
        slots_per_epoch,
        num_validators,
        params,
        message_hashes,
        privkeys,
        fork):
    valid_params = copy.deepcopy(params)

    (validator_indices, signatures) = _get_indices_and_signatures(
        num_validators,
        message_hashes[0],  # custody bit is False
        privkeys,
        fork,
        slot_to_epoch(params["data"].slot, slots_per_epoch),
    )

    valid_params["validator_indices"] = validator_indices
    valid_params["custody_bitfield"] = get_empty_bitfield(len(validator_indices))

    aggregate_signature = bls.aggregate_signatures(signatures)

    valid_params["aggregate_signature"] = aggregate_signature

    return valid_params
Example #14
0
def get_crosslink_committees_at_slot(
    state: 'BeaconState', slot: SlotNumber, genesis_epoch: EpochNumber,
    epoch_length: int, target_committee_size: int, shard_count: int
) -> Iterable[Tuple[Iterable[ValidatorIndex], ShardNumber]]:
    """
    Return the list of ``(committee, shard)`` tuples for the ``slot``.
    """

    epoch = slot_to_epoch(slot, epoch_length)
    current_epoch = state.current_epoch(epoch_length)

    validate_epoch_for_current_epoch(
        current_epoch=current_epoch,
        given_epoch=epoch,
        genesis_epoch=genesis_epoch,
        epoch_length=epoch_length,
    )

    # TODO: need to update according to https://github.com/ethereum/eth2.0-specs/pull/520
    if epoch < current_epoch:
        committees_per_epoch = get_previous_epoch_committee_count(
            state=state,
            shard_count=shard_count,
            epoch_length=epoch_length,
            target_committee_size=target_committee_size,
        )
        seed = state.previous_epoch_seed
        shuffling_epoch = state.previous_calculation_epoch
        shuffling_start_shard = state.previous_epoch_start_shard
    else:
        committees_per_epoch = get_current_epoch_committee_count(
            state=state,
            shard_count=shard_count,
            epoch_length=epoch_length,
            target_committee_size=target_committee_size,
        )
        seed = state.current_epoch_seed
        shuffling_epoch = state.current_calculation_epoch
        shuffling_start_shard = state.current_epoch_start_shard

    shuffling = get_shuffling(
        seed=seed,
        validators=state.validator_registry,
        epoch=shuffling_epoch,
        epoch_length=epoch_length,
        target_committee_size=target_committee_size,
        shard_count=shard_count,
    )
    offset = slot % epoch_length
    committees_per_slot = committees_per_epoch // epoch_length
    slot_start_shard = (shuffling_start_shard +
                        committees_per_slot * offset) % shard_count

    for index in range(committees_per_slot):
        committee = shuffling[committees_per_slot * offset + index]
        yield (
            committee,
            ShardNumber((slot_start_shard + index) % shard_count),
        )
def get_current_epoch_attestations(
        state: 'BeaconState',
        slots_per_epoch: int) -> Iterable[PendingAttestationRecord]:
    current_epoch = state.current_epoch(slots_per_epoch)
    for attestation in state.latest_attestations:
        if current_epoch == slot_to_epoch(attestation.data.slot,
                                          slots_per_epoch):
            yield attestation
def get_previous_epoch_attestations(
        state: 'BeaconState', slots_per_epoch: int,
        genesis_epoch: Epoch) -> Iterable[PendingAttestationRecord]:
    previous_epoch = state.previous_epoch(slots_per_epoch, genesis_epoch)
    for attestation in state.latest_attestations:
        if previous_epoch == slot_to_epoch(attestation.data.slot,
                                           slots_per_epoch):
            yield attestation
Example #17
0
def test_process_validator_registry(
        monkeypatch, genesis_state, epoch_length, state_slot, need_to_update,
        num_shards_in_committees, validator_registry_update_epoch,
        epochs_since_last_registry_change_is_power_of_two,
        current_calculation_epoch, latest_randao_mixes,
        expected_current_calculation_epoch, entry_exit_delay, config):
    # Mock check_if_update_validator_registry
    from eth2.beacon.state_machines.forks.serenity import epoch_processing

    def mock_check_if_update_validator_registry(state, config):
        return need_to_update, num_shards_in_committees

    monkeypatch.setattr(epoch_processing,
                        '_check_if_update_validator_registry',
                        mock_check_if_update_validator_registry)

    # Mock generate_seed
    new_seed = b'\x88' * 32

    def mock_generate_seed(state, epoch, epoch_length, seed_lookahead,
                           entry_exit_delay, latest_index_roots_length,
                           latest_randao_mixes_length):
        return new_seed

    monkeypatch.setattr('eth2.beacon.helpers.generate_seed',
                        mock_generate_seed)

    # Set state
    state = genesis_state.copy(
        slot=state_slot,
        validator_registry_update_epoch=validator_registry_update_epoch,
        current_calculation_epoch=current_calculation_epoch,
        latest_randao_mixes=latest_randao_mixes,
    )

    result_state = process_validator_registry(state, config)

    assert result_state.previous_calculation_epoch == state.current_calculation_epoch
    assert result_state.previous_epoch_start_shard == state.current_epoch_start_shard
    assert result_state.previous_epoch_seed == state.current_epoch_seed

    if need_to_update:
        assert result_state.current_calculation_epoch == slot_to_epoch(
            state_slot, epoch_length)
        assert result_state.current_epoch_seed == new_seed
        # TODO: Add test for validator registry updates
    else:
        assert (result_state.current_calculation_epoch ==
                expected_current_calculation_epoch)
        # state.current_epoch_start_shard is left unchanged.
        assert result_state.current_epoch_start_shard == state.current_epoch_start_shard

        if epochs_since_last_registry_change_is_power_of_two:
            assert result_state.current_epoch_seed == new_seed
        else:
            assert result_state.current_epoch_seed != new_seed
Example #18
0
async def test_validator_get_committee_assigment(event_loop, event_bus):
    alice_indices = [7]
    alice = await get_validator(event_loop=event_loop, event_bus=event_bus, indices=alice_indices)
    state_machine = alice.chain.get_state_machine()
    state = state_machine.state
    epoch = slot_to_epoch(state.slot, state_machine.config.SLOTS_PER_EPOCH)

    assert alice.this_epoch_assignment[alice_indices[0]][0] == -1
    alice._get_this_epoch_assignment(alice_indices[0], epoch)
    assert alice.this_epoch_assignment[alice_indices[0]][0] == epoch
Example #19
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 = slot_to_epoch(
        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_epoch=state.current_justified_epoch,
            source_root=state.current_justified_root,
            target_root=target_root,
            target_epoch=target_epoch,
            crosslink=Crosslink(
                shard=shard,
                parent_root=parent_crosslink.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,
        )
Example #20
0
async def test_validator_propose_or_skip_block(event_loop, event_bus,
                                               monkeypatch):
    alice, bob = await get_linked_validators(event_loop=event_loop,
                                             event_bus=event_bus)
    state_machine = alice.chain.get_state_machine()
    state = state_machine.state

    # test: `propose_or_skip_block` should call `propose_block` if the validator get selected
    def is_alice_selected(proposer_index):
        return proposer_index in alice.validator_privkeys

    slot_to_propose, index = _get_slot_with_validator_selected(
        is_desired_proposer_index=is_alice_selected,
        start_slot=state.slot + 1,
        state=state,
        state_machine=state_machine,
    )
    alice.latest_proposed_epoch = slot_to_epoch(slot_to_propose,
                                                alice.slots_per_epoch) - 1

    is_proposing = None

    def propose_block(proposer_index, slot, state, state_machine, head_block):
        nonlocal is_proposing
        is_proposing = True

    def skip_block(slot, state, state_machine):
        nonlocal is_proposing
        is_proposing = False

    monkeypatch.setattr(alice, 'propose_block', propose_block)
    monkeypatch.setattr(alice, 'skip_block', skip_block)

    await alice.propose_or_skip_block(slot_to_propose, False)
    assert is_proposing

    is_proposing = None

    # test: `propose_or_skip_block` should call `skip_block`.
    def is_not_alice_bob_selected(proposer_index):
        return (proposer_index not in alice.validator_privkeys
                and proposer_index not in bob.validator_privkeys)

    slot_to_skip, index = _get_slot_with_validator_selected(
        is_desired_proposer_index=is_not_alice_bob_selected,
        start_slot=state.slot + 1,
        state=state,
        state_machine=state_machine,
    )

    await alice.propose_or_skip_block(slot_to_skip, is_second_tick=False)
    assert is_proposing is None, "`skip_block` should not be called if `is_second_tick == False`"

    await alice.propose_or_skip_block(slot_to_skip, is_second_tick=True)
    assert is_proposing is False, "`skip_block` should have been called"
Example #21
0
 async def handle_first_tick(self, slot: Slot) -> None:
     head = self.chain.get_canonical_head()
     state_machine = self.chain.get_state_machine()
     state = state_machine.state
     self.logger.debug(
         # Align with debug log below
         bold_green("Head       epoch=%s slot=%s state_root=%s"),
         state.current_epoch(self.slots_per_epoch),
         head.slot,
         encode_hex(head.state_root),
     )
     self.logger.debug(
         bold_green("Justified  epoch=%s root=%s  (current)"),
         state.current_justified_epoch,
         encode_hex(state.current_justified_root),
     )
     self.logger.debug(
         bold_green("Justified  epoch=%s root=%s  (previous)"),
         state.previous_justified_epoch,
         encode_hex(state.previous_justified_root),
     )
     self.logger.debug(
         bold_green("Finalized  epoch=%s root=%s"),
         state.finalized_epoch,
         encode_hex(state.finalized_root),
     )
     self.logger.debug(
         bold_green("current_epoch_attestations  %s"),
         state.current_epoch_attestations,
     )
     self.logger.debug(
         bold_green("previous_epoch_attestations %s"),
         state.previous_epoch_attestations,
     )
     proposer_index = _get_proposer_index(
         state,
         slot,
         state_machine.config,
     )
     # `latest_proposed_epoch` is used to prevent validator from erraneously proposing twice
     # in the same epoch due to service crashing.
     epoch = slot_to_epoch(slot, self.slots_per_epoch)
     if proposer_index in self.validator_privkeys:
         has_proposed = epoch <= self.latest_proposed_epoch[proposer_index]
         if not has_proposed:
             self.propose_block(
                 proposer_index=proposer_index,
                 slot=slot,
                 state=state,
                 state_machine=state_machine,
                 head_block=head,
             )
             self.latest_proposed_epoch[proposer_index] = epoch
Example #22
0
def _corrupt_signature(slots_per_epoch, params, fork):
    message_hash = b'\x12' * 32
    privkey = 42
    domain_type = SignatureDomain.DOMAIN_ATTESTATION
    domain = get_domain(
        fork=fork,
        epoch=slot_to_epoch(params["data"].slot, slots_per_epoch),
        domain_type=domain_type,
    )
    corrupt_signature = bls.sign(message_hash, privkey, domain)

    return assoc(params, "aggregate_signature", corrupt_signature)
Example #23
0
def sign_attestation(message: bytes, privkey: int, fork: Fork,
                     slot: SlotNumber, epoch_length: int) -> BLSSignature:
    domain = get_domain(
        fork,
        slot_to_epoch(slot, epoch_length),
        SignatureDomain.DOMAIN_ATTESTATION,
    )
    return bls.sign(
        message=message,
        privkey=privkey,
        domain=domain,
    )
Example #24
0
def validate_attestation_aggregate_signature(state: BeaconState,
                                             attestation: Attestation,
                                             genesis_epoch: EpochNumber,
                                             epoch_length: int,
                                             target_committee_size: int,
                                             shard_count: int) -> None:
    """
    Validate ``aggregate_signature`` field of ``attestation``.
    Raise ``ValidationError`` if it's invalid.

    Note: This is the phase 0 version of `aggregate_signature`` validation.
    All proof of custody bits are assumed to be 0 within the signed data.
    This will change to reflect real proof of custody bits in the Phase 1.
    """
    participant_indices = get_attestation_participants(
        state=state,
        attestation_data=attestation.data,
        bitfield=attestation.aggregation_bitfield,
        genesis_epoch=genesis_epoch,
        epoch_length=epoch_length,
        target_committee_size=target_committee_size,
        shard_count=shard_count,
    )
    pubkeys = tuple(
        state.validator_registry[validator_index].pubkey
        for validator_index in participant_indices
    )
    group_public_key = bls.aggregate_pubkeys(pubkeys)
    # TODO: change to tree hashing when we have SSZ
    message = AttestationDataAndCustodyBit.create_attestation_message(attestation.data)
    domain = get_domain(
        fork=state.fork,
        epoch=slot_to_epoch(attestation.data.slot, epoch_length),
        domain_type=SignatureDomain.DOMAIN_ATTESTATION,
    )

    is_valid_signature = bls.verify(
        message=message,
        pubkey=group_public_key,
        signature=attestation.aggregate_signature,
        domain=domain,
    )

    if not is_valid_signature:
        raise ValidationError(
            "Attestation aggregate_signature is invalid. "
            "message={}, participant_indices={} "
            "domain={}".format(
                message,
                participant_indices,
                domain,
            )
        )
Example #25
0
def _corrupt_signature(epoch_length, params, fork):
    message = bytes.fromhex("deadbeefcafe")
    privkey = 42
    domain_type = SignatureDomain.DOMAIN_ATTESTATION
    domain = get_domain(
        fork=fork,
        epoch=slot_to_epoch(params["data"].slot, epoch_length),
        domain_type=domain_type,
    )
    corrupt_signature = bls.sign(message, privkey, domain)

    return assoc(params, "aggregate_signature", corrupt_signature)
Example #26
0
def sign_transaction(*, message_hash: Hash32, privkey: int, fork: Fork,
                     slot: Slot, signature_domain: SignatureDomain,
                     slots_per_epoch: int) -> BLSSignature:
    domain = get_domain(
        fork,
        slot_to_epoch(slot, slots_per_epoch),
        signature_domain,
    )
    return bls.sign(
        message_hash=message_hash,
        privkey=privkey,
        domain=domain,
    )
Example #27
0
def sign_proof_of_possession(deposit_input: DepositInput, privkey: int,
                             fork: Fork, slot: Slot,
                             slots_per_epoch: int) -> BLSSignature:
    domain = get_domain(
        fork,
        slot_to_epoch(slot, slots_per_epoch),
        SignatureDomain.DOMAIN_DEPOSIT,
    )
    return bls.sign(
        message_hash=deposit_input.root,
        privkey=privkey,
        domain=domain,
    )
Example #28
0
def _find_latest_attestation_targets(
        state: BeaconState, store: Store,
        config: Eth2Config) -> Iterable[AttestationTarget]:
    epoch = slot_to_epoch(state.slot, config.SLOTS_PER_EPOCH)
    active_validators = get_active_validator_indices(
        state.validators,
        epoch,
    )
    return filter(
        second, map(
            _find_latest_attestation_target(store),
            active_validators,
        ))
Example #29
0
def sign_transaction(*, message_hash: Hash32, privkey: int, state: BeaconState,
                     slot: Slot, signature_domain: SignatureDomain,
                     slots_per_epoch: int) -> BLSSignature:
    domain = get_domain(
        state,
        signature_domain,
        slots_per_epoch,
        message_epoch=slot_to_epoch(slot, slots_per_epoch),
    )
    return bls.sign(
        message_hash=message_hash,
        privkey=privkey,
        domain=domain,
    )
Example #30
0
def _get_target_root(state: BeaconState, config: Eth2Config,
                     beacon_block_root: Hash32) -> Hash32:
    epoch_start_slot = get_epoch_start_slot(
        slot_to_epoch(state.slot, config.SLOTS_PER_EPOCH),
        config.SLOTS_PER_EPOCH,
    )
    if epoch_start_slot == state.slot:
        return beacon_block_root
    else:
        return get_block_root(
            state,
            epoch_start_slot,
            config.SLOTS_PER_HISTORICAL_ROOT,
        )