def verify_state_test(test): print("Verifying state test") if "env" not in test: raise EnvNotFoundException("Env not found") _state = init_state(test["env"], test["pre"]) for config_name, results in test["post"].items(): # Old protocol versions may not be supported if config_name not in configs: continue print("Testing for %s" % config_name) for result in results: data = test["transaction"]['data'][result["indexes"]["data"]] if len(data) > 2000: data = "data<%d>" % (len(data) // 2 - 1) print("Checking for values: g %d v %d d %s (indexes g %d v %d d %d)" % ( parse_int_or_hex(test["transaction"]['gasLimit'][result["indexes"]["gas"]]), parse_int_or_hex(test["transaction"]['value'][result["indexes"]["value"]]), data, result["indexes"]["gas"], result["indexes"]["value"], result["indexes"]["data"])) computed = compute_state_test_unit(_state, test["transaction"], result["indexes"], configs[config_name]) if computed["hash"][-64:] != result["hash"][-64:]: for k in computed["diff"]: print(k, computed["diff"][k]) raise Exception("Hash mismatch, computed: %s, supplied: %s" % (computed["hash"], result["hash"])) else: # for k in computed["diff"]: # print(k, computed["diff"][k]) print("Hash matched!: %s" % computed["hash"]) return True
def compute_state_test_unit(state, txdata, indices, konfig): state.env.config = konfig s = state.snapshot() try: # Create the transaction tx = transactions.Transaction( nonce=parse_int_or_hex(txdata['nonce'] or b"0"), gasprice=parse_int_or_hex(txdata['gasPrice'] or b"0"), startgas=parse_int_or_hex( txdata['gasLimit'][indices["gas"]] or b"0"), to=decode_hex(remove_0x_head(txdata['to'])), value=parse_int_or_hex(txdata['value'][indices["value"]] or b"0"), data=decode_hex(remove_0x_head(txdata['data'][indices["data"]]))) if 'secretKey' in txdata: tx.sign(decode_hex(remove_0x_head(txdata['secretKey']))) else: tx.v = parse_int_or_hex(txdata['v']) # Run it prev = state.to_dict() success, output = apply_transaction(state, tx) print("Applied tx") except InvalidTransaction as e: print("Exception: %r" % e) success, output = False, b'' # state.set_code('0x3e180b1862f9d158abb5e519a6d8605540c23682', b'') state.commit() post = state.to_dict() # print('pozt', post) output_decl = { "hash": '0x' + encode_hex(state.trie.root_hash), "indexes": indices, "diff": mk_state_diff(prev, post) } state.revert(s) return output_decl
def compute_state_test_unit(state, txdata, konfig): state.env.config = konfig s = state.snapshot() try: # Create the transaction tx = transactions.Transaction( nonce=parse_int_or_hex(txdata['nonce'] or b"0"), gasprice=parse_int_or_hex(txdata['gasPrice'] or b"0"), startgas=parse_int_or_hex(txdata['gasLimit'] or b"0"), to=decode_hex(remove_0x_head(txdata['to'])), value=parse_int_or_hex(txdata['value'] or b"0"), data=decode_hex(remove_0x_head(txdata['data']))) if 'secretKey' in txdata: tx.sign(decode_hex(remove_0x_head(txdata['secretKey']))) else: tx.v = parse_int_or_hex(txdata['v']) # Run it prev = state.to_dict() print("calling apply_transaction") success, output = apply_transaction(state, tx) print("Applied tx") except InvalidTransaction as e: print("Exception: %r" % e) success, output = False, b'' state.commit() post = state.to_dict() output_decl = { "hash": '0x' + encode_hex(state.trie.root_hash), #"indexes": indices, #"diff": mk_state_diff(prev, post) } state.revert(s) return output_decl
def acct_standard_form(a): return { "balance": parse_int_or_hex(a["balance"]), "nonce": parse_int_or_hex(a["nonce"]), "code": to_string(a["code"]), "storage": {normalize_hex(k): normalize_hex(v) for k, v in a["storage"].items() if normalize_hex(v).rstrip(b'0') != b'0x'} }
def getIntrinsicGas(test_tx): tx = transactions.Transaction( nonce=parse_int_or_hex(test_tx['nonce'] or b"0"), gasprice=parse_int_or_hex(test_tx['gasPrice'] or b"0"), startgas=parse_int_or_hex(test_tx['gasLimit'] or b"0"), to=decode_hex(remove_0x_head(test_tx['to'])), value=parse_int_or_hex(test_tx['value'] or b"0"), data=decode_hex(remove_0x_head(test_tx['data']))) return tx.intrinsic_gas_used
def getTxSender(test_tx): tx = transactions.Transaction( nonce=parse_int_or_hex(test_tx['nonce'] or b"0"), gasprice=parse_int_or_hex(test_tx['gasPrice'] or b"0"), startgas=parse_int_or_hex(test_tx['gasLimit'] or b"0"), to=decode_hex(remove_0x_head(test_tx['to'])), value=parse_int_or_hex(test_tx['value'] or b"0"), data=decode_hex(remove_0x_head(test_tx['data']))) if 'secretKey' in test_tx: tx.sign(decode_hex(remove_0x_head(test_tx['secretKey']))) return encode_hex(tx.sender)
def init_state(env, pre): # Setup env state = State( env=Env(config=konfig), block_prevhash=decode_hex(remove_0x_head(env['previousHash'])), prev_headers=[mk_fake_header(i) for i in range(parse_int_or_hex(env['currentNumber']) - 1, max(-1, parse_int_or_hex(env['currentNumber']) - 257), -1)], block_number=parse_int_or_hex(env['currentNumber']), block_coinbase=decode_hex(remove_0x_head(env['currentCoinbase'])), block_difficulty=parse_int_or_hex(env['currentDifficulty']), gas_limit=parse_int_or_hex(env['currentGasLimit']), timestamp=parse_int_or_hex(env['currentTimestamp'])) # Fill up pre for address, h in list(pre.items()): assert len(address) in (40, 42) address = decode_hex(remove_0x_head(address)) assert set(h.keys()) == set(['code', 'nonce', 'balance', 'storage']) state.set_nonce(address, parse_int_or_hex(h['nonce'])) state.set_balance(address, parse_int_or_hex(h['balance'])) state.set_code(address, decode_hex(remove_0x_head(h['code']))) for k, v in h['storage'].items(): state.set_storage_data(address, big_endian_to_int(decode_hex(k[2:])), big_endian_to_int(decode_hex(v[2:]))) state.commit(allow_empties=True) # state.commit() return state
def update_config_from_genesis_json(config, genesis_json_filename): with open(genesis_json_filename, "r") as genesis_json_file: genesis_dict = yaml.load(genesis_json_file) config.setdefault('eth', {}).setdefault('block', {}) cfg = config['eth']['block'] cfg['GENESIS_INITIAL_ALLOC'] = genesis_dict['alloc'] cfg['GENESIS_DIFFICULTY'] = parse_int_or_hex(genesis_dict['difficulty']) cfg['GENESIS_TIMESTAMP'] = parse_int_or_hex(genesis_dict['timestamp']) cfg['GENESIS_EXTRA_DATA'] = decode_hex(remove_0x_head(genesis_dict['extraData'])) cfg['GENESIS_GAS_LIMIT'] = parse_int_or_hex(genesis_dict['gasLimit']) cfg['GENESIS_MIXHASH'] = decode_hex(remove_0x_head(genesis_dict['mixhash'])) cfg['GENESIS_PREVHASH'] = decode_hex(remove_0x_head(genesis_dict['parentHash'])) cfg['GENESIS_COINBASE'] = decode_hex(remove_0x_head(genesis_dict['coinbase'])) cfg['GENESIS_NONCE'] = decode_hex(remove_0x_head(genesis_dict['nonce'])) return config
def normalize_value(k, p): if k in p: if k == 'gas': return parse_int_or_hex(p[k]) elif k == 'callcreates': return list(map(callcreate_standard_form, p[k])) else: return utils.to_string(k) return None
def update_config_from_genesis_json(config, genesis_json_filename): with open(genesis_json_filename, "r") as genesis_json_file: genesis_dict = yaml.load(genesis_json_file) config.setdefault('eth', {}).setdefault('block', {}) cfg = config['eth']['block'] cfg['GENESIS_INITIAL_ALLOC'] = genesis_dict['alloc'] cfg['GENESIS_DIFFICULTY'] = parse_int_or_hex(genesis_dict['difficulty']) cfg['GENESIS_TIMESTAMP'] = parse_int_or_hex(genesis_dict['timestamp']) cfg['GENESIS_EXTRA_DATA'] = decode_hex( remove_0x_head(genesis_dict['extraData'])) cfg['GENESIS_GAS_LIMIT'] = parse_int_or_hex(genesis_dict['gasLimit']) cfg['GENESIS_MIXHASH'] = decode_hex(remove_0x_head( genesis_dict['mixhash'])) cfg['GENESIS_PREVHASH'] = decode_hex( remove_0x_head(genesis_dict['parentHash'])) cfg['GENESIS_COINBASE'] = decode_hex( remove_0x_head(genesis_dict['coinbase'])) cfg['GENESIS_NONCE'] = decode_hex(remove_0x_head(genesis_dict['nonce'])) return config
def deploy_contract_and_accounts(state, n_devs, start=1, end=2, deploy_contract=True): dev_keys = [] dev_accounts = [] milestone = int(math.log10(n_devs)) notify_step = milestone - 2 notify_value = 10**notify_step if notify_step > 0 else 1 # create developer accounts and keys in fashion of testers for account_number in range(n_devs): if account_number % notify_value == 0: print "Account", account_number + 1, "out of", n_devs dev_keys.append(sha3('dev' + to_string(account_number))) dev_accounts.append(privtoaddr(dev_keys[-1])) # developer balances block = state.block for i in range(n_devs): if i % notify_value == 0: print "Balance", i + 1, "out of", n_devs addr, data = dev_accounts[i], {'wei': 10**24} if len(addr) == 40: addr = decode_hex(addr) assert len(addr) == 20 block.set_balance(addr, parse_int_or_hex(data['wei'])) block.commit_state() block.state.db.commit() dev_addresses = [ContractHelper.dev_address(a) for a in dev_accounts] # deploy the gnt contract with updated developer accounts if deploy_contract: contract, _, _ = deploy_gnt(state, tester.accounts[9], start, end, replacements=[(dev_addresses, DEV_ADDR_REGEX)]) alloc_addr = mk_contract_address(contract.address, 0) allocation = tester.ABIContract(state, ALLOC_ABI, alloc_addr) else: contract, allocation = None, None return contract, allocation, dev_keys, dev_accounts
def run_block_test(params): b = blocks.genesis(env, start_alloc=params["pre"]) gbh = params["genesisBlockHeader"] b.bloom = utils.scanners['int256b'](gbh["bloom"]) b.timestamp = utils.scanners['int'](gbh["timestamp"]) b.nonce = utils.scanners['bin'](gbh["nonce"]) b.extra_data = utils.scanners['bin'](gbh["extraData"]) b.gas_limit = utils.scanners['int'](gbh["gasLimit"]) b.gas_used = utils.scanners['int'](gbh["gasUsed"]) b.coinbase = utils.scanners['addr'](decode_hex(gbh["coinbase"])) b.difficulty = utils.parse_int_or_hex(gbh["difficulty"]) b.prevhash = utils.scanners['bin'](gbh["parentHash"]) b.mixhash = utils.scanners['bin'](gbh["mixHash"]) assert b.receipts.root_hash == \ utils.scanners['bin'](gbh["receiptTrie"]) assert b.transactions.root_hash == \ utils.scanners['bin'](gbh["transactionsTrie"]) assert utils.sha3rlp(b.uncles) == \ utils.scanners['bin'](gbh["uncleHash"]) h = encode_hex(b.state.root_hash) if h != str_to_bytes(gbh["stateRoot"]): raise Exception("state root mismatch") if b.hash != utils.scanners['bin'](gbh["hash"]): raise Exception("header hash mismatch") assert b.header.check_pow() blockmap = {b.hash: b} env.db.put(b.hash, rlp.encode(b)) for blk in params["blocks"]: if 'blockHeader' not in blk: try: rlpdata = decode_hex(blk["rlp"][2:]) blkparent = rlp.decode( rlp.encode(rlp.decode(rlpdata)[0]), blocks.BlockHeader).prevhash b2 = rlp.decode(rlpdata, blocks.Block, parent=blockmap[blkparent], env=env) success = b2.validate_uncles() except (ValueError, TypeError, AttributeError, VerificationFailed, DecodingError, DeserializationError, InvalidTransaction, KeyError): success = False assert not success else: rlpdata = decode_hex(blk["rlp"][2:]) blkparent = rlp.decode(rlp.encode(rlp.decode(rlpdata)[0]), blocks.BlockHeader).prevhash b2 = rlp.decode(rlpdata, blocks.Block, parent=blockmap[blkparent], env=env) assert b2.validate_uncles() blockmap[b2.hash] = b2 env.db.put(b2.hash, rlp.encode(b2))
def mktest(code, language, data=None, fun=None, args=None, gas=1000000, value=0, test_type=VM): s = t.state(1) if language == 'evm': ca = s.contract('x = 5') s.block.set_code(ca, code) d = data or b'' else: c = s.abi_contract(code, language=language) d = c._translator.encode(fun, args) if fun else (data or b'') ca = c.address pre = s.block.to_dict(True)['state'] if test_type == VM: exek = { "address": ca, "caller": t.a0, "code": b'0x' + encode_hex(s.block.get_code(ca)), "data": b'0x' + encode_hex(d), "gas": to_string(gas), "gasPrice": to_string(1), "origin": t.a0, "value": to_string(value) } return fill_vm_test({"env": env, "pre": pre, "exec": exek}) else: tx = { "data": b'0x' + encode_hex(d), "gasLimit": parse_int_or_hex(gas), "gasPrice": to_string(1), "nonce": to_string(s.block.get_nonce(t.a0)), "secretKey": encode_hex(t.k0), "to": ca, "value": to_string(value) } return fill_state_test({"env": env, "pre": pre, "transaction": tx})
def run_genesis_test(params, mode): params = copy.deepcopy(params) if 'difficulty' not in params: params['difficulty'] = int_to_hex(2**34) if 'mixhash' not in params: params['mixhash'] = '0x' + '0' * 64 if 'nonce' not in params: params['nonce'] = '0x0000000000000042' if 'timestamp' not in params: params['timestamp'] = int_to_hex(5000) if 'parentHash' not in params: params['parentHash'] = '0x' + '0' * 64 if 'gasLimit' not in params: params['gasLimit'] = int_to_hex(5000) if 'extraData' not in params: params['extraData'] = '0x' if 'coinbase' not in params: params['coinbase'] = '0x' + '3' * 40 x = time.time() b = blocks.genesis( EphemDB(), start_alloc=params['alloc'], difficulty=parse_int_or_hex(params['difficulty']), timestamp=parse_int_or_hex(params['timestamp']), extra_data=decode_hex(remove_0x_head(params['extraData'])), gas_limit=parse_int_or_hex(params['gasLimit']), mixhash=decode_hex(remove_0x_head(params['mixhash'])), prevhash=decode_hex(remove_0x_head(params['parentHash'])), coinbase=decode_hex(remove_0x_head(params['coinbase'])), nonce=decode_hex(remove_0x_head(params['nonce']))) assert b.difficulty == parse_int_or_hex(params['difficulty']) assert b.timestamp == parse_int_or_hex(params['timestamp']) assert b.extra_data == decode_hex(remove_0x_head(params['extraData'])) assert b.gas_limit == parse_int_or_hex(params['gasLimit']) assert b.mixhash == decode_hex(remove_0x_head(params['mixhash'])) assert b.prevhash == decode_hex(remove_0x_head(params['parentHash'])) assert b.nonce == decode_hex(remove_0x_head(params['nonce'])) print 9 if mode == FILL: params['result'] = encode_hex(rlp.encode(b)) return params elif mode == VERIFY: assert params['result'] == encode_hex(rlp.encode(b)) elif mode == TIME: return {'creation': time.time() - x}
def run_genesis_test(params, mode): params = copy.deepcopy(params) if 'difficulty' not in params: params['difficulty'] = int_to_hex(2 ** 34) if 'mixhash' not in params: params['mixhash'] = '0x' + '0' * 64 if 'nonce' not in params: params['nonce'] = '0x0000000000000042' if 'timestamp' not in params: params['timestamp'] = int_to_hex(5000) if 'parentHash' not in params: params['parentHash'] = '0x' + '0' * 64 if 'gasLimit' not in params: params['gasLimit'] = int_to_hex(5000) if 'extraData' not in params: params['extraData'] = '0x' if 'coinbase' not in params: params['coinbase'] = '0x' + '3' * 40 x = time.time() b = blocks.genesis(EphemDB(), start_alloc=params['alloc'], difficulty=parse_int_or_hex(params['difficulty']), timestamp=parse_int_or_hex(params['timestamp']), extra_data=decode_hex(remove_0x_head(params['extraData'])), gas_limit=parse_int_or_hex(params['gasLimit']), mixhash=decode_hex(remove_0x_head(params['mixhash'])), prevhash=decode_hex(remove_0x_head(params['parentHash'])), coinbase=decode_hex(remove_0x_head(params['coinbase'])), nonce=decode_hex(remove_0x_head(params['nonce']))) assert b.difficulty == parse_int_or_hex(params['difficulty']) assert b.timestamp == parse_int_or_hex(params['timestamp']) assert b.extra_data == decode_hex(remove_0x_head(params['extraData'])) assert b.gas_limit == parse_int_or_hex(params['gasLimit']) assert b.mixhash == decode_hex(remove_0x_head(params['mixhash'])) assert b.prevhash == decode_hex(remove_0x_head(params['parentHash'])) assert b.nonce == decode_hex(remove_0x_head(params['nonce'])) print(9) if mode == FILL: params['result'] = encode_hex(rlp.encode(b)) return params elif mode == VERIFY: assert params['result'] == encode_hex(rlp.encode(b)) elif mode == TIME: return { 'creation': time.time() - x }
def mktest(code, language, data=None, fun=None, args=None, gas=1000000, value=0, test_type=VM): s = t.state(1) if language == 'evm': ca = s.contract('x = 5') s.block.set_code(ca, code) d = data or b'' else: c = s.abi_contract(code, language=language) d = c._translator.encode(fun, args) if fun else (data or b'') ca = c.address pre = s.block.to_dict(True)['state'] if test_type == VM: exek = {"address": ca, "caller": t.a0, "code": b'0x' + encode_hex(s.block.get_code(ca)), "data": b'0x' + encode_hex(d), "gas": to_string(gas), "gasPrice": to_string(1), "origin": t.a0, "value": to_string(value)} return fill_vm_test({"env": env, "pre": pre, "exec": exek}) else: tx = {"data": b'0x' + encode_hex(d), "gasLimit": parse_int_or_hex(gas), "gasPrice": to_string(1), "nonce": to_string(s.block.get_nonce(t.a0)), "secretKey": encode_hex(t.k0), "to": ca, "value": to_string(value)} return fill_state_test({"env": env, "pre": pre, "transaction": tx})
def run_state_test(params, mode): pre = params['pre'] exek = params['transaction'] env = params['env'] assert set(env.keys()) == set([ 'currentGasLimit', 'currentTimestamp', 'previousHash', 'currentCoinbase', 'currentDifficulty', 'currentNumber' ]) assert len(env['currentCoinbase']) == 40 # setup env header = blocks.BlockHeader( prevhash=decode_hex(env['previousHash']), number=parse_int_or_hex(env['currentNumber']), coinbase=decode_hex(env['currentCoinbase']), difficulty=parse_int_or_hex(env['currentDifficulty']), gas_limit=parse_int_or_hex(env['currentGasLimit']), timestamp=parse_int_or_hex(env['currentTimestamp'])) blk = blocks.Block(header, env=db_env) # setup state for address, h in list(pre.items()): assert len(address) == 40 address = decode_hex(address) assert set(h.keys()) == set(['code', 'nonce', 'balance', 'storage']) blk.set_nonce(address, parse_int_or_hex(h['nonce'])) blk.set_balance(address, parse_int_or_hex(h['balance'])) blk.set_code(address, decode_hex(h['code'][2:])) for k, v in h['storage'].items(): blk.set_storage_data(address, utils.big_endian_to_int(decode_hex(k[2:])), utils.big_endian_to_int(decode_hex(v[2:]))) for address, h in list(pre.items()): address = decode_hex(address) assert blk.get_nonce(address) == parse_int_or_hex(h['nonce']) assert blk.get_balance(address) == parse_int_or_hex(h['balance']) assert blk.get_code(address) == decode_hex(h['code'][2:]) for k, v in h['storage'].items(): assert blk.get_storage_data( address, utils.big_endian_to_int(decode_hex( k[2:]))) == utils.big_endian_to_int(decode_hex(v[2:])) # execute transactions orig_apply_msg = pb.apply_msg def apply_msg_wrapper(ext, msg): def blkhash(n): if n >= blk.number or n < blk.number - 256: return b'' else: return utils.sha3(to_string(n)) ext.block_hash = blkhash return orig_apply_msg(ext, msg) pb.apply_msg = apply_msg_wrapper try: tx = transactions.Transaction( nonce=parse_int_or_hex(exek['nonce'] or b"0"), gasprice=parse_int_or_hex(exek['gasPrice'] or b"0"), startgas=parse_int_or_hex(exek['gasLimit'] or b"0"), to=decode_hex(exek['to'][2:] if exek['to'][:2] == b'0x' else exek['to']), value=parse_int_or_hex(exek['value'] or b"0"), data=decode_hex(remove_0x_head(exek['data']))) except InvalidTransaction: tx = None success, output = False, b'' time_pre = time.time() time_post = time_pre else: if 'secretKey' in exek: tx.sign(exek['secretKey']) elif all(key in exek for key in ['v', 'r', 's']): tx.v = decode_hex(remove_0x_head(exek['v'])) tx.r = decode_hex(remove_0x_head(exek['r'])) tx.s = decode_hex(remove_0x_head(exek['s'])) else: assert False time_pre = time.time() try: success, output = pb.apply_transaction(blk, tx) blk.commit_state() except pb.InvalidTransaction: success, output = False, b'' blk.commit_state() pass time_post = time.time() if tx.to == b'': output = blk.get_code(output) pb.apply_msg = orig_apply_msg params2 = copy.deepcopy(params) if success: params2['logs'] = [log.to_dict() for log in blk.get_receipt(0).logs] params2['out'] = b'0x' + encode_hex(output) params2['post'] = copy.deepcopy(blk.to_dict(True)['state']) params2['postStateRoot'] = encode_hex(blk.state.root_hash) assert 'post' in params # we always have a post state in the tests if mode == FILL: return params2 elif mode == VERIFY: params1 = copy.deepcopy(params) shouldbe, reallyis = params1.get('post', None), params2.get('post', None) compare_post_states(shouldbe, reallyis) for k in [ 'pre', 'exec', 'env', 'callcreates', 'out', 'gas', 'logs', 'postStateRoot' ]: shouldbe = params1.get(k, None) reallyis = params2.get(k, None) if shouldbe != reallyis: raise Exception("Mismatch: " + k + ':\n shouldbe %r\n reallyis %r' % (shouldbe, reallyis)) elif mode == TIME: return time_post - time_pre
def run_vm_test(params, mode, profiler=None): pre = params['pre'] exek = params['exec'] env = params['env'] if 'previousHash' not in env: env['previousHash'] = encode_hex(db_env.config['GENESIS_PREVHASH']) assert set(env.keys()) == set(['currentGasLimit', 'currentTimestamp', 'previousHash', 'currentCoinbase', 'currentDifficulty', 'currentNumber']) # setup env header = blocks.BlockHeader( prevhash=decode_hex(env['previousHash']), number=parse_int_or_hex(env['currentNumber']), coinbase=decode_hex(env['currentCoinbase']), difficulty=parse_int_or_hex(env['currentDifficulty']), gas_limit=parse_int_or_hex(env['currentGasLimit']), timestamp=parse_int_or_hex(env['currentTimestamp'])) blk = blocks.Block(header, env=db_env) # setup state for address, h in list(pre.items()): assert len(address) == 40 address = decode_hex(address) assert set(h.keys()) == set(['code', 'nonce', 'balance', 'storage']) blk.set_nonce(address, parse_int_or_hex(h['nonce'])) blk.set_balance(address, parse_int_or_hex(h['balance'])) blk.set_code(address, decode_hex(h['code'][2:])) for k, v in h['storage'].items(): blk.set_storage_data(address, utils.big_endian_to_int(decode_hex(k[2:])), utils.big_endian_to_int(decode_hex(v[2:]))) # execute transactions sender = decode_hex(exek['caller']) # a party that originates a call recvaddr = decode_hex(exek['address']) nonce = blk._get_acct_item(sender, 'nonce') gasprice = parse_int_or_hex(exek['gasPrice']) startgas = parse_int_or_hex(exek['gas']) value = parse_int_or_hex(exek['value']) data = decode_hex(exek['data'][2:]) # bypass gas check in tx initialization by temporarily increasing startgas num_zero_bytes = str_to_bytes(data).count(ascii_chr(0)) num_non_zero_bytes = len(data) - num_zero_bytes intrinsic_gas = (opcodes.GTXCOST + opcodes.GTXDATAZERO * num_zero_bytes + opcodes.GTXDATANONZERO * num_non_zero_bytes) startgas += intrinsic_gas tx = transactions.Transaction(nonce=nonce, gasprice=gasprice, startgas=startgas, to=recvaddr, value=value, data=data) tx.startgas -= intrinsic_gas tx.sender = sender # capture apply_message calls apply_message_calls = [] orig_apply_msg = pb.apply_msg ext = pb.VMExt(blk, tx) def msg_wrapper(msg): hexdata = encode_hex(msg.data.extract_all()) apply_message_calls.append(dict(gasLimit=to_string(msg.gas), value=to_string(msg.value), destination=encode_hex(msg.to), data=b'0x' + hexdata)) return 1, msg.gas, b'' def create_wrapper(msg): sender = decode_hex(msg.sender) if \ len(msg.sender) == 40 else msg.sender nonce = utils.encode_int(ext._block.get_nonce(msg.sender)) addr = utils.sha3(rlp.encode([sender, nonce]))[12:] hexdata = encode_hex(msg.data.extract_all()) apply_message_calls.append(dict(gasLimit=to_string(msg.gas), value=to_string(msg.value), destination=b'', data=b'0x' + hexdata)) return 1, msg.gas, addr ext.msg = msg_wrapper ext.create = create_wrapper def blkhash(n): if n >= ext.block_number or n < ext.block_number - 256: return b'' else: return utils.sha3(to_string(n)) ext.block_hash = blkhash msg = vm.Message(tx.sender, tx.to, tx.value, tx.startgas, vm.CallData([safe_ord(x) for x in tx.data])) code = decode_hex(exek['code'][2:]) time_pre = time.time() if profiler: profiler.enable() success, gas_remained, output = vm.vm_execute(ext, msg, code) if profiler: profiler.disable() pb.apply_msg = orig_apply_msg blk.commit_state() for s in blk.suicides: blk.del_account(s) time_post = time.time() """ generally expected that the test implementer will read env, exec and pre then check their results against gas, logs, out, post and callcreates. If an exception is expected, then latter sections are absent in the test. Since the reverting of the state is not part of the VM tests. """ params2 = copy.deepcopy(params) if success: params2['callcreates'] = apply_message_calls params2['out'] = b'0x' + encode_hex(b''.join(map(ascii_chr, output))) params2['gas'] = to_string(gas_remained) params2['logs'] = [log.to_dict() for log in blk.logs] params2['post'] = blk.to_dict(with_state=True)['state'] if mode == FILL: return params2 elif mode == VERIFY: if not success: assert 'post' not in params, 'failed, but expected to succeed' params1 = copy.deepcopy(params) shouldbe, reallyis = params1.get('post', None), params2.get('post', None) compare_post_states(shouldbe, reallyis) def normalize_value(k, p): if k in p: if k == 'gas': return parse_int_or_hex(p[k]) elif k == 'callcreates': return list(map(callcreate_standard_form, p[k])) else: return utils.to_string(k) return None for k in ['pre', 'exec', 'env', 'callcreates', 'out', 'gas', 'logs']: shouldbe = normalize_value(k, params1) reallyis = normalize_value(k, params2) if shouldbe != reallyis: raise Exception("Mismatch: " + k + ':\n shouldbe %r\n reallyis %r' % (shouldbe, reallyis)) elif mode == TIME: return time_post - time_pre
def run_vm_test(params, mode, profiler=None): pre = params['pre'] exek = params['exec'] env = params['env'] if 'previousHash' not in env: env['previousHash'] = encode_hex(db_env.config['GENESIS_PREVHASH']) assert set(env.keys()) == set([ 'currentGasLimit', 'currentTimestamp', 'previousHash', 'currentCoinbase', 'currentDifficulty', 'currentNumber' ]) # setup env header = blocks.BlockHeader( prevhash=decode_hex(env['previousHash']), number=parse_int_or_hex(env['currentNumber']), coinbase=decode_hex(env['currentCoinbase']), difficulty=parse_int_or_hex(env['currentDifficulty']), gas_limit=parse_int_or_hex(env['currentGasLimit']), timestamp=parse_int_or_hex(env['currentTimestamp'])) blk = blocks.Block(header, env=db_env) # setup state for address, h in list(pre.items()): assert len(address) == 40 address = decode_hex(address) assert set(h.keys()) == set(['code', 'nonce', 'balance', 'storage']) blk.set_nonce(address, parse_int_or_hex(h['nonce'])) blk.set_balance(address, parse_int_or_hex(h['balance'])) blk.set_code(address, decode_hex(h['code'][2:])) for k, v in h['storage'].items(): blk.set_storage_data(address, utils.big_endian_to_int(decode_hex(k[2:])), utils.big_endian_to_int(decode_hex(v[2:]))) # execute transactions sender = decode_hex(exek['caller']) # a party that originates a call recvaddr = decode_hex(exek['address']) nonce = blk._get_acct_item(sender, 'nonce') gasprice = parse_int_or_hex(exek['gasPrice']) startgas = parse_int_or_hex(exek['gas']) value = parse_int_or_hex(exek['value']) data = decode_hex(exek['data'][2:]) # bypass gas check in tx initialization by temporarily increasing startgas num_zero_bytes = str_to_bytes(data).count(ascii_chr(0)) num_non_zero_bytes = len(data) - num_zero_bytes intrinsic_gas = (opcodes.GTXCOST + opcodes.GTXDATAZERO * num_zero_bytes + opcodes.GTXDATANONZERO * num_non_zero_bytes) startgas += intrinsic_gas tx = transactions.Transaction(nonce=nonce, gasprice=gasprice, startgas=startgas, to=recvaddr, value=value, data=data) tx.startgas -= intrinsic_gas tx.sender = sender # capture apply_message calls apply_message_calls = [] orig_apply_msg = pb.apply_msg ext = pb.VMExt(blk, tx) def msg_wrapper(msg): hexdata = encode_hex(msg.data.extract_all()) apply_message_calls.append( dict(gasLimit=to_string(msg.gas), value=to_string(msg.value), destination=encode_hex(msg.to), data=b'0x' + hexdata)) return 1, msg.gas, b'' def create_wrapper(msg): sender = decode_hex(msg.sender) if \ len(msg.sender) == 40 else msg.sender nonce = utils.encode_int(ext._block.get_nonce(msg.sender)) addr = utils.sha3(rlp.encode([sender, nonce]))[12:] hexdata = encode_hex(msg.data.extract_all()) apply_message_calls.append( dict(gasLimit=to_string(msg.gas), value=to_string(msg.value), destination=b'', data=b'0x' + hexdata)) return 1, msg.gas, addr ext.msg = msg_wrapper ext.create = create_wrapper def blkhash(n): if n >= ext.block_number or n < ext.block_number - 256: return b'' else: return utils.sha3(to_string(n)) ext.block_hash = blkhash msg = vm.Message(tx.sender, tx.to, tx.value, tx.startgas, vm.CallData([safe_ord(x) for x in tx.data])) code = decode_hex(exek['code'][2:]) time_pre = time.time() if profiler: profiler.enable() success, gas_remained, output = vm.vm_execute(ext, msg, code) if profiler: profiler.disable() pb.apply_msg = orig_apply_msg blk.commit_state() for s in blk.suicides: blk.del_account(s) time_post = time.time() """ generally expected that the test implementer will read env, exec and pre then check their results against gas, logs, out, post and callcreates. If an exception is expected, then latter sections are absent in the test. Since the reverting of the state is not part of the VM tests. """ params2 = copy.deepcopy(params) if success: params2['callcreates'] = apply_message_calls params2['out'] = b'0x' + encode_hex(b''.join(map(ascii_chr, output))) params2['gas'] = to_string(gas_remained) params2['logs'] = [log.to_dict() for log in blk.logs] params2['post'] = blk.to_dict(with_state=True)['state'] if mode == FILL: return params2 elif mode == VERIFY: if not success: assert 'post' not in params, 'failed, but expected to succeed' params1 = copy.deepcopy(params) shouldbe, reallyis = params1.get('post', None), params2.get('post', None) compare_post_states(shouldbe, reallyis) def normalize_value(k, p): if k in p: if k == 'gas': return parse_int_or_hex(p[k]) elif k == 'callcreates': return list(map(callcreate_standard_form, p[k])) else: return utils.to_string(k) return None for k in ['pre', 'exec', 'env', 'callcreates', 'out', 'gas', 'logs']: shouldbe = normalize_value(k, params1) reallyis = normalize_value(k, params2) if shouldbe != reallyis: raise Exception("Mismatch: " + k + ':\n shouldbe %r\n reallyis %r' % (shouldbe, reallyis)) elif mode == TIME: return time_post - time_pre
def toHexQuantities(vals): quantities = [] for val in vals: val_int = parse_int_or_hex(val) quantities.append('0x{0:01x}'.format(val_int)) return quantities
def run_state_test(params, mode): pre = params['pre'] exek = params['transaction'] env = params['env'] assert set(env.keys()) == set(['currentGasLimit', 'currentTimestamp', 'previousHash', 'currentCoinbase', 'currentDifficulty', 'currentNumber']) assert len(env['currentCoinbase']) == 40 # setup env header = blocks.BlockHeader( prevhash=decode_hex(env['previousHash']), number=parse_int_or_hex(env['currentNumber']), coinbase=decode_hex(env['currentCoinbase']), difficulty=parse_int_or_hex(env['currentDifficulty']), timestamp=parse_int_or_hex(env['currentTimestamp']), # work around https://github.com/ethereum/pyethereum/issues/390 [1]: gas_limit=min(2 ** 63 - 1, parse_int_or_hex(env['currentGasLimit']))) blk = blocks.Block(header, env=db_env) # work around https://github.com/ethereum/pyethereum/issues/390 [2]: blk.gas_limit = parse_int_or_hex(env['currentGasLimit']) # setup state for address, h in list(pre.items()): assert len(address) == 40 address = decode_hex(address) assert set(h.keys()) == set(['code', 'nonce', 'balance', 'storage']) blk.set_nonce(address, parse_int_or_hex(h['nonce'])) blk.set_balance(address, parse_int_or_hex(h['balance'])) blk.set_code(address, decode_hex(h['code'][2:])) for k, v in h['storage'].items(): blk.set_storage_data(address, utils.big_endian_to_int(decode_hex(k[2:])), utils.big_endian_to_int(decode_hex(v[2:]))) for address, h in list(pre.items()): address = decode_hex(address) assert blk.get_nonce(address) == parse_int_or_hex(h['nonce']) assert blk.get_balance(address) == parse_int_or_hex(h['balance']) assert blk.get_code(address) == decode_hex(h['code'][2:]) for k, v in h['storage'].items(): assert blk.get_storage_data(address, utils.big_endian_to_int( decode_hex(k[2:]))) == utils.big_endian_to_int(decode_hex(v[2:])) # execute transactions orig_apply_msg = pb.apply_msg def apply_msg_wrapper(ext, msg): def blkhash(n): if n >= blk.number or n < blk.number - 256: return b'' else: return utils.sha3(to_string(n)) ext.block_hash = blkhash return orig_apply_msg(ext, msg) pb.apply_msg = apply_msg_wrapper try: tx = transactions.Transaction( nonce=parse_int_or_hex(exek['nonce'] or b"0"), gasprice=parse_int_or_hex(exek['gasPrice'] or b"0"), startgas=parse_int_or_hex(exek['gasLimit'] or b"0"), to=normalize_address(exek['to'], allow_blank=True), value=parse_int_or_hex(exek['value'] or b"0"), data=decode_hex(remove_0x_head(exek['data']))) except InvalidTransaction: tx = None success, output = False, b'' time_pre = time.time() time_post = time_pre else: if 'secretKey' in exek: tx.sign(exek['secretKey']) elif all(key in exek for key in ['v', 'r', 's']): tx.v = decode_hex(remove_0x_head(exek['v'])) tx.r = decode_hex(remove_0x_head(exek['r'])) tx.s = decode_hex(remove_0x_head(exek['s'])) else: assert False time_pre = time.time() try: print('trying') success, output = pb.apply_transaction(blk, tx) blk.commit_state() print('success', blk.get_receipts()[-1].gas_used) except InvalidTransaction: success, output = False, b'' blk.commit_state() pass time_post = time.time() if tx.to == b'': output = blk.get_code(output) pb.apply_msg = orig_apply_msg params2 = copy.deepcopy(params) if success: params2['logs'] = [log.to_dict() for log in blk.get_receipt(0).logs] params2['out'] = b'0x' + encode_hex(output) params2['post'] = copy.deepcopy(blk.to_dict(True)['state']) params2['postStateRoot'] = encode_hex(blk.state.root_hash) if mode == FILL: return params2 elif mode == VERIFY: params1 = copy.deepcopy(params) shouldbe, reallyis = params1.get('post', None), params2.get('post', None) compare_post_states(shouldbe, reallyis) for k in ['pre', 'exec', 'env', 'callcreates', 'out', 'gas', 'logs', 'postStateRoot']: _shouldbe = params1.get(k, None) _reallyis = params2.get(k, None) if _shouldbe != _reallyis: print(('Mismatch {key}: shouldbe {shouldbe_key} != reallyis {reallyis_key}.\n' 'post: {shouldbe_post} != {reallyis_post}').format( shouldbe_key=_shouldbe, reallyis_key=_reallyis, shouldbe_post=shouldbe, reallyis_post=reallyis, key=k)) raise Exception("Mismatch: " + k + ':\n shouldbe %r\n reallyis %r' % (_shouldbe, _reallyis)) elif mode == TIME: return time_post - time_pre
def run_block_test(params, config_overrides={}): b = blocks.genesis(env, start_alloc=params["pre"]) gbh = params["genesisBlockHeader"] b.bloom = utils.scanners['int256b'](gbh["bloom"]) b.timestamp = utils.scanners['int'](gbh["timestamp"]) b.nonce = utils.scanners['bin'](gbh["nonce"]) b.extra_data = utils.scanners['bin'](gbh["extraData"]) b.gas_limit = utils.scanners['int'](gbh["gasLimit"]) b.gas_used = utils.scanners['int'](gbh["gasUsed"]) b.coinbase = utils.scanners['addr'](decode_hex(gbh["coinbase"])) b.difficulty = utils.parse_int_or_hex(gbh["difficulty"]) b.prevhash = utils.scanners['bin'](gbh["parentHash"]) b.mixhash = utils.scanners['bin'](gbh["mixHash"]) assert b.receipts.root_hash == \ utils.scanners['bin'](gbh["receiptTrie"]) assert b.transactions.root_hash == \ utils.scanners['bin'](gbh["transactionsTrie"]) assert utils.sha3rlp(b.uncles) == \ utils.scanners['bin'](gbh["uncleHash"]) h = encode_hex(b.state.root_hash) if h != str_to_bytes(gbh["stateRoot"]): raise Exception("state root mismatch") if b.hash != utils.scanners['bin'](gbh["hash"]): raise Exception("header hash mismatch") # assert b.header.check_pow() blockmap = {b.hash: b} env.db.put(b.hash, rlp.encode(b)) old_config = copy.deepcopy(env.config) try: for k, v in config_overrides.items(): env.config[k] = v b2 = None for blk in params["blocks"]: if 'blockHeader' not in blk: try: rlpdata = decode_hex(blk["rlp"][2:]) blkparent = rlp.decode(rlp.encode(rlp.decode(rlpdata)[0]), blocks.BlockHeader).prevhash b2 = rlp.decode(rlpdata, blocks.Block, parent=blockmap[blkparent], env=env) success = b2.validate_uncles() except (ValueError, TypeError, AttributeError, VerificationFailed, DecodingError, DeserializationError, InvalidTransaction, KeyError): success = False assert not success else: rlpdata = decode_hex(blk["rlp"][2:]) blkparent = rlp.decode(rlp.encode(rlp.decode(rlpdata)[0]), blocks.BlockHeader).prevhash b2 = rlp.decode(rlpdata, blocks.Block, parent=blockmap[blkparent], env=env) assert b2.validate_uncles() blockmap[b2.hash] = b2 env.db.put(b2.hash, rlp.encode(b2)) if b2: print('Block %d with state root %s' % (b2.number, encode_hex(b2.state.root_hash))) # blkdict = b.to_dict(False, True, False, True) # assert blk["blockHeader"] == \ # translate_keys(blkdict["header"], translator_list, lambda y, x: x, []) # assert blk["transactions"] == \ # [translate_keys(t, translator_list, valueconv, ['hash']) # for t in blkdict["transactions"]] # assert blk["uncleHeader"] == \ # [translate_keys(u, translator_list, lambda x: x, []) # for u in blkdict["uncles"]] finally: env.config = old_config
def callcreate_standard_form(c): return { "gasLimit": parse_int_or_hex(c["gasLimit"]), "value": parse_int_or_hex(c["value"]), "data": to_string(c["data"]) }
def update_config_from_genesis_json(config, genesis_json_filename_or_dict): """ Sets the genesis configuration. Note: This function will not copy config, it will be modified in place and then returned. Args: config (dict): The app full configuration. genesis_json_filename_or_dict: The path to a yaml file or a dictionary with the genesis configuration, the required keys are: - alloc: a mapping from address to balance - difficulty: the difficulty hex encoded - timestamp: the timestamp hex encoded - extraData: extra binary data hex encoded - gasLimit: gas limit hex encoded - mixhash: mixhash hex encoded - parentHash: the parent hash hex encoded - coinbase: coinbase hex encoded - nonce: nonce hex encoded Returns: dict: The first function argument. """ if isinstance(genesis_json_filename_or_dict, dict): genesis_dict = genesis_json_filename_or_dict else: with open(genesis_json_filename_or_dict, 'r') as genesis_json_file: genesis_dict = yaml.load(genesis_json_file) valid_keys = set(( 'alloc', 'difficulty', 'timestamp', 'extraData', 'gasLimit', 'mixhash', 'parentHash', 'coinbase', 'nonce', )) unknown_keys = set(genesis_dict.keys()) - valid_keys if unknown_keys: raise ValueError('genesis_dict contains invalid keys.') config.setdefault('eth', {}).setdefault('block', {}) ethblock_config = config['eth']['block'] def _dec(data): return decode_hex(remove_0x_head(data)) if 'alloc' in genesis_dict: ethblock_config['GENESIS_INITIAL_ALLOC'] = genesis_dict['alloc'] if 'difficulty' in genesis_dict: ethblock_config['GENESIS_DIFFICULTY'] = parse_int_or_hex( genesis_dict['difficulty']) if 'timestamp' in genesis_dict: ethblock_config['GENESIS_TIMESTAMP'] = parse_int_or_hex( genesis_dict['timestamp']) if 'extraData' in genesis_dict: ethblock_config['GENESIS_EXTRA_DATA'] = _dec(genesis_dict['extraData']) if 'gasLimit' in genesis_dict: ethblock_config['GENESIS_GAS_LIMIT'] = parse_int_or_hex( genesis_dict['gasLimit']) if 'mixhash' in genesis_dict: ethblock_config['GENESIS_MIXHASH'] = _dec(genesis_dict['mixhash']) if 'parentHash' in genesis_dict: ethblock_config['GENESIS_PREVHASH'] = _dec(genesis_dict['parentHash']) if 'coinbase' in genesis_dict: ethblock_config['GENESIS_COINBASE'] = _dec(genesis_dict['coinbase']) if 'nonce' in genesis_dict: ethblock_config['GENESIS_NONCE'] = _dec(genesis_dict['nonce']) return config
def run_state_test(params, mode): pre = params['pre'] exek = params['transaction'] env = params['env'] assert set(env.keys()) == set(['currentGasLimit', 'currentTimestamp', 'previousHash', 'currentCoinbase', 'currentDifficulty', 'currentNumber']) assert len(env['currentCoinbase']) == 40 # setup env header = blocks.BlockHeader( prevhash=decode_hex(env['previousHash']), number=parse_int_or_hex(env['currentNumber']), coinbase=decode_hex(env['currentCoinbase']), difficulty=parse_int_or_hex(env['currentDifficulty']), timestamp=parse_int_or_hex(env['currentTimestamp']), # work around https://github.com/ethereum/pyethereum/issues/390 [1]: gas_limit=min(db_env.config['MAX_GAS_LIMIT'], parse_int_or_hex(env['currentGasLimit']))) blk = blocks.Block(header, env=db_env) # work around https://github.com/ethereum/pyethereum/issues/390 [2]: blk.gas_limit = parse_int_or_hex(env['currentGasLimit']) # setup state for address, h in list(pre.items()): assert len(address) == 40 address = decode_hex(address) assert set(h.keys()) == set(['code', 'nonce', 'balance', 'storage']) blk.set_nonce(address, parse_int_or_hex(h['nonce'])) blk.set_balance(address, parse_int_or_hex(h['balance'])) blk.set_code(address, decode_hex(h['code'][2:])) for k, v in h['storage'].items(): blk.set_storage_data(address, utils.big_endian_to_int(decode_hex(k[2:])), utils.big_endian_to_int(decode_hex(v[2:]))) for address, h in list(pre.items()): address = decode_hex(address) assert blk.get_nonce(address) == parse_int_or_hex(h['nonce']) assert blk.get_balance(address) == parse_int_or_hex(h['balance']) assert blk.get_code(address) == decode_hex(h['code'][2:]) for k, v in h['storage'].items(): assert blk.get_storage_data(address, utils.big_endian_to_int( decode_hex(k[2:]))) == utils.big_endian_to_int(decode_hex(v[2:])) # execute transactions orig_apply_msg = pb.apply_msg def apply_msg_wrapper(ext, msg): def blkhash(n): if n >= blk.number or n < blk.number - 256: return b'' else: return utils.sha3(to_string(n)) ext.block_hash = blkhash return orig_apply_msg(ext, msg) pb.apply_msg = apply_msg_wrapper try: tx = transactions.Transaction( nonce=parse_int_or_hex(exek['nonce'] or b"0"), gasprice=parse_int_or_hex(exek['gasPrice'] or b"0"), startgas=parse_int_or_hex(exek['gasLimit'] or b"0"), to=normalize_address(exek['to'], allow_blank=True), value=parse_int_or_hex(exek['value'] or b"0"), data=decode_hex(remove_0x_head(exek['data']))) except InvalidTransaction: tx = None success, output = False, b'' time_pre = time.time() time_post = time_pre else: if 'secretKey' in exek: tx.sign(exek['secretKey']) elif all(key in exek for key in ['v', 'r', 's']): tx.v = decode_hex(remove_0x_head(exek['v'])) tx.r = decode_hex(remove_0x_head(exek['r'])) tx.s = decode_hex(remove_0x_head(exek['s'])) else: assert False time_pre = time.time() try: print('trying') success, output = pb.apply_transaction(blk, tx) blk.commit_state() print('success', blk.get_receipts()[-1].gas_used) except InvalidTransaction: success, output = False, b'' blk.commit_state() pass time_post = time.time() if tx.to == b'': output = blk.get_code(output) pb.apply_msg = orig_apply_msg params2 = copy.deepcopy(params) if success: params2['logs'] = [log.to_dict() for log in blk.get_receipt(0).logs] params2['out'] = b'0x' + encode_hex(output) params2['post'] = copy.deepcopy(blk.to_dict(True)['state']) params2['postStateRoot'] = encode_hex(blk.state.root_hash) if mode == FILL: return params2 elif mode == VERIFY: params1 = copy.deepcopy(params) shouldbe, reallyis = params1.get('post', None), params2.get('post', None) compare_post_states(shouldbe, reallyis) for k in ['pre', 'exec', 'env', 'callcreates', 'out', 'gas', 'logs', 'postStateRoot']: _shouldbe = params1.get(k, None) _reallyis = params2.get(k, None) if str_to_bytes(k) == b'out' and _shouldbe[:1] in ('#', b'#'): _reallyis = str_to_bytes('#%s' % ((len(_reallyis) - 2) // 2)) if _shouldbe != _reallyis: print(('Mismatch {key}: shouldbe {shouldbe_key} != reallyis {reallyis_key}.\n' 'post: {shouldbe_post} != {reallyis_post}').format( shouldbe_key=_shouldbe, reallyis_key=_reallyis, shouldbe_post=shouldbe, reallyis_post=reallyis, key=k)) raise Exception("Mismatch: " + k + ':\n shouldbe %r\n reallyis %r' % (_shouldbe, _reallyis)) elif mode == TIME: return time_post - time_pre
def startGeth(test_case, test_tx): logger.info("running state test in geth.") genesis = gen.Genesis() for account_key in test_case['pre']: account = test_case['pre'][account_key] account['address'] = account_key genesis.addPrestateAccount(account) genesis.setCoinbase(test_case['env']['currentCoinbase']) genesis.setTimestamp(test_case['env']['currentTimestamp']) genesis.setGasLimit(test_case['env']['currentGasLimit']) genesis.setDifficulty(test_case['env']['currentDifficulty']) genesis.setBlockNumber(test_case['env']['currentNumber']) if cfg['FORK_CONFIG'] == 'Metropolis' or cfg['FORK_CONFIG'] == 'Byzantium': genesis.setConfigMetropolis() if cfg['FORK_CONFIG'] == 'Homestead': genesis.setConfigHomestead() geth_genesis = genesis.geth() g_path = genesis.export_geth() if sys.platform == "darwin": # OS X workaround for https://github.com/docker/for-mac/issues/1298 "The path /var/folders/wb/d8qys65575g8m2691vvglpmm0000gn/T/tmpctxz3buh.json is not shared from OS X and is not known to Docker." g_path = "/private" + g_path input_data = test_tx['data'] if input_data[0:2] == "0x": input_data = input_data[2:] tx_to = test_tx['to'] tx_value = parse_int_or_hex(test_tx['value']) gas_limit = parse_int_or_hex(test_tx['gasLimit']) gas_price = parse_int_or_hex(test_tx['gasPrice']) block_gaslimit = parse_int_or_hex(test_case['env']['currentGasLimit']) if gas_limit > block_gaslimit: logger.info("Tx gas limit exceeds block gas limit. not calling geth") return [] sender = '0x' + getTxSender(test_tx) sender_balance = parse_int_or_hex(test_case['pre'][sender]['balance']) balance_required = (gas_price * gas_limit) + tx_value if balance_required > sender_balance: logger.info("Insufficient balance. not calling geth") return [] intrinsic_gas = getIntrinsicGas(test_tx) if tx_to == "": # create contract cost not included in getIntrinsicGas intrinsic_gas += 32000 if gas_limit < intrinsic_gas: logger.info("Insufficient startgas. not calling geth") return [] if tx_to == "" and input_data == "": logger.info("no init code. not calling geth") return [] if tx_to in test_case['pre']: if 'code' in test_case['pre'][tx_to]: if test_case['pre'][tx_to]['code'] == '': logger.info( "To account in prestate has no code. not calling geth") return [] vm = VMUtils.GethVM(executable=cfg['GETH_DOCKER_NAME'], docker=True) return vm.start(genesis=g_path, gas=gas_limit, price=gas_price, json=True, sender=sender, receiver=tx_to, input=input_data, value=tx_value)
def run_block_test(params, config_overrides = {}): b = blocks.genesis(env, start_alloc=params["pre"]) gbh = params["genesisBlockHeader"] b.bloom = utils.scanners['int256b'](gbh["bloom"]) b.timestamp = utils.scanners['int'](gbh["timestamp"]) b.nonce = utils.scanners['bin'](gbh["nonce"]) b.extra_data = utils.scanners['bin'](gbh["extraData"]) b.gas_limit = utils.scanners['int'](gbh["gasLimit"]) b.gas_used = utils.scanners['int'](gbh["gasUsed"]) b.coinbase = utils.scanners['addr'](decode_hex(gbh["coinbase"])) b.difficulty = utils.parse_int_or_hex(gbh["difficulty"]) b.prevhash = utils.scanners['bin'](gbh["parentHash"]) b.mixhash = utils.scanners['bin'](gbh["mixHash"]) assert b.receipts.root_hash == \ utils.scanners['bin'](gbh["receiptTrie"]) assert b.transactions.root_hash == \ utils.scanners['bin'](gbh["transactionsTrie"]) assert utils.sha3rlp(b.uncles) == \ utils.scanners['bin'](gbh["uncleHash"]) h = encode_hex(b.state.root_hash) if h != str_to_bytes(gbh["stateRoot"]): raise Exception("state root mismatch") if b.hash != utils.scanners['bin'](gbh["hash"]): raise Exception("header hash mismatch") # assert b.header.check_pow() blockmap = {b.hash: b} env.db.put(b.hash, rlp.encode(b)) old_config = copy.deepcopy(env.config) for k, v in config_overrides.items(): env.config[k] = v b2 = None for blk in params["blocks"]: if 'blockHeader' not in blk: try: rlpdata = decode_hex(blk["rlp"][2:]) blkparent = rlp.decode( rlp.encode(rlp.decode(rlpdata)[0]), blocks.BlockHeader).prevhash b2 = rlp.decode(rlpdata, blocks.Block, parent=blockmap[blkparent], env=env) success = b2.validate_uncles() except (ValueError, TypeError, AttributeError, VerificationFailed, DecodingError, DeserializationError, InvalidTransaction, KeyError): success = False assert not success else: rlpdata = decode_hex(blk["rlp"][2:]) blkparent = rlp.decode(rlp.encode(rlp.decode(rlpdata)[0]), blocks.BlockHeader).prevhash b2 = rlp.decode(rlpdata, blocks.Block, parent=blockmap[blkparent], env=env) assert b2.validate_uncles() blockmap[b2.hash] = b2 env.db.put(b2.hash, rlp.encode(b2)) if b2: print('Block %d with state root %s' % (b2.number, encode_hex(b2.state.root_hash))) # blkdict = b.to_dict(False, True, False, True) # assert blk["blockHeader"] == \ # translate_keys(blkdict["header"], translator_list, lambda y, x: x, []) # assert blk["transactions"] == \ # [translate_keys(t, translator_list, valueconv, ['hash']) # for t in blkdict["transactions"]] # assert blk["uncleHeader"] == \ # [translate_keys(u, translator_list, lambda x: x, []) # for u in blkdict["uncles"]] env.config = old_config