Beispiel #1
0
def validate_proposer_signature(state: BeaconState, block: BaseBeaconBlock,
                                beacon_chain_shard_number: ShardNumber,
                                committee_config: CommitteeConfig) -> None:
    block_without_signature_root = block.block_without_signature_root

    # TODO: Replace this root with tree hash root
    proposal_root = ProposalSignedData(
        state.slot,
        beacon_chain_shard_number,
        block_without_signature_root,
    ).root

    # Get the public key of proposer
    beacon_proposer_index = get_beacon_proposer_index(
        state,
        state.slot,
        committee_config,
    )
    proposer_pubkey = state.validator_registry[beacon_proposer_index].pubkey
    domain = get_domain(state.fork,
                        state.current_epoch(committee_config.EPOCH_LENGTH),
                        SignatureDomain.DOMAIN_PROPOSAL)

    is_valid_signature = bls.verify(
        pubkey=proposer_pubkey,
        message=proposal_root,
        signature=block.signature,
        domain=domain,
    )

    if not is_valid_signature:
        raise ValidationError(
            f"Invalid Proposer Signature on block, beacon_proposer_index={beacon_proposer_index}, "
            f"pubkey={proposer_pubkey}, message={proposal_root},"
            f"block.signature={block.signature}, domain={domain}")
Beispiel #2
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
Beispiel #3
0
def validate_serenity_proposer_signature(
        state: BeaconState, block: BaseBeaconBlock,
        beacon_chain_shard_number: ShardNumber, epoch_length: int) -> None:
    block_without_signature_root = block.block_without_signature_root

    # TODO: Replace this root with tree hash root
    proposal_root = ProposalSignedData(
        state.slot,
        beacon_chain_shard_number,
        block_without_signature_root,
    ).root

    # Get the public key of proposer
    beacon_proposer_index = get_beacon_proposer_index(state, state.slot,
                                                      epoch_length)
    proposer_pubkey = state.validator_registry[beacon_proposer_index].pubkey

    is_valid_signature = bls.verify(
        pubkey=proposer_pubkey,
        message=proposal_root,
        signature=block.signature,
        domain=get_domain(state.fork_data, state.slot,
                          SignatureDomain.DOMAIN_PROPOSAL),
    )

    if not is_valid_signature:
        raise ValidationError("Invalid Proposer Signature on block")
Beispiel #4
0
def sample_proposer_slashing_params(sample_proposal_signed_data_params):
    proposal_data = ProposalSignedData(**sample_proposal_signed_data_params)
    return {
        'proposer_index': 1,
        'proposal_data_1': proposal_data,
        'proposal_signature_1': EMPTY_SIGNATURE,
        'proposal_data_2': proposal_data,
        'proposal_signature_2': EMPTY_SIGNATURE,
    }
Beispiel #5
0
def sample_proposer_slashing_params(sample_proposal_signed_data_params):
    proposal_data = ProposalSignedData(**sample_proposal_signed_data_params)
    return {
        'proposer_index': 1,
        'proposal_data_1': proposal_data,
        'proposal_signature_1': (1, 2, 3),
        'proposal_data_2': proposal_data,
        'proposal_signature_2': (4, 5, 6),
    }
Beispiel #6
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
Beispiel #7
0
def test_validate_serenity_proposer_signature(
        proposer_privkey, proposer_pubkey, is_valid_signature,
        sample_beacon_block_params, sample_beacon_state_params,
        sample_shard_committee_params, beacon_chain_shard_number, epoch_length,
        max_deposit):

    state = BeaconState(**sample_beacon_state_params).copy(
        validator_registry=tuple(
            mock_validator_record(proposer_pubkey) for _ in range(10)),
        validator_balances=(max_deposit * GWEI_PER_ETH, ) * 10,
        shard_committees_at_slots=get_sample_shard_committees_at_slots(
            num_slot=128,
            num_shard_committee_per_slot=10,
            sample_shard_committee_params=sample_shard_committee_params,
        ),
    )

    default_block = BeaconBlock(**sample_beacon_block_params)
    empty_signature_block_root = default_block.block_without_signature_root

    proposal_root = ProposalSignedData(
        state.slot,
        beacon_chain_shard_number,
        empty_signature_block_root,
    ).root

    proposed_block = BeaconBlock(**sample_beacon_block_params).copy(
        signature=bls.sign(
            message=proposal_root,
            privkey=proposer_privkey,
            domain=SignatureDomain.DOMAIN_PROPOSAL,
        ), )

    if is_valid_signature:
        validate_serenity_proposer_signature(
            state,
            proposed_block,
            beacon_chain_shard_number,
            epoch_length,
        )
    else:
        with pytest.raises(ValidationError):
            validate_serenity_proposer_signature(
                state,
                proposed_block,
                beacon_chain_shard_number,
                epoch_length,
            )
