Skip to content

Commit ef52da2

Browse files
authored
Merge pull request #1697 from ralexstokes/slashable-vote-data-cleanup
Slashable vote data cleanup
2 parents cf421d1 + 569849c commit ef52da2

File tree

1 file changed

+95
-31
lines changed

1 file changed

+95
-31
lines changed

tests/beacon/test_helpers.py

Lines changed: 95 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
denoms,
1313
ValidationError,
1414
)
15+
from eth_utils.toolz import assoc
1516

1617
from eth.constants import (
1718
ZERO_HASH32,
@@ -779,28 +780,33 @@ def test_verify_vote_count(max_casper_votes, sample_slashable_vote_data_params,
779780
assert verify_vote_count(votes, max_casper_votes)
780781

781782

782-
def _get_indices_and_signatures(num_validators, message, privkeys):
783+
def _get_indices_and_signatures(num_validators, message, privkeys, fork_data, slot):
783784
num_indices = 5
784785
assert num_validators >= num_indices
785786
indices = random.sample(range(num_validators), num_indices)
786787
privkeys = [privkeys[i] for i in indices]
787-
domain = SignatureDomain.DOMAIN_ATTESTATION
788+
domain_type = SignatureDomain.DOMAIN_ATTESTATION
789+
domain = get_domain(
790+
fork_data=fork_data,
791+
slot=slot,
792+
domain_type=domain_type,
793+
)
788794
signatures = tuple(
789795
map(lambda key: bls.sign(message, key, domain), privkeys)
790796
)
791797
return (indices, signatures)
792798

793799

794-
def _correct_slashable_vote_data_params(params, validators, messages, privkeys):
800+
def _correct_slashable_vote_data_params(num_validators, params, messages, privkeys, fork_data):
795801
valid_params = copy.deepcopy(params)
796802

797-
num_validators = len(validators)
798-
799803
key = "custody_bit_0_indices"
800804
(poc_0_indices, poc_0_signatures) = _get_indices_and_signatures(
801805
num_validators,
802806
messages[0],
803807
privkeys,
808+
fork_data,
809+
params["data"].slot,
804810
)
805811
valid_params[key] = poc_0_indices
806812

@@ -810,6 +816,8 @@ def _correct_slashable_vote_data_params(params, validators, messages, privkeys):
810816
num_validators,
811817
messages[1],
812818
privkeys,
819+
fork_data,
820+
params["data"].slot,
813821
)
814822
valid_params[key] = poc_1_indices
815823

@@ -821,23 +829,32 @@ def _correct_slashable_vote_data_params(params, validators, messages, privkeys):
821829
return valid_params
822830

823831

824-
def _corrupt_signature(params):
825-
params = copy.deepcopy(params)
832+
def _corrupt_signature(params, fork_data):
826833
message = bytes.fromhex("deadbeefcafe")
827834
privkey = 42
828-
domain = SignatureDomain.DOMAIN_ATTESTATION
829-
params["aggregate_signature"] = bls.sign(message, privkey, domain)
830-
return params
835+
domain_type = SignatureDomain.DOMAIN_ATTESTATION
836+
domain = get_domain(
837+
fork_data=fork_data,
838+
slot=params["data"].slot,
839+
domain_type=domain_type,
840+
)
841+
corrupt_signature = bls.sign(message, privkey, domain)
842+
843+
return assoc(params, "aggregate_signature", corrupt_signature)
831844

832845

833846
def _corrupt_vote_count(params):
834-
params = copy.deepcopy(params)
835847
key = "custody_bit_0_indices"
836848
for i in itertools.count():
837849
if i not in params[key]:
838-
params[key].append(i)
839-
break
840-
return params
850+
new_vote_count = params[key] + [i]
851+
return assoc(
852+
params,
853+
key,
854+
new_vote_count,
855+
)
856+
else:
857+
raise Exception("Unreachable code path")
841858

842859

843860
def _create_slashable_vote_data_messages(params):
@@ -846,27 +863,47 @@ def _create_slashable_vote_data_messages(params):
846863
return votes.messages
847864

848865

849-
def test_verify_slashable_vote_data_signature(privkeys,
866+
@pytest.mark.parametrize(
867+
(
868+
'num_validators',
869+
),
870+
[
871+
(40,),
872+
]
873+
)
874+
def test_verify_slashable_vote_data_signature(num_validators,
875+
privkeys,
850876
sample_beacon_state_params,
851877
genesis_validators,
852-
sample_slashable_vote_data_params):
853-
sample_beacon_state_params["validator_registry"] = genesis_validators
854-
state = BeaconState(**sample_beacon_state_params)
878+
sample_slashable_vote_data_params,
879+
sample_fork_data_params):
880+
beacon_state_params_with_genesis_validators = assoc(
881+
sample_beacon_state_params,
882+
"validator_registry",
883+
genesis_validators,
884+
)
885+
beacon_state_params_with_fork_data = assoc(
886+
beacon_state_params_with_genesis_validators,
887+
"fork_data",
888+
ForkData(**sample_fork_data_params),
889+
)
890+
state = BeaconState(**beacon_state_params_with_fork_data)
855891

856892
# NOTE: we can do this before "correcting" the params as they
857893
# touch disjoint subsets of the provided params
858894
messages = _create_slashable_vote_data_messages(sample_slashable_vote_data_params)
859895

860896
valid_params = _correct_slashable_vote_data_params(
897+
num_validators,
861898
sample_slashable_vote_data_params,
862-
genesis_validators,
863899
messages,
864900
privkeys,
901+
state.fork_data,
865902
)
866903
valid_votes = SlashableVoteData(**valid_params)
867904
assert verify_slashable_vote_data_signature(state, valid_votes)
868905

869-
invalid_params = _corrupt_signature(valid_params)
906+
invalid_params = _corrupt_signature(valid_params, state.fork_data)
870907
invalid_votes = SlashableVoteData(**invalid_params)
871908
assert not verify_slashable_vote_data_signature(state, invalid_votes)
872909

@@ -882,37 +919,64 @@ def _run_verify_slashable_vote(params, state, max_casper_votes, should_succeed):
882919

883920
@pytest.mark.parametrize(
884921
(
885-
'param_mapper,'
886-
'should_succeed'
922+
'num_validators',
887923
),
888924
[
889-
(lambda params: params, True),
890-
(lambda params: _corrupt_vote_count(params), False),
891-
(lambda params: _corrupt_signature(params), False),
892-
(lambda params: _corrupt_vote_count(_corrupt_signature(params)), False),
925+
(40,),
926+
]
927+
)
928+
@pytest.mark.parametrize(
929+
(
930+
'param_mapper',
931+
'should_succeed',
932+
'needs_fork_data',
933+
),
934+
[
935+
(lambda params: params, True, False),
936+
(_corrupt_vote_count, False, False),
937+
(_corrupt_signature, False, True),
938+
(lambda params, fork_data: _corrupt_vote_count(
939+
_corrupt_signature(params, fork_data)
940+
), False, True),
893941
],
894942
)
895-
def test_verify_slashable_vote_data(param_mapper,
943+
def test_verify_slashable_vote_data(num_validators,
944+
param_mapper,
896945
should_succeed,
946+
needs_fork_data,
897947
privkeys,
898948
sample_beacon_state_params,
899949
genesis_validators,
900950
sample_slashable_vote_data_params,
951+
sample_fork_data_params,
901952
max_casper_votes):
902-
sample_beacon_state_params["validator_registry"] = genesis_validators
903-
state = BeaconState(**sample_beacon_state_params)
953+
beacon_state_params_with_genesis_validators = assoc(
954+
sample_beacon_state_params,
955+
"validator_registry",
956+
genesis_validators,
957+
)
958+
beacon_state_params_with_fork_data = assoc(
959+
beacon_state_params_with_genesis_validators,
960+
"fork_data",
961+
ForkData(**sample_fork_data_params),
962+
)
963+
state = BeaconState(**beacon_state_params_with_fork_data)
904964

905965
# NOTE: we can do this before "correcting" the params as they
906966
# touch disjoint subsets of the provided params
907967
messages = _create_slashable_vote_data_messages(sample_slashable_vote_data_params)
908968

909969
params = _correct_slashable_vote_data_params(
970+
num_validators,
910971
sample_slashable_vote_data_params,
911-
genesis_validators,
912972
messages,
913973
privkeys,
974+
state.fork_data,
914975
)
915-
params = param_mapper(params)
976+
if needs_fork_data:
977+
params = param_mapper(params, state.fork_data)
978+
else:
979+
params = param_mapper(params)
916980
_run_verify_slashable_vote(params, state, max_casper_votes, should_succeed)
917981

918982

0 commit comments

Comments
 (0)