Skip to content

Commit

Permalink
Merge pull request #839 from ethereum/output-sanity-tests
Browse files Browse the repository at this point in the history
cleanup tests to more easily dump output
  • Loading branch information
djrtwo authored Mar 25, 2019
2 parents 729757d + 65b1b85 commit 7db21e3
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 47 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
/.pytest_cache

build/
output/
Empty file added tests/phase0/__init__.py
Empty file.
18 changes: 13 additions & 5 deletions tests/phase0/block_processing/test_process_deposit.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,24 @@
import build.phase0.spec as spec

from build.phase0.spec import (
Deposit,
ZERO_HASH,
process_deposit,
)
from tests.phase0.helpers import (
build_deposit,
privkeys,
pubkeys,
)


# mark entire file as 'voluntary_exits'
pytestmark = pytest.mark.voluntary_exits


def test_success(state, deposit_data_leaves, pubkeys, privkeys):
def test_success(state):
pre_state = deepcopy(state)
# fill previous deposits with zero-hash
deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry)

index = len(deposit_data_leaves)
pubkey = pubkeys[index]
Expand Down Expand Up @@ -45,8 +49,9 @@ def test_success(state, deposit_data_leaves, pubkeys, privkeys):
return pre_state, deposit, post_state


def test_success_top_up(state, deposit_data_leaves, pubkeys, privkeys):
def test_success_top_up(state):
pre_state = deepcopy(state)
deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry)

validator_index = 0
amount = spec.MAX_DEPOSIT_AMOUNT // 4
Expand Down Expand Up @@ -76,8 +81,10 @@ def test_success_top_up(state, deposit_data_leaves, pubkeys, privkeys):
return pre_state, deposit, post_state


def test_wrong_index(state, deposit_data_leaves, pubkeys, privkeys):
def test_wrong_index(state):
pre_state = deepcopy(state)
deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry)


index = len(deposit_data_leaves)
pubkey = pubkeys[index]
Expand All @@ -104,8 +111,9 @@ def test_wrong_index(state, deposit_data_leaves, pubkeys, privkeys):
return pre_state, deposit, None


def test_bad_merkle_proof(state, deposit_data_leaves, pubkeys, privkeys):
def test_bad_merkle_proof(state):
pre_state = deepcopy(state)
deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry)

index = len(deposit_data_leaves)
pubkey = pubkeys[index]
Expand Down
21 changes: 11 additions & 10 deletions tests/phase0/block_processing/test_voluntary_exit.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@
)
from tests.phase0.helpers import (
build_voluntary_exit,
pubkey_to_privkey,
)


# mark entire file as 'voluntary_exits'
pytestmark = pytest.mark.voluntary_exits


def test_success(state, pub_to_priv):
def test_success(state):
pre_state = deepcopy(state)
#
# setup pre_state
Expand All @@ -30,7 +31,7 @@ def test_success(state, pub_to_priv):
#
current_epoch = get_current_epoch(pre_state)
validator_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[0]
privkey = pub_to_priv[pre_state.validator_registry[validator_index].pubkey]
privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey]

voluntary_exit = build_voluntary_exit(
pre_state,
Expand All @@ -52,11 +53,11 @@ def test_success(state, pub_to_priv):
return pre_state, voluntary_exit, post_state


def test_validator_not_active(state, pub_to_priv):
def test_validator_not_active(state):
pre_state = deepcopy(state)
current_epoch = get_current_epoch(pre_state)
validator_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[0]
privkey = pub_to_priv[pre_state.validator_registry[validator_index].pubkey]
privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey]

#
# setup pre_state
Expand All @@ -79,7 +80,7 @@ def test_validator_not_active(state, pub_to_priv):
return pre_state, voluntary_exit, None


def test_validator_already_exited(state, pub_to_priv):
def test_validator_already_exited(state):
pre_state = deepcopy(state)
#
# setup pre_state
Expand All @@ -89,7 +90,7 @@ def test_validator_already_exited(state, pub_to_priv):

current_epoch = get_current_epoch(pre_state)
validator_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[0]
privkey = pub_to_priv[pre_state.validator_registry[validator_index].pubkey]
privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey]

