|
| 1 | +from ethereum.state import State |
| 2 | +from ethereum.block import FakeHeader, Block |
| 3 | +from ethereum.utils import decode_hex, parse_int_or_hex, sha3, to_string, \ |
| 4 | + remove_0x_head, encode_hex, big_endian_to_int |
| 5 | +from ethereum.config import default_config, Env |
| 6 | +from ethereum.exceptions import InvalidTransaction |
| 7 | +import ethereum.transactions as transactions |
| 8 | +import ethereum.state_transition as state_transition |
| 9 | +import copy |
| 10 | + |
| 11 | +#from ethereum.slogging import LogRecorder, configure_logging, set_level |
| 12 | +#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' |
| 13 | +#configure_logging(config_string=config_string) |
| 14 | + |
| 15 | +fake_headers = {} |
| 16 | + |
| 17 | +def mk_fake_header(blknum): |
| 18 | + if blknum not in fake_headers: |
| 19 | + fake_headers[blknum] = FakeHeader(sha3(to_string(blknum))) |
| 20 | + return fake_headers[blknum] |
| 21 | + |
| 22 | +basic_env = { |
| 23 | + "currentCoinbase": "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", |
| 24 | + "currentDifficulty": "256", |
| 25 | + "currentGasLimit": "1000000000", |
| 26 | + "currentNumber": "257", |
| 27 | + "currentTimestamp": "1", |
| 28 | + "previousHash": "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" |
| 29 | +} |
| 30 | + |
| 31 | +konfig = copy.copy(default_config) |
| 32 | + |
| 33 | +konfig_spurious = copy.copy(konfig) |
| 34 | +konfig_spurious["HOMESTEAD_FORK_BLKNUM"] = 0 |
| 35 | +konfig_spurious["ANTI_DOS_FORK_BLKNUM"] = 0 |
| 36 | +konfig_spurious["CLEARING_FORK_BLKNUM"] = 0 |
| 37 | +konfig_spurious["METROPOLIS_FORK_BLKNUM"] = 2**99 |
| 38 | + |
| 39 | +konfig_metropolis = copy.copy(konfig) |
| 40 | +konfig_metropolis["HOMESTEAD_FORK_BLKNUM"] = 0 |
| 41 | +konfig_metropolis["ANTI_DOS_FORK_BLKNUM"] = 0 |
| 42 | +konfig_metropolis["CLEARING_FORK_BLKNUM"] = 0 |
| 43 | +konfig_metropolis["METROPOLIS_FORK_BLKNUM"] = 0 |
| 44 | + |
| 45 | +configs = { |
| 46 | + "EIP158": konfig_spurious, |
| 47 | + "Metropolis": konfig_metropolis |
| 48 | +} |
| 49 | + |
| 50 | +def compute_state_test_post(test, indices=None, _configs=None): |
| 51 | + env, pre, txdata = test["env"], test["pre"], test["transaction"] |
| 52 | + # Setup env |
| 53 | + state = State( |
| 54 | + env=Env(config=konfig), |
| 55 | + block_prevhash=decode_hex(env['previousHash']), |
| 56 | + prev_headers=[mk_fake_header(i) for i in range(parse_int_or_hex(env['currentNumber']) -1, |
| 57 | + max(-1, parse_int_or_hex(env['currentNumber']) -257), -1)], |
| 58 | + block_number=parse_int_or_hex(env['currentNumber']), |
| 59 | + block_coinbase=decode_hex(env['currentCoinbase']), |
| 60 | + block_difficulty=parse_int_or_hex(env['currentDifficulty']), |
| 61 | + gas_limit=parse_int_or_hex(env['currentGasLimit']), |
| 62 | + timestamp=parse_int_or_hex(env['currentTimestamp'])) |
| 63 | + |
| 64 | + # Fill up pre |
| 65 | + for address, h in list(pre.items()): |
| 66 | + assert len(address) == 40 |
| 67 | + address = decode_hex(address) |
| 68 | + assert set(h.keys()) == set(['code', 'nonce', 'balance', 'storage']) |
| 69 | + state.set_nonce(address, parse_int_or_hex(h['nonce'])) |
| 70 | + state.set_balance(address, parse_int_or_hex(h['balance'])) |
| 71 | + state.set_code(address, decode_hex(h['code'][2:])) |
| 72 | + for k, v in h['storage'].items(): |
| 73 | + state.set_storage_data(address, |
| 74 | + big_endian_to_int(decode_hex(k[2:])), |
| 75 | + decode_hex(v[2:])) |
| 76 | + |
| 77 | + |
| 78 | + # We have an optional argument which is a list of JSONs specifying indices. |
| 79 | + # If this argument is set, we compute only those scenarios. If not, we |
| 80 | + # compute all of them. |
| 81 | + if indices is None: |
| 82 | + indices = [] |
| 83 | + for data_index in range(len(txdata['data'])): |
| 84 | + for value_index in range(len(txdata['value'])): |
| 85 | + for gaslimit_index in range(len(txdata['gasLimit'])): |
| 86 | + indices.append({"data": data_index, "gas": gaslimit_index, "value": value_index}) |
| 87 | + |
| 88 | + o = {} |
| 89 | + for config_name in (configs.keys() if _configs is None else _configs): |
| 90 | + state.env.config = configs[config_name] |
| 91 | + output_decls = [] |
| 92 | + for index_json in indices: |
| 93 | + print("Executing for indices %r" % index_json) |
| 94 | + data_index, value_index, gaslimit_index = index_json["data"], index_json["value"], index_json["gas"] |
| 95 | + try: |
| 96 | + # Create the transaction |
| 97 | + tx = transactions.Transaction( |
| 98 | + nonce=parse_int_or_hex(txdata['nonce'] or b"0"), |
| 99 | + gasprice=parse_int_or_hex(txdata['gasPrice'] or b"0"), |
| 100 | + startgas=parse_int_or_hex(txdata['gasLimit'][gaslimit_index] or b"0"), |
| 101 | + to=decode_hex(txdata['to']), |
| 102 | + value=parse_int_or_hex(txdata['value'][value_index] or b"0"), |
| 103 | + data=decode_hex(remove_0x_head(txdata['data'][data_index]))) |
| 104 | + tx.sign(decode_hex(txdata['secretKey'])) |
| 105 | + # Run it |
| 106 | + success, output = state_transition.apply_transaction(state, tx) |
| 107 | + print("Applied tx") |
| 108 | + except InvalidTransaction as e: |
| 109 | + print("Exception: %r" % e) |
| 110 | + success, output = False, b'' |
| 111 | + state.commit() |
| 112 | + output_decl = { |
| 113 | + "hash": encode_hex(state.trie.root_hash), |
| 114 | + "indexes": index_json |
| 115 | + } |
| 116 | + output_decls.append(output_decl) |
| 117 | + o[config_name] = output_decls |
| 118 | + return o |
| 119 | + |
| 120 | +def verify_state_test(test): |
| 121 | + print("Verifying state test") |
| 122 | + for config_name, result in test["post"].items(): |
| 123 | + # Old protocol versions may not be supported |
| 124 | + if config_name not in configs: |
| 125 | + continue |
| 126 | + print("Testing for %s" % config_name) |
| 127 | + computed = compute_state_test_post(test, [x["indexes"] for x in result], [config_name])[config_name] |
| 128 | + supplied = test["post"][config_name] |
| 129 | + assert len(computed) == len(supplied) |
| 130 | + for c, s in zip(computed, supplied): |
| 131 | + assert c["hash"] == s["hash"] |
0 commit comments