def test_randao_reveal_validation(
    is_valid,
    epoch,
    expected_epoch,
    proposer_key_index,
    expected_proposer_key_index,
    privkeys,
    pubkeys,
    sample_fork_params,
    genesis_state,
    config,
):
    state = genesis_state.set(
        "slot", compute_start_slot_at_epoch(epoch, config.SLOTS_PER_EPOCH))
    slots_per_epoch = config.SLOTS_PER_EPOCH
    domain = get_domain(state, SignatureDomain.DOMAIN_RANDAO, slots_per_epoch)
    signing_root = compute_signing_root(SerializableUint64(epoch), domain)

    proposer_privkey = privkeys[proposer_key_index]
    randao_reveal = bls.sign(proposer_privkey, signing_root)

    try:
        validate_randao_reveal(
            state=state,
            proposer_index=expected_proposer_key_index,
            epoch=expected_epoch,
            randao_reveal=randao_reveal,
            slots_per_epoch=slots_per_epoch,
        )
    except ValidationError:
        if is_valid:
            raise
    else:
        if not is_valid:
            pytest.fail("Did not raise")
예제 #2
0
def sign(duty: Duty, operation: Operation,
         private_key_provider: PrivateKeyProvider) -> BLSSignature:
    privkey = private_key_provider(duty.validator_public_key)
    # TODO use correct ``domain`` value
    # NOTE currently only uses part of the domain value
    # need to get fork from the state and compute the full domain value locally
    domain = compute_domain(duty.signature_domain)
    signing_root = compute_signing_root(operation, domain)

    return bls.sign(privkey, signing_root)
예제 #3
0
def get_block_signature(state: BeaconState, block: BeaconBlock,
                        private_key: int,
                        slots_per_epoch: int) -> BLSSignature:
    epoch = compute_epoch_at_slot(block.slot, slots_per_epoch)
    domain = get_domain(
        state,
        SignatureDomain.DOMAIN_BEACON_PROPOSER,
        slots_per_epoch,
        message_epoch=epoch,
    )
    signing_root = compute_signing_root(block, domain)
    return bls.sign(private_key, signing_root)
예제 #4
0
def validate_indexed_attestation_aggregate_signature(
        state: BeaconState, indexed_attestation: IndexedAttestation,
        slots_per_epoch: int) -> None:
    public_keys = tuple(state.validators[i].pubkey
                        for i in indexed_attestation.attesting_indices)
    domain = get_domain(
        state,
        SignatureDomain.DOMAIN_BEACON_ATTESTER,
        slots_per_epoch,
        indexed_attestation.data.target.epoch,
    )
    signing_root = compute_signing_root(indexed_attestation.data, domain)
    bls.validate(signing_root, indexed_attestation.signature, *public_keys)
예제 #5
0
def get_slot_signature(
    state: BeaconState, slot: Slot, privkey: int, config: Eth2Config
) -> BLSSignature:
    """
    Sign on ``slot`` and return the signature.
    """
    domain = get_domain(
        state,
        SignatureDomain.DOMAIN_BEACON_ATTESTER,
        config.SLOTS_PER_EPOCH,
        message_epoch=compute_epoch_at_slot(slot, config.SLOTS_PER_EPOCH),
    )
    signing_root = compute_signing_root(SerializableUint64(slot), domain)
    return bls.sign(privkey, signing_root)
예제 #6
0
def validate_aggregator_proof(
    state: BeaconState, aggregate_and_proof: AggregateAndProof, config: Eth2Config
) -> None:
    slot = aggregate_and_proof.aggregate.data.slot
    pubkey = state.validators[aggregate_and_proof.aggregator_index].pubkey
    domain = get_domain(
        state,
        SignatureDomain.DOMAIN_BEACON_ATTESTER,
        config.SLOTS_PER_EPOCH,
        message_epoch=compute_epoch_at_slot(slot, config.SLOTS_PER_EPOCH),
    )
    signing_root = compute_signing_root(SerializableUint64(slot), domain)

    bls.validate(signing_root, aggregate_and_proof.selection_proof, pubkey)
