Пример #1
0
def test_process_voluntary_exits(genesis_state, sample_beacon_block_params,
                                 sample_beacon_block_body_params, config,
                                 keymap, success):
    state = genesis_state.copy(slot=get_epoch_start_slot(
        config.GENESIS_EPOCH + config.PERSISTENT_COMMITTEE_PERIOD,
        config.SLOTS_PER_EPOCH,
    ), )
    validator_index = 0
    validator = state.validators[validator_index].copy(
        activation_epoch=config.GENESIS_EPOCH, )
    state = state.update_validator(validator_index, validator)
    valid_voluntary_exit = create_mock_voluntary_exit(
        state,
        config,
        keymap,
        validator_index,
    )

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

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

        with pytest.raises(ValidationError):
            process_voluntary_exits(
                state,
                block,
                config,
            )
Пример #2
0
def test_process_attester_slashings(genesis_state, sample_beacon_block_params,
                                    sample_beacon_block_body_params, config,
                                    keymap, min_attestation_inclusion_delay,
                                    success):
    attesting_state = genesis_state.copy(
        slot=genesis_state.slot + config.SLOTS_PER_EPOCH,
        block_roots=tuple(
            i.to_bytes(32, "little")
            for i in range(config.SLOTS_PER_HISTORICAL_ROOT)))
    valid_attester_slashing = create_mock_attester_slashing_is_double_vote(
        attesting_state,
        config,
        keymap,
        attestation_epoch=0,
    )
    state = attesting_state.copy(slot=attesting_state.slot +
                                 min_attestation_inclusion_delay, )

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

        attester_index = valid_attester_slashing.attestation_1.custody_bit_0_indices[
            0]

        new_state = process_attester_slashings(
            state,
            block,
            config,
        )
        # Check if slashed
        assert not state.validators[attester_index].slashed
        assert new_state.validators[attester_index].slashed
    else:
        invalid_attester_slashing = valid_attester_slashing.copy(
            attestation_2=valid_attester_slashing.attestation_2.copy(
                data=valid_attester_slashing.attestation_1.data, ))
        block_body = BeaconBlockBody(**sample_beacon_block_body_params).copy(
            attester_slashings=(invalid_attester_slashing, ), )
        block = SerenityBeaconBlock(**sample_beacon_block_params).copy(
            slot=state.slot,
            body=block_body,
        )

        with pytest.raises(ValidationError):
            process_attester_slashings(
                state,
                block,
                config,
            )
Пример #3
0
def test_process_attester_slashings(genesis_state, sample_beacon_block_params,
                                    sample_beacon_block_body_params, config,
                                    keymap, min_attestation_inclusion_delay,
                                    success):
    attesting_state = genesis_state.copy(slot=genesis_state.slot +
                                         config.SLOTS_PER_EPOCH, )
    valid_attester_slashing = create_mock_attester_slashing_is_double_vote(
        attesting_state,
        config,
        keymap,
        attestation_epoch=0,
    )
    state = attesting_state.copy(slot=attesting_state.slot +
                                 min_attestation_inclusion_delay, )

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

        attester_index = valid_attester_slashing.slashable_attestation_1.validator_indices[
            0]

        new_state = process_attester_slashings(
            state,
            block,
            config,
        )
        # Check if slashed
        assert (new_state.validator_balances[attester_index] <
                state.validator_balances[attester_index])
    else:
        invalid_attester_slashing = valid_attester_slashing.copy(
            slashable_attestation_2=valid_attester_slashing.
            slashable_attestation_2.copy(
                data=valid_attester_slashing.slashable_attestation_1.data, ))
        block_body = BeaconBlockBody(**sample_beacon_block_body_params).copy(
            attester_slashings=(invalid_attester_slashing, ), )
        block = SerenityBeaconBlock(**sample_beacon_block_params).copy(
            slot=state.slot,
            body=block_body,
        )

        with pytest.raises(ValidationError):
            process_attester_slashings(
                state,
                block,
                config,
            )
