diff --git a/tests/core/pyspec/eth2spec/test/helpers/deposits.py b/tests/core/pyspec/eth2spec/test/helpers/deposits.py index dae05c2ebe..18929b1d79 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/deposits.py +++ b/tests/core/pyspec/eth2spec/test/helpers/deposits.py @@ -137,14 +137,21 @@ def prepare_random_genesis_deposits(spec, return deposits, root, deposit_data_list -def prepare_state_and_deposit(spec, state, validator_index, amount, withdrawal_credentials=None, signed=False): +def prepare_state_and_deposit(spec, state, validator_index, amount, + pubkey=None, + privkey=None, + withdrawal_credentials=None, + signed=False): """ Prepare the state for the deposit, and create a deposit for the given validator, depositing the given amount. """ deposit_data_list = [] - pubkey = pubkeys[validator_index] - privkey = privkeys[validator_index] + if pubkey is None: + pubkey = pubkeys[validator_index] + + if privkey is None: + privkey = privkeys[validator_index] # insecurely use pubkey as withdrawal key if no credentials provided if withdrawal_credentials is None: @@ -196,7 +203,7 @@ def run_deposit_processing(spec, state, deposit, validator_index, valid=True, ef yield 'post', state - if not effective: + if not effective or not bls.KeyValidate(deposit.data.pubkey): assert len(state.validators) == pre_validator_count assert len(state.balances) == pre_validator_count if validator_index < pre_validator_count: diff --git a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_deposit.py b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_deposit.py index df0bd2a17c..8922032b41 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_deposit.py +++ b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_deposit.py @@ -233,3 +233,33 @@ def test_bad_merkle_proof(spec, state): sign_deposit_data(spec, deposit.data, privkeys[validator_index]) yield from run_deposit_processing(spec, state, deposit, validator_index, valid=False) + + +@with_all_phases +@spec_state_test +def test_key_validate_invalid_subgroup(spec, state): + validator_index = len(state.validators) + amount = spec.MAX_EFFECTIVE_BALANCE + + # All-zero pubkey would not pass `bls.KeyValidate`, but `process_deposit` would not throw exception. + pubkey = b'\x00' * 48 + + deposit = prepare_state_and_deposit(spec, state, validator_index, amount, pubkey=pubkey, signed=True) + + yield from run_deposit_processing(spec, state, deposit, validator_index) + + +@with_all_phases +@spec_state_test +def test_key_validate_invalid_decompression(spec, state): + validator_index = len(state.validators) + amount = spec.MAX_EFFECTIVE_BALANCE + + # `deserialization_fails_infinity_with_true_b_flag` BLS G1 deserialization test case. + # This pubkey would not pass `bls.KeyValidate`, but `process_deposit` would not throw exception. + pubkey_hex = 'c01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' + pubkey = bytes.fromhex(pubkey_hex) + + deposit = prepare_state_and_deposit(spec, state, validator_index, amount, pubkey=pubkey, signed=True) + + yield from run_deposit_processing(spec, state, deposit, validator_index) diff --git a/tests/core/pyspec/eth2spec/utils/bls.py b/tests/core/pyspec/eth2spec/utils/bls.py index e33017ade5..fd5fd89bfb 100644 --- a/tests/core/pyspec/eth2spec/utils/bls.py +++ b/tests/core/pyspec/eth2spec/utils/bls.py @@ -138,3 +138,8 @@ def pairing_check(values): * pairing(p_q_2[1], p_q_2[0], final_exponentiate=False) ) return final_exponentiation == FQ12.one() + + +@only_with_bls(alt_return=True) +def KeyValidate(pubkey): + return py_ecc_bls.KeyValidate(pubkey)