|
| 1 | +import pytest |
| 2 | + |
| 3 | +from ethereum import utils, db |
| 4 | +from ethereum.pow import chain |
| 5 | +from ethereum.exceptions import VerificationFailed, InvalidTransaction, InvalidNonce |
| 6 | +from ethereum.block import Block |
| 7 | +from ethereum.config import Env |
| 8 | +from ethereum.genesis_helpers import state_from_genesis_declaration |
| 9 | +import rlp |
| 10 | +from rlp.utils import decode_hex, encode_hex, str_to_bytes |
| 11 | +from rlp import DecodingError, DeserializationError |
| 12 | +import os |
| 13 | +import sys |
| 14 | +import ethereum.tools.testutils as testutils |
| 15 | +import copy |
| 16 | + |
| 17 | +from ethereum.slogging import get_logger |
| 18 | +logger = get_logger() |
| 19 | + |
| 20 | +# from ethereum.slogging import LogRecorder, configure_logging, set_level |
| 21 | +# 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' |
| 22 | +# configure_logging(config_string=config_string) |
| 23 | + |
| 24 | + |
| 25 | +def translate_keys(olddict, keymap, valueconv, deletes): |
| 26 | + o = {} |
| 27 | + for k in list(olddict.keys()): |
| 28 | + if k not in deletes: |
| 29 | + o[keymap.get(k, k)] = valueconv(k, olddict[k]) |
| 30 | + return o |
| 31 | + |
| 32 | + |
| 33 | +translator_list = { |
| 34 | + "extra_data": "extraData", |
| 35 | + "gas_limit": "gasLimit", |
| 36 | + "gas_used": "gasUsed", |
| 37 | + "mixhash": "mixHash", |
| 38 | + "prevhash": "parentHash", |
| 39 | + "receipts_root": "receiptTrie", |
| 40 | + "tx_list_root": "transactionsTrie", |
| 41 | + "uncles_hash": "uncleHash", |
| 42 | + "gas_price": "gasPrice", |
| 43 | + "header": "blockHeader", |
| 44 | + "uncles": "uncleHeaders" |
| 45 | +} |
| 46 | + |
| 47 | + |
| 48 | +def valueconv(k, v): |
| 49 | + if k in ['r', 's']: |
| 50 | + return '0x' + encode_hex(utils.int_to_big_endian(v)) |
| 51 | + return v |
| 52 | + |
| 53 | + |
| 54 | +def safe_decode(x): |
| 55 | + if x[:2] == '0x': |
| 56 | + x = x[2:] |
| 57 | + return decode_hex(x) |
| 58 | + |
| 59 | + |
| 60 | +def run_block_test(params, config_overrides=None): |
| 61 | + if config_overrides is None: |
| 62 | + config_overrides = {} |
| 63 | + env = Env(db.EphemDB()) |
| 64 | + genesis_decl = {} |
| 65 | + for param in ("bloom", "timestamp", "nonce", "extraData", |
| 66 | + "gasLimit", "coinbase", "difficulty", |
| 67 | + "parentHash", "mixHash", "gasUsed"): |
| 68 | + genesis_decl[param] = params["genesisBlockHeader"][param] |
| 69 | + genesis_decl["alloc"] = params["pre"] |
| 70 | + |
| 71 | + old_config = copy.deepcopy(env.config) |
| 72 | + for k, v in config_overrides.items(): |
| 73 | + env.config[k] = v |
| 74 | + |
| 75 | + # print('overrides', config_overrides) |
| 76 | + s = state_from_genesis_declaration(genesis_decl, env, allow_empties=True) |
| 77 | + c = chain.Chain(genesis=s, localtime=2**99) |
| 78 | + # print('h', encode_hex(c.state.prev_headers[0].state_root)) |
| 79 | + # print(c.state.to_dict()) |
| 80 | + # print(params["pre"]) |
| 81 | + assert c.state.env == env |
| 82 | + assert c.state.prev_headers[0].state_root == safe_decode(params["genesisBlockHeader"]["stateRoot"]), (encode_hex(c.state.prev_headers[0].state_root), params["genesisBlockHeader"]["stateRoot"]) |
| 83 | + assert c.state.trie.root_hash == safe_decode(params["genesisBlockHeader"]["stateRoot"]) |
| 84 | + assert c.state.prev_headers[0].hash == safe_decode(params["genesisBlockHeader"]["hash"]) |
| 85 | + |
| 86 | + |
| 87 | + for blk in params["blocks"]: |
| 88 | + if 'blockHeader' not in blk: |
| 89 | + success = True |
| 90 | + try: |
| 91 | + rlpdata = safe_decode(blk["rlp"][2:]) |
| 92 | + success = c.add_block(rlp.decode(rlpdata, Block)) |
| 93 | + except (ValueError, TypeError, AttributeError, VerificationFailed, |
| 94 | + DecodingError, DeserializationError, InvalidTransaction, |
| 95 | + InvalidNonce, KeyError) as e: |
| 96 | + success = False |
| 97 | + assert not success |
| 98 | + else: |
| 99 | + rlpdata = safe_decode(blk["rlp"][2:]) |
| 100 | + assert c.add_block(rlp.decode(rlpdata, Block)) |
| 101 | + env.config = old_config |
| 102 | + |
| 103 | +def get_config_overrides(filename, testname): |
| 104 | + o = {} |
| 105 | + if 'Homestead' in testname: |
| 106 | + o['HOMESTEAD_FORK_BLKNUM'] = 0 |
| 107 | + if 'TestNetwork' in filename: |
| 108 | + o['HOMESTEAD_FORK_BLKNUM'] = 5 |
| 109 | + if 'EIP150' in filename: |
| 110 | + o['DAO_FORK_BLKNUM'] = 8 |
| 111 | + o['ANTI_DOS_FORK_BLKNUM'] = 10 |
| 112 | + elif 'EIP150' in testname: |
| 113 | + o['HOMESTEAD_FORK_BLKNUM'] = 0 |
| 114 | + o['DAO_FORK_BLKNUM'] = 2**99 |
| 115 | + o['ANTI_DOS_FORK_BLKNUM'] = 0 |
| 116 | + elif 'EIP158' in testname: |
| 117 | + o['HOMESTEAD_FORK_BLKNUM'] = 0 |
| 118 | + o['DAO_FORK_BLKNUM'] = 2**99 |
| 119 | + o['ANTI_DOS_FORK_BLKNUM'] = 0 |
| 120 | + o['CLEARING_FORK_BLKNUM'] = 0 |
| 121 | + elif 'Metropolis' in testname: |
| 122 | + o['HOMESTEAD_FORK_BLKNUM'] = 0 |
| 123 | + o['DAO_FORK_BLKNUM'] = 2**99 |
| 124 | + o['ANTI_DOS_FORK_BLKNUM'] = 0 |
| 125 | + o['CLEARING_FORK_BLKNUM'] = 0 |
| 126 | + o['METROPOLIS_FORK_BLKNUM'] = 0 |
| 127 | + if 'bcTheDaoTest' in filename: |
| 128 | + o['DAO_FORK_BLKNUM'] = 8 |
| 129 | + return o |
| 130 | + |
| 131 | + |
| 132 | +def test_block(filename, testname, testdata): |
| 133 | + run_block_test(testdata, get_config_overrides(filename, testname)) |
| 134 | + |
| 135 | + |
| 136 | +skips = { |
| 137 | + ('bcWalletTest.json', u'walletReorganizeOwners'), |
| 138 | + ('bl10251623GO.json', u'randomBlockTest'), |
| 139 | + ('bl201507071825GO.json', u'randomBlockTest'), |
| 140 | + ('call_OOG_additionalGasCosts2.json', 'call_OOG_additionalGasCosts2_d0g0v0_EIP158'), |
| 141 | +} |
| 142 | + |
| 143 | +def exclude(filename, testname, _): |
| 144 | + if 'MemoryStressTest' in filename or 'QuadraticComplexityTest' in filename: |
| 145 | + return True |
| 146 | + if 'Metropolis' in testname or 'Frontier' in testname or 'Homestead' in testname or 'EIP150' in testname: |
| 147 | + return True |
| 148 | + return False |
| 149 | + |
| 150 | + |
| 151 | +def pytest_generate_tests(metafunc): |
| 152 | + testutils.generate_test_params( |
| 153 | + 'BlockchainTests', |
| 154 | + metafunc, |
| 155 | + skip_func=lambda filename, testname, _: (filename.split('/')[-1], testname) in skips, |
| 156 | + exclude_func=exclude, |
| 157 | + ) |
| 158 | + |
| 159 | + |
| 160 | +def main(): |
| 161 | + assert len(sys.argv) >= 2, "Please specify file or dir name" |
| 162 | + fixtures = testutils.get_tests_from_file_or_dir(sys.argv[1]) |
| 163 | + if len(sys.argv) >= 3: |
| 164 | + for filename, tests in list(fixtures.items()): |
| 165 | + for testname, testdata in list(tests.items()): |
| 166 | + if testname == sys.argv[2]: |
| 167 | + print("Testing: %s %s" % (filename, testname)) |
| 168 | + run_block_test(testdata, get_config_overrides(filename, testname)) |
| 169 | + else: |
| 170 | + for filename, tests in list(fixtures.items()): |
| 171 | + for testname, testdata in list(tests.items()): |
| 172 | + if (filename.split('/')[-1], testname) not in skips: |
| 173 | + print("Testing: %s %s" % (filename, testname)) |
| 174 | + run_block_test(testdata, get_config_overrides(filename, testname)) |
| 175 | + |
| 176 | + |
| 177 | +if __name__ == '__main__': |
| 178 | + main() |
0 commit comments