Beispiel #1
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 #2
0
def sign_proof_of_possession(deposit_input, privkey, fork_data, slot):
    domain = get_domain(
        fork_data,
        slot,
        SignatureDomain.DOMAIN_DEPOSIT,
    )
    return bls.sign(deposit_input.root, privkey, domain)
Beispiel #3
0
    def create_mock_signed_attestation(state, shard_committee,
                                       voting_committee_indices,
                                       attestation_data):
        message = hash_eth2(
            rlp.encode(attestation_data) + (0).to_bytes(1, "big"))
        # participants sign message
        signatures = [
            bls.sign(message,
                     privkeys[shard_committee.committee[committee_index]],
                     domain=get_domain(
                         fork_data=state.fork_data,
                         slot=attestation_data.slot,
                         domain_type=SignatureDomain.DOMAIN_ATTESTATION,
                     )) for committee_index in voting_committee_indices
        ]

        # aggregate signatures and construct participant bitfield
        participation_bitfield, aggregate_signature = aggregate_votes(
            bitfield=get_empty_bitfield(len(shard_committee.committee)),
            sigs=(),
            voting_sigs=signatures,
            voting_committee_indices=voting_committee_indices,
        )

        # create attestation from attestation_data, particpipant_bitfield, and signature
        return Attestation(
            data=attestation_data,
            participation_bitfield=participation_bitfield,
            custody_bitfield=b'',
            aggregate_signature=aggregate_signature,
        )
Beispiel #4
0
def validate_proof_of_possession(state: BeaconState, pubkey: BLSPubkey,
                                 proof_of_possession: BLSSignature,
                                 withdrawal_credentials: Hash32,
                                 randao_commitment: Hash32) -> None:
    deposit_input = DepositInput(
        pubkey=pubkey,
        withdrawal_credentials=withdrawal_credentials,
        randao_commitment=randao_commitment,
        proof_of_possession=EMPTY_SIGNATURE,
    )

    is_valid_signature = bls.verify(
        pubkey=pubkey,
        # TODO: change to hash_tree_root(deposit_input) when we have SSZ tree hashing
        message=deposit_input.root,
        signature=proof_of_possession,
        domain=get_domain(
            state.fork_data,
            state.slot,
            SignatureDomain.DOMAIN_DEPOSIT,
        ),
    )

    if not is_valid_signature:
        raise ValidationError("BLS signature verification error")
Beispiel #5
0
def test_get_domain(pre_fork_version, post_fork_version, fork_slot,
                    current_slot, domain_type, expected):
    fork_data = ForkData(
        pre_fork_version=pre_fork_version,
        post_fork_version=post_fork_version,
        fork_slot=fork_slot,
    )
    assert expected == get_domain(
        fork_data=fork_data,
        slot=current_slot,
        domain_type=domain_type,
    )
Beispiel #6
0
def _corrupt_signature(params, fork_data):
    message = bytes.fromhex("deadbeefcafe")
    privkey = 42
    domain_type = SignatureDomain.DOMAIN_ATTESTATION
    domain = get_domain(
        fork_data=fork_data,
        slot=params["data"].slot,
        domain_type=domain_type,
    )
    corrupt_signature = bls.sign(message, privkey, domain)

    return assoc(params, "aggregate_signature", corrupt_signature)
Beispiel #7
0
def _get_indices_and_signatures(num_validators, message, privkeys, fork_data,
                                slot):
    num_indices = 5
    assert num_validators >= num_indices
    indices = random.sample(range(num_validators), num_indices)
    privkeys = [privkeys[i] for i in indices]
    domain_type = SignatureDomain.DOMAIN_ATTESTATION
    domain = get_domain(
        fork_data=fork_data,
        slot=slot,
        domain_type=domain_type,
    )
    signatures = tuple(
        map(lambda key: bls.sign(message, key, domain), privkeys))
    return (indices, signatures)
def test_validate_proof_of_possession(sample_beacon_state_params, pubkeys,
                                      privkeys, expected):
    state = BeaconState(**sample_beacon_state_params)

    privkey = privkeys[0]
    pubkey = pubkeys[0]
    withdrawal_credentials = b'\x34' * 32
    custody_commitment = b'\x12' * 32
    randao_commitment = b'\x56' * 32
    domain = get_domain(
        state.fork_data,
        state.slot,
        SignatureDomain.DOMAIN_DEPOSIT,
    )

    deposit_input = make_deposit_input(
        pubkey=pubkey,
        withdrawal_credentials=withdrawal_credentials,
        randao_commitment=randao_commitment,
        custody_commitment=custody_commitment,
    )
    if expected is True:
        proof_of_possession = sign_proof_of_possession(deposit_input, privkey,
                                                       domain)

        validate_proof_of_possession(
            state=state,
            pubkey=pubkey,
            proof_of_possession=proof_of_possession,
            withdrawal_credentials=withdrawal_credentials,
            randao_commitment=randao_commitment,
            custody_commitment=custody_commitment,
        )
    else:
        proof_of_possession = b'\x11' * 32
        with pytest.raises(ValidationError):
            validate_proof_of_possession(
                state=state,
                pubkey=pubkey,
                proof_of_possession=proof_of_possession,
                withdrawal_credentials=withdrawal_credentials,
                randao_commitment=randao_commitment,
                custody_commitment=custody_commitment,
            )