예제 #7
0
def process_deposit(state: BeaconState, deposit: Deposit,
                    config: Eth2Config) -> BeaconState:
    """
    Process a deposit from Ethereum 1.0.
    """
    validate_deposit_proof(state, deposit, DEPOSIT_CONTRACT_TREE_DEPTH)

    # Increment the next deposit index we are expecting. Note that this
    # needs to be done here because while the deposit contract will never
    # create an invalid Merkle branch, it may admit an invalid deposit
    # object, and we need to be able to skip over it
    state = state.set("eth1_deposit_index", state.eth1_deposit_index + 1)

    pubkey = deposit.data.pubkey
    amount = deposit.data.amount
    withdrawal_credentials = deposit.data.withdrawal_credentials
    validator_pubkeys = tuple(v.pubkey for v in state.validators)
    if pubkey not in validator_pubkeys:
        # Verify the deposit signature (proof of possession) for new validators.
        # Note: The deposit contract does not check signatures.
        # Note: Deposits are valid across forks, thus the deposit domain
        # is retrieved directly from `compute_domain`.
        deposit_message = DepositMessage.create(
            pubkey=pubkey,
            withdrawal_credentials=withdrawal_credentials,
            amount=amount)
        domain = compute_domain(SignatureDomain.DOMAIN_DEPOSIT,
                                fork_version=config.GENESIS_FORK_VERSION)
        signing_root = compute_signing_root(deposit_message, domain)

        is_valid_proof_of_possession = bls.verify(signing_root,
                                                  deposit.data.signature,
                                                  pubkey)

        if not is_valid_proof_of_possession:
            return state

        validator = Validator.create_pending_validator(pubkey,
                                                       withdrawal_credentials,
                                                       amount, config)

        return state.mset(
            "validators",
            state.validators.append(validator),
            "balances",
            state.balances.append(amount),
        )
    else:
        index = ValidatorIndex(validator_pubkeys.index(pubkey))
        return increase_balance(state, index, amount)
예제 #8
0
def sign(duty: Duty, operation: Operation,
         private_key_provider: PrivateKeyProvider) -> BLSSignature:
    privkey = private_key_provider(duty.validator_public_key)
    # TODO use correct ``domain`` value
    # NOTE currently only uses part of the domain value
    # need to get fork from the state and compute the full domain value locally
    # NOTE: hardcoded for testing, based on generating the minimal set of validators
    genesis_validators_root = Root(
        Hash32(
            bytes.fromhex(
                "83431ec7fcf92cfc44947fc0418e831c25e1d0806590231c439830db7ad54fda"
            )))
    domain = compute_domain(duty.signature_domain,
                            genesis_validators_root=genesis_validators_root)
    signing_root = compute_signing_root(operation, domain)

    return bls.sign(privkey, signing_root)
def _get_indices_and_signatures(validator_count, state, config, attestation,
                                privkeys):
    num_indices = 5
    assert validator_count >= num_indices
    indices = random.sample(range(validator_count), num_indices)
    indices.sort()

    privkeys = [privkeys[i] for i in indices]
    domain = get_domain(
        state=state,
        signature_domain=SignatureDomain.DOMAIN_BEACON_ATTESTER,
        slots_per_epoch=config.SLOTS_PER_EPOCH,
    )
    signing_root = compute_signing_root(attestation.data, domain)

    signatures = tuple(map(lambda key: bls.sign(key, signing_root), privkeys))
    return (indices, signatures)
예제 #10
0
def validate_proposer_signature(
    state: BeaconState, signed_block: BaseSignedBeaconBlock, config: Eth2Config
) -> None:
    # Get the public key of proposer
    beacon_proposer_index = get_beacon_proposer_index(state, config)
    proposer_pubkey = state.validators[beacon_proposer_index].pubkey
    domain = get_domain(
        state, SignatureDomain.DOMAIN_BEACON_PROPOSER, config.SLOTS_PER_EPOCH
    )
    signing_root = compute_signing_root(signed_block.message, domain)

    try:
        bls.validate(signing_root, signed_block.signature, proposer_pubkey)
    except SignatureError as error:
        raise ValidationError(
            f"Invalid Proposer Signature on block, beacon_proposer_index={beacon_proposer_index}",
            error,
        )
예제 #11
0
def validate_block_header_signature(
    state: BeaconState,
    header: SignedBeaconBlockHeader,
    pubkey: BLSPubkey,
    slots_per_epoch: int,
) -> None:
    domain = get_domain(
        state,
        SignatureDomain.DOMAIN_BEACON_PROPOSER,
        slots_per_epoch,
        compute_epoch_at_slot(header.message.slot, slots_per_epoch),
    )
    signing_root = compute_signing_root(header.message, domain)

    try:
        bls.validate(signing_root, header.signature, pubkey)
    except SignatureError as error:
        raise ValidationError("Header signature is invalid:", error)