Пример #4
0
def test_block_body_empty(sample_attestation_params):
    block_body = BeaconBlockBody()
    assert block_body.proposer_slashings == ()
    assert block_body.attester_slashings == ()
    assert block_body.attestations == ()
    assert block_body.deposits == ()
    assert block_body.voluntary_exits == ()

    assert block_body.is_empty

    block_body = block_body.copy(attestations=(Attestation(
        **sample_attestation_params), ))
    assert not block_body.is_empty
Пример #5
0
def test_process_voluntary_exits(
    genesis_state,
    sample_beacon_block_params,
    sample_beacon_block_body_params,
    config,
    keymap,
    success,
):
    state = genesis_state.set(
        "slot",
        compute_start_slot_at_epoch(
            config.GENESIS_EPOCH + config.PERSISTENT_COMMITTEE_PERIOD,
            config.SLOTS_PER_EPOCH,
        ),
    )
    validator_index = 0
    validator = state.validators[validator_index].set("activation_epoch",
                                                      config.GENESIS_EPOCH)
    state = state.transform(["validators", validator_index], validator)
    valid_voluntary_exit = create_mock_voluntary_exit(state, config, keymap,
                                                      validator_index)

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

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

        with pytest.raises(ValidationError):
            process_voluntary_exits(state, block, config)
Пример #6
0
def test_process_voluntary_exits(genesis_state, sample_beacon_block_params,
                                 sample_beacon_block_body_params, config,
                                 keymap, success):
    state = genesis_state.copy(slot=get_epoch_start_slot(
        config.GENESIS_EPOCH + config.PERSISTENT_COMMITTEE_PERIOD,
        config.SLOTS_PER_EPOCH,
    ), )
    validator_index = 0
    validator = state.validator_registry[validator_index].copy(
        activation_epoch=config.GENESIS_EPOCH, )
    state = state.update_validator_registry(validator_index, validator)
    valid_voluntary_exit = create_mock_voluntary_exit(
        state,
        config,
        keymap,
        validator_index,
    )

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

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

        with pytest.raises(ValidationError):
            process_voluntary_exits(
                state,
                block,
                config,
            )
Пример #7
0
def test_process_attester_slashings(
    genesis_state,
    sample_beacon_block_params,
    sample_beacon_block_body_params,
    config,
    keymap,
    min_attestation_inclusion_delay,
    success,
):
    attesting_state = genesis_state.mset(
        "slot",
        genesis_state.slot + config.SLOTS_PER_EPOCH,
        "block_roots",
        tuple(
            i.to_bytes(32, "little")
            for i in range(config.SLOTS_PER_HISTORICAL_ROOT)),
    )
    valid_attester_slashing = create_mock_attester_slashing_is_double_vote(
        attesting_state, config, keymap, attestation_epoch=0)
    state = attesting_state.set(
        "slot", attesting_state.slot + min_attestation_inclusion_delay)

    if success:
        block_body = BeaconBlockBody.create(
            **sample_beacon_block_body_params).set("attester_slashings",
                                                   (valid_attester_slashing, ))
        block = SerenityBeaconBlock.create(**sample_beacon_block_params).mset(
            "slot", state.slot, "body", block_body)

        attester_index = valid_attester_slashing.attestation_1.attesting_indices[
            0]

        new_state = process_attester_slashings(state, block, config)
        # Check if slashed
        assert not state.validators[attester_index].slashed
        assert new_state.validators[attester_index].slashed
    else:
        invalid_attester_slashing = valid_attester_slashing.transform(
            ["attestation_2", "data"],
            valid_attester_slashing.attestation_1.data)
        block_body = BeaconBlockBody.create(
            **sample_beacon_block_body_params).set(
                "attester_slashings", (invalid_attester_slashing, ))
        block = SerenityBeaconBlock.create(**sample_beacon_block_params).mset(
            "slot", state.slot, "body", block_body)

        with pytest.raises(ValidationError):
            process_attester_slashings(state, block, config)