# but validator already has exited
pre_state.validator_registry[validator_index].exit_epoch = current_epoch + 2
Expand All @@ -110,7 +111,7 @@ def test_validator_already_exited(state, pub_to_priv):
return pre_state, voluntary_exit, None


def test_validator_already_initiated_exit(state, pub_to_priv):
def test_validator_already_initiated_exit(state):
pre_state = deepcopy(state)
#
# setup pre_state
Expand All @@ -120,7 +121,7 @@ def test_validator_already_initiated_exit(state, pub_to_priv):

current_epoch = get_current_epoch(pre_state)
validator_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[0]
privkey = pub_to_priv[pre_state.validator_registry[validator_index].pubkey]
privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey]

# but validator already has initiated exit
pre_state.validator_registry[validator_index].initiated_exit = True
Expand All @@ -141,14 +142,14 @@ def test_validator_already_initiated_exit(state, pub_to_priv):
return pre_state, voluntary_exit, None


def test_validator_not_active_long_enough(state, pub_to_priv):
def test_validator_not_active_long_enough(state):
pre_state = deepcopy(state)
#
# setup pre_state
#
current_epoch = get_current_epoch(pre_state)
validator_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[0]
privkey = pub_to_priv[pre_state.validator_registry[validator_index].pubkey]
privkey = pubkey_to_privkey[pre_state.validator_registry[validator_index].pubkey]

# but validator already has initiated exit
pre_state.validator_registry[validator_index].initiated_exit = True
Expand Down
18 changes: 0 additions & 18 deletions tests/phase0/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
from build.phase0 import spec

from tests.phase0.helpers import (
privkeys_list,
pubkeys_list,
pubkey_to_privkey,
create_genesis_state,
)

Expand All @@ -25,21 +22,6 @@
}


@pytest.fixture
def privkeys():
return privkeys_list


@pytest.fixture
def pubkeys():
return pubkeys_list


@pytest.fixture
def pub_to_priv():
return pubkey_to_privkey


def overwrite_spec_config(config):
for field in config:
setattr(spec, field, config[field])
Expand Down
14 changes: 8 additions & 6 deletions tests/phase0/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,20 @@
)


privkeys_list = [i + 1 for i in range(1000)]
pubkeys_list = [bls.privtopub(privkey) for privkey in privkeys_list]
pubkey_to_privkey = {pubkey: privkey for privkey, pubkey in zip(privkeys_list, pubkeys_list)}
privkeys = [i + 1 for i in range(1000)]
pubkeys = [bls.privtopub(privkey) for privkey in privkeys]
pubkey_to_privkey = {pubkey: privkey for privkey, pubkey in zip(privkeys, pubkeys)}


def create_mock_genesis_validator_deposits(num_validators, deposit_data_leaves):
def create_mock_genesis_validator_deposits(num_validators, deposit_data_leaves=None):
if not deposit_data_leaves:
deposit_data_leaves = []
deposit_timestamp = 0
proof_of_possession = b'\x33' * 96

deposit_data_list = []
for i in range(num_validators):
pubkey = pubkeys_list[i]
pubkey = pubkeys[i]
deposit_data = DepositData(
amount=spec.MAX_DEPOSIT_AMOUNT,
timestamp=deposit_timestamp,
Expand Down Expand Up @@ -71,7 +73,7 @@ def create_mock_genesis_validator_deposits(num_validators, deposit_data_leaves):
return genesis_validator_deposits, root


def create_genesis_state(num_validators, deposit_data_leaves):
def create_genesis_state(num_validators, deposit_data_leaves=None):
initial_deposits, deposit_root = create_mock_genesis_validator_deposits(
num_validators,
deposit_data_leaves,
Expand Down
18 changes: 10 additions & 8 deletions tests/phase0/test_sanity.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
build_attestation_data,
build_deposit_data,
build_empty_block_for_next_slot,
privkeys,
pubkeys,
)


Expand Down Expand Up @@ -112,7 +114,7 @@ def test_empty_epoch_transition_not_finalizing(state):
return state, [block], test_state


def test_proposer_slashing(state, pubkeys, privkeys):
def test_proposer_slashing(state):
test_state = deepcopy(state)
current_epoch = get_current_epoch(test_state)
validator_index = get_active_validator_indices(test_state.validator_registry, current_epoch)[-1]
Expand Down Expand Up @@ -172,9 +174,9 @@ def test_proposer_slashing(state, pubkeys, privkeys):
return state, [block], test_state


def test_deposit_in_block(state, deposit_data_leaves, pubkeys, privkeys):
def test_deposit_in_block(state):
pre_state = deepcopy(state)
test_deposit_data_leaves = deepcopy(deposit_data_leaves)
test_deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry)