예제 #12
0
def sign_transaction(
    *,
    object: ssz.Serializable,
    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=compute_epoch_at_slot(slot, slots_per_epoch),
    )
    signing_root = compute_signing_root(object, domain)

    return bls.sign(privkey, signing_root)
예제 #13
0
 def _randao_provider_of_epoch_signature(
     public_key: BLSPubkey, epoch: Epoch
 ) -> BLSSignature:
     privkey = private_key_provider(public_key)
     # NOTE: hardcoded for testing, based on generating the minimal set of validators
     genesis_validators_root = Root(
         Hash32(
             bytes.fromhex(
                 "83431ec7fcf92cfc44947fc0418e831c25e1d0806590231c439830db7ad54fda"
             )
         )
     )
     domain = compute_domain(
         SignatureDomain.DOMAIN_RANDAO,
         genesis_validators_root=genesis_validators_root,
     )
     signing_root = compute_signing_root(SerializableUint64(epoch), domain)
     return bls.sign(privkey, signing_root)
예제 #14
0
def validate_randao_reveal(
    state: BeaconState,
    proposer_index: int,
    epoch: Epoch,
    randao_reveal: BLSSignature,
    slots_per_epoch: int,
) -> None:
    proposer = state.validators[proposer_index]
    proposer_pubkey = proposer.pubkey
    domain = get_domain(state, SignatureDomain.DOMAIN_RANDAO, slots_per_epoch)

    signing_root = compute_signing_root(SerializableUint64(epoch), domain)

    try:
        bls.validate(signing_root, randao_reveal, proposer_pubkey)
    except SignatureError as error:
        raise ValidationError(
            f"RANDAO reveal is invalid for proposer index {proposer_index} at slot {state.slot}",
            error,
        )
예제 #15
0
def _validate_voluntary_exit_signature(
    state: BeaconState,
    signed_voluntary_exit: SignedVoluntaryExit,
    validator: Validator,
    slots_per_epoch: int,
) -> None:
    voluntary_exit = signed_voluntary_exit.message
    domain = get_domain(
        state,
        SignatureDomain.DOMAIN_VOLUNTARY_EXIT,
        slots_per_epoch,
        voluntary_exit.epoch,
    )
    signing_root = compute_signing_root(voluntary_exit, domain)

    try:
        bls.validate(signing_root, signed_voluntary_exit.signature, validator.pubkey)
    except SignatureError as error:
        raise ValidationError(
            f"Invalid VoluntaryExit signature, validator_index={voluntary_exit.validator_index}",
            error,
        )
def test_validate_proposer_signature(
    slots_per_epoch,
    max_committees_per_slot,
    proposer_privkey,
    proposer_pubkey,
    is_valid_signature,
    sample_beacon_block_params,
    sample_beacon_state_params,
    target_committee_size,
    max_effective_balance,
    config,
):

    state = BeaconState.create(**sample_beacon_state_params).mset(
        "validators",
        tuple(
            create_mock_validator(proposer_pubkey, config) for _ in range(10)),
        "balances",
        (max_effective_balance, ) * 10,
    )

    block = BeaconBlock.create(**sample_beacon_block_params)
    domain = get_domain(state, SignatureDomain.DOMAIN_BEACON_PROPOSER,
                        slots_per_epoch)
    signing_root = compute_signing_root(block, domain)

    proposed_block = SignedBeaconBlock.create(message=block,
                                              signature=bls.sign(
                                                  proposer_privkey,
                                                  signing_root))

    if is_valid_signature:
        validate_proposer_signature(state, proposed_block, config)
    else:
        with pytest.raises(ValidationError):
            validate_proposer_signature(state, proposed_block, config)
예제 #17
0
 def _randao_provider_of_epoch_signature(public_key: BLSPubkey,
                                         epoch: Epoch) -> BLSSignature:
     privkey = private_key_provider(public_key)
     domain = compute_domain(SignatureDomain.DOMAIN_RANDAO)
     signing_root = compute_signing_root(SerializableUint64(epoch), domain)
     return bls.sign(privkey, signing_root)
예제 #18
0
def sign_proof_of_possession(deposit_message: DepositMessage,
                             privkey: int) -> BLSSignature:
    domain = compute_domain(SignatureDomain.DOMAIN_DEPOSIT)
    signing_root = compute_signing_root(deposit_message, domain)

    return bls.sign(privkey, signing_root)