Beispiel #9
0
def validate_serenity_attestation_aggregate_signature(
        state: BeaconState, attestation: Attestation,
        epoch_length: 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,
        slot=attestation.data.slot,
        shard=attestation.data.shard,
        participation_bitfield=attestation.participation_bitfield,
        epoch_length=epoch_length,
    )

    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
    # TODO: Replace with AttestationAndCustodyBit data structure
    message = hash_eth2(rlp.encode(attestation.data) + (0).to_bytes(1, "big"))

    is_valid_signature = bls.verify(
        message=message,
        pubkey=group_public_key,
        signature=attestation.aggregate_signature,
        domain=get_domain(
            fork_data=state.fork_data,
            slot=attestation.data.slot,
            domain_type=SignatureDomain.DOMAIN_ATTESTATION,
        ),
    )
    if not is_valid_signature:
        raise ValidationError(
            "Attestation ``aggregate_signature`` is invalid.")
def test_process_deposit(sample_beacon_state_params,
                         zero_balance_validator_ttl, privkeys, pubkeys):
    state = BeaconState(**sample_beacon_state_params).copy(
        slot=zero_balance_validator_ttl + 1,
        validator_registry=(),
    )

    privkey_1 = privkeys[0]
    pubkey_1 = pubkeys[0]
    deposit = 32 * denoms.gwei
    withdrawal_credentials = b'\x34' * 32
    custody_commitment = b'\x11' * 32
    randao_commitment = b'\x56' * 32
    domain = get_domain(
        state.fork_data,
        state.slot,
        SignatureDomain.DOMAIN_DEPOSIT,
    )

    deposit_input = make_deposit_input(
        pubkey=pubkey_1,
        withdrawal_credentials=withdrawal_credentials,
        randao_commitment=randao_commitment,
        custody_commitment=custody_commitment,
    )
    proof_of_possession = sign_proof_of_possession(deposit_input, privkey_1,
                                                   domain)
    # Add the first validator
    result_state, index = process_deposit(
        state=state,
        pubkey=pubkey_1,
        deposit=deposit,
        proof_of_possession=proof_of_possession,
        withdrawal_credentials=withdrawal_credentials,
        randao_commitment=randao_commitment,
        custody_commitment=custody_commitment,
        zero_balance_validator_ttl=zero_balance_validator_ttl,
    )

    assert len(result_state.validator_registry) == 1
    index = 0
    assert result_state.validator_registry[0].pubkey == pubkey_1
    assert result_state.validator_registry[
        index].withdrawal_credentials == withdrawal_credentials
    assert result_state.validator_registry[
        index].randao_commitment == randao_commitment
    assert result_state.validator_balances[index] == deposit
    # test immutable
    assert len(state.validator_registry) == 0

    # Add the second validator
    privkey_2 = privkeys[1]
    pubkey_2 = pubkeys[1]
    deposit_input = make_deposit_input(
        pubkey=pubkey_2,
        withdrawal_credentials=withdrawal_credentials,
        randao_commitment=randao_commitment,
        custody_commitment=custody_commitment,
    )
    proof_of_possession = sign_proof_of_possession(deposit_input, privkey_2,
                                                   domain)
    result_state, index = process_deposit(
        state=result_state,
        pubkey=pubkey_2,
        deposit=deposit,
        proof_of_possession=proof_of_possession,
        withdrawal_credentials=withdrawal_credentials,
        randao_commitment=randao_commitment,
        custody_commitment=custody_commitment,
        zero_balance_validator_ttl=zero_balance_validator_ttl,
    )
    assert len(result_state.validator_registry) == 2
    assert result_state.validator_registry[1].pubkey == pubkey_2

    # Force the first validator exited -> a empty slot in state.validator_registry.
    result_state = result_state.copy(validator_registry=(
        result_state.validator_registry[0].copy(latest_status_change_slot=0, ),
        result_state.validator_registry[1],
    ),
                                     validator_balances=(0, ) +
                                     result_state.validator_balances[1:])

    # Add the third validator.
    # Should overwrite previously exited validator.
    privkey_3 = privkeys[2]
    pubkey_3 = pubkeys[2]
    deposit_input = make_deposit_input(
        pubkey=pubkey_3,
        withdrawal_credentials=withdrawal_credentials,
        randao_commitment=randao_commitment,
        custody_commitment=custody_commitment,
    )
    proof_of_possession = sign_proof_of_possession(deposit_input, privkey_3,
                                                   domain)
    result_state, index = process_deposit(
        state=result_state,
        pubkey=pubkey_3,
        deposit=deposit,
        proof_of_possession=proof_of_possession,
        withdrawal_credentials=withdrawal_credentials,
        randao_commitment=randao_commitment,
        custody_commitment=custody_commitment,
        zero_balance_validator_ttl=zero_balance_validator_ttl,
    )
    # Overwrite the second validator.
    assert len(result_state.validator_registry) == 2
    assert result_state.validator_registry[0].pubkey == pubkey_3