diff --git a/casper4/simple_casper_tester.py b/casper4/simple_casper_tester.py index 22655db..1a725c9 100644 --- a/casper4/simple_casper_tester.py +++ b/casper4/simple_casper_tester.py @@ -55,26 +55,31 @@ def mk_status_flicker(epoch, login, key): # Begin the test +print("Starting tests") # Initialize the first epoch s.state.block_number = EPOCH_LENGTH casper.initialize_epoch(1) assert casper.get_nextValidatorIndex() == 1 start = s.snapshot() +print("Epoch initialized") # Send a prepare message casper.prepare(0, mk_prepare(1, '\x35' * 32, '\x00' * 32, 0, '\x00' * 32, t.k0)) epoch_1_anchash = utils.sha3(b'\x35' * 32 + b'\x00' * 32) assert casper.get_consensus_messages__hash_justified(1, b'\x35' * 32) assert casper.get_consensus_messages__ancestry_hash_justified(1, epoch_1_anchash) +print("Prepare message processed") # Send a commit message casper.commit(0, mk_commit(1, '\x35' * 32, t.k0)) # Check that we committed assert casper.get_consensus_messages__committed(1) +print("Commit message processed") # Initialize the second epoch s.state.block_number += EPOCH_LENGTH casper.initialize_epoch(2) # Check that the dynasty increased as expected assert casper.get_dynasty() == 1 assert casper.get_total_deposits(1) == casper.get_total_deposits(0) > 0 +print("Second epoch initialized, dynasty increased as expected") # Send a prepare message casper.prepare(0, mk_prepare(2, '\x45' * 32, epoch_1_anchash, 1, epoch_1_anchash, t.k0)) # Send a commit message @@ -87,17 +92,20 @@ assert casper.get_consensus_messages__committed(2) # Initialize the third epoch s.state.block_number += EPOCH_LENGTH casper.initialize_epoch(3) +print("Second epoch prepared and committed, third epoch initialized") # Test the NO_DBL_PREPARE slashing condition p1 = mk_prepare(3, '\x56' * 32, epoch_2_anchash, 2, epoch_2_anchash, t.k0) p2 = mk_prepare(3, '\x57' * 32, epoch_2_anchash, 2, epoch_2_anchash, t.k0) snapshot = s.snapshot() casper.double_prepare_slash(0, p1, p2) s.revert(snapshot) +print("NO_DBL_PREPARE slashing condition works") # Test the PREPARE_COMMIT_CONSISTENCY slashing condition p3 = mk_prepare(3, '\x58' * 32, epoch_2_anchash, 0, b'\x00' * 32, t.k0) snapshot = s.snapshot() casper.prepare_commit_inconsistency_slash(0, p3, epoch_2_commit) s.revert(snapshot) +print("PREPARE_COMMIT_CONSISTENCY slashing condition works") # Finish the third epoch casper.prepare(0, p1) casper.commit(0, mk_commit(3, '\x56' * 32, t.k0)) @@ -114,6 +122,7 @@ p4 = mk_prepare(4, '\x78' * 32, '\x12' * 32, 3, '\x24' * 32, t.k0) # Initialize the fifth epoch s.state.block_number += EPOCH_LENGTH casper.initialize_epoch(5) +print("Epochs up to 5 initialized") # Dynasty not incremented because no commits were made assert casper.get_dynasty() == 3 epoch_5_anchash = utils.sha3(b'\x78' * 32 + epoch_4_anchash) @@ -122,8 +131,10 @@ casper.prepare(0, p5) # Test the COMMIT_REQ slashing condition kommit = mk_commit(5, b'\x80' * 32, t.k0) s.state.block_number += EPOCH_LENGTH * 30 +print("Speeding up time to test remaining two slashing conditions") for i in range(6, 36): casper.initialize_epoch(i) +print("Epochs up to 36 initialized") snapshot = s.snapshot() casper.commit_non_justification_slash(0, kommit) s.revert(snapshot) @@ -133,6 +144,7 @@ try: except: success = False assert not success +print("COMMIT_REQ slashing condition works") # Test the PREPARE_REQ slashing condition casper.derive_ancestry(epoch_3_anchash, epoch_2_anchash, epoch_1_anchash) snapshot = s.snapshot() @@ -144,31 +156,40 @@ try: except: success = False assert not success +print("PREPARE_REQ slashing condition works") +print("Restarting the chain for test 2") # Restart the chain s.revert(start) assert casper.get_dynasty() == 0 assert casper.get_current_epoch() == 1 assert casper.get_consensus_messages__ancestry_hash_justified(0, b'\x00' * 32) +print("Epoch 1 initialized") for k in (t.k1, t.k2, t.k3, t.k4, t.k5, t.k6): casper.deposit(utils.privtoaddr(k), utils.privtoaddr(k), value=3 * 10**15) +print("Processed 6 deposits") casper.prepare(0, mk_prepare(1, b'\x10' * 32, b'\x00' * 32, 0, b'\x00' * 32, t.k0)) casper.commit(0, mk_commit(1, b'\x10' * 32, t.k0)) epoch_1_anchash = utils.sha3(b'\x10' * 32 + b'\x00' * 32) assert casper.get_consensus_messages__committed(1) +print("Prepared and committed") s.state.block_number += EPOCH_LENGTH casper.initialize_epoch(2) +print("Epoch 2 initialized") assert casper.get_dynasty() == 1 casper.prepare(0, mk_prepare(2, b'\x20' * 32, epoch_1_anchash, 1, epoch_1_anchash, t.k0)) casper.commit(0, mk_commit(2, b'\x20' * 32, t.k0)) epoch_2_anchash = utils.sha3(b'\x20' * 32 + epoch_1_anchash) assert casper.get_consensus_messages__committed(2) +print("Confirmed that one key is still sufficient to prepare and commit") s.state.block_number += EPOCH_LENGTH casper.initialize_epoch(3) +print("Epoch 3 initialized") assert casper.get_dynasty() == 2 assert 3 * 10**15 <= casper.get_total_deposits(0) < 4 * 10**15 assert 3 * 10**15 <= casper.get_total_deposits(1) < 4 * 10**15 assert 21 * 10**15 <= casper.get_total_deposits(2) < 22 * 10**15 +print("Confirmed new total_deposits") try: # Try to log out, but sign with the wrong key casper.flick_status(0, mk_status_flicker(3, 0, t.k1)) @@ -180,6 +201,7 @@ assert not success casper.flick_status(4, mk_status_flicker(3, 0, t.k4)) casper.flick_status(5, mk_status_flicker(3, 0, t.k5)) casper.flick_status(6, mk_status_flicker(3, 0, t.k6)) +print("Logged out three validators") # Validators leave the fwd validator set in dynasty 4 assert casper.get_validators__dynasty_end(4) == 4 epoch_3_anchash = utils.sha3(b'\x30' * 32 + epoch_2_anchash) @@ -187,24 +209,29 @@ epoch_3_anchash = utils.sha3(b'\x30' * 32 + epoch_2_anchash) casper.prepare(0, mk_prepare(3, b'\x30' * 32, epoch_2_anchash, 2, epoch_2_anchash, t.k0)) # Not prepared yet assert not casper.get_consensus_messages__hash_justified(3, b'\x30' * 32) +print("Prepare from one validator no longer sufficient") # Prepare from 3 more validators for i, k in ((1, t.k1), (2, t.k2), (3, t.k3)): casper.prepare(i, mk_prepare(3, b'\x30' * 32, epoch_2_anchash, 2, epoch_2_anchash, k)) # Still not prepared assert not casper.get_consensus_messages__hash_justified(3, b'\x30' * 32) +print("Prepare from four of seven validators still not sufficient") # Prepare from a firth validator casper.prepare(4, mk_prepare(3, b'\x30' * 32, epoch_2_anchash, 2, epoch_2_anchash, t.k4)) # NOW we're prepared! assert casper.get_consensus_messages__hash_justified(3, b'\x30' * 32) +print("Prepare from five of seven validators sufficient!") # Five commits for i, k in enumerate([t.k0, t.k1, t.k2, t.k3, t.k4]): casper.commit(i, mk_commit(3, b'\x30' * 32, k)) # And we committed! assert casper.get_consensus_messages__committed(3) +print("Commit from five of seven validators sufficient") # Start epoch 4 s.state.block_number += EPOCH_LENGTH casper.initialize_epoch(4) assert casper.get_dynasty() == 3 +print("Epoch 4 initialized") # Prepare and commit epoch_4_anchash = utils.sha3(b'\x40' * 32 + epoch_3_anchash) for i, k in enumerate([t.k0, t.k1, t.k2, t.k3, t.k4]): @@ -212,9 +239,11 @@ for i, k in enumerate([t.k0, t.k1, t.k2, t.k3, t.k4]): for i, k in enumerate([t.k0, t.k1, t.k2, t.k3, t.k4]): casper.commit(i, mk_commit(4, b'\x40' * 32, k)) assert casper.get_consensus_messages__committed(4) +print("Prepared and committed") # Start epoch 5 / dynasty 4 s.state.block_number += EPOCH_LENGTH casper.initialize_epoch(5) +print("Epoch 5 initialized") assert casper.get_dynasty() == 4 assert 21 * 10**15 <= casper.get_total_deposits(3) <= 22 * 10**15 assert 12 * 10**15 <= casper.get_total_deposits(4) <= 13 * 10**15 @@ -224,11 +253,13 @@ for i, k in enumerate([t.k0, t.k1, t.k2]): casper.prepare(i, mk_prepare(5, b'\x50' * 32, epoch_4_anchash, 4, epoch_4_anchash, k)) # Three prepares are insufficient because there are still five validators in the rear validator set assert not casper.get_consensus_messages__hash_justified(5, b'\x50' * 32) +print("Three prepares insufficient, as rear validator set still has seven") # Do two more prepares for i, k in [(3, t.k3), (4, t.k4)]: casper.prepare(i, mk_prepare(5, b'\x50' * 32, epoch_4_anchash, 4, epoch_4_anchash, k)) # Now we're good! assert casper.get_consensus_messages__hash_justified(5, b'\x50' * 32) +print("Five prepares sufficient") for i, k in enumerate([t.k0, t.k1, t.k2, t.k3, t.k4]): casper.commit(i, mk_commit(5, b'\x50' * 32, k)) # Committed! @@ -237,8 +268,10 @@ assert casper.get_consensus_messages__committed(5) s.state.block_number += EPOCH_LENGTH casper.initialize_epoch(6) assert casper.get_dynasty() == 5 +print("Epoch 6 initialized") # Log back in casper.flick_status(4, mk_status_flicker(6, 1, t.k4)) +print("One validator logging back in") assert casper.get_validators__dynasty_start(4) == 7 # Here three prepares and three commits should be sufficient! epoch_6_anchash = utils.sha3(b'\x60' * 32 + epoch_5_anchash) @@ -247,10 +280,12 @@ for i, k in enumerate([t.k0, t.k1, t.k2]): for i, k in enumerate([t.k0, t.k1, t.k2]): casper.commit(i, mk_commit(6, b'\x60' * 32, k)) assert casper.get_consensus_messages__committed(6) +print("Three of four prepares and commits sufficient") # Start epoch 7 / dynasty 6 s.state.block_number += EPOCH_LENGTH casper.initialize_epoch(7) assert casper.get_dynasty() == 6 +print("Epoch 7 initialized") # Here three prepares and three commits should be sufficient! epoch_7_anchash = utils.sha3(b'\x70' * 32 + epoch_6_anchash) for i, k in enumerate([t.k0, t.k1, t.k2]): @@ -258,10 +293,12 @@ for i, k in enumerate([t.k0, t.k1, t.k2]): for i, k in enumerate([t.k0, t.k1, t.k2]): casper.commit(i, mk_commit(7, b'\x70' * 32, k)) assert casper.get_consensus_messages__committed(7) +print("Three of four prepares and commits sufficient") # Start epoch 8 / dynasty 7 s.state.block_number += EPOCH_LENGTH casper.initialize_epoch(8) assert casper.get_dynasty() == 7 +print("Epoch 8 initialized") assert 12 * 10**15 <= casper.get_total_deposits(6) <= 13 * 10**15 assert 15 * 10**15 <= casper.get_total_deposits(7) <= 16 * 10**15 epoch_8_anchash = utils.sha3(b'\x80' * 32 + epoch_7_anchash) @@ -270,11 +307,16 @@ for i, k in enumerate([t.k0, t.k1, t.k2]): casper.prepare(i, mk_prepare(8, b'\x80' * 32, epoch_7_anchash, 7, epoch_7_anchash, k)) # Three prepares are insufficient because there are still five validators in the rear validator set assert not casper.get_consensus_messages__hash_justified(8, b'\x80' * 32) +print("Three prepares no longer sufficient, as the forward validator set has five validators") # Do one more prepare for i, k in [(3, t.k3)]: casper.prepare(i, mk_prepare(8, b'\x80' * 32, epoch_7_anchash, 7, epoch_7_anchash, k)) # Now we're good! assert casper.get_consensus_messages__hash_justified(8, b'\x80' * 32) +print("Four of five prepares sufficient") for i, k in enumerate([t.k0, t.k1, t.k2, t.k3, t.k4]): casper.commit(i, mk_commit(8, b'\x80' * 32, k)) assert casper.get_consensus_messages__committed(8) +print("Committed") + +print("All tests passed")