Skip to content

Commit

Permalink
Merge branch 'master' of github.com:ethereum/research
Browse files Browse the repository at this point in the history
  • Loading branch information
djrtwo committed Mar 12, 2019
2 parents f005f85 + e2d13bf commit b986cb7
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 14 deletions.
41 changes: 41 additions & 0 deletions spec_pythonizer/apply_test_suite.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import sys
import json
from jsonize import dejsonize
import spec
from copy import deepcopy

if len(sys.argv) != 2:
print("Usage: python apply_test_suite json_file.json")
sys.exit(1)

with open(sys.argv[1], "rb") as f:
j = json.load(f)

print("Loaded test suite {0}".format(j["title"]))
print("Summary: {0}".format(j["summary"]))
print("Test suite: {0[test_suite]}, fork: {0[fork]}, version: {0[version]}".format(j))

def apply_test(config, initial_state, blocks, expected_state, expected_state_root):
print("Applying config")
print(json.dumps(config, indent=4))
for key, value in config.items():
setattr(spec, key, value)
state = deepcopy(initial_state)
for block in blocks:
spec.state_transition(state, block)

assert state == expected_state
if expected_state_root:
assert spec.hash_tree_root(state) == expected_state_root

print("Test passed\n")

for i, test_case in enumerate(j["test_cases"]):
config = test_case["config"]
initial_state = dejsonize(test_case["initial_state"], spec.BeaconState)
blocks = dejsonize(test_case["blocks"], [spec.BeaconBlock])
expected_state = dejsonize(test_case["expected_state"], spec.BeaconState)
expected_state_root = bytes.fromhex(test_case["expected_state_root"]) if "expected_state_root" in test_case else None

print("Running test {0}".format(i))
apply_test(config, initial_state, blocks, expected_state, expected_state_root)
2 changes: 1 addition & 1 deletion spec_pythonizer/minimal_ssz.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def serialize_value(value, typ):
return serialized_length + serialized_bytes
elif isinstance(typ, list) and len(typ) == 2:
assert len(value) == typ[1]
return ''.join([serialize_value(element, typ[0]) for element in value])
return b''.join([serialize_value(element, typ[0]) for element in value])
elif isinstance(typ, str) and len(typ) > 5 and typ[:5] == 'bytes':
assert len(value) == int(typ[5:]), (value, int(typ[5:]))
return coerce_to_bytes(value)
Expand Down
91 changes: 78 additions & 13 deletions spec_pythonizer/sanity_check.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from copy import deepcopy
import time
import sys
import json
from jsonize import jsonize

import spec
from spec import (
Expand Down Expand Up @@ -210,7 +213,7 @@ def test_empty_block_transition(state):
assert len(test_state.eth1_data_votes) == len(state.eth1_data_votes) + 1
assert get_block_root(test_state, state.slot) == block.previous_block_root

return [block], test_state
return state, [block], test_state


@timeit
Expand All @@ -225,6 +228,8 @@ def test_skipped_slots(state):
for slot in range(state.slot, test_state.slot):
assert get_block_root(test_state, slot) == block.previous_block_root

return state, [block], test_state


@timeit
def test_empty_epoch_transition(state):
Expand All @@ -238,6 +243,8 @@ def test_empty_epoch_transition(state):
for slot in range(state.slot, test_state.slot):
assert get_block_root(test_state, slot) == block.previous_block_root

return state, [block], test_state


@timeit
def test_empty_epoch_transition_not_finalizing(state):
Expand All @@ -250,6 +257,8 @@ def test_empty_epoch_transition_not_finalizing(state):
assert test_state.slot == block.slot
assert test_state.finalized_epoch < get_current_epoch(test_state) - 4

return state, [block], test_state


@timeit
def test_proposer_slashing(state):
Expand Down Expand Up @@ -292,6 +301,8 @@ def test_proposer_slashing(state):
# lost whistleblower reward
assert test_state.validator_balances[validator_index] < state.validator_balances[validator_index]

return state, [block], test_state


@timeit
def test_deposit_in_block(state):
Expand Down Expand Up @@ -333,6 +344,8 @@ def test_deposit_in_block(state):
assert len(test_state.validator_balances) == len(state.validator_balances) + 1
assert test_state.validator_registry[index].pubkey == pubkeys[index]

return state, [block], test_state


@timeit
def test_attestation(state):
Expand Down Expand Up @@ -378,6 +391,8 @@ def test_attestation(state):
assert len(test_state.current_epoch_attestations) == 0
assert test_state.previous_epoch_attestations == pre_current_epoch_attestations

return state, [block], test_state


@timeit
def test_voluntary_exit(state):
Expand Down Expand Up @@ -417,6 +432,8 @@ def test_voluntary_exit(state):

assert test_state.validator_registry[validator_index].exit_epoch < FAR_FUTURE_EPOCH

return state, [block], test_state


@timeit
def test_transfer(state):
Expand Down Expand Up @@ -456,6 +473,8 @@ def test_transfer(state):
assert sender_balance == 0
assert recipient_balance == pre_transfer_recipient_balance + amount

return state, [block], test_state


@timeit
def test_ejection(state):
Expand All @@ -479,6 +498,8 @@ def test_ejection(state):

assert test_state.validator_registry[validator_index].exit_epoch < FAR_FUTURE_EPOCH

return state, [block], test_state


@timeit
def test_historical_batch(state):
Expand All @@ -493,6 +514,8 @@ def test_historical_batch(state):
assert get_current_epoch(test_state) % (SLOTS_PER_HISTORICAL_ROOT // SLOTS_PER_EPOCH) == 0
assert len(test_state.historical_roots) == len(state.historical_roots) + 1

return state, [block], test_state


@timeit
def sanity_tests():
Expand All @@ -501,33 +524,36 @@ def sanity_tests():
print("done!")
print()

test_cases = []

print("Running some sanity check tests...\n")
test_slot_transition(genesis_state)
print("Passed slot transition test\n")
test_empty_block_transition(genesis_state)
test_cases.append(test_empty_block_transition(genesis_state))
print("Passed empty block transition test\n")
test_skipped_slots(genesis_state)
test_cases.append(test_skipped_slots(genesis_state))
print("Passed skipped slot test\n")
test_empty_epoch_transition(genesis_state)
test_cases.append(test_empty_epoch_transition(genesis_state))
print("Passed empty epoch transition test\n")
test_empty_epoch_transition_not_finalizing(genesis_state)
test_cases.append(test_empty_epoch_transition_not_finalizing(genesis_state))
print("Passed non-finalizing epoch test\n")
test_proposer_slashing(genesis_state)
test_cases.append(test_proposer_slashing(genesis_state))
print("Passed proposer slashing test\n")
test_attestation(genesis_state)
test_cases.append(test_attestation(genesis_state))
print("Passed attestation test\n")
test_deposit_in_block(genesis_state)
test_cases.append(test_deposit_in_block(genesis_state))
print("Passed deposit test\n")
test_voluntary_exit(genesis_state)
test_cases.append(test_voluntary_exit(genesis_state))
print("Passed voluntary exit test\n")
test_transfer(genesis_state)
test_cases.append(test_transfer(genesis_state))
print("Passed transfer test\n")
test_ejection(genesis_state)
test_cases.append(test_ejection(genesis_state))
print("Passed ejection test\n")
test_historical_batch(genesis_state)
test_cases.append(test_historical_batch(genesis_state))
print("Passed historical batch test\n")
print("done!")

return test_cases

# Monkey patch validator shuffling cache
_get_shuffling = spec.get_shuffling
Expand Down Expand Up @@ -564,4 +590,43 @@ def hash(x):
spec.hash = hash

if __name__ == "__main__":
sanity_tests()
test_cases = sanity_tests()

if "--generate-json" in sys.argv:
j = {}
j["title"] = "Sanity tests"
j["summary"] = "Basic sanity checks from phase 0 spec pythonization"
j["test_suite"] = "sanity_tests"
j["fork"] = "tchaikovsky"
j["version"] = "1.0"

test_cases_json = []
for test_case in test_cases:
config = {
"SHARD_COUNT": spec.SHARD_COUNT,
"TARGET_COMMITTEE_SIZE": spec.TARGET_COMMITTEE_SIZE,
"GENESIS_SLOT": spec.GENESIS_SLOT,
"GENESIS_EPOCH": spec.GENESIS_EPOCH,
"MIN_ATTESTATION_INCLUSION_DELAY": spec.MIN_ATTESTATION_INCLUSION_DELAY,
"SLOTS_PER_EPOCH": spec.SLOTS_PER_EPOCH,
"LATEST_RANDAO_MIXES_LENGTH": spec.LATEST_RANDAO_MIXES_LENGTH,
"SLOTS_PER_HISTORICAL_ROOT": spec.SLOTS_PER_HISTORICAL_ROOT,
"LATEST_ACTIVE_INDEX_ROOTS_LENGTH": spec.LATEST_ACTIVE_INDEX_ROOTS_LENGTH,
"LATEST_SLASHED_EXIT_LENGTH": spec.LATEST_SLASHED_EXIT_LENGTH,
}
initial_state = jsonize(test_case[0], type(test_case[0]))
blocks = jsonize(test_case[1], [type(test_case[1][0])])
expected_state = jsonize(test_case[2], type(test_case[2]))
expected_state_root = hash_tree_root(test_case[2], type(test_case[2]))
test_cases_json.append({
"config": config,
"initial_state": initial_state,
"blocks": blocks,
"expected_state": expected_state,
"expected_state_root": expected_state_root.hex(),
})

j["test_cases"] = test_cases_json

with open("test_cases.json", "w") as f:
json.dump(j, f, indent=4)

0 comments on commit b986cb7

Please sign in to comment.