Пример #8
0
def test_process_eth1_data(original_votes,
                           block_data,
                           expected_votes,
                           sample_beacon_state_params,
                           sample_beacon_block_params,
                           sample_beacon_block_body_params):
    eth1_data_votes = tuple(
        Eth1DataVote(data, vote_count)
        for data, vote_count in original_votes
    )
    state = BeaconState(**sample_beacon_state_params).copy(
        eth1_data_votes=eth1_data_votes,
    )

    block_body = BeaconBlockBody(**sample_beacon_block_body_params).copy(
        eth1_data=block_data,
    )

    block = BeaconBlock(**sample_beacon_block_params).copy(
        body=block_body,
    )

    updated_state = process_eth1_data(state, block)
    updated_votes = tuple(
        (vote.eth1_data, vote.vote_count)
        for vote in updated_state.eth1_data_votes
    )
    assert updated_votes == expected_votes
Пример #9
0
def test_process_max_attestations(genesis_state, genesis_block,
                                  sample_beacon_block_params,
                                  sample_beacon_block_body_params, config,
                                  keymap):
    attestation_slot = config.GENESIS_SLOT
    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,
        attestation_slot=attestation_slot,
        beacon_block_root=genesis_block.root,
        keymap=keymap,
        voted_attesters_ratio=1.0,
    )

    attestations_count = len(attestations)
    assert attestations_count > 0

    block_body = BeaconBlockBody(**sample_beacon_block_body_params).copy(
        attestations=attestations *
        (attestations_count // config.MAX_ATTESTATIONS + 1), )
    block = SerenityBeaconBlock(**sample_beacon_block_params).copy(
        slot=current_slot,
        body=block_body,
    )

    with pytest.raises(ValidationError):
        process_attestations(
            state,
            block,
            config,
        )
Пример #10
0
def sample_beacon_block_params(sample_beacon_block_body_params):
    return {
        "slot": GENESIS_SLOT + 10,
        "parent_root": ZERO_HASH32,
        "state_root": b"\x55" * 32,
        "body": BeaconBlockBody.create(**sample_beacon_block_body_params),
    }
def test_ensure_update_eth1_vote_if_exists(genesis_state, config,
                                           vote_offsets):
    # one less than a majority is the majority divided by 2
    threshold = config.SLOTS_PER_ETH1_VOTING_PERIOD // 2
    data_votes = tuple(
        concat((Eth1Data.create(block_hash=(i).to_bytes(32, "little")), ) *
               (threshold + offset) for i, offset in enumerate(vote_offsets)))
    state = genesis_state

    for vote in data_votes:
        state = process_eth1_data(
            state,
            BeaconBlock.create(body=BeaconBlockBody.create(eth1_data=vote)),
            config,
        )

    if not vote_offsets:
        assert state.eth1_data == genesis_state.eth1_data

    # we should update the 'latest' entry if we have a majority
    for offset in vote_offsets:
        if offset <= 0:
            assert genesis_state.eth1_data == state.eth1_data
        else:
            assert state.eth1_data == data_votes[0]
Пример #12
0
def test_process_eth1_data(original_votes,
                           block_data,
                           expected_votes,
                           sample_beacon_state_params,
                           sample_beacon_block_params,
                           sample_beacon_block_body_params,
                           config):
    eth1_data_votes = tuple(mapcat(
        _expand_eth1_votes,
        original_votes,
    ))
    state = BeaconState(**sample_beacon_state_params).copy(
        eth1_data_votes=eth1_data_votes,
    )

    block_body = BeaconBlockBody(**sample_beacon_block_body_params).copy(
        eth1_data=Eth1Data(
            block_hash=block_data,
        ),
    )

    block = BeaconBlock(**sample_beacon_block_params).copy(
        body=block_body,
    )

    updated_state = process_eth1_data(state, block, config)
    updated_votes = updated_state.eth1_data_votes
    expanded_expected_votes = tuple(mapcat(
        _expand_eth1_votes,
        expected_votes,
    ))

    assert updated_votes == expanded_expected_votes
Пример #13
0
def create_block_proposal(
    slot: Slot,
    parent_root: Root,
    randao_reveal: BLSSignature,
    eth1_data: Eth1Data,
    attestations: Sequence[Attestation],
    state: BeaconState,
    state_machine: BaseBeaconStateMachine,
) -> BeaconBlock:
    config = state_machine.config
    state_at_slot, _ = state_machine.apply_state_transition(state,
                                                            future_slot=slot)
    proposer_index = get_beacon_proposer_index(state_at_slot, config)

    block_body = BeaconBlockBody.create(randao_reveal=randao_reveal,
                                        eth1_data=eth1_data,
                                        attestations=attestations)
    proposal = BeaconBlock.create(
        slot=slot,
        parent_root=parent_root,
        body=block_body,
        proposer_index=proposer_index,
    )
    block_with_empty_signature = SignedBeaconBlock.create(
        message=proposal, signature=EMPTY_SIGNATURE)
    post_state, block_with_state_root = state_machine.apply_state_transition(
        state, block_with_empty_signature, check_proposer_signature=False)
    return block_with_state_root.message
Пример #14
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
Пример #15
0
 def run_with(
     cls,
     inputs: Tuple[BeaconState, OperationOrBlockHeader],
     config: Optional[Eth2Config],
 ) -> BeaconState:
     state, operation = inputs
     # NOTE: we do not have an easy way to evaluate a single operation on the state
     # So, we wrap it in a beacon block. The following statement lets us rely on
     # the config given in a particular handler class while working w/in the
     # update API provided by `py-ssz`.
     # NOTE: we ignore the type here, otherwise need to spell out each of the keyword
     # arguments individually... save some work and just build them dynamically
     block = BeaconBlock(
         body=BeaconBlockBody(**{f"{cls.name}s": (
             operation, )})  # type: ignore
     )
     try:
         return cls.processor(state, block, config)
     except ValidationError as e:
         # if already a ValidationError, re-raise
         raise e
     except Exception as e:
         # check if the exception is expected...
         for exception in cls.expected_exceptions:
             if isinstance(e, exception):
                 raise ValidationError(e)
         # else raise (and fail the pytest test case ...)
         raise e
Пример #16
0
def create_unsigned_block_on_state(
    *,
    state: BeaconState,
    config: Eth2Config,
    block_class: Type[BaseBeaconBlock],
    parent_block: BaseBeaconBlock,
    slot: Slot,
    attestations: Sequence[Attestation],
    eth1_data: Eth1Data = None,
    deposits: Sequence[Deposit] = None,
    check_proposer_index: bool = True,
) -> BeaconBlock:
    """
    Create a beacon block with the given parameters.
    """
    block = block_class.from_parent(parent_block=parent_block,
                                    block_params=FromBlockParams(slot=slot))

    # MAX_ATTESTATIONS
    attestations = attestations[:config.MAX_ATTESTATIONS]

    # TODO: Add more operations
    if eth1_data is None:
        eth1_data = state.eth1_data
    body = BeaconBlockBody.create(eth1_data=eth1_data,
                                  attestations=attestations)
    if deposits is not None and len(deposits) > 0:
        body = body.set("deposits", deposits)

    block = block.set("body", body)

    return block
def test_randao_processing_validates_randao_reveal(
    sample_beacon_block_params,
    sample_beacon_block_body_params,
    sample_beacon_state_params,
    sample_fork_params,
    keymap,
    config,
):
    proposer_pubkey, proposer_privkey = first(keymap.items())
    state = SerenityBeaconState.create(**sample_beacon_state_params).mset(
        "validators",
        tuple(
            create_mock_validator(proposer_pubkey, config)
            for _ in range(config.TARGET_COMMITTEE_SIZE)),
        "balances",
        (config.MAX_EFFECTIVE_BALANCE, ) * config.TARGET_COMMITTEE_SIZE,
        "randao_mixes",
        tuple(ZERO_HASH32 for _ in range(config.EPOCHS_PER_HISTORICAL_VECTOR)),
    )

    epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    message_hash = (epoch + 1).to_bytes(32, byteorder="little")
    domain = get_domain(state, SignatureDomain.DOMAIN_RANDAO,
                        config.SLOTS_PER_EPOCH)
    randao_reveal = bls.sign(message_hash, proposer_privkey, domain)

    block_body = BeaconBlockBody.create(**sample_beacon_block_body_params).set(
        "randao_reveal", randao_reveal)

    block = SerenityBeaconBlock.create(**sample_beacon_block_params).set(
        "body", block_body)

    with pytest.raises(ValidationError):
        process_randao(state, block, config)
Пример #18
0
async def test_get_blocks_from_canonical_chain_by_slot(
    monkeypatch, db_block_slots, slot_of_requested_blocks, expected_block_slots
):
    node = NodeFactory()

    # Mock up block database
    mock_slot_to_block_db = {
        slot: BeaconBlock(
            slot=slot,
            parent_root=ZERO_HASH32,
            state_root=ZERO_HASH32,
            signature=EMPTY_SIGNATURE,
            body=BeaconBlockBody(),
        )
        for slot in db_block_slots
    }

    def get_canonical_block_by_slot(slot):
        if slot in mock_slot_to_block_db:
            return mock_slot_to_block_db[slot]
        else:
            raise BlockNotFound

    monkeypatch.setattr(
        node.chain, "get_canonical_block_by_slot", get_canonical_block_by_slot
    )

    result_blocks = node._get_blocks_from_canonical_chain_by_slot(
        slot_of_requested_blocks=slot_of_requested_blocks
    )

    expected_blocks = [mock_slot_to_block_db[slot] for slot in expected_block_slots]
    assert len(result_blocks) == len(expected_blocks)
    assert set(result_blocks) == set(expected_blocks)
def test_process_eth1_data(
    original_votes,
    block_data,
    expected_votes,
    sample_beacon_state_params,
    sample_beacon_block_params,
    sample_beacon_block_body_params,
    config,
):
    eth1_data_votes = tuple(mapcat(_expand_eth1_votes, original_votes))
    state = BeaconState.create(**sample_beacon_state_params).set(
        "eth1_data_votes", eth1_data_votes)

    block_body = BeaconBlockBody.create(
        **sample_beacon_block_body_params).mset(
            "eth1_data", Eth1Data.create(block_hash=block_data))

    block = BeaconBlock.create(**sample_beacon_block_params).set(
        "body", block_body)

    updated_state = process_eth1_data(state, block, config)
    updated_votes = updated_state.eth1_data_votes
    expanded_expected_votes = tuple(mapcat(_expand_eth1_votes, expected_votes))

    assert tuple(updated_votes) == expanded_expected_votes
Пример #20
0
def sample_beacon_block_params(sample_beacon_block_body_params, genesis_slot):
    return {
        "slot": genesis_slot + 10,
        "parent_root": ZERO_HASH32,
        "state_root": b"\x55" * 32,
        "body": BeaconBlockBody.create(**sample_beacon_block_body_params),
    }
Пример #21
0
def sample_beacon_block_params(sample_beacon_block_body_params, genesis_slot):
    return {
        'slot': genesis_slot + 10,
        'previous_block_root': ZERO_HASH32,
        'state_root': b'\x55' * 32,
        'signature': SAMPLE_SIGNATURE,
        'body': BeaconBlockBody(**sample_beacon_block_body_params)
    }
Пример #22
0
 async def _get_block_proposal(self, request: web.Request) -> web.Response:
     slot = Slot(int(request.query["slot"]))
     randao_reveal = BLSSignature(
         decode_hex(request.query["randao_reveal"]).ljust(96, b"\x00"))
     block = BeaconBlock.create(
         slot=slot,
         body=BeaconBlockBody.create(randao_reveal=randao_reveal))
     return web.json_response(to_formatted_dict(block))
Пример #23
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,
            )
Пример #24
0
def test_process_voluntary_exits(genesis_state, sample_beacon_block_params,
                                 sample_beacon_block_body_params, config,
                                 keymap, min_attestation_inclusion_delay,
                                 success):
    state = genesis_state
    validator_index = 0
    valid_voluntary_exit = create_mock_voluntary_exit(
        state,
        config,
        keymap,
        validator_index,
    )

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

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

        with pytest.raises(ValidationError):
            process_voluntary_exits(
                state,
                block,
                config,
            )
Пример #25
0
def sample_beacon_block_params(sample_signature,
                               sample_beacon_block_body_params, genesis_slot):
    return {
        'slot': genesis_slot + 10,
        'parent_root': ZERO_HASH32,
        'state_root': b'\x55' * 32,
        'body': BeaconBlockBody(**sample_beacon_block_body_params),
        'signature': sample_signature,
    }
Пример #26
0
def create_block_on_state(state: BeaconState, config: BeaconConfig,
                          block_class: BaseBeaconBlock,
                          parent_block: BaseBeaconBlock, slot: SlotNumber,
                          validator_index: int, privkey: int,
                          attestations: Sequence[Attestation]):
    """
    Create a beacon block with the given parameters.
    """
    # Check proposer
    beacon_proposer_index = get_beacon_proposer_index(
        state.copy(slot=slot, ),
        slot,
        config.EPOCH_LENGTH,
        config.TARGET_COMMITTEE_SIZE,
        config.SHARD_COUNT,
    )

    if validator_index != beacon_proposer_index:
        raise ProposerIndexError

    # 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,
    )

    # 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,
        SignatureDomain.DOMAIN_PROPOSAL,
    )
    block = block.copy(signature=bls.sign(
        message=proposal_root,
        privkey=privkey,
        domain=domain,
    ), )

    return block
Пример #27
0
def sample_beacon_block_params(sample_beacon_block_body_params):
    return {
        'slot': 10,
        'parent_root': ZERO_HASH32,
        'state_root': b'\x55' * 32,
        'randao_reveal': b'\x55' * 32,
        'candidate_pow_receipt_root': b'\x55' * 32,
        'signature': (0, 0),
        'body': BeaconBlockBody(**sample_beacon_block_body_params)
    }
Пример #28
0
def sample_beacon_block_params(sample_beacon_block_body_params,
                               sample_eth1_data_params):
    return {
        'slot': 10,
        'parent_root': ZERO_HASH32,
        'state_root': b'\x55' * 32,
        'randao_reveal': EMPTY_SIGNATURE,
        'eth1_data': Eth1Data(**sample_eth1_data_params),
        'signature': EMPTY_SIGNATURE,
        'body': BeaconBlockBody(**sample_beacon_block_body_params)
    }
Пример #29
0
def empty_body():
    return BeaconBlockBody(
        proposer_slashings=(),
        casper_slashings=(),
        attestations=(),
        custody_reseeds=(),
        custody_challenges=(),
        custody_responses=(),
        deposits=(),
        exits=(),
    )
Пример #30
0
def create_block_on_state(
        *,
        state: BeaconState,
        config: Eth2Config,
        state_machine: BaseBeaconStateMachine,
        block_class: Type[BaseBeaconBlock],
        parent_block: BaseBeaconBlock,
        slot: Slot,
        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 previous_block_root
    block = block_class.from_parent(
        parent_block=parent_block,
        block_params=FromBlockParams(slot=slot),
    )

    # TODO: Add more operations
    randao_reveal = _generate_randao_reveal(privkey, slot, state.fork, config)
    eth1_data = Eth1Data.create_empty_data()
    body = BeaconBlockBody.create_empty_body().copy(
        randao_reveal=randao_reveal,
        eth1_data=eth1_data,
        attestations=attestations,
    )

    block = block.copy(body=body, )

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

    # Sign
    # TODO make sure we use the correct signed_root
    signature = sign_transaction(
        message_hash=block.signed_root,
        privkey=privkey,
        fork=state.fork,
        slot=slot,
        signature_domain=SignatureDomain.DOMAIN_BEACON_BLOCK,
        slots_per_epoch=config.SLOTS_PER_EPOCH,
    )

    block = block.copy(signature=signature, )

    return block