index = len(test_deposit_data_leaves)
pubkey = pubkeys[index]
Expand Down Expand Up @@ -207,9 +209,9 @@ def test_deposit_in_block(state, deposit_data_leaves, pubkeys, privkeys):
return pre_state, [block], post_state


def test_deposit_top_up(state, pubkeys, privkeys, deposit_data_leaves):
def test_deposit_top_up(state):
pre_state = deepcopy(state)
test_deposit_data_leaves = deepcopy(deposit_data_leaves)
test_deposit_data_leaves = [ZERO_HASH] * len(pre_state.validator_registry)

validator_index = 0
amount = spec.MAX_DEPOSIT_AMOUNT // 4
Expand Down Expand Up @@ -245,7 +247,7 @@ def test_deposit_top_up(state, pubkeys, privkeys, deposit_data_leaves):
return pre_state, [block], post_state


def test_attestation(state, pubkeys, privkeys):
def test_attestation(state):
test_state = deepcopy(state)
slot = state.slot
shard = state.current_shuffling_start_shard
Expand Down Expand Up @@ -314,7 +316,7 @@ def test_attestation(state, pubkeys, privkeys):
return state, [attestation_block, epoch_block], test_state


def test_voluntary_exit(state, pubkeys, privkeys):
def test_voluntary_exit(state):
pre_state = deepcopy(state)
validator_index = get_active_validator_indices(pre_state.validator_registry, get_current_epoch(pre_state))[-1]

Expand Down Expand Up @@ -363,7 +365,7 @@ def test_voluntary_exit(state, pubkeys, privkeys):
return pre_state, [initiate_exit_block, exit_block], post_state


def test_transfer(state, pubkeys, privkeys):
def test_transfer(state):
pre_state = deepcopy(state)
current_epoch = get_current_epoch(pre_state)
sender_index = get_active_validator_indices(pre_state.validator_registry, current_epoch)[-1]
Expand Down
52 changes: 52 additions & 0 deletions utils/phase0/jsonize.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from .minimal_ssz import hash_tree_root


def jsonize(value, typ, include_hash_tree_roots=False):
if isinstance(typ, str) and typ[:4] == 'uint':
return value
elif typ == 'bool':
assert value in (True, False)
return value
elif isinstance(typ, list):
return [jsonize(element, typ[0], include_hash_tree_roots) for element in value]
elif isinstance(typ, str) and typ[:4] == 'byte':
return '0x' + value.hex()
elif hasattr(typ, 'fields'):
ret = {}
for field, subtype in typ.fields.items():
ret[field] = jsonize(getattr(value, field), subtype, include_hash_tree_roots)
if include_hash_tree_roots:
ret[field + "_hash_tree_root"] = '0x' + hash_tree_root(getattr(value, field), subtype).hex()
if include_hash_tree_roots:
ret["hash_tree_root"] = '0x' + hash_tree_root(value, typ).hex()
return ret
else:
print(value, typ)
raise Exception("Type not recognized")


def dejsonize(json, typ):
if isinstance(typ, str) and typ[:4] == 'uint':
return json
elif typ == 'bool':
assert json in (True, False)
return json
elif isinstance(typ, list):
return [dejsonize(element, typ[0]) for element in json]
elif isinstance(typ, str) and typ[:4] == 'byte':
return bytes.fromhex(json[2:])
elif hasattr(typ, 'fields'):
temp = {}
for field, subtype in typ.fields.items():
temp[field] = dejsonize(json[field], subtype)
if field + "_hash_tree_root" in json:
assert(json[field + "_hash_tree_root"][2:] ==
hash_tree_root(temp[field], subtype).hex())
ret = typ(**temp)
if "hash_tree_root" in json:
assert(json["hash_tree_root"][2:] ==
hash_tree_root(ret, typ).hex())
return ret
else:
print(json, typ)
raise Exception("Type not recognized")

0 comments on commit 7db21e3

Please sign in to comment.