def test_difficulty(filename, testname, testdata): testdata = fixture_to_bytes(testdata) parent_timestamp = int(testdata["parentTimestamp"], 10 if testdata["parentTimestamp"].isdigit() else 16) parent_difficulty = int( testdata["parentDifficulty"], 10 if testdata["parentDifficulty"].isdigit() else 16) parent_blk_number = int( testdata["currentBlockNumber"], 10 if testdata["currentBlockNumber"].isdigit() else 16) - 1 cur_blk_timestamp = int( testdata["currentTimestamp"], 10 if testdata["currentTimestamp"].isdigit() else 16) reference_dif = int(testdata["currentDifficulty"], 10 if testdata["currentDifficulty"].isdigit() else 16) env = tester.state().env if 'Homestead' in filename: env.config['HOMESTEAD_FORK_BLKNUM'] = 0 if 'difficultyMorden' in filename: env.config['HOMESTEAD_FORK_BLKNUM'] = 494000 parent_bh = blocks.BlockHeader(timestamp=parent_timestamp, difficulty=parent_difficulty, number=parent_blk_number) block = blocks.Block(parent_bh, [], env=env, making=True) calculated_dif = blocks.calc_difficulty(block, cur_blk_timestamp) print(calculated_dif) print(reference_dif) assert calculated_dif == reference_dif
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_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