def test_validate_proposer_signature(
        epoch_length, shard_count, proposer_privkey, proposer_pubkey,
        is_valid_signature, sample_beacon_block_params,
        sample_beacon_state_params, beacon_chain_shard_number, genesis_epoch,
        target_committee_size, max_deposit_amount, config):

    state = BeaconState(**sample_beacon_state_params).copy(
        validator_registry=tuple(
            mock_validator_record(proposer_pubkey) for _ in range(10)),
        validator_balances=(max_deposit_amount, ) * 10,
    )

    default_block = BeaconBlock(**sample_beacon_block_params)
    empty_signature_block_root = default_block.block_without_signature_root

    proposal_root = ProposalSignedData(
        state.slot,
        beacon_chain_shard_number,
        empty_signature_block_root,
    ).root

    proposed_block = BeaconBlock(**sample_beacon_block_params).copy(
        signature=bls.sign(
            message=proposal_root,
            privkey=proposer_privkey,
            domain=SignatureDomain.DOMAIN_PROPOSAL,
        ), )

    if is_valid_signature:
        validate_proposer_signature(
            state,
            proposed_block,
            beacon_chain_shard_number,
            CommitteeConfig(config),
        )
    else:
        with pytest.raises(ValidationError):
            validate_proposer_signature(
                state,
                proposed_block,
                beacon_chain_shard_number,
                CommitteeConfig(config),
            )
Beispiel #9
0
def test_demo(base_db, sample_beacon_block_params, genesis_state,
              fixture_sm_class, config, privkeys, pubkeys):
    chaindb = BeaconChainDB(base_db)
    state = genesis_state
    block = SerenityBeaconBlock(**sample_beacon_block_params).copy(
        slot=state.slot + 2,
        state_root=state.root,
    )

    # Sign block
    beacon_proposer_index = get_beacon_proposer_index(
        state,
        block.slot,
        config.EPOCH_LENGTH,
    )
    index_in_privkeys = pubkeys.index(
        state.validator_registry[beacon_proposer_index].pubkey)
    beacon_proposer_privkey = privkeys[index_in_privkeys]
    empty_signature_block_root = block.block_without_signature_root
    proposal_root = ProposalSignedData(
        block.slot,
        config.BEACON_CHAIN_SHARD_NUMBER,
        empty_signature_block_root,
    ).root
    block = block.copy(signature=bls.sign(
        message=proposal_root,
        privkey=beacon_proposer_privkey,
        domain=SignatureDomain.DOMAIN_PROPOSAL,
    ), )

    # Store in chaindb
    chaindb.persist_block(block, SerenityBeaconBlock)
    chaindb.persist_state(state)

    # Get state machine instance
    sm = fixture_sm_class(chaindb, block.root, SerenityBeaconBlock)
    result_state, _ = sm.import_block(block)

    assert state.slot == 0
    assert result_state.slot == block.slot
    assert isinstance(sm.block, SerenityBeaconBlock)
def test_defaults(sample_proposal_signed_data_params):
    proposal_signed_data = ProposalSignedData(**sample_proposal_signed_data_params)
    assert proposal_signed_data.slot == sample_proposal_signed_data_params['slot']
    assert proposal_signed_data.shard == sample_proposal_signed_data_params['shard']
    assert proposal_signed_data.block_root == sample_proposal_signed_data_params['block_root']