From c13f032e9d2598483ae1dc79f47321dec72191e9 Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Sun, 30 Apr 2017 19:57:13 -0400 Subject: [PATCH 01/10] Begin converting Casper tests to tester2 --- casper/contracts/simple_casper_tester.py | 75 +++++++++++++++++++----- 1 file changed, 60 insertions(+), 15 deletions(-) diff --git a/casper/contracts/simple_casper_tester.py b/casper/contracts/simple_casper_tester.py index 61433c3..ee818e2 100644 --- a/casper/contracts/simple_casper_tester.py +++ b/casper/contracts/simple_casper_tester.py @@ -1,11 +1,26 @@ +import copy from ethereum import tester as t -from ethereum import utils, state_transition, transactions, abi +from ethereum import tester2 +from ethereum import utils, state_transition, transactions, abi, config from viper import compiler import serpent + from ethereum.slogging import LogRecorder, configure_logging, set_level config_string = ':info,eth.vm.log:trace,eth.vm.op:trace,eth.vm.stack:trace,eth.vm.exit:trace,eth.pb.msg:trace,eth.pb.tx:debug' #configure_logging(config_string=config_string) import rlp + + +# The Casper-specific config declaration +casper_config = copy.deepcopy(config.default_config) +casper_config['HOMESTEAD_FORK_BLKNUM'] = 0 +casper_config['ANTI_DOS_FORK_BLKNUM'] = 0 +casper_config['CLEARING_FORK_BLKNUM'] = 0 + +t2 = tester2.Chain(alloc={a: {'balance': 5*10**18} for a in tester2.accounts}, env=config.Env(config=casper_config)) + + + s = t.state() t.languages['viper'] = compiler.Compiler() t.gas_limit = 9999999 @@ -14,8 +29,17 @@ def inject_tx(txhex): tx = rlp.decode(utils.decode_hex(txhex[2:]), transactions.Transaction) - s.state.set_balance(tx.sender, tx.startgas * tx.gasprice) - state_transition.apply_transaction(s.state, tx) + s.state.set_balance(tx.sender, tx.startgas * tx.gasprice) # NOTE: Old + state_transition.apply_transaction(s.state, tx) # NOTE: Old + + # Set test2 balance + t2.head_state.set_balance(tx.sender, tx.startgas * tx.gasprice) + t2.chain.state.set_balance(tx.sender, tx.startgas * tx.gasprice) + success, output = state_transition.apply_transaction(t2.head_state, tx) + t2.block.transactions.append(tx) + t2.mine() + assert success + contract_address = utils.mk_contract_address(tx.sender, 0) assert s.state.get_code(contract_address) return contract_address @@ -30,25 +54,33 @@ def mk_validation_code(address): return serpent.compile(code_template % (utils.checksum_encode(address))) # Install RLP decoder library -rlp_decoder_address = inject_tx( '0xf90237808506fc23ac00830330888080b902246102128061000e60003961022056600060007f010000000000000000000000000000000000000000000000000000000000000060003504600060c082121515585760f882121561004d5760bf820336141558576001905061006e565b600181013560f783036020035260005160f6830301361415585760f6820390505b5b368112156101c2577f010000000000000000000000000000000000000000000000000000000000000081350483602086026040015260018501945060808112156100d55760018461044001526001828561046001376001820191506021840193506101bc565b60b881121561014357608081038461044001526080810360018301856104600137608181141561012e5760807f010000000000000000000000000000000000000000000000000000000000000060018401350412151558575b607f81038201915060608103840193506101bb565b60c08112156101b857600182013560b782036020035260005160388112157f010000000000000000000000000000000000000000000000000000000000000060018501350402155857808561044001528060b6838501038661046001378060b6830301830192506020810185019450506101ba565bfe5b5b5b5061006f565b601f841315155857602060208502016020810391505b6000821215156101fc578082604001510182826104400301526020820391506101d8565b808401610420528381018161044003f350505050505b6000f31b2d4f') +rlp_decoder_address = inject_tx('0xf90237808506fc23ac00830330888080b902246102128061000e60003961022056600060007f010000000000000000000000000000000000000000000000000000000000000060003504600060c082121515585760f882121561004d5760bf820336141558576001905061006e565b600181013560f783036020035260005160f6830301361415585760f6820390505b5b368112156101c2577f010000000000000000000000000000000000000000000000000000000000000081350483602086026040015260018501945060808112156100d55760018461044001526001828561046001376001820191506021840193506101bc565b60b881121561014357608081038461044001526080810360018301856104600137608181141561012e5760807f010000000000000000000000000000000000000000000000000000000000000060018401350412151558575b607f81038201915060608103840193506101bb565b60c08112156101b857600182013560b782036020035260005160388112157f010000000000000000000000000000000000000000000000000000000000000060018501350402155857808561044001528060b6838501038661046001378060b6830301830192506020810185019450506101ba565bfe5b5b5b5061006f565b601f841315155857602060208502016020810391505b6000821215156101fc578082604001510182826104400301526020820391506101d8565b808401610420528381018161044003f350505050505b6000f31b2d4f') +t2.mine() # Install sig hasher -s.state.set_balance('0x6e7406512b244843c1171840dfcd3d7532d979fe', 7291200000000000) +s.state.set_balance('0x6e7406512b244843c1171840dfcd3d7532d979fe', 7291200000000000) # NOTE: Old +t2.chain.state.set_balance('0x6e7406512b244843c1171840dfcd3d7532d979fe', 7291200000000000) +t2.head_state.set_balance('0x6e7406512b244843c1171840dfcd3d7532d979fe', 7291200000000000) -sighasher_address = inject_tx( '0xf9016d808506fc23ac0083026a508080b9015a6101488061000e6000396101565660007f01000000000000000000000000000000000000000000000000000000000000006000350460f8811215610038576001915061003f565b60f6810391505b508060005b368312156100c8577f01000000000000000000000000000000000000000000000000000000000000008335048391506080811215610087576001840193506100c2565b60b881121561009d57607f8103840193506100c1565b60c08112156100c05760b68103600185013560b783036020035260005101840193505b5b5b50610044565b81810360388112156100f4578060c00160005380836001378060010160002060e052602060e0f3610143565b61010081121561010557600161011b565b6201000081121561011757600261011a565b60035b5b8160005280601f038160f701815382856020378282600101018120610140526020610140f350505b505050505b6000f31b2d4f') +sighasher_address = inject_tx('0xf9016d808506fc23ac0083026a508080b9015a6101488061000e6000396101565660007f01000000000000000000000000000000000000000000000000000000000000006000350460f8811215610038576001915061003f565b60f6810391505b508060005b368312156100c8577f01000000000000000000000000000000000000000000000000000000000000008335048391506080811215610087576001840193506100c2565b60b881121561009d57607f8103840193506100c1565b60c08112156100c05760b68103600185013560b783036020035260005101840193505b5b5b50610044565b81810360388112156100f4578060c00160005380836001378060010160002060e052602060e0f3610143565b61010081121561010557600161011b565b6201000081121561011757600261011a565b60035b5b8160005280601f038160f701815382856020378282600101018120610140526020610140f350505b505050505b6000f31b2d4f') # Install purity checker -purity_checker_address = inject_tx( '0xf90467808506fc23ac00830583c88080b904546104428061000e60003961045056600061033f537c0100000000000000000000000000000000000000000000000000000000600035047f80010000000000000000000000000000000000000030ffff1c0e00000000000060205263a1903eab8114156103f7573659905901600090523660048237600435608052506080513b806020015990590160009052818152602081019050905060a0526080513b600060a0516080513c6080513b8060200260200159905901600090528181526020810190509050610100526080513b806020026020015990590160009052818152602081019050905061016052600060005b602060a05103518212156103c957610100601f8360a051010351066020518160020a161561010a57fe5b80606013151561011e57607f811315610121565b60005b1561014f5780607f036101000a60018460a0510101510482602002610160510152605e8103830192506103b2565b60f18114801561015f5780610164565b60f282145b905080156101725780610177565b60f482145b9050156103aa5760028212151561019e5760606001830360200261010051015112156101a1565b60005b156101bc57607f6001830360200261010051015113156101bf565b60005b156101d157600282036102605261031e565b6004821215156101f057600360018303602002610100510151146101f3565b60005b1561020d57605a6002830360200261010051015114610210565b60005b1561022b57606060038303602002610100510151121561022e565b60005b1561024957607f60038303602002610100510151131561024c565b60005b1561025e57600482036102605261031d565b60028212151561027d57605a6001830360200261010051015114610280565b60005b1561029257600282036102605261031c565b6002821215156102b157609060018303602002610100510151146102b4565b60005b156102c657600282036102605261031b565b6002821215156102e65760806001830360200261010051015112156102e9565b60005b156103035760906001830360200261010051015112610306565b60005b1561031857600282036102605261031a565bfe5b5b5b5b5b604060405990590160009052600081526102605160200261016051015181602001528090502054156103555760016102a052610393565b60306102605160200261010051015114156103755760016102a052610392565b60606102605160200261010051015114156103915760016102a0525b5b5b6102a051151561039f57fe5b6001830192506103b1565b6001830192505b5b8082602002610100510152600182019150506100e0565b50506001604060405990590160009052600081526080518160200152809050205560016102e05260206102e0f35b63c23697a8811415610440573659905901600090523660048237600435608052506040604059905901600090526000815260805181602001528090502054610300526020610300f35b505b6000f31b2d4f') +purity_checker_address = inject_tx('0xf90467808506fc23ac00830583c88080b904546104428061000e60003961045056600061033f537c0100000000000000000000000000000000000000000000000000000000600035047f80010000000000000000000000000000000000000030ffff1c0e00000000000060205263a1903eab8114156103f7573659905901600090523660048237600435608052506080513b806020015990590160009052818152602081019050905060a0526080513b600060a0516080513c6080513b8060200260200159905901600090528181526020810190509050610100526080513b806020026020015990590160009052818152602081019050905061016052600060005b602060a05103518212156103c957610100601f8360a051010351066020518160020a161561010a57fe5b80606013151561011e57607f811315610121565b60005b1561014f5780607f036101000a60018460a0510101510482602002610160510152605e8103830192506103b2565b60f18114801561015f5780610164565b60f282145b905080156101725780610177565b60f482145b9050156103aa5760028212151561019e5760606001830360200261010051015112156101a1565b60005b156101bc57607f6001830360200261010051015113156101bf565b60005b156101d157600282036102605261031e565b6004821215156101f057600360018303602002610100510151146101f3565b60005b1561020d57605a6002830360200261010051015114610210565b60005b1561022b57606060038303602002610100510151121561022e565b60005b1561024957607f60038303602002610100510151131561024c565b60005b1561025e57600482036102605261031d565b60028212151561027d57605a6001830360200261010051015114610280565b60005b1561029257600282036102605261031c565b6002821215156102b157609060018303602002610100510151146102b4565b60005b156102c657600282036102605261031b565b6002821215156102e65760806001830360200261010051015112156102e9565b60005b156103035760906001830360200261010051015112610306565b60005b1561031857600282036102605261031a565bfe5b5b5b5b5b604060405990590160009052600081526102605160200261016051015181602001528090502054156103555760016102a052610393565b60306102605160200261010051015114156103755760016102a052610392565b60606102605160200261010051015114156103915760016102a0525b5b5b6102a051151561039f57fe5b6001830192506103b1565b6001830192505b5b8082602002610100510152600182019150506100e0565b50506001604060405990590160009052600081526080518160200152809050205560016102e05260206102e0f35b63c23697a8811415610440573659905901600090523660048237600435608052506040604059905901600090526000815260805181602001528090502054610300526020610300f35b505b6000f31b2d4f') ct = abi.ContractTranslator([{'name': 'check(address)', 'type': 'function', 'constant': True, 'inputs': [{'name': 'addr', 'type': 'address'}], 'outputs': [{'name': 'out', 'type': 'bool'}]}, {'name': 'submit(address)', 'type': 'function', 'constant': False, 'inputs': [{'name': 'addr', 'type': 'address'}], 'outputs': [{'name': 'out', 'type': 'bool'}]}]) # Check that the RLP decoding library and the sig hashing library are "pure" -assert utils.big_endian_to_int(s.send(t.k0, purity_checker_address, 0, ct.encode('submit', [rlp_decoder_address]))) == 1 -assert utils.big_endian_to_int(s.send(t.k0, purity_checker_address, 0, ct.encode('submit', [sighasher_address]))) == 1 +assert utils.big_endian_to_int(s.send(t.k0, purity_checker_address, 0, ct.encode('submit', [rlp_decoder_address]))) == 1 # NOTE: Old +assert utils.big_endian_to_int(s.send(t.k0, purity_checker_address, 0, ct.encode('submit', [sighasher_address]))) == 1 # NOTE: Old +# Check for tester2 +assert utils.big_endian_to_int(t2.tx(tester2.k0, purity_checker_address, 0, ct.encode('submit', [rlp_decoder_address]))) == 1 +assert utils.big_endian_to_int(t2.tx(tester2.k0, purity_checker_address, 0, ct.encode('submit', [sighasher_address]))) == 1 k1_valcode_addr = s.send(t.k0, "", 0, mk_validation_code(t.a0)) -assert utils.big_endian_to_int(s.send(t.k0, purity_checker_address, 0, ct.encode('submit', [k1_valcode_addr]))) == 1 +k1_valcode_addr = t2.tx(tester2.k0, "", 0, mk_validation_code(t.a0)) +assert utils.big_endian_to_int(s.send(t.k0, purity_checker_address, 0, ct.encode('submit', [k1_valcode_addr]))) == 1 # NOTE: Old +assert utils.big_endian_to_int(t2.tx(tester2.k0, purity_checker_address, 0, ct.encode('submit', [k1_valcode_addr]))) == 1 # Install Casper @@ -58,9 +90,12 @@ def mk_validation_code(address): print('Casper code length', len(compiler.compile(casper_code))) -casper = s.abi_contract(casper_code, language='viper', startgas=5555555) +casper = s.abi_contract(casper_code, language='viper', startgas=5555555) # NOTE: Old -print('Gas consumed to launch Casper', s.state.receipts[-1].gas_used - s.state.receipts[-2].gas_used) +casper2 = t2.contract(casper_code, language='viper', startgas=4096181) +t2.mine() + +print('Gas consumed to launch Casper', s.state.receipts[-1].gas_used - s.state.receipts[-2].gas_used) # NOTE: Old # Helper functions for making a prepare, commit, login and logout message @@ -86,8 +121,18 @@ def mk_status_flicker(validator_index, epoch, login, key): print("Starting tests") casper.initiate() + +# Test basic casper2 initialization +casper2.initiate() +t2.mine(number_of_blocks=EPOCH_LENGTH-t2.chain.state.block_number) +start2 = t2.snapshot() +print(t2.chain.state.block_number) +print('foo', casper2.initialize_epoch(1)) +assert casper2.get_nextValidatorIndex() == 1 +assert False + # Initialize the first epoch -s.state.block_number = EPOCH_LENGTH +s.state.block_number = EPOCH_LENGTH print('foo', casper.initialize_epoch(1)) assert casper.get_nextValidatorIndex() == 1 start = s.snapshot() @@ -116,7 +161,7 @@ def mk_status_flicker(validator_index, epoch, login, key): # Check that we committed assert casper.get_consensus_messages__committed(1) print("Commit message processed") -# Initialize the second epoch +# Initialize the second epoch s.state.block_number += EPOCH_LENGTH casper.initialize_epoch(2) # Check that the dynasty increased as expected @@ -331,7 +376,7 @@ def mk_status_flicker(validator_index, epoch, login, key): assert [casper.check_eligible_in_epoch(4, i) for i in range(7)] == [0, 0, 0, 2, 3, 1, 0] casper.flick_status(mk_status_flicker(4, 6, 1, t.k4)) # Explanation: -# * During dynasty 7, the validator will log on again. Hence, the dynasty mask +# * During dynasty 7, the validator will log on again. Hence, the dynasty mask # should include dynasties 4, 5, 6 assert [casper.check_eligible_in_epoch(4, i) for i in range(7)] == [0, 0, 0, 2, 3, 1, 0] new_deposit = casper.get_validators__deposit(4) From ebb7e7349f6337852535c1677f36836cfd77eb1f Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Sun, 30 Apr 2017 20:43:59 -0400 Subject: [PATCH 02/10] Begin replacing tester with tester2 --- casper/contracts/simple_casper_tester.py | 59 ++++++++---------------- 1 file changed, 19 insertions(+), 40 deletions(-) diff --git a/casper/contracts/simple_casper_tester.py b/casper/contracts/simple_casper_tester.py index ee818e2..17b8810 100644 --- a/casper/contracts/simple_casper_tester.py +++ b/casper/contracts/simple_casper_tester.py @@ -1,5 +1,4 @@ import copy -from ethereum import tester as t from ethereum import tester2 from ethereum import utils, state_transition, transactions, abi, config from viper import compiler @@ -10,38 +9,26 @@ #configure_logging(config_string=config_string) import rlp - # The Casper-specific config declaration casper_config = copy.deepcopy(config.default_config) casper_config['HOMESTEAD_FORK_BLKNUM'] = 0 casper_config['ANTI_DOS_FORK_BLKNUM'] = 0 casper_config['CLEARING_FORK_BLKNUM'] = 0 -t2 = tester2.Chain(alloc={a: {'balance': 5*10**18} for a in tester2.accounts}, env=config.Env(config=casper_config)) - - - -s = t.state() -t.languages['viper'] = compiler.Compiler() -t.gas_limit = 9999999 +t = tester2.Chain(alloc={a: {'balance': 5*10**18} for a in tester2.accounts}, env=config.Env(config=casper_config)) EPOCH_LENGTH = 100 def inject_tx(txhex): tx = rlp.decode(utils.decode_hex(txhex[2:]), transactions.Transaction) - s.state.set_balance(tx.sender, tx.startgas * tx.gasprice) # NOTE: Old - state_transition.apply_transaction(s.state, tx) # NOTE: Old - - # Set test2 balance - t2.head_state.set_balance(tx.sender, tx.startgas * tx.gasprice) - t2.chain.state.set_balance(tx.sender, tx.startgas * tx.gasprice) - success, output = state_transition.apply_transaction(t2.head_state, tx) - t2.block.transactions.append(tx) - t2.mine() - assert success - + t.head_state.set_balance(tx.sender, tx.startgas * tx.gasprice) + t.chain.state.set_balance(tx.sender, tx.startgas * tx.gasprice) + success, output = state_transition.apply_transaction(t.head_state, tx) + t.block.transactions.append(tx) + t.mine() contract_address = utils.mk_contract_address(tx.sender, 0) - assert s.state.get_code(contract_address) + assert success + assert t.chain.state.get_code(contract_address) return contract_address code_template = """ @@ -55,13 +42,12 @@ def mk_validation_code(address): # Install RLP decoder library rlp_decoder_address = inject_tx('0xf90237808506fc23ac00830330888080b902246102128061000e60003961022056600060007f010000000000000000000000000000000000000000000000000000000000000060003504600060c082121515585760f882121561004d5760bf820336141558576001905061006e565b600181013560f783036020035260005160f6830301361415585760f6820390505b5b368112156101c2577f010000000000000000000000000000000000000000000000000000000000000081350483602086026040015260018501945060808112156100d55760018461044001526001828561046001376001820191506021840193506101bc565b60b881121561014357608081038461044001526080810360018301856104600137608181141561012e5760807f010000000000000000000000000000000000000000000000000000000000000060018401350412151558575b607f81038201915060608103840193506101bb565b60c08112156101b857600182013560b782036020035260005160388112157f010000000000000000000000000000000000000000000000000000000000000060018501350402155857808561044001528060b6838501038661046001378060b6830301830192506020810185019450506101ba565bfe5b5b5b5061006f565b601f841315155857602060208502016020810391505b6000821215156101fc578082604001510182826104400301526020820391506101d8565b808401610420528381018161044003f350505050505b6000f31b2d4f') -t2.mine() +t.mine() # Install sig hasher -s.state.set_balance('0x6e7406512b244843c1171840dfcd3d7532d979fe', 7291200000000000) # NOTE: Old -t2.chain.state.set_balance('0x6e7406512b244843c1171840dfcd3d7532d979fe', 7291200000000000) -t2.head_state.set_balance('0x6e7406512b244843c1171840dfcd3d7532d979fe', 7291200000000000) +t.chain.state.set_balance('0x6e7406512b244843c1171840dfcd3d7532d979fe', 7291200000000000) +t.head_state.set_balance('0x6e7406512b244843c1171840dfcd3d7532d979fe', 7291200000000000) sighasher_address = inject_tx('0xf9016d808506fc23ac0083026a508080b9015a6101488061000e6000396101565660007f01000000000000000000000000000000000000000000000000000000000000006000350460f8811215610038576001915061003f565b60f6810391505b508060005b368312156100c8577f01000000000000000000000000000000000000000000000000000000000000008335048391506080811215610087576001840193506100c2565b60b881121561009d57607f8103840193506100c1565b60c08112156100c05760b68103600185013560b783036020035260005101840193505b5b5b50610044565b81810360388112156100f4578060c00160005380836001378060010160002060e052602060e0f3610143565b61010081121561010557600161011b565b6201000081121561011757600261011a565b60035b5b8160005280601f038160f701815382856020378282600101018120610140526020610140f350505b505050505b6000f31b2d4f') @@ -71,16 +57,11 @@ def mk_validation_code(address): ct = abi.ContractTranslator([{'name': 'check(address)', 'type': 'function', 'constant': True, 'inputs': [{'name': 'addr', 'type': 'address'}], 'outputs': [{'name': 'out', 'type': 'bool'}]}, {'name': 'submit(address)', 'type': 'function', 'constant': False, 'inputs': [{'name': 'addr', 'type': 'address'}], 'outputs': [{'name': 'out', 'type': 'bool'}]}]) # Check that the RLP decoding library and the sig hashing library are "pure" -assert utils.big_endian_to_int(s.send(t.k0, purity_checker_address, 0, ct.encode('submit', [rlp_decoder_address]))) == 1 # NOTE: Old -assert utils.big_endian_to_int(s.send(t.k0, purity_checker_address, 0, ct.encode('submit', [sighasher_address]))) == 1 # NOTE: Old -# Check for tester2 -assert utils.big_endian_to_int(t2.tx(tester2.k0, purity_checker_address, 0, ct.encode('submit', [rlp_decoder_address]))) == 1 -assert utils.big_endian_to_int(t2.tx(tester2.k0, purity_checker_address, 0, ct.encode('submit', [sighasher_address]))) == 1 +assert utils.big_endian_to_int(t.tx(tester2.k0, purity_checker_address, 0, ct.encode('submit', [rlp_decoder_address]))) == 1 +assert utils.big_endian_to_int(t.tx(tester2.k0, purity_checker_address, 0, ct.encode('submit', [sighasher_address]))) == 1 -k1_valcode_addr = s.send(t.k0, "", 0, mk_validation_code(t.a0)) -k1_valcode_addr = t2.tx(tester2.k0, "", 0, mk_validation_code(t.a0)) -assert utils.big_endian_to_int(s.send(t.k0, purity_checker_address, 0, ct.encode('submit', [k1_valcode_addr]))) == 1 # NOTE: Old -assert utils.big_endian_to_int(t2.tx(tester2.k0, purity_checker_address, 0, ct.encode('submit', [k1_valcode_addr]))) == 1 +k1_valcode_addr = t.tx(tester2.k0, "", 0, mk_validation_code(tester2.a0)) +assert utils.big_endian_to_int(t.tx(tester2.k0, purity_checker_address, 0, ct.encode('submit', [k1_valcode_addr]))) == 1 # Install Casper @@ -90,12 +71,10 @@ def mk_validation_code(address): print('Casper code length', len(compiler.compile(casper_code))) -casper = s.abi_contract(casper_code, language='viper', startgas=5555555) # NOTE: Old - -casper2 = t2.contract(casper_code, language='viper', startgas=4096181) -t2.mine() - -print('Gas consumed to launch Casper', s.state.receipts[-1].gas_used - s.state.receipts[-2].gas_used) # NOTE: Old +casper = t.contract(casper_code, language='viper', startgas=4096181) +print('Gas consumed to launch Casper', t.chain.state.receipts[-1].gas_used - t.chain.state.receipts[-2].gas_used) +t.mine() +assert False # Helper functions for making a prepare, commit, login and logout message From 2cfd385a76a112255c85a7667494494a645f6f87 Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Sun, 30 Apr 2017 22:46:27 -0400 Subject: [PATCH 03/10] Add helper methods, blockhash & small edits * Add mine_and_init_epoch() * Add epoch_blockhash() for getting the blockhash at a specific epoch * Change t.k0 to just k0 * Change a few tests to pass --- casper/contracts/simple_casper.v.py | 4 +- casper/contracts/simple_casper_tester.py | 146 ++++++++++++----------- 2 files changed, 78 insertions(+), 72 deletions(-) diff --git a/casper/contracts/simple_casper.v.py b/casper/contracts/simple_casper.v.py index 541d4e1..11a4556 100644 --- a/casper/contracts/simple_casper.v.py +++ b/casper/contracts/simple_casper.v.py @@ -348,7 +348,7 @@ def prepare(prepare_msg: bytes <= 1024): # Check that we have not yet prepared for this epoch # Pay the reward if the prepare was submitted in time and the blockhash is correct this_validators_deposit = self.validators[validator_index].deposit - if self.current_epoch == epoch: #if blockhash(epoch * self.epoch_length) == hash: + if self.current_epoch == epoch and blockhash(epoch * self.epoch_length) == hash: reward = floor(this_validators_deposit * self.reward_factor) self.validators[validator_index].deposit += reward self.total_deposits[self.dynasty] += reward @@ -408,7 +408,7 @@ def commit(commit_msg: bytes <= 1024): self.validators[validator_index].prev_commit_epoch = epoch this_validators_deposit = self.validators[validator_index].deposit # Pay the reward if the blockhash is correct - if True: #if blockhash(epoch * self.epoch_length) == hash: + if blockhash(epoch * self.epoch_length) == hash: reward = floor(this_validators_deposit * self.reward_factor) self.validators[validator_index].deposit += reward self.total_deposits[self.dynasty] += reward diff --git a/casper/contracts/simple_casper_tester.py b/casper/contracts/simple_casper_tester.py index 17b8810..22611f9 100644 --- a/casper/contracts/simple_casper_tester.py +++ b/casper/contracts/simple_casper_tester.py @@ -15,7 +15,9 @@ casper_config['ANTI_DOS_FORK_BLKNUM'] = 0 casper_config['CLEARING_FORK_BLKNUM'] = 0 -t = tester2.Chain(alloc={a: {'balance': 5*10**18} for a in tester2.accounts}, env=config.Env(config=casper_config)) +k0, k1, k2, k3, k4, k5, k6, k7, k8, k9 = tester2.keys[:10] +a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = tester2.accounts[:10] +t = tester2.Chain(alloc={a: {'balance': 5*10**18} for a in tester2.accounts[:10]}, env=config.Env(config=casper_config)) EPOCH_LENGTH = 100 @@ -57,11 +59,11 @@ def mk_validation_code(address): ct = abi.ContractTranslator([{'name': 'check(address)', 'type': 'function', 'constant': True, 'inputs': [{'name': 'addr', 'type': 'address'}], 'outputs': [{'name': 'out', 'type': 'bool'}]}, {'name': 'submit(address)', 'type': 'function', 'constant': False, 'inputs': [{'name': 'addr', 'type': 'address'}], 'outputs': [{'name': 'out', 'type': 'bool'}]}]) # Check that the RLP decoding library and the sig hashing library are "pure" -assert utils.big_endian_to_int(t.tx(tester2.k0, purity_checker_address, 0, ct.encode('submit', [rlp_decoder_address]))) == 1 -assert utils.big_endian_to_int(t.tx(tester2.k0, purity_checker_address, 0, ct.encode('submit', [sighasher_address]))) == 1 +assert utils.big_endian_to_int(t.tx(k0, purity_checker_address, 0, ct.encode('submit', [rlp_decoder_address]))) == 1 +assert utils.big_endian_to_int(t.tx(k0, purity_checker_address, 0, ct.encode('submit', [sighasher_address]))) == 1 -k1_valcode_addr = t.tx(tester2.k0, "", 0, mk_validation_code(tester2.a0)) -assert utils.big_endian_to_int(t.tx(tester2.k0, purity_checker_address, 0, ct.encode('submit', [k1_valcode_addr]))) == 1 +k1_valcode_addr = t.tx(k0, "", 0, mk_validation_code(a0)) +assert utils.big_endian_to_int(t.tx(k0, purity_checker_address, 0, ct.encode('submit', [k1_valcode_addr]))) == 1 # Install Casper @@ -74,7 +76,6 @@ def mk_validation_code(address): casper = t.contract(casper_code, language='viper', startgas=4096181) print('Gas consumed to launch Casper', t.chain.state.receipts[-1].gas_used - t.chain.state.receipts[-2].gas_used) t.mine() -assert False # Helper functions for making a prepare, commit, login and logout message @@ -96,61 +97,66 @@ def mk_status_flicker(validator_index, epoch, login, key): sig = utils.encode_int32(v) + utils.encode_int32(r) + utils.encode_int32(s) return rlp.encode([validator_index, epoch, login, sig]) +# Helper function for gettting blockhashes by epoch, based on the current chain +def epoch_blockhash(epoch): + if epoch == 0: + return b'\x00' * 32 + return t.chain.get_blockhash_by_number(epoch*EPOCH_LENGTH) + +def mine_and_init_epochs(number_of_epochs): + distance_to_next_epoch = (EPOCH_LENGTH - t.chain.state.block_number) % EPOCH_LENGTH + t.mine(number_of_blocks=distance_to_next_epoch+2) + casper.initialize_epoch(t.chain.state.block_number // EPOCH_LENGTH) + for i in range(number_of_epochs-1): + print("Initializing epoch", t.chain.state.block_number // EPOCH_LENGTH) + t.mine(number_of_blocks=EPOCH_LENGTH) + casper.initialize_epoch(t.chain.state.block_number // EPOCH_LENGTH) + print("Initializing epoch", t.chain.state.block_number // EPOCH_LENGTH) + # Begin the test print("Starting tests") casper.initiate() -# Test basic casper2 initialization -casper2.initiate() -t2.mine(number_of_blocks=EPOCH_LENGTH-t2.chain.state.block_number) -start2 = t2.snapshot() -print(t2.chain.state.block_number) -print('foo', casper2.initialize_epoch(1)) -assert casper2.get_nextValidatorIndex() == 1 -assert False - # Initialize the first epoch -s.state.block_number = EPOCH_LENGTH -print('foo', casper.initialize_epoch(1)) +# t.mine(number_of_blocks=EPOCH_LENGTH-t.chain.state.block_number+2) +mine_and_init_epochs(1) +# print('foo', casper.initialize_epoch(1)) assert casper.get_nextValidatorIndex() == 1 -start = s.snapshot() +start = t.snapshot() print("Epoch initialized") print("Reward factor: %.8f" % (casper.get_reward_factor() * 2 / 3)) # Send a prepare message -#configure_logging(config_string=config_string) -casper.prepare(mk_prepare(0, 1, '\x35' * 32, '\x00' * 32, 0, '\x00' * 32, t.k0)) +# configure_logging(config_string=config_string) +assert casper.prepare(mk_prepare(0, 1, epoch_blockhash(1), epoch_blockhash(0), 0, epoch_blockhash(0), k0)) is not False print('Gas consumed for a prepare: %d (including %d intrinsic gas)' % - (s.state.receipts[-1].gas_used - s.state.receipts[-2].gas_used, s.last_tx.intrinsic_gas_used)) -epoch_1_anchash = utils.sha3(b'\x35' * 32 + b'\x00' * 32) -assert casper.get_consensus_messages__hash_justified(1, b'\x35' * 32) + (t.chain.state.receipts[-1].gas_used - t.chain.state.receipts[-2].gas_used, t.last_tx.intrinsic_gas_used)) +epoch_1_anchash = utils.sha3(epoch_blockhash(1) + epoch_blockhash(0)) +assert casper.get_consensus_messages__hash_justified(1, epoch_blockhash(1)) assert casper.get_consensus_messages__ancestry_hash_justified(1, epoch_1_anchash) print("Prepare message processed") -try: - casper.prepare(mk_prepare(0, 1, '\x35' * 32, '\x00' * 32, 0, '\x00' * 32, t.k0)) - success = True -except: - success = False -assert not success +assert casper.prepare(mk_prepare(0, 1, epoch_blockhash(1), epoch_blockhash(0), 0, epoch_blockhash(0), k0)) is False print("Prepare message fails the second time") +# Mine our prepares +t.mine() # Send a commit message -casper.commit(mk_commit(0, 1, '\x35' * 32, 0, t.k0)) +print('commit!', casper.commit(mk_commit(0, 1, epoch_blockhash(1), 0, k0))) print('Gas consumed for a commit: %d (including %d intrinsic gas)' % - (s.state.receipts[-1].gas_used - s.state.receipts[-2].gas_used, s.last_tx.intrinsic_gas_used)) + (t.chain.state.receipts[-1].gas_used, t.last_tx.intrinsic_gas_used)) # 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) +mine_and_init_epochs(1) # 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(mk_prepare(0, 2, '\x45' * 32, epoch_1_anchash, 1, epoch_1_anchash, t.k0)) +casper.prepare(mk_prepare(0, 2, epoch_blockhash(2), epoch_1_anchash, 1, epoch_1_anchash, k0)) # Send a commit message -epoch_2_commit = mk_commit(0, 2, '\x45' * 32, 1, t.k0) +epoch_2_commit = mk_commit(0, 2, epoch_blockhash(2), 1, k0) +raise SystemExit casper.commit(epoch_2_commit) epoch_2_anchash = utils.sha3(b'\x45' * 32 + epoch_1_anchash) assert casper.get_consensus_messages__ancestry_hash_justified(2, epoch_2_anchash) @@ -161,21 +167,21 @@ def mk_status_flicker(validator_index, epoch, login, key): casper.initialize_epoch(3) print("Second epoch prepared and committed, third epoch initialized") # Test the NO_DBL_PREPARE slashing condition -p1 = mk_prepare(0, 3, '\x56' * 32, epoch_2_anchash, 2, epoch_2_anchash, t.k0) -p2 = mk_prepare(0, 3, '\x57' * 32, epoch_2_anchash, 2, epoch_2_anchash, t.k0) +p1 = mk_prepare(0, 3, '\x56' * 32, epoch_2_anchash, 2, epoch_2_anchash, k0) +p2 = mk_prepare(0, 3, '\x57' * 32, epoch_2_anchash, 2, epoch_2_anchash, k0) snapshot = s.snapshot() casper.double_prepare_slash(p1, p2) s.revert(snapshot) print("NO_DBL_PREPARE slashing condition works") # Test the PREPARE_COMMIT_CONSISTENCY slashing condition -p3 = mk_prepare(0, 3, '\x58' * 32, epoch_2_anchash, 0, b'\x00' * 32, t.k0) +p3 = mk_prepare(0, 3, '\x58' * 32, epoch_2_anchash, 0, b'\x00' * 32, k0) snapshot = s.snapshot() casper.prepare_commit_inconsistency_slash(p3, epoch_2_commit) s.revert(snapshot) print("PREPARE_COMMIT_CONSISTENCY slashing condition works") # Finish the third epoch casper.prepare(p1) -casper.commit(mk_commit(0, 3, '\x56' * 32, 2, t.k0)) +casper.commit(mk_commit(0, 3, '\x56' * 32, 2, k0)) epoch_3_anchash = utils.sha3(b'\x56' * 32 + epoch_2_anchash) assert casper.get_consensus_messages__ancestry_hash_justified(3, epoch_3_anchash) assert casper.get_consensus_messages__committed(3) @@ -185,7 +191,7 @@ def mk_status_flicker(validator_index, epoch, login, key): assert casper.get_dynasty() == 3 epoch_4_anchash = utils.sha3(b'\x67' * 32 + epoch_3_anchash) # Not publishing this prepare for the time being -p4 = mk_prepare(0, 4, '\x78' * 32, '\x12' * 32, 3, '\x24' * 32, t.k0) +p4 = mk_prepare(0, 4, '\x78' * 32, '\x12' * 32, 3, '\x24' * 32, k0) # Initialize the fifth epoch s.state.block_number += EPOCH_LENGTH casper.initialize_epoch(5) @@ -193,10 +199,10 @@ def mk_status_flicker(validator_index, epoch, login, key): # Dynasty not incremented because no commits were made assert casper.get_dynasty() == 3 epoch_5_anchash = utils.sha3(b'\x78' * 32 + epoch_4_anchash) -p5 = mk_prepare(0, 5, '\x78' * 32, epoch_4_anchash, 3, epoch_3_anchash, t.k0) +p5 = mk_prepare(0, 5, '\x78' * 32, epoch_4_anchash, 3, epoch_3_anchash, k0) casper.prepare(p5) # Test the COMMIT_REQ slashing condition -kommit = mk_commit(0, 5, b'\x80' * 32, 3, t.k0) +kommit = mk_commit(0, 5, b'\x80' * 32, 3, k0) epoch_inc = 1 + int(86400 / 14 / EPOCH_LENGTH) s.state.block_number += EPOCH_LENGTH * epoch_inc print("Speeding up time to test remaining two slashing conditions") @@ -237,13 +243,13 @@ def mk_status_flicker(validator_index, epoch, login, key): 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): - valcode_addr = s.send(t.k0, '', 0, mk_validation_code(utils.privtoaddr(k))) - assert utils.big_endian_to_int(s.send(t.k0, purity_checker_address, 0, ct.encode('submit', [valcode_addr]))) == 1 +for k in (k1, k2, k3, k4, k5, k6): + valcode_addr = s.send(k0, '', 0, mk_validation_code(utils.privtoaddr(k))) + assert utils.big_endian_to_int(s.send(k0, purity_checker_address, 0, ct.encode('submit', [valcode_addr]))) == 1 casper.deposit(valcode_addr, utils.privtoaddr(k), value=3 * 10**18) print("Processed 6 deposits") -casper.prepare(mk_prepare(0, 1, b'\x10' * 32, b'\x00' * 32, 0, b'\x00' * 32, t.k0)) -casper.commit(mk_commit(0, 1, b'\x10' * 32, 0, t.k0)) +casper.prepare(mk_prepare(0, 1, b'\x10' * 32, b'\x00' * 32, 0, b'\x00' * 32, k0)) +casper.commit(mk_commit(0, 1, b'\x10' * 32, 0, k0)) epoch_1_anchash = utils.sha3(b'\x10' * 32 + b'\x00' * 32) assert casper.get_consensus_messages__committed(1) print("Prepared and committed") @@ -251,8 +257,8 @@ def mk_status_flicker(validator_index, epoch, login, key): casper.initialize_epoch(2) print("Epoch 2 initialized") assert casper.get_dynasty() == 1 -casper.prepare(mk_prepare(0, 2, b'\x20' * 32, epoch_1_anchash, 1, epoch_1_anchash, t.k0)) -casper.commit(mk_commit(0, 2, b'\x20' * 32, 1, t.k0)) +casper.prepare(mk_prepare(0, 2, b'\x20' * 32, epoch_1_anchash, 1, epoch_1_anchash, k0)) +casper.commit(mk_commit(0, 2, b'\x20' * 32, 1, 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") @@ -266,37 +272,37 @@ def mk_status_flicker(validator_index, epoch, login, key): print("Confirmed new total_deposits") try: # Try to log out, but sign with the wrong key - casper.flick_status(mk_status_flicker(0, 3, 0, t.k1)) + casper.flick_status(mk_status_flicker(0, 3, 0, k1)) success = True except: success = False assert not success # Log out -casper.flick_status(mk_status_flicker(4, 3, 0, t.k4)) -casper.flick_status(mk_status_flicker(5, 3, 0, t.k5)) -casper.flick_status(mk_status_flicker(6, 3, 0, t.k6)) +casper.flick_status(mk_status_flicker(4, 3, 0, k4)) +casper.flick_status(mk_status_flicker(5, 3, 0, k5)) +casper.flick_status(mk_status_flicker(6, 3, 0, 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) # Prepare from one validator -casper.prepare(mk_prepare(0, 3, b'\x30' * 32, epoch_2_anchash, 2, epoch_2_anchash, t.k0)) +casper.prepare(mk_prepare(0, 3, b'\x30' * 32, epoch_2_anchash, 2, epoch_2_anchash, 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)): +for i, k in ((1, k1), (2, k2), (3, k3)): casper.prepare(mk_prepare(i, 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 fifth validator -casper.prepare(mk_prepare(4, 3, b'\x30' * 32, epoch_2_anchash, 2, epoch_2_anchash, t.k4)) +casper.prepare(mk_prepare(4, 3, b'\x30' * 32, epoch_2_anchash, 2, epoch_2_anchash, 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]): +for i, k in enumerate([k0, k1, k2, k3, k4]): casper.commit(mk_commit(i, 3, b'\x30' * 32, 2 if i == 0 else 0, k)) # And we committed! assert casper.get_consensus_messages__committed(3) @@ -308,9 +314,9 @@ def mk_status_flicker(validator_index, epoch, login, key): 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]): +for i, k in enumerate([k0, k1, k2, k3, k4]): casper.prepare(mk_prepare(i, 4, b'\x40' * 32, epoch_3_anchash, 3, epoch_3_anchash, k)) -for i, k in enumerate([t.k0, t.k1, t.k2, t.k3, t.k4]): +for i, k in enumerate([k0, k1, k2, k3, k4]): casper.commit(mk_commit(i, 4, b'\x40' * 32, 3, k)) assert casper.get_consensus_messages__committed(4) print("Prepared and committed") @@ -323,18 +329,18 @@ def mk_status_flicker(validator_index, epoch, login, key): assert 12 * 10**18 <= casper.get_total_deposits(4) <= 13 * 10**18 epoch_5_anchash = utils.sha3(b'\x50' * 32 + epoch_4_anchash) # Do three prepares -for i, k in enumerate([t.k0, t.k1, t.k2]): +for i, k in enumerate([k0, k1, k2]): casper.prepare(mk_prepare(i, 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)]: +for i, k in [(3, k3), (4, k4)]: casper.prepare(mk_prepare(i, 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]): +for i, k in enumerate([k0, k1, k2, k3, k4]): casper.commit(mk_commit(i, 5, b'\x50' * 32, 4, k)) # Committed! assert casper.get_consensus_messages__committed(5) @@ -353,7 +359,7 @@ def mk_status_flicker(validator_index, epoch, login, key): # * During dynasty 2, the validator logs off, so he leaves the current set in dynasty 4 # (epoch 5) and the previous set in dynasty 5 (epoch 6) assert [casper.check_eligible_in_epoch(4, i) for i in range(7)] == [0, 0, 0, 2, 3, 1, 0] -casper.flick_status(mk_status_flicker(4, 6, 1, t.k4)) +casper.flick_status(mk_status_flicker(4, 6, 1, k4)) # Explanation: # * During dynasty 7, the validator will log on again. Hence, the dynasty mask # should include dynasties 4, 5, 6 @@ -364,9 +370,9 @@ def mk_status_flicker(validator_index, epoch, login, key): 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) -for i, k in enumerate([t.k0, t.k1, t.k2]): +for i, k in enumerate([k0, k1, k2]): casper.prepare(mk_prepare(i, 6, b'\x60' * 32, epoch_5_anchash, 5, epoch_5_anchash, k)) -for i, k in enumerate([t.k0, t.k1, t.k2]): +for i, k in enumerate([k0, k1, k2]): casper.commit(mk_commit(i, 6, b'\x60' * 32, 5, k)) assert casper.get_consensus_messages__committed(6) print("Three of four prepares and commits sufficient") @@ -377,7 +383,7 @@ def mk_status_flicker(validator_index, epoch, login, key): 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]): +for i, k in enumerate([k0, k1, k2]): #if i == 1: # configure_logging(config_string=config_string) casper.prepare(mk_prepare(i, 7, b'\x70' * 32, epoch_6_anchash, 6, epoch_6_anchash, k)) @@ -387,7 +393,7 @@ def mk_status_flicker(validator_index, epoch, login, key): print('Gas consumed for first prepare', s.state.receipts[-1].gas_used - s.state.receipts[-2].gas_used) print('Gas consumed for second prepare', s.state.receipts[-2].gas_used - s.state.receipts[-3].gas_used) print('Gas consumed for third prepare', s.state.receipts[-3].gas_used - s.state.receipts[-4].gas_used) -for i, k in enumerate([t.k0, t.k1, t.k2]): +for i, k in enumerate([k0, k1, k2]): casper.commit(mk_commit(i, 7, b'\x70' * 32, 6, k)) print('Gas consumed for first commit', s.state.receipts[-1].gas_used - s.state.receipts[-2].gas_used) print('Gas consumed for second commit', s.state.receipts[-2].gas_used - s.state.receipts[-3].gas_used) @@ -403,18 +409,18 @@ def mk_status_flicker(validator_index, epoch, login, key): assert 15 * 10**18 <= casper.get_total_deposits(7) <= 16 * 10**18 epoch_8_anchash = utils.sha3(b'\x80' * 32 + epoch_7_anchash) # Do three prepares -for i, k in enumerate([t.k0, t.k1, t.k2]): +for i, k in enumerate([k0, k1, k2]): casper.prepare(mk_prepare(i, 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)]: +for i, k in [(3, k3)]: casper.prepare(mk_prepare(i, 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]): +for i, k in enumerate([k0, k1, k2, k3, k4]): casper.commit(mk_commit(i, 8, b'\x80' * 32, 7 if i < 3 else 5, k)) assert casper.get_consensus_messages__committed(8) print("Committed") From 2f43da9150ac096d7e9e6108f04fcb7f583b9c46 Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Mon, 1 May 2017 17:40:28 -0400 Subject: [PATCH 04/10] Fix small validator deposit bug --- casper/contracts/simple_casper.v.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/casper/contracts/simple_casper.v.py b/casper/contracts/simple_casper.v.py index 11a4556..6395d86 100644 --- a/casper/contracts/simple_casper.v.py +++ b/casper/contracts/simple_casper.v.py @@ -452,7 +452,7 @@ def double_prepare_slash(prepare1: bytes <= 1000, prepare2: bytes <= 1000): validator_deposit = self.validators[validator_index].deposit send(msg.sender, validator_deposit / 25) self.total_destroyed += validator_deposit * 24 / 25 - self.total_deposits[self.dynasty] -= (validator_deposit - validator_deposit / 25) + self.total_deposits[self.dynasty] -= validator_deposit self.delete_validator(validator_index) def prepare_commit_inconsistency_slash(prepare_msg: bytes <= 1024, commit_msg: bytes <= 1024): From a0a47dd5d0c76c3d48f8f6aa18886d6fbd48a09d Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Mon, 1 May 2017 17:46:59 -0400 Subject: [PATCH 05/10] Pass tests up to epoch 5 --- casper/contracts/simple_casper_tester.py | 50 +++++++++++------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/casper/contracts/simple_casper_tester.py b/casper/contracts/simple_casper_tester.py index 22611f9..f6f5a28 100644 --- a/casper/contracts/simple_casper_tester.py +++ b/casper/contracts/simple_casper_tester.py @@ -44,7 +44,6 @@ def mk_validation_code(address): # Install RLP decoder library rlp_decoder_address = inject_tx('0xf90237808506fc23ac00830330888080b902246102128061000e60003961022056600060007f010000000000000000000000000000000000000000000000000000000000000060003504600060c082121515585760f882121561004d5760bf820336141558576001905061006e565b600181013560f783036020035260005160f6830301361415585760f6820390505b5b368112156101c2577f010000000000000000000000000000000000000000000000000000000000000081350483602086026040015260018501945060808112156100d55760018461044001526001828561046001376001820191506021840193506101bc565b60b881121561014357608081038461044001526080810360018301856104600137608181141561012e5760807f010000000000000000000000000000000000000000000000000000000000000060018401350412151558575b607f81038201915060608103840193506101bb565b60c08112156101b857600182013560b782036020035260005160388112157f010000000000000000000000000000000000000000000000000000000000000060018501350402155857808561044001528060b6838501038661046001378060b6830301830192506020810185019450506101ba565bfe5b5b5b5061006f565b601f841315155857602060208502016020810391505b6000821215156101fc578082604001510182826104400301526020820391506101d8565b808401610420528381018161044003f350505050505b6000f31b2d4f') -t.mine() # Install sig hasher @@ -72,7 +71,6 @@ def mk_validation_code(address): .replace('0xD7a3BD6C9eA32efF147d067f907AE6b22d436F91', utils.checksum_encode(purity_checker_address)) print('Casper code length', len(compiler.compile(casper_code))) - casper = t.contract(casper_code, language='viper', startgas=4096181) print('Gas consumed to launch Casper', t.chain.state.receipts[-1].gas_used - t.chain.state.receipts[-2].gas_used) t.mine() @@ -105,13 +103,14 @@ def epoch_blockhash(epoch): def mine_and_init_epochs(number_of_epochs): distance_to_next_epoch = (EPOCH_LENGTH - t.chain.state.block_number) % EPOCH_LENGTH - t.mine(number_of_blocks=distance_to_next_epoch+2) + t.mine(number_of_blocks=distance_to_next_epoch) casper.initialize_epoch(t.chain.state.block_number // EPOCH_LENGTH) for i in range(number_of_epochs-1): print("Initializing epoch", t.chain.state.block_number // EPOCH_LENGTH) t.mine(number_of_blocks=EPOCH_LENGTH) casper.initialize_epoch(t.chain.state.block_number // EPOCH_LENGTH) print("Initializing epoch", t.chain.state.block_number // EPOCH_LENGTH) + t.mine(number_of_blocks=2) # Begin the test @@ -119,9 +118,7 @@ def mine_and_init_epochs(number_of_epochs): casper.initiate() # Initialize the first epoch -# t.mine(number_of_blocks=EPOCH_LENGTH-t.chain.state.block_number+2) mine_and_init_epochs(1) -# print('foo', casper.initialize_epoch(1)) assert casper.get_nextValidatorIndex() == 1 start = t.snapshot() print("Epoch initialized") @@ -156,58 +153,55 @@ def mine_and_init_epochs(number_of_epochs): casper.prepare(mk_prepare(0, 2, epoch_blockhash(2), epoch_1_anchash, 1, epoch_1_anchash, k0)) # Send a commit message epoch_2_commit = mk_commit(0, 2, epoch_blockhash(2), 1, k0) -raise SystemExit casper.commit(epoch_2_commit) -epoch_2_anchash = utils.sha3(b'\x45' * 32 + epoch_1_anchash) +epoch_2_anchash = utils.sha3(epoch_blockhash(2) + epoch_1_anchash) assert casper.get_consensus_messages__ancestry_hash_justified(2, epoch_2_anchash) # Check that we committed assert casper.get_consensus_messages__committed(2) # Initialize the third epoch -s.state.block_number += EPOCH_LENGTH -casper.initialize_epoch(3) +mine_and_init_epochs(1) print("Second epoch prepared and committed, third epoch initialized") # Test the NO_DBL_PREPARE slashing condition -p1 = mk_prepare(0, 3, '\x56' * 32, epoch_2_anchash, 2, epoch_2_anchash, k0) +p1 = mk_prepare(0, 3, epoch_blockhash(3), epoch_2_anchash, 2, epoch_2_anchash, k0) p2 = mk_prepare(0, 3, '\x57' * 32, epoch_2_anchash, 2, epoch_2_anchash, k0) -snapshot = s.snapshot() +snapshot = t.snapshot() casper.double_prepare_slash(p1, p2) -s.revert(snapshot) +t.revert(snapshot) print("NO_DBL_PREPARE slashing condition works") # Test the PREPARE_COMMIT_CONSISTENCY slashing condition -p3 = mk_prepare(0, 3, '\x58' * 32, epoch_2_anchash, 0, b'\x00' * 32, k0) -snapshot = s.snapshot() +p3 = mk_prepare(0, 3, epoch_blockhash(3), epoch_2_anchash, 0, epoch_blockhash(0), k0) +snapshot = t.snapshot() casper.prepare_commit_inconsistency_slash(p3, epoch_2_commit) -s.revert(snapshot) +t.revert(snapshot) print("PREPARE_COMMIT_CONSISTENCY slashing condition works") # Finish the third epoch +t.mine() casper.prepare(p1) -casper.commit(mk_commit(0, 3, '\x56' * 32, 2, k0)) -epoch_3_anchash = utils.sha3(b'\x56' * 32 + epoch_2_anchash) +casper.commit(mk_commit(0, 3, epoch_blockhash(3), 2, k0)) +epoch_3_anchash = utils.sha3(epoch_blockhash(3) + epoch_2_anchash) assert casper.get_consensus_messages__ancestry_hash_justified(3, epoch_3_anchash) assert casper.get_consensus_messages__committed(3) # Initialize the fourth epoch. Not doing prepares or commits during this epoch. -s.state.block_number += EPOCH_LENGTH -casper.initialize_epoch(4) +mine_and_init_epochs(1) assert casper.get_dynasty() == 3 -epoch_4_anchash = utils.sha3(b'\x67' * 32 + epoch_3_anchash) +epoch_4_anchash = utils.sha3(epoch_blockhash(4) + epoch_3_anchash) # Not publishing this prepare for the time being -p4 = mk_prepare(0, 4, '\x78' * 32, '\x12' * 32, 3, '\x24' * 32, k0) +p4 = mk_prepare(0, 4, epoch_blockhash(4), '\x12' * 32, 3, '\x24' * 32, k0) # Initialize the fifth epoch -s.state.block_number += EPOCH_LENGTH -casper.initialize_epoch(5) +mine_and_init_epochs(1) print("Epochs up to 5 initialized") # Dynasty not incremented because no commits were made assert casper.get_dynasty() == 3 +t.mine() epoch_5_anchash = utils.sha3(b'\x78' * 32 + epoch_4_anchash) -p5 = mk_prepare(0, 5, '\x78' * 32, epoch_4_anchash, 3, epoch_3_anchash, k0) -casper.prepare(p5) +p5 = mk_prepare(0, 5, epoch_blockhash(4), epoch_4_anchash, 3, epoch_3_anchash, k0) +assert casper.prepare(p5) is not False # Prepare works, but no reward is given +raise SystemExit # Test the COMMIT_REQ slashing condition kommit = mk_commit(0, 5, b'\x80' * 32, 3, k0) epoch_inc = 1 + int(86400 / 14 / EPOCH_LENGTH) -s.state.block_number += EPOCH_LENGTH * epoch_inc print("Speeding up time to test remaining two slashing conditions") -for i in range(6, 6 + epoch_inc): - casper.initialize_epoch(i) +mine_and_init_epochs(epoch_inc) print("Epochs up to %d initialized" % (6 + epoch_inc)) snapshot = s.snapshot() casper.commit_non_justification_slash(kommit) From 7280d6080b852740a4c22ed74c9e1a6e71c08a4a Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Mon, 1 May 2017 19:06:29 -0400 Subject: [PATCH 06/10] Finish porting test 1 --- casper/contracts/simple_casper_tester.py | 48 ++++++++++++------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/casper/contracts/simple_casper_tester.py b/casper/contracts/simple_casper_tester.py index f6f5a28..c9e1585 100644 --- a/casper/contracts/simple_casper_tester.py +++ b/casper/contracts/simple_casper_tester.py @@ -20,6 +20,7 @@ t = tester2.Chain(alloc={a: {'balance': 5*10**18} for a in tester2.accounts[:10]}, env=config.Env(config=casper_config)) EPOCH_LENGTH = 100 +SLASH_DELAY = 8640 def inject_tx(txhex): tx = rlp.decode(utils.decode_hex(txhex[2:]), transactions.Transaction) @@ -66,7 +67,9 @@ def mk_validation_code(address): # Install Casper -casper_code = open('simple_casper.v.py').read().replace('0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6', utils.checksum_encode(k1_valcode_addr)) \ +casper_code = open('simple_casper.v.py').read().replace('epoch_length = 100', 'epoch_length = ' + str(EPOCH_LENGTH)) \ + .replace('insufficiency_slash_delay = 86400', 'insufficiency_slash_delay = ' + str(SLASH_DELAY)) \ + .replace('0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6', utils.checksum_encode(k1_valcode_addr)) \ .replace('0x476c2cA9a7f3B16FeCa86512276271FAf63B6a24', utils.checksum_encode(sighasher_address)) \ .replace('0xD7a3BD6C9eA32efF147d067f907AE6b22d436F91', utils.checksum_encode(purity_checker_address)) @@ -193,42 +196,39 @@ def mine_and_init_epochs(number_of_epochs): # Dynasty not incremented because no commits were made assert casper.get_dynasty() == 3 t.mine() -epoch_5_anchash = utils.sha3(b'\x78' * 32 + epoch_4_anchash) +epoch_5_anchash = utils.sha3(epoch_blockhash(4) + epoch_4_anchash) p5 = mk_prepare(0, 5, epoch_blockhash(4), epoch_4_anchash, 3, epoch_3_anchash, k0) assert casper.prepare(p5) is not False # Prepare works, but no reward is given -raise SystemExit +t.mine() # Test the COMMIT_REQ slashing condition kommit = mk_commit(0, 5, b'\x80' * 32, 3, k0) -epoch_inc = 1 + int(86400 / 14 / EPOCH_LENGTH) +epoch_inc = 1 + int(SLASH_DELAY / 14 / EPOCH_LENGTH) print("Speeding up time to test remaining two slashing conditions") mine_and_init_epochs(epoch_inc) print("Epochs up to %d initialized" % (6 + epoch_inc)) -snapshot = s.snapshot() -casper.commit_non_justification_slash(kommit) -s.revert(snapshot) -try: - casper.commit_non_justification_slash(0, epoch_2_commit) - success = True -except: - success = False -assert not success +snapshot = t.snapshot() +assert casper.commit_non_justification_slash(kommit) is not False +t.revert(snapshot) +assert casper.commit_non_justification_slash(epoch_2_commit) is False +t.mine() print("COMMIT_REQ slashing condition works") # Test the PREPARE_REQ slashing condition -casper.derive_parenthood(epoch_3_anchash, b'\x67' * 32, epoch_4_anchash) +assert casper.derive_parenthood(epoch_3_anchash, epoch_blockhash(4), epoch_4_anchash) is not False +t.mine() assert casper.get_ancestry(epoch_3_anchash, epoch_4_anchash) == 1 +t.mine() assert casper.get_ancestry(epoch_4_anchash, epoch_5_anchash) == 1 -casper.derive_ancestry(epoch_3_anchash, epoch_4_anchash, epoch_5_anchash) +t.mine() +assert casper.derive_ancestry(epoch_3_anchash, epoch_4_anchash, epoch_5_anchash) is not False +t.mine() assert casper.get_ancestry(epoch_3_anchash, epoch_5_anchash) == 2 -snapshot = s.snapshot() -casper.prepare_non_justification_slash(p4) -s.revert(snapshot) -try: - casper.prepare_non_justification_slash(p5) - success = True -except: - success = False -assert not success +t.mine() +snapshot = t.snapshot() +assert casper.prepare_non_justification_slash(p4) is not False +t.revert(snapshot) +assert casper.prepare_non_justification_slash(p5) is False print("PREPARE_REQ slashing condition works") +raise SystemExit print("Restarting the chain for test 2") # Restart the chain From 759f16998bcb13845ce827fd3fc01f4200cf6f35 Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Wed, 3 May 2017 21:39:49 -0400 Subject: [PATCH 07/10] Add make_casper_chain() for chain reinitialization *Turn the Casper chain setup into a method to allow it to be reused when initializing the chain during test 2 --- casper/contracts/simple_casper_tester.py | 81 +++++++++++++----------- 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/casper/contracts/simple_casper_tester.py b/casper/contracts/simple_casper_tester.py index c9e1585..31c4e2e 100644 --- a/casper/contracts/simple_casper_tester.py +++ b/casper/contracts/simple_casper_tester.py @@ -1,6 +1,6 @@ import copy from ethereum import tester2 -from ethereum import utils, state_transition, transactions, abi, config +from ethereum import utils, state_transition, transactions, abi, config, state from viper import compiler import serpent @@ -17,23 +17,10 @@ k0, k1, k2, k3, k4, k5, k6, k7, k8, k9 = tester2.keys[:10] a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = tester2.accounts[:10] -t = tester2.Chain(alloc={a: {'balance': 5*10**18} for a in tester2.accounts[:10]}, env=config.Env(config=casper_config)) EPOCH_LENGTH = 100 SLASH_DELAY = 8640 -def inject_tx(txhex): - tx = rlp.decode(utils.decode_hex(txhex[2:]), transactions.Transaction) - t.head_state.set_balance(tx.sender, tx.startgas * tx.gasprice) - t.chain.state.set_balance(tx.sender, tx.startgas * tx.gasprice) - success, output = state_transition.apply_transaction(t.head_state, tx) - t.block.transactions.append(tx) - t.mine() - contract_address = utils.mk_contract_address(tx.sender, 0) - assert success - assert t.chain.state.get_code(contract_address) - return contract_address - code_template = """ ~calldatacopy(0, 0, 128) ~call(3000, 1, 0, 0, 128, 0, 32) @@ -43,40 +30,57 @@ def inject_tx(txhex): def mk_validation_code(address): return serpent.compile(code_template % (utils.checksum_encode(address))) -# Install RLP decoder library -rlp_decoder_address = inject_tx('0xf90237808506fc23ac00830330888080b902246102128061000e60003961022056600060007f010000000000000000000000000000000000000000000000000000000000000060003504600060c082121515585760f882121561004d5760bf820336141558576001905061006e565b600181013560f783036020035260005160f6830301361415585760f6820390505b5b368112156101c2577f010000000000000000000000000000000000000000000000000000000000000081350483602086026040015260018501945060808112156100d55760018461044001526001828561046001376001820191506021840193506101bc565b60b881121561014357608081038461044001526080810360018301856104600137608181141561012e5760807f010000000000000000000000000000000000000000000000000000000000000060018401350412151558575b607f81038201915060608103840193506101bb565b60c08112156101b857600182013560b782036020035260005160388112157f010000000000000000000000000000000000000000000000000000000000000060018501350402155857808561044001528060b6838501038661046001378060b6830301830192506020810185019450506101ba565bfe5b5b5b5061006f565b601f841315155857602060208502016020810391505b6000821215156101fc578082604001510182826104400301526020820391506101d8565b808401610420528381018161044003f350505050505b6000f31b2d4f') +def make_casper_chain(): + t = tester2.Chain(alloc={a: {'balance': 5*10**19} for a in tester2.accounts[:10]}, env=config.Env(config=casper_config)) -# Install sig hasher + def inject_tx(txhex): + tx = rlp.decode(utils.decode_hex(txhex[2:]), transactions.Transaction) + t.head_state.set_balance(tx.sender, tx.startgas * tx.gasprice) + t.chain.state.set_balance(tx.sender, tx.startgas * tx.gasprice) + success, output = state_transition.apply_transaction(t.head_state, tx) + t.block.transactions.append(tx) + t.mine() + contract_address = utils.mk_contract_address(tx.sender, 0) + assert success + assert t.chain.state.get_code(contract_address) + return contract_address -t.chain.state.set_balance('0x6e7406512b244843c1171840dfcd3d7532d979fe', 7291200000000000) -t.head_state.set_balance('0x6e7406512b244843c1171840dfcd3d7532d979fe', 7291200000000000) -sighasher_address = inject_tx('0xf9016d808506fc23ac0083026a508080b9015a6101488061000e6000396101565660007f01000000000000000000000000000000000000000000000000000000000000006000350460f8811215610038576001915061003f565b60f6810391505b508060005b368312156100c8577f01000000000000000000000000000000000000000000000000000000000000008335048391506080811215610087576001840193506100c2565b60b881121561009d57607f8103840193506100c1565b60c08112156100c05760b68103600185013560b783036020035260005101840193505b5b5b50610044565b81810360388112156100f4578060c00160005380836001378060010160002060e052602060e0f3610143565b61010081121561010557600161011b565b6201000081121561011757600261011a565b60035b5b8160005280601f038160f701815382856020378282600101018120610140526020610140f350505b505050505b6000f31b2d4f') + # Install RLP decoder library + rlp_decoder_address = inject_tx('0xf90237808506fc23ac00830330888080b902246102128061000e60003961022056600060007f010000000000000000000000000000000000000000000000000000000000000060003504600060c082121515585760f882121561004d5760bf820336141558576001905061006e565b600181013560f783036020035260005160f6830301361415585760f6820390505b5b368112156101c2577f010000000000000000000000000000000000000000000000000000000000000081350483602086026040015260018501945060808112156100d55760018461044001526001828561046001376001820191506021840193506101bc565b60b881121561014357608081038461044001526080810360018301856104600137608181141561012e5760807f010000000000000000000000000000000000000000000000000000000000000060018401350412151558575b607f81038201915060608103840193506101bb565b60c08112156101b857600182013560b782036020035260005160388112157f010000000000000000000000000000000000000000000000000000000000000060018501350402155857808561044001528060b6838501038661046001378060b6830301830192506020810185019450506101ba565bfe5b5b5b5061006f565b601f841315155857602060208502016020810391505b6000821215156101fc578082604001510182826104400301526020820391506101d8565b808401610420528381018161044003f350505050505b6000f31b2d4f') -# Install purity checker + # Install sig hasher -purity_checker_address = inject_tx('0xf90467808506fc23ac00830583c88080b904546104428061000e60003961045056600061033f537c0100000000000000000000000000000000000000000000000000000000600035047f80010000000000000000000000000000000000000030ffff1c0e00000000000060205263a1903eab8114156103f7573659905901600090523660048237600435608052506080513b806020015990590160009052818152602081019050905060a0526080513b600060a0516080513c6080513b8060200260200159905901600090528181526020810190509050610100526080513b806020026020015990590160009052818152602081019050905061016052600060005b602060a05103518212156103c957610100601f8360a051010351066020518160020a161561010a57fe5b80606013151561011e57607f811315610121565b60005b1561014f5780607f036101000a60018460a0510101510482602002610160510152605e8103830192506103b2565b60f18114801561015f5780610164565b60f282145b905080156101725780610177565b60f482145b9050156103aa5760028212151561019e5760606001830360200261010051015112156101a1565b60005b156101bc57607f6001830360200261010051015113156101bf565b60005b156101d157600282036102605261031e565b6004821215156101f057600360018303602002610100510151146101f3565b60005b1561020d57605a6002830360200261010051015114610210565b60005b1561022b57606060038303602002610100510151121561022e565b60005b1561024957607f60038303602002610100510151131561024c565b60005b1561025e57600482036102605261031d565b60028212151561027d57605a6001830360200261010051015114610280565b60005b1561029257600282036102605261031c565b6002821215156102b157609060018303602002610100510151146102b4565b60005b156102c657600282036102605261031b565b6002821215156102e65760806001830360200261010051015112156102e9565b60005b156103035760906001830360200261010051015112610306565b60005b1561031857600282036102605261031a565bfe5b5b5b5b5b604060405990590160009052600081526102605160200261016051015181602001528090502054156103555760016102a052610393565b60306102605160200261010051015114156103755760016102a052610392565b60606102605160200261010051015114156103915760016102a0525b5b5b6102a051151561039f57fe5b6001830192506103b1565b6001830192505b5b8082602002610100510152600182019150506100e0565b50506001604060405990590160009052600081526080518160200152809050205560016102e05260206102e0f35b63c23697a8811415610440573659905901600090523660048237600435608052506040604059905901600090526000815260805181602001528090502054610300526020610300f35b505b6000f31b2d4f') + t.chain.state.set_balance('0x6e7406512b244843c1171840dfcd3d7532d979fe', 7291200000000000) + t.head_state.set_balance('0x6e7406512b244843c1171840dfcd3d7532d979fe', 7291200000000000) -ct = abi.ContractTranslator([{'name': 'check(address)', 'type': 'function', 'constant': True, 'inputs': [{'name': 'addr', 'type': 'address'}], 'outputs': [{'name': 'out', 'type': 'bool'}]}, {'name': 'submit(address)', 'type': 'function', 'constant': False, 'inputs': [{'name': 'addr', 'type': 'address'}], 'outputs': [{'name': 'out', 'type': 'bool'}]}]) -# Check that the RLP decoding library and the sig hashing library are "pure" -assert utils.big_endian_to_int(t.tx(k0, purity_checker_address, 0, ct.encode('submit', [rlp_decoder_address]))) == 1 -assert utils.big_endian_to_int(t.tx(k0, purity_checker_address, 0, ct.encode('submit', [sighasher_address]))) == 1 + sighasher_address = inject_tx('0xf9016d808506fc23ac0083026a508080b9015a6101488061000e6000396101565660007f01000000000000000000000000000000000000000000000000000000000000006000350460f8811215610038576001915061003f565b60f6810391505b508060005b368312156100c8577f01000000000000000000000000000000000000000000000000000000000000008335048391506080811215610087576001840193506100c2565b60b881121561009d57607f8103840193506100c1565b60c08112156100c05760b68103600185013560b783036020035260005101840193505b5b5b50610044565b81810360388112156100f4578060c00160005380836001378060010160002060e052602060e0f3610143565b61010081121561010557600161011b565b6201000081121561011757600261011a565b60035b5b8160005280601f038160f701815382856020378282600101018120610140526020610140f350505b505050505b6000f31b2d4f') -k1_valcode_addr = t.tx(k0, "", 0, mk_validation_code(a0)) -assert utils.big_endian_to_int(t.tx(k0, purity_checker_address, 0, ct.encode('submit', [k1_valcode_addr]))) == 1 + # Install purity checker -# Install Casper + purity_checker_address = inject_tx('0xf90467808506fc23ac00830583c88080b904546104428061000e60003961045056600061033f537c0100000000000000000000000000000000000000000000000000000000600035047f80010000000000000000000000000000000000000030ffff1c0e00000000000060205263a1903eab8114156103f7573659905901600090523660048237600435608052506080513b806020015990590160009052818152602081019050905060a0526080513b600060a0516080513c6080513b8060200260200159905901600090528181526020810190509050610100526080513b806020026020015990590160009052818152602081019050905061016052600060005b602060a05103518212156103c957610100601f8360a051010351066020518160020a161561010a57fe5b80606013151561011e57607f811315610121565b60005b1561014f5780607f036101000a60018460a0510101510482602002610160510152605e8103830192506103b2565b60f18114801561015f5780610164565b60f282145b905080156101725780610177565b60f482145b9050156103aa5760028212151561019e5760606001830360200261010051015112156101a1565b60005b156101bc57607f6001830360200261010051015113156101bf565b60005b156101d157600282036102605261031e565b6004821215156101f057600360018303602002610100510151146101f3565b60005b1561020d57605a6002830360200261010051015114610210565b60005b1561022b57606060038303602002610100510151121561022e565b60005b1561024957607f60038303602002610100510151131561024c565b60005b1561025e57600482036102605261031d565b60028212151561027d57605a6001830360200261010051015114610280565b60005b1561029257600282036102605261031c565b6002821215156102b157609060018303602002610100510151146102b4565b60005b156102c657600282036102605261031b565b6002821215156102e65760806001830360200261010051015112156102e9565b60005b156103035760906001830360200261010051015112610306565b60005b1561031857600282036102605261031a565bfe5b5b5b5b5b604060405990590160009052600081526102605160200261016051015181602001528090502054156103555760016102a052610393565b60306102605160200261010051015114156103755760016102a052610392565b60606102605160200261010051015114156103915760016102a0525b5b5b6102a051151561039f57fe5b6001830192506103b1565b6001830192505b5b8082602002610100510152600182019150506100e0565b50506001604060405990590160009052600081526080518160200152809050205560016102e05260206102e0f35b63c23697a8811415610440573659905901600090523660048237600435608052506040604059905901600090526000815260805181602001528090502054610300526020610300f35b505b6000f31b2d4f') -casper_code = open('simple_casper.v.py').read().replace('epoch_length = 100', 'epoch_length = ' + str(EPOCH_LENGTH)) \ - .replace('insufficiency_slash_delay = 86400', 'insufficiency_slash_delay = ' + str(SLASH_DELAY)) \ - .replace('0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6', utils.checksum_encode(k1_valcode_addr)) \ - .replace('0x476c2cA9a7f3B16FeCa86512276271FAf63B6a24', utils.checksum_encode(sighasher_address)) \ - .replace('0xD7a3BD6C9eA32efF147d067f907AE6b22d436F91', utils.checksum_encode(purity_checker_address)) + ct = abi.ContractTranslator([{'name': 'check(address)', 'type': 'function', 'constant': True, 'inputs': [{'name': 'addr', 'type': 'address'}], 'outputs': [{'name': 'out', 'type': 'bool'}]}, {'name': 'submit(address)', 'type': 'function', 'constant': False, 'inputs': [{'name': 'addr', 'type': 'address'}], 'outputs': [{'name': 'out', 'type': 'bool'}]}]) + # Check that the RLP decoding library and the sig hashing library are "pure" + assert utils.big_endian_to_int(t.tx(k0, purity_checker_address, 0, ct.encode('submit', [rlp_decoder_address]))) == 1 + assert utils.big_endian_to_int(t.tx(k0, purity_checker_address, 0, ct.encode('submit', [sighasher_address]))) == 1 -print('Casper code length', len(compiler.compile(casper_code))) -casper = t.contract(casper_code, language='viper', startgas=4096181) -print('Gas consumed to launch Casper', t.chain.state.receipts[-1].gas_used - t.chain.state.receipts[-2].gas_used) -t.mine() + k1_valcode_addr = t.tx(k0, "", 0, mk_validation_code(a0)) + assert utils.big_endian_to_int(t.tx(k0, purity_checker_address, 0, ct.encode('submit', [k1_valcode_addr]))) == 1 + + # Install Casper + + casper_code = open('simple_casper.v.py').read().replace('epoch_length = 100', 'epoch_length = ' + str(EPOCH_LENGTH)) \ + .replace('insufficiency_slash_delay = 86400', 'insufficiency_slash_delay = ' + str(SLASH_DELAY)) \ + .replace('0x1Db3439a222C519ab44bb1144fC28167b4Fa6EE6', utils.checksum_encode(k1_valcode_addr)) \ + .replace('0x476c2cA9a7f3B16FeCa86512276271FAf63B6a24', utils.checksum_encode(sighasher_address)) \ + .replace('0xD7a3BD6C9eA32efF147d067f907AE6b22d436F91', utils.checksum_encode(purity_checker_address)) + + print('Casper code length', len(compiler.compile(casper_code))) + casper = t.contract(casper_code, language='viper', startgas=4096181) + print('Gas consumed to launch Casper', t.chain.state.receipts[-1].gas_used - t.chain.state.receipts[-2].gas_used) + t.mine() + return t, casper # Helper functions for making a prepare, commit, login and logout message @@ -118,6 +122,7 @@ def mine_and_init_epochs(number_of_epochs): # Begin the test print("Starting tests") +t, casper = make_casper_chain() casper.initiate() # Initialize the first epoch From 468552cebd53a124e1e6e79859ce2f678494a3c3 Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Wed, 3 May 2017 22:03:29 -0400 Subject: [PATCH 08/10] Port second round of tests & minor edits *Port second round of tests *Change tester2 to raise TransactionFailed() if a tx doesn't go through. This allows us to distinguish between a contract returning False and a tx exception *Remove a few unneeded t.mine() statements --- casper/contracts/simple_casper_tester.py | 185 +++++++++++++---------- 1 file changed, 101 insertions(+), 84 deletions(-) diff --git a/casper/contracts/simple_casper_tester.py b/casper/contracts/simple_casper_tester.py index 31c4e2e..d92660d 100644 --- a/casper/contracts/simple_casper_tester.py +++ b/casper/contracts/simple_casper_tester.py @@ -1,6 +1,6 @@ import copy from ethereum import tester2 -from ethereum import utils, state_transition, transactions, abi, config, state +from ethereum import utils, state_transition, transactions, abi, config from viper import compiler import serpent @@ -80,7 +80,7 @@ def inject_tx(txhex): casper = t.contract(casper_code, language='viper', startgas=4096181) print('Gas consumed to launch Casper', t.chain.state.receipts[-1].gas_used - t.chain.state.receipts[-2].gas_used) t.mine() - return t, casper + return t, casper, purity_checker_address, ct # Helper functions for making a prepare, commit, login and logout message @@ -122,28 +122,31 @@ def mine_and_init_epochs(number_of_epochs): # Begin the test print("Starting tests") -t, casper = make_casper_chain() +t, casper, purity_checker_address, ct = make_casper_chain() casper.initiate() # Initialize the first epoch mine_and_init_epochs(1) assert casper.get_nextValidatorIndex() == 1 -start = t.snapshot() print("Epoch initialized") print("Reward factor: %.8f" % (casper.get_reward_factor() * 2 / 3)) # Send a prepare message # configure_logging(config_string=config_string) -assert casper.prepare(mk_prepare(0, 1, epoch_blockhash(1), epoch_blockhash(0), 0, epoch_blockhash(0), k0)) is not False +casper.prepare(mk_prepare(0, 1, epoch_blockhash(1), epoch_blockhash(0), 0, epoch_blockhash(0), k0)) print('Gas consumed for a prepare: %d (including %d intrinsic gas)' % - (t.chain.state.receipts[-1].gas_used - t.chain.state.receipts[-2].gas_used, t.last_tx.intrinsic_gas_used)) + (t.chain.state.receipts[-1].gas_used, t.last_tx.intrinsic_gas_used)) epoch_1_anchash = utils.sha3(epoch_blockhash(1) + epoch_blockhash(0)) assert casper.get_consensus_messages__hash_justified(1, epoch_blockhash(1)) assert casper.get_consensus_messages__ancestry_hash_justified(1, epoch_1_anchash) print("Prepare message processed") -assert casper.prepare(mk_prepare(0, 1, epoch_blockhash(1), epoch_blockhash(0), 0, epoch_blockhash(0), k0)) is False -print("Prepare message fails the second time") -# Mine our prepares +try: + casper.prepare(mk_prepare(0, 1, epoch_blockhash(1), epoch_blockhash(0), 0, epoch_blockhash(0), k0)) + success = True +except: + success = False +assert not success t.mine() +print("Prepare message fails the second time") # Send a commit message print('commit!', casper.commit(mk_commit(0, 1, epoch_blockhash(1), 0, k0))) print('Gas consumed for a commit: %d (including %d intrinsic gas)' % @@ -183,7 +186,6 @@ def mine_and_init_epochs(number_of_epochs): t.revert(snapshot) print("PREPARE_COMMIT_CONSISTENCY slashing condition works") # Finish the third epoch -t.mine() casper.prepare(p1) casper.commit(mk_commit(0, 3, epoch_blockhash(3), 2, k0)) epoch_3_anchash = utils.sha3(epoch_blockhash(3) + epoch_2_anchash) @@ -200,11 +202,9 @@ def mine_and_init_epochs(number_of_epochs): print("Epochs up to 5 initialized") # Dynasty not incremented because no commits were made assert casper.get_dynasty() == 3 -t.mine() epoch_5_anchash = utils.sha3(epoch_blockhash(4) + epoch_4_anchash) p5 = mk_prepare(0, 5, epoch_blockhash(4), epoch_4_anchash, 3, epoch_3_anchash, k0) -assert casper.prepare(p5) is not False # Prepare works, but no reward is given -t.mine() +casper.prepare(p5) # Prepare works, but no reward is given TODO: Add test for this! # Test the COMMIT_REQ slashing condition kommit = mk_commit(0, 5, b'\x80' * 32, 3, k0) epoch_inc = 1 + int(SLASH_DELAY / 14 / EPOCH_LENGTH) @@ -212,57 +212,68 @@ def mine_and_init_epochs(number_of_epochs): mine_and_init_epochs(epoch_inc) print("Epochs up to %d initialized" % (6 + epoch_inc)) snapshot = t.snapshot() -assert casper.commit_non_justification_slash(kommit) is not False +casper.commit_non_justification_slash(kommit) t.revert(snapshot) -assert casper.commit_non_justification_slash(epoch_2_commit) is False +try: + casper.commit_non_justification_slash(epoch_2_commit) + success = True +except: + success = False +assert not success t.mine() print("COMMIT_REQ slashing condition works") # Test the PREPARE_REQ slashing condition -assert casper.derive_parenthood(epoch_3_anchash, epoch_blockhash(4), epoch_4_anchash) is not False +casper.derive_parenthood(epoch_3_anchash, epoch_blockhash(4), epoch_4_anchash) t.mine() assert casper.get_ancestry(epoch_3_anchash, epoch_4_anchash) == 1 -t.mine() assert casper.get_ancestry(epoch_4_anchash, epoch_5_anchash) == 1 -t.mine() -assert casper.derive_ancestry(epoch_3_anchash, epoch_4_anchash, epoch_5_anchash) is not False +casper.derive_ancestry(epoch_3_anchash, epoch_4_anchash, epoch_5_anchash) t.mine() assert casper.get_ancestry(epoch_3_anchash, epoch_5_anchash) == 2 t.mine() snapshot = t.snapshot() -assert casper.prepare_non_justification_slash(p4) is not False +casper.prepare_non_justification_slash(p4) t.revert(snapshot) -assert casper.prepare_non_justification_slash(p5) is False +try: + casper.prepare_non_justification_slash(p5) + success = True +except: + success = False +assert not success print("PREPARE_REQ slashing condition works") -raise SystemExit -print("Restarting the chain for test 2") -# Restart the chain -s.revert(start) +print("Creating a new chain for test 2") +# Create a new chain +t, casper, purity_checker_address, ct = make_casper_chain() +casper.initiate() + +# Initialize the first epoch +mine_and_init_epochs(1) +assert casper.get_nextValidatorIndex() == 1 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 (k1, k2, k3, k4, k5, k6): - valcode_addr = s.send(k0, '', 0, mk_validation_code(utils.privtoaddr(k))) - assert utils.big_endian_to_int(s.send(k0, purity_checker_address, 0, ct.encode('submit', [valcode_addr]))) == 1 + valcode_addr = t.tx(k0, '', 0, mk_validation_code(utils.privtoaddr(k))) + assert utils.big_endian_to_int(t.call(k0, purity_checker_address, 0, ct.encode('submit', [valcode_addr]))) == 1 casper.deposit(valcode_addr, utils.privtoaddr(k), value=3 * 10**18) + t.mine() print("Processed 6 deposits") -casper.prepare(mk_prepare(0, 1, b'\x10' * 32, b'\x00' * 32, 0, b'\x00' * 32, k0)) -casper.commit(mk_commit(0, 1, b'\x10' * 32, 0, k0)) -epoch_1_anchash = utils.sha3(b'\x10' * 32 + b'\x00' * 32) +casper.prepare(mk_prepare(0, 1, epoch_blockhash(1), epoch_blockhash(0), 0, epoch_blockhash(0), k0)) +casper.commit(mk_commit(0, 1, epoch_blockhash(1), 0, k0)) +epoch_1_anchash = utils.sha3(epoch_blockhash(1) + epoch_blockhash(0)) assert casper.get_consensus_messages__committed(1) print("Prepared and committed") -s.state.block_number += EPOCH_LENGTH -casper.initialize_epoch(2) +mine_and_init_epochs(1) print("Epoch 2 initialized") assert casper.get_dynasty() == 1 -casper.prepare(mk_prepare(0, 2, b'\x20' * 32, epoch_1_anchash, 1, epoch_1_anchash, k0)) -casper.commit(mk_commit(0, 2, b'\x20' * 32, 1, k0)) -epoch_2_anchash = utils.sha3(b'\x20' * 32 + epoch_1_anchash) -assert casper.get_consensus_messages__committed(2) +casper.prepare(mk_prepare(0, 2, epoch_blockhash(2), epoch_1_anchash, 1, epoch_1_anchash, k0)) +casper.commit(mk_commit(0, 2, epoch_blockhash(2), 1, k0)) +epoch_2_anchash = utils.sha3(epoch_blockhash(2) + epoch_1_anchash) +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) +mine_and_init_epochs(1) print("Epoch 3 initialized") assert casper.get_dynasty() == 2 assert 3 * 10**18 <= casper.get_total_deposits(0) < 4 * 10**18 @@ -270,12 +281,12 @@ def mine_and_init_epochs(number_of_epochs): assert 21 * 10**18 <= casper.get_total_deposits(2) < 22 * 10**18 print("Confirmed new total_deposits") try: - # Try to log out, but sign with the wrong key casper.flick_status(mk_status_flicker(0, 3, 0, k1)) success = True except: success = False assert not success +t.mine() # Log out casper.flick_status(mk_status_flicker(4, 3, 0, k4)) casper.flick_status(mk_status_flicker(5, 3, 0, k5)) @@ -283,69 +294,73 @@ def mine_and_init_epochs(number_of_epochs): 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) +epoch_3_anchash = utils.sha3(epoch_blockhash(3) + epoch_2_anchash) # Prepare from one validator -casper.prepare(mk_prepare(0, 3, b'\x30' * 32, epoch_2_anchash, 2, epoch_2_anchash, k0)) +casper.prepare(mk_prepare(0, 3, epoch_blockhash(3), epoch_2_anchash, 2, epoch_2_anchash, k0)) # Not prepared yet -assert not casper.get_consensus_messages__hash_justified(3, b'\x30' * 32) +assert not casper.get_consensus_messages__hash_justified(3, epoch_blockhash(3)) print("Prepare from one validator no longer sufficient") # Prepare from 3 more validators for i, k in ((1, k1), (2, k2), (3, k3)): - casper.prepare(mk_prepare(i, 3, b'\x30' * 32, epoch_2_anchash, 2, epoch_2_anchash, k)) + casper.prepare(mk_prepare(i, 3, epoch_blockhash(3), epoch_2_anchash, 2, epoch_2_anchash, k)) + t.mine() # Still not prepared -assert not casper.get_consensus_messages__hash_justified(3, b'\x30' * 32) +assert not casper.get_consensus_messages__hash_justified(3, epoch_blockhash(3)) print("Prepare from four of seven validators still not sufficient") # Prepare from a fifth validator -casper.prepare(mk_prepare(4, 3, b'\x30' * 32, epoch_2_anchash, 2, epoch_2_anchash, k4)) +casper.prepare(mk_prepare(4, 3, epoch_blockhash(3), epoch_2_anchash, 2, epoch_2_anchash, k4)) # NOW we're prepared! -assert casper.get_consensus_messages__hash_justified(3, b'\x30' * 32) +assert casper.get_consensus_messages__hash_justified(3, epoch_blockhash(3)) print("Prepare from five of seven validators sufficient!") # Five commits for i, k in enumerate([k0, k1, k2, k3, k4]): - casper.commit(mk_commit(i, 3, b'\x30' * 32, 2 if i == 0 else 0, k)) + casper.commit(mk_commit(i, 3, epoch_blockhash(3), 2 if i == 0 else 0, k)) + t.mine() # 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) +mine_and_init_epochs(1) assert casper.get_dynasty() == 3 print("Epoch 4 initialized") # Prepare and commit -epoch_4_anchash = utils.sha3(b'\x40' * 32 + epoch_3_anchash) +epoch_4_anchash = utils.sha3(epoch_blockhash(4) + epoch_3_anchash) for i, k in enumerate([k0, k1, k2, k3, k4]): - casper.prepare(mk_prepare(i, 4, b'\x40' * 32, epoch_3_anchash, 3, epoch_3_anchash, k)) + casper.prepare(mk_prepare(i, 4, epoch_blockhash(4), epoch_3_anchash, 3, epoch_3_anchash, k)) + t.mine() for i, k in enumerate([k0, k1, k2, k3, k4]): - casper.commit(mk_commit(i, 4, b'\x40' * 32, 3, k)) + casper.commit(mk_commit(i, 4, epoch_blockhash(4), 3, k)) + t.mine() 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) +mine_and_init_epochs(1) print("Epoch 5 initialized") assert casper.get_dynasty() == 4 assert 21 * 10**18 <= casper.get_total_deposits(3) <= 22 * 10**18 assert 12 * 10**18 <= casper.get_total_deposits(4) <= 13 * 10**18 -epoch_5_anchash = utils.sha3(b'\x50' * 32 + epoch_4_anchash) +epoch_5_anchash = utils.sha3(epoch_blockhash(5) + epoch_4_anchash) # Do three prepares for i, k in enumerate([k0, k1, k2]): - casper.prepare(mk_prepare(i, 5, b'\x50' * 32, epoch_4_anchash, 4, epoch_4_anchash, k)) + casper.prepare(mk_prepare(i, 5, epoch_blockhash(5), epoch_4_anchash, 4, epoch_4_anchash, k)) + t.mine() # 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) +assert not casper.get_consensus_messages__hash_justified(5, epoch_blockhash(5)) print("Three prepares insufficient, as rear validator set still has seven") # Do two more prepares for i, k in [(3, k3), (4, k4)]: - casper.prepare(mk_prepare(i, 5, b'\x50' * 32, epoch_4_anchash, 4, epoch_4_anchash, k)) + casper.prepare(mk_prepare(i, 5, epoch_blockhash(5), epoch_4_anchash, 4, epoch_4_anchash, k)) + t.mine() # Now we're good! -assert casper.get_consensus_messages__hash_justified(5, b'\x50' * 32) +assert casper.get_consensus_messages__hash_justified(5, epoch_blockhash(5)) print("Five prepares sufficient") for i, k in enumerate([k0, k1, k2, k3, k4]): - casper.commit(mk_commit(i, 5, b'\x50' * 32, 4, k)) + casper.commit(mk_commit(i, 5, epoch_blockhash(5), 4, k)) + t.mine() # Committed! assert casper.get_consensus_messages__committed(5) # Start epoch 6 / dynasty 5 -s.state.block_number += EPOCH_LENGTH -casper.initialize_epoch(6) +mine_and_init_epochs(1) assert casper.get_dynasty() == 5 print("Epoch 6 initialized") # Log back in @@ -359,6 +374,7 @@ def mine_and_init_epochs(number_of_epochs): # (epoch 5) and the previous set in dynasty 5 (epoch 6) assert [casper.check_eligible_in_epoch(4, i) for i in range(7)] == [0, 0, 0, 2, 3, 1, 0] casper.flick_status(mk_status_flicker(4, 6, 1, k4)) +t.mine() # Explanation: # * During dynasty 7, the validator will log on again. Hence, the dynasty mask # should include dynasties 4, 5, 6 @@ -368,59 +384,60 @@ def mine_and_init_epochs(number_of_epochs): print("Penalty from %d epochs: %.4f" % (old_deposit_end - old_deposit_start, 1 - new_deposit / old_deposit)) 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) +epoch_6_anchash = utils.sha3(epoch_blockhash(6) + epoch_5_anchash) for i, k in enumerate([k0, k1, k2]): - casper.prepare(mk_prepare(i, 6, b'\x60' * 32, epoch_5_anchash, 5, epoch_5_anchash, k)) + casper.prepare(mk_prepare(i, 6, epoch_blockhash(6), epoch_5_anchash, 5, epoch_5_anchash, k)) + t.mine() for i, k in enumerate([k0, k1, k2]): - casper.commit(mk_commit(i, 6, b'\x60' * 32, 5, k)) + casper.commit(mk_commit(i, 6, epoch_blockhash(6), 5, k)) + t.mine() 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) +mine_and_init_epochs(1) 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) +epoch_7_anchash = utils.sha3(epoch_blockhash(7) + epoch_6_anchash) for i, k in enumerate([k0, k1, k2]): #if i == 1: # configure_logging(config_string=config_string) - casper.prepare(mk_prepare(i, 7, b'\x70' * 32, epoch_6_anchash, 6, epoch_6_anchash, k)) + casper.prepare(mk_prepare(i, 7, epoch_blockhash(7), epoch_6_anchash, 6, epoch_6_anchash, k)) + print('Gas consumed for prepare', i, t.chain.state.receipts[-1].gas_used) + t.mine() #if i == 1: # import sys # sys.exit() -print('Gas consumed for first prepare', s.state.receipts[-1].gas_used - s.state.receipts[-2].gas_used) -print('Gas consumed for second prepare', s.state.receipts[-2].gas_used - s.state.receipts[-3].gas_used) -print('Gas consumed for third prepare', s.state.receipts[-3].gas_used - s.state.receipts[-4].gas_used) for i, k in enumerate([k0, k1, k2]): - casper.commit(mk_commit(i, 7, b'\x70' * 32, 6, k)) -print('Gas consumed for first commit', s.state.receipts[-1].gas_used - s.state.receipts[-2].gas_used) -print('Gas consumed for second commit', s.state.receipts[-2].gas_used - s.state.receipts[-3].gas_used) -print('Gas consumed for third commit', s.state.receipts[-3].gas_used - s.state.receipts[-4].gas_used) + casper.commit(mk_commit(i, 7, epoch_blockhash(7), 6, k)) + print('Gas consumed for prepare', i, t.chain.state.receipts[-1].gas_used) + t.mine() 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) +mine_and_init_epochs(1) assert casper.get_dynasty() == 7 print("Epoch 8 initialized") assert 12 * 10**18 <= casper.get_total_deposits(6) <= 13 * 10**18 assert 15 * 10**18 <= casper.get_total_deposits(7) <= 16 * 10**18 -epoch_8_anchash = utils.sha3(b'\x80' * 32 + epoch_7_anchash) +epoch_8_anchash = utils.sha3(epoch_blockhash(8) + epoch_7_anchash) # Do three prepares for i, k in enumerate([k0, k1, k2]): - casper.prepare(mk_prepare(i, 8, b'\x80' * 32, epoch_7_anchash, 7, epoch_7_anchash, k)) + casper.prepare(mk_prepare(i, 8, epoch_blockhash(8), epoch_7_anchash, 7, epoch_7_anchash, k)) + t.mine() # 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) +assert not casper.get_consensus_messages__hash_justified(8, epoch_blockhash(8)) print("Three prepares no longer sufficient, as the forward validator set has five validators") # Do one more prepare for i, k in [(3, k3)]: - casper.prepare(mk_prepare(i, 8, b'\x80' * 32, epoch_7_anchash, 7, epoch_7_anchash, k)) + casper.prepare(mk_prepare(i, 8, epoch_blockhash(8), epoch_7_anchash, 7, epoch_7_anchash, k)) + t.mine() # Now we're good! -assert casper.get_consensus_messages__hash_justified(8, b'\x80' * 32) +assert casper.get_consensus_messages__hash_justified(8, epoch_blockhash(8)) print("Four of five prepares sufficient") for i, k in enumerate([k0, k1, k2, k3, k4]): - casper.commit(mk_commit(i, 8, b'\x80' * 32, 7 if i < 3 else 5, k)) + casper.commit(mk_commit(i, 8, epoch_blockhash(8), 7 if i < 3 else 5, k)) + t.mine() assert casper.get_consensus_messages__committed(8) print("Committed") # Validator rejoins current validator set in epoch 8 From 962e05f3ee4284e1e325b98ef569cd7d73b6b4e5 Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Wed, 3 May 2017 22:27:24 -0400 Subject: [PATCH 09/10] Test that prepare & commit rewards are given --- casper/contracts/simple_casper_tester.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/casper/contracts/simple_casper_tester.py b/casper/contracts/simple_casper_tester.py index d92660d..46ec65a 100644 --- a/casper/contracts/simple_casper_tester.py +++ b/casper/contracts/simple_casper_tester.py @@ -3,7 +3,6 @@ from ethereum import utils, state_transition, transactions, abi, config from viper import compiler import serpent - from ethereum.slogging import LogRecorder, configure_logging, set_level config_string = ':info,eth.vm.log:trace,eth.vm.op:trace,eth.vm.stack:trace,eth.vm.exit:trace,eth.pb.msg:trace,eth.pb.tx:debug' #configure_logging(config_string=config_string) @@ -124,7 +123,6 @@ def mine_and_init_epochs(number_of_epochs): print("Starting tests") t, casper, purity_checker_address, ct = make_casper_chain() casper.initiate() - # Initialize the first epoch mine_and_init_epochs(1) assert casper.get_nextValidatorIndex() == 1 @@ -158,10 +156,11 @@ def mine_and_init_epochs(number_of_epochs): mine_and_init_epochs(1) # 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(mk_prepare(0, 2, epoch_blockhash(2), epoch_1_anchash, 1, epoch_1_anchash, k0)) +# Save the total deposits after the prepare for later +post_prepare_deposits = casper.get_total_deposits(1) # Send a commit message epoch_2_commit = mk_commit(0, 2, epoch_blockhash(2), 1, k0) casper.commit(epoch_2_commit) @@ -169,6 +168,10 @@ def mine_and_init_epochs(number_of_epochs): assert casper.get_consensus_messages__ancestry_hash_justified(2, epoch_2_anchash) # Check that we committed assert casper.get_consensus_messages__committed(2) +# Check that the reward was given for the prepare and commit +assert post_prepare_deposits - casper.get_total_deposits(0) > 0 +assert casper.get_total_deposits(1) - post_prepare_deposits > 0 +print('Initial deposits: %d, post-prepare: %d, post-commit: %d' % (casper.get_total_deposits(0), post_prepare_deposits, casper.get_total_deposits(1))) # Initialize the third epoch mine_and_init_epochs(1) print("Second epoch prepared and committed, third epoch initialized") @@ -204,7 +207,7 @@ def mine_and_init_epochs(number_of_epochs): assert casper.get_dynasty() == 3 epoch_5_anchash = utils.sha3(epoch_blockhash(4) + epoch_4_anchash) p5 = mk_prepare(0, 5, epoch_blockhash(4), epoch_4_anchash, 3, epoch_3_anchash, k0) -casper.prepare(p5) # Prepare works, but no reward is given TODO: Add test for this! +casper.prepare(p5) # Prepare works, and no reward is given # Test the COMMIT_REQ slashing condition kommit = mk_commit(0, 5, b'\x80' * 32, 3, k0) epoch_inc = 1 + int(SLASH_DELAY / 14 / EPOCH_LENGTH) From a976cd55ca5ea4419022ab7247388db22cc55013 Mon Sep 17 00:00:00 2001 From: Karl Floersch Date: Mon, 8 May 2017 00:51:56 -0400 Subject: [PATCH 10/10] Update to support state_revamp refactor --- casper/contracts/simple_casper_tester.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/casper/contracts/simple_casper_tester.py b/casper/contracts/simple_casper_tester.py index 46ec65a..23d81d4 100644 --- a/casper/contracts/simple_casper_tester.py +++ b/casper/contracts/simple_casper_tester.py @@ -1,6 +1,6 @@ import copy -from ethereum import tester2 -from ethereum import utils, state_transition, transactions, abi, config +from ethereum import utils, messages, transactions, abi, config +from ethereum.tools import tester2 from viper import compiler import serpent from ethereum.slogging import LogRecorder, configure_logging, set_level @@ -36,7 +36,7 @@ def inject_tx(txhex): tx = rlp.decode(utils.decode_hex(txhex[2:]), transactions.Transaction) t.head_state.set_balance(tx.sender, tx.startgas * tx.gasprice) t.chain.state.set_balance(tx.sender, tx.startgas * tx.gasprice) - success, output = state_transition.apply_transaction(t.head_state, tx) + success, output = messages.apply_transaction(t.head_state, tx) t.block.transactions.append(tx) t.mine() contract_address = utils.mk_contract_address(tx.sender, 0) @@ -77,7 +77,7 @@ def inject_tx(txhex): print('Casper code length', len(compiler.compile(casper_code))) casper = t.contract(casper_code, language='viper', startgas=4096181) - print('Gas consumed to launch Casper', t.chain.state.receipts[-1].gas_used - t.chain.state.receipts[-2].gas_used) + print('Gas consumed to launch Casper', t.head_state.receipts[-1].gas_used - t.head_state.receipts[-2].gas_used) t.mine() return t, casper, purity_checker_address, ct @@ -132,7 +132,7 @@ def mine_and_init_epochs(number_of_epochs): # configure_logging(config_string=config_string) casper.prepare(mk_prepare(0, 1, epoch_blockhash(1), epoch_blockhash(0), 0, epoch_blockhash(0), k0)) print('Gas consumed for a prepare: %d (including %d intrinsic gas)' % - (t.chain.state.receipts[-1].gas_used, t.last_tx.intrinsic_gas_used)) + (t.head_state.receipts[-1].gas_used, t.last_tx.intrinsic_gas_used)) epoch_1_anchash = utils.sha3(epoch_blockhash(1) + epoch_blockhash(0)) assert casper.get_consensus_messages__hash_justified(1, epoch_blockhash(1)) assert casper.get_consensus_messages__ancestry_hash_justified(1, epoch_1_anchash) @@ -148,7 +148,7 @@ def mine_and_init_epochs(number_of_epochs): # Send a commit message print('commit!', casper.commit(mk_commit(0, 1, epoch_blockhash(1), 0, k0))) print('Gas consumed for a commit: %d (including %d intrinsic gas)' % - (t.chain.state.receipts[-1].gas_used, t.last_tx.intrinsic_gas_used)) + (t.head_state.receipts[-1].gas_used, t.last_tx.intrinsic_gas_used)) # Check that we committed assert casper.get_consensus_messages__committed(1) print("Commit message processed") @@ -406,14 +406,14 @@ def mine_and_init_epochs(number_of_epochs): #if i == 1: # configure_logging(config_string=config_string) casper.prepare(mk_prepare(i, 7, epoch_blockhash(7), epoch_6_anchash, 6, epoch_6_anchash, k)) - print('Gas consumed for prepare', i, t.chain.state.receipts[-1].gas_used) + print('Gas consumed for prepare', i, t.head_state.receipts[-1].gas_used) t.mine() #if i == 1: # import sys # sys.exit() for i, k in enumerate([k0, k1, k2]): casper.commit(mk_commit(i, 7, epoch_blockhash(7), 6, k)) - print('Gas consumed for prepare', i, t.chain.state.receipts[-1].gas_used) + print('Gas consumed for prepare', i, t.head_state.receipts[-1].gas_used) t.mine() assert casper.get_consensus_messages__committed(7) print("Three of four prepares and commits sufficient")