def test_store_multiple(self): data = ['key1', 'value1', 'key2', 'value2'] ans = self.sim.tx(self.ALICE, self.contract, 0, data) assert ans == [1] storage = self.sim.get_storage_dict(self.contract) assert storage.get(utils.zpad('key1', 32)) == 'value1' assert storage.get(utils.zpad('key2', 32)) == 'value2'
def test_reveal_returns_entropy(self): assert self.c.commit(1, self.COW_HASH, value=self.DEPOSIT_COST) == [1] assert self.c.request_entropy(sender=tester.k1, value=self.ENTROPY_COST) == [0, 4] assert self.c.get_block(self.s.block.number + 1) == [0, 1, 0, 1] self.s.mine(2) COW_SEED = utils.big_endian_to_int( utils.sha3( utils.sha3(utils.zpad('cow', 32)) + utils.zpad('cow', 32))) COW_HASH_1 = utils.big_endian_to_int( utils.sha3(utils.int_to_big_endian(COW_SEED))) balance = self.s.block.get_balance(tester.a0) assert self.c.reveal(1, self.COW_INT) == [1] assert self.s.block.get_balance( tester.a0 ) - balance == self.DEPOSIT_COST + self.ENTROPY_COST # deposit return + payout of committer share assert self.c.get_block(1) == [COW_SEED, 1, 1, 1] # signed vs unsigned as introduced by tester.send assert self.c.get_entropy_ticket(0) == [ int(tester.a1, 16), 1, 1, COW_HASH_1 - 2**256 ] assert self.c.get_entropy( 0, sender=tester.k1) == [1, COW_HASH_1 - 2**256] # ready
def test_reservation(self): data = ['ethereum.bit', '54.200.236.204'] ans = self.sim.tx(self.ALICE, self.contract, 0, data) assert ans == [1] assert self.sim.get_storage_dict(self.contract) == { utils.zpad('ethereum.bit', 32): '54.200.236.204' }
def hash_list(l): def g(x): if type(x) in [int, long]: x=utils.int_to_big_endian(x) return x y=map(g, l) y=[utils.zpad(x, 32) for x in y] y=''.join(y) #save for pretty print z="".join("{:02x}".format(ord(c)) for c in y) return b.sha256(y)
def test_double_reservation(self): data = ['ethereum.bit', '127.0.0.1'] ans = self.sim.tx(self.ALICE, self.contract, 0, data) assert ans == [1] data = ['ethereum.bit', '127.0.0.2'] ans = self.sim.tx(self.ALICE, self.contract, 0, data) assert ans == [0] assert self.sim.get_storage_dict(self.contract) == {utils.zpad('ethereum.bit', 32): '127.0.0.1'}
def hash_list(l): def g(x): if type(x) in [int, long]: x = utils.int_to_big_endian(x) return x y = map(g, l) y = [utils.zpad(x, 32) for x in y] y = ''.join(y) #save for pretty print z="".join("{:02x}".format(ord(c)) for c in y) return b.sha256(y)
def test_double_reservation(self): data = ['ethereum.bit', '127.0.0.1'] ans = self.sim.tx(self.ALICE, self.contract, 0, data) assert ans == [1] data = ['ethereum.bit', '127.0.0.2'] ans = self.sim.tx(self.ALICE, self.contract, 0, data) assert ans == [0] assert self.sim.get_storage_dict(self.contract) == { utils.zpad('ethereum.bit', 32): '127.0.0.1' }
def get_proposal_id(self, proposal): return big_endian_to_int(sha3(zpad(proposal, 32)))
def spvstorage(addr, index): prf1 = chain_manager.head.state.produce_spv_proof(addr.decode('hex')) storetree = chain_manager.head.get_storage(addr) prf2 = storetree.produce_spv_proof(utils.zpad(utils.encode_int(index), 32)) return rlp.encode(prf1 + prf2).encode('hex')
def encode_hex_from_int(x): return utils.zpad(utils.int_to_big_endian(x), 64).encode('hex')
def hash_value(value): return utils.big_endian_to_int(utils.sha3(utils.zpad(value, 32)))
def run_test_vm(params): pre = params['pre'] exek = params['exec'] callcreates = params.get('callcreates', []) env = params['env'] post = params.get('post', {}) check_testdata(env.keys(), [ 'currentGasLimit', 'currentTimestamp', 'previousHash', 'currentCoinbase', 'currentDifficulty', 'currentNumber' ]) # setup env db = new_db() blk = blocks.Block(db, prevhash=env['previousHash'].decode('hex'), number=int(env['currentNumber']), coinbase=env['currentCoinbase'], difficulty=int(env['currentDifficulty']), gas_limit=int(env['currentGasLimit']), timestamp=int(env['currentTimestamp'])) # code FIXME WHAT TO DO WITH THIS CODE??? # if isinstance(env['code'], str): # continue # else: # addr = 0 # FIXME # blk.set_code(addr, ''.join(map(chr, env['code']))) # setup state for address, h in pre.items(): check_testdata(h.keys(), ['code', 'nonce', 'balance', 'storage']) blk.set_nonce(address, int(h['nonce'])) blk.set_balance(address, int(h['balance'])) blk.set_code(address, h['code'][2:].decode('hex')) for k, v in h['storage']: blk.set_storage_data(address, u.big_endian_to_int(k.decode('hex')), u.big_endian_to_int(v.decode('hex'))) # execute transactions sender = exek['caller'] # a party that originates a call recvaddr = exek['address'] tx = transactions.Transaction(nonce=blk._get_acct_item( exek['caller'], 'nonce'), gasprice=int(exek['gasPrice']), startgas=int(exek['gas']), to=recvaddr, value=int(exek['value']), data=exek['data'][2:].decode('hex')) tx.sender = sender # capture apply_message calls apply_message_calls = [] orig_apply_msg = pb.apply_msg def apply_msg_wrapper(_ext, msg, code, toplevel=False): hexdata = msg.data.extract_all().encode('hex') apply_message_calls.append( dict(gasLimit=msg.gas, value=msg.value, destination=msg.to, data=hexdata)) if not toplevel: pb.apply_msg = orig_apply_msg result, gas_rem, data = orig_apply_msg(_ext, msg, code) if not toplevel: pb.apply_msg = apply_msg_wrapper return result, gas_rem, data pb.apply_msg = apply_msg_wrapper ext = pb.VMExt(blk, tx) msg = vm.Message(tx.sender, tx.to, tx.value, tx.startgas, vm.CallData([ord(x) for x in tx.data])) success, gas_remained, output = \ vm.vm_execute(ext, msg, exek['code'][2:].decode('hex')) pb.apply_msg = orig_apply_msg blk.commit_state() """ 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. """ if not success: return for k in ['gas', 'logs', 'out', 'post', 'callcreates']: assert k in params assert len(callcreates) == len(apply_message_calls) # check against callcreates for i, callcreate in enumerate(callcreates): amc = apply_message_calls[i] assert callcreate['data'] == '0x' + amc['data'] assert callcreate['gasLimit'] == str(amc['gasLimit']) assert callcreate['value'] == str(amc['value']) assert callcreate['destination'] == amc['destination'] if 'out' in params: assert '0x' + ''.join(map(chr, output)).encode('hex') == params['out'] if 'gas' in params: assert str(gas_remained) == params['gas'] if 'logs' in params: """ The logs sections is a mapping between the blooms and their corresponding logentries. Each logentry has the format: address: The address of the logentry. data: The data of the logentry. topics: The topics of the logentry, given as an array of values. """ test_logs = params['logs'] vm_logs = [] for log in tx.logs: vm_logs.append({ "bloom": bloom.b64(bloom.bloom_from_list( log.bloomables())).encode('hex'), "address": log.address, "data": '0x' + log.data.encode('hex'), "topics": [ u.zpad(u.int_to_big_endian(t), 32).encode('hex') for t in log.topics ] }) assert len(vm_logs) == len(test_logs) assert vm_logs == test_logs # check state for address, data in post.items(): state = blk.account_to_dict(address, for_vmtest=True) state.pop('storage_root', None) # attribute not present in vmtest fixtures assert data == state db.delete_db()
def generate_op_tests(): outs = {} for opcode, (name, inargs, outargs, _) in opcodes.opcodes.items(): _subid = 0 for push_depths in push_params: for jump_num, code_size in codesize_params: if name in ['CALL', 'CREATE', 'CALLCODE', 'LOG', 'POP', 'RETURN', 'STOP', 'INVALID', 'JUMP', 'JUMPI', 'CALLDATALOAD', 'CALLDATACOPY', 'CODECOPY', 'EXTCODECOPY', 'SHA3', 'MLOAD', 'MSTORE', 'MSTORE8', 'SUICIDE']: continue if name[:3] in ['DUP', 'SWA', 'LOG']: continue if name == 'SSTORE': jump_num /= 10 c = '\x5b' if name[:4] == 'PUSH': if push_depths != push_params[0]: continue for i in range(code_size): v = int(name[4:]) w = random.randrange(256**v) c += chr(0x5f + v) + utils.zpad(utils.encode_int(w), v) else: for i in range(code_size): for _ in range(inargs): v = push_depths[i * len(push_depths) // code_size] w = random.randrange(256**v) c += chr(0x5f + v) + utils.zpad(utils.encode_int(w), v) c += chr(opcode) for _ in range(outargs): c += chr(0x50) # PUSH1 0 MLOAD . DUP1 . PUSH1 1 ADD PUSH1 0 MSTORE . PUSH2 <jumps> GT PUSH1 0 JUMPI c += '\x60\x00\x51' + '\x80' + '\x60\x01\x01\x60\x00\x52' + \ '\x61'+chr(jump_num // 256) + chr(jump_num % 256) + '\x11\x60\x00\x57' o = { "callcreates": [], "env": { "currentCoinbase": "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", "currentDifficulty": "256", "currentGasLimit": "1000000000", "currentNumber": "257", "currentTimestamp": "1", "previousHash": "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" }, "exec": { "address": "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "caller": "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "code": "0x"+c.encode('hex'), "data": "0x", "gas": "1000000", "gasPrice": "100000000000000", "origin": "cd1722f3947def4cf144679da39c4c32bdc35681", "value": "1000000000000000000" }, "pre": { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6": { "balance": "1000000000000000000", "code": "0x", "nonce": "0", "storage": { } } }, "gas": "1000000", "logs": [], "out": "0x" } env = o['env'] pre = o['pre'] exek = o['exec'] blk = blocks.Block(db, prevhash=env['previousHash'].decode('hex'), number=int(env['currentNumber']), coinbase=env['currentCoinbase'], difficulty=int(env['currentDifficulty']), gas_limit=int(env['currentGasLimit']), timestamp=int(env['currentTimestamp'])) # setup state for address, h in pre.items(): blk.set_nonce(address, int(h['nonce'])) blk.set_balance(address, int(h['balance'])) blk.set_code(address, h['code'][2:].decode('hex')) for k, v in h['storage'].iteritems(): blk.set_storage_data(address, u.big_endian_to_int(k[2:].decode('hex')), u.big_endian_to_int(v[2:].decode('hex'))) # execute transactions sender = exek['caller'] # a party that originates a call recvaddr = exek['address'] tx = transactions.Transaction( nonce=blk._get_acct_item(exek['caller'], 'nonce'), gasprice=int(exek['gasPrice']), startgas=int(exek['gas']), to=recvaddr, value=int(exek['value']), data=exek['data'][2:].decode('hex')) tx.sender = sender ext = pb.VMExt(blk, tx) def blkhash(n): if n >= ext.block_number or n < ext.block_number - 256: return '' else: return u.sha3(str(n)) ext.block_hash = blkhash msg = vm.Message(tx.sender, tx.to, tx.value, tx.startgas, vm.CallData([ord(x) for x in tx.data])) success, gas_remained, output = \ vm.vm_execute(ext, msg, exek['code'][2:].decode('hex')) o['post'] = blk.to_dict(True)['state'] outs[name+str(_subid)] = o _subid += 1 return outs
def test_store_single(self): data = ['key', 'value'] ans = self.sim.tx(self.ALICE, self.contract, 0, data) assert ans == [] storage = self.sim.get_storage_dict(self.contract) assert storage.get(utils.zpad('key', 32)) == 'value'
def generate_op_tests(): outs = {} for opcode, (name, inargs, outargs, _) in opcodes.opcodes.items(): _subid = 0 for push_depths in push_params: for jump_num, code_size in codesize_params: if name in [ 'CALL', 'CREATE', 'CALLCODE', 'LOG', 'POP', 'RETURN', 'STOP', 'INVALID', 'JUMP', 'JUMPI', 'CALLDATALOAD', 'CALLDATACOPY', 'CODECOPY', 'EXTCODECOPY', 'SHA3', 'MLOAD', 'MSTORE', 'MSTORE8', 'SUICIDE' ]: continue if name[:3] in ['DUP', 'SWA', 'LOG']: continue if name == 'SSTORE': jump_num /= 10 c = '\x5b' if name[:4] == 'PUSH': if push_depths != push_params[0]: continue for i in range(code_size): v = int(name[4:]) w = random.randrange(256**v) c += chr(0x5f + v) + utils.zpad(utils.encode_int(w), v) else: for i in range(code_size): for _ in range(inargs): v = push_depths[i * len(push_depths) // code_size] w = random.randrange(256**v) c += chr(0x5f + v) + utils.zpad( utils.encode_int(w), v) c += chr(opcode) for _ in range(outargs): c += chr(0x50) # PUSH1 0 MLOAD . DUP1 . PUSH1 1 ADD PUSH1 0 MSTORE . PUSH2 <jumps> GT PUSH1 0 JUMPI c += '\x60\x00\x51' + '\x80' + '\x60\x01\x01\x60\x00\x52' + \ '\x61'+chr(jump_num // 256) + chr(jump_num % 256) + '\x11\x60\x00\x57' o = { "callcreates": [], "env": { "currentCoinbase": "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", "currentDifficulty": "256", "currentGasLimit": "1000000000", "currentNumber": "257", "currentTimestamp": "1", "previousHash": "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" }, "exec": { "address": "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "caller": "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "code": "0x" + c.encode('hex'), "data": "0x", "gas": "1000000", "gasPrice": "100000000000000", "origin": "cd1722f3947def4cf144679da39c4c32bdc35681", "value": "1000000000000000000" }, "pre": { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6": { "balance": "1000000000000000000", "code": "0x", "nonce": "0", "storage": {} } }, "gas": "1000000", "logs": [], "out": "0x" } env = o['env'] pre = o['pre'] exek = o['exec'] blk = blocks.Block(db, prevhash=env['previousHash'].decode('hex'), number=int(env['currentNumber']), coinbase=env['currentCoinbase'], difficulty=int(env['currentDifficulty']), gas_limit=int(env['currentGasLimit']), timestamp=int(env['currentTimestamp'])) # setup state for address, h in pre.items(): blk.set_nonce(address, int(h['nonce'])) blk.set_balance(address, int(h['balance'])) blk.set_code(address, h['code'][2:].decode('hex')) for k, v in h['storage'].iteritems(): blk.set_storage_data( address, u.big_endian_to_int(k[2:].decode('hex')), u.big_endian_to_int(v[2:].decode('hex'))) # execute transactions sender = exek['caller'] # a party that originates a call recvaddr = exek['address'] tx = transactions.Transaction( nonce=blk._get_acct_item(exek['caller'], 'nonce'), gasprice=int(exek['gasPrice']), startgas=int(exek['gas']), to=recvaddr, value=int(exek['value']), data=exek['data'][2:].decode('hex')) tx.sender = sender ext = pb.VMExt(blk, tx) def blkhash(n): if n >= ext.block_number or n < ext.block_number - 256: return '' else: return u.sha3(str(n)) ext.block_hash = blkhash msg = vm.Message(tx.sender, tx.to, tx.value, tx.startgas, vm.CallData([ord(x) for x in tx.data])) success, gas_remained, output = \ vm.vm_execute(ext, msg, exek['code'][2:].decode('hex')) o['post'] = blk.to_dict(True)['state'] outs[name + str(_subid)] = o _subid += 1 return outs
def generate_op_tests(): out = {} for opcode, (name, inargs, outargs, _) in opcodes.items(): _subid = 0 for push_depths in push_params: for jump_num, code_size in codesize_params: if name in [ 'DELEGATECALL', 'LOG0', 'LOG1', 'LOG2', 'LOG3', 'LOG4', 'CALL', 'CREATE', 'CALLCODE', 'RETURNDATACOPY', 'RETURNDATASIZE', 'CALLBLACKBOX', 'STATICCALL', 'REVERT', 'RETURN', 'STOP', 'INVALID', 'JUMP', 'JUMPI', 'SUICIDE' ]: continue if name == 'SSTORE': jump_num /= 10 c = '' if name[:4] == 'PUSH': if push_depths != push_params[0]: continue for i in range(code_size): v = int(name[4:]) w = random.randrange(256**v) c += chr(0x5f + v) + utils.zpad(utils.encode_int(w), v) elif name[:3] == 'DUP': if push_depths != push_params[0]: continue for _ in range(inargs): v = push_depths[_ * len(push_depths) // code_size] w = random.randrange(256**v) c += chr(0x5f + v) + utils.zpad(utils.encode_int(w), v) for i in range(code_size): c += chr(opcode) for i in range(outargs): c += chr(0x50) elif name[:4] == "SWAP": if push_depths != push_params[0]: continue for _ in range(inargs): v = push_depths[_ * len(push_depths) // code_size] w = random.randrange(256**v) c += chr(0x5f + v) + utils.zpad(utils.encode_int(w), v) for i in range(code_size): c += chr(opcode) for i in range(outargs): c += chr(0x50) elif name == "POP": if push_depths != push_params[0]: continue for _ in range(code_size): v = push_depths[_ * len(push_depths) // code_size] w = random.randrange(256**v) c += chr(0x5f + v) + utils.zpad(utils.encode_int(w), v) c += '\x50' # for i in range(code_size): # c += chr(opcode) elif name == 'SHA3': if push_depths != push_params[0]: continue v = 32 w = random.randrange(256**v) c += chr(0x5f + v) + utils.zpad(utils.encode_int(w), v) _w = 0 c += chr(0x5f + 1) + utils.zpad(utils.encode_int(_w), 1) c += '\x52' c += chr(0x5f + v) + utils.zpad(utils.encode_int(w), v) _w += 32 c += chr(0x5f + 1) + utils.zpad(utils.encode_int(_w), 1) c += '\x52' c += chr(0x5f + v) + utils.zpad(utils.encode_int(w), v) _w += 64 c += chr(0x5f + 1) + utils.zpad(utils.encode_int(_w), 1) c += '\x52' c += chr(0x5f + v) + utils.zpad(utils.encode_int(w), v) _w += 128 c += chr(0x5f + 1) + utils.zpad(utils.encode_int(_w), 1) c += '\x52' # c += chr(0x5f + v) + utils.zpad(utils.encode_int(w), v) for i in range(code_size): c += chr(0x59) c += '\x60\x00' c += chr(opcode) c += '\x50' c += '\x60\x48' + '\x60\x00' + '\x53' + '\x60\x45' + '\x60\x01' + '\x53' + '\x60\x4c' + '\x60\x02' + '\x53' + '\x60\x4c' + '\x60\x03' + '\x53' + '\x60\x4f' + '\x60\x04' + '\x53' + '\x60\x48' + '\x60\x05' + '\x53' + '\x60\x45' + '\x60\x06' + '\x53' + '\x60\x4c' + '\x60\x07' + '\x53' + '\x60\x4c' + '\x60\x08' + '\x53' + '\x60\x4f' + '\x60\x09' + '\x53' + '\x60\x48' + '\x60\x0a' + '\x53' + '\x60\x45' + '\x60\x0b' + '\x53' + '\x60\x4c' + '\x60\x0c' + '\x53' + '\x60\x4c' + '\x60\x0d' + '\x53' + '\x60\x4f' + '\x60\x0e' + '\x53' + '\x60\x48' + '\x60\x0f' + '\x53' + '\x60\x45' + '\x60\x10' + '\x53' + '\x60\x4c' + '\x60\x11' + '\x53' + '\x60\x4c' + '\x60\x12' + '\x53' + '\x60\x4f' + '\x60\x13' + '\x53' + '\x60\x48' + '\x60\x14' + '\x53' + '\x60\x45' + '\x60\x15' + '\x53' + '\x60\x4c' + '\x60\x16' + '\x53' + '\x60\x4c' + '\x60\x17' + '\x53' + '\x60\x4f' + '\x60\x18' + '\x53' + '\x60\x48' + '\x60\x19' + '\x53' + '\x60\x45' + '\x60\x1a' + '\x53' + '\x60\x4c' + '\x60\x1b' + '\x53' + '\x60\x4c' + '\x60\x1c' + '\x53' + '\x60\x4f' + '\x60\x1d' + '\x53' + '\x60\x48' + '\x60\x1e' + '\x53' + '\x60\x45' + '\x60\x1f' + '\x53' + '\x60\x1f' + '\x60\x00' for i in range(code_size): c += chr(opcode) c += '\x50' elif name == 'MLOAD': if push_depths != push_params[0]: continue w = random.randrange(256**32) c += chr(0x7f) + utils.zpad(utils.encode_int(w), 32) c += '\x60\x00' + '\x52' + '\x60\x00' for i in range(code_size): c += chr(opcode) c += '\x50' + '\x60\x00' elif name == 'MSTORE': if push_depths != push_params[0]: continue for i in range(code_size): v = 32 w = random.randrange(256**v) c += chr(0x5f + v) + utils.zpad(utils.encode_int(w), v) _w = random.randrange(256**1) c += chr(0x5f + 1) + utils.zpad( utils.encode_int(_w), 1) c += chr(opcode) elif name == 'MSTORE8': if push_depths != push_params[0]: continue for i in range(code_size): w = random.randrange(256) c += chr(0x5f + 1) + utils.zpad(utils.encode_int(w), 1) _w = random.randrange(32) c += chr(0x5f + 1) + utils.zpad( utils.encode_int(_w), 1) c += chr(opcode) elif name == 'CALLDATALOAD': if push_depths != push_params[0]: continue for i in range(code_size): c += '\x60\x00' c += chr(opcode) c += '\x50' elif name == 'CALLDATACOPY': if push_depths != push_params[0]: continue v = 32 w = random.randrange(256**v) c += chr(0x5f + v) + utils.zpad(utils.encode_int(w), v) _w = 0 c += chr(0x5f + 1) + utils.zpad(utils.encode_int(_w), 1) c += '\x52' for i in range(code_size): c += '\x36\x60\x00' _w = 256 c += chr(0x5f + 2) + utils.zpad( utils.encode_int(_w), 1) c += chr(opcode) elif name == 'EXTCODECOPY': if push_depths != push_params[0]: continue for i in range(code_size): c += '\x73\xee\xefSt\xfc\xe5\xed\xbc\x8e*\x86\x97\xc1S1g~n\xbf\x0b' + '\x3b' + '\x60\x00\x60\x00' '\x73\xee\xefSt\xfc\xe5\xed\xbc\x8e*\x86\x97\xc1S1g~n\xbf\x0b' c += chr(opcode) elif name == 'EXTCODESIZE': if push_depths != push_params[0]: continue for i in range(code_size): c += '\x73\x0fW.R\x95\xc5\x7f\x15\x88o\x9b&>/m-l{^\xc6' c += chr(opcode) elif name == 'CODECOPY': if push_depths != push_params[0]: continue # coded = '`r`\xb5\x01P`\xb9`\xb4\x01P`\x8a`S\x01P`\xa4`z\x01P`\x92`\xc3\x01P`J' # c += coded for i in range(code_size): c += '\x73\x0fW.R\x95\xc5\x7f\x15\x88o\x9b&>/m-l{^\xc6' c += '\x38\x60\x00\x60\x00' + chr(opcode) elif name == "BALANCE": if push_depths != push_params[0]: continue for i in range(code_size): c += '\x73\x0fW.R\x95\xc5\x7f\x15\x88o\x9b&>/m-l{^\xc6' c += chr(opcode) elif name == 'SSTORE': if push_depths != push_params[0]: continue for i in range(code_size): v = 32 w = random.randrange(256**v) c += chr(0x5f + v) + utils.zpad(utils.encode_int(w), v) _w = 86 c += chr(0x5f + 1) + utils.zpad( utils.encode_int(_w), 1) c += chr(opcode) elif name == 'SLOAD': if push_depths != push_params[0]: continue for i in range(code_size): v = 1 w = 86 c += chr(0x5f + v) + utils.zpad(utils.encode_int(w), v) c += chr(opcode) elif name == "BLOCKHASH": for i in range(code_size): for i in range(inargs): v = 1 w = random.randrange(256**v) c += chr(0x5f + v) + utils.zpad( utils.encode_int(w), 1) c += chr(opcode) # for _ in range(outargs): # c += chr(0x50) elif name == "EXP": if push_depths != push_params[0]: continue for i in range(code_size): for _ in range(inargs): v = 32 w = random.randrange(256**v) c += chr(0x5f + v) + utils.zpad( utils.encode_int(w), 1) c += chr(opcode) for _ in range(outargs): c += chr(0x50) # elif name == "RETURNDATACOPY": # if push_depths != push_params[0]: # continue # for i in range(code_size): # c += '\x60\x00\x60\x00\x60\x00' # c += chr(opcode) # elif name == "RETURNDATASIZE": # if push_depths != push_params[0]: # continue # for i in range(code_size): # c += chr(opcode) else: for i in range(code_size): for _ in range(inargs): v = push_depths[i * len(push_depths) // code_size] w = random.randrange(256**v) c += chr(0x5f + v) + utils.zpad( utils.encode_int(w), v) c += chr(opcode) for _ in range(outargs): c += chr(0x50) # PUSH1 0 MLOAD . DUP1 . PUSH1 1 ADD PUSH1 0 MSTORE . PUSH2 <jumps> GT PUSH1 0 JUMPI # c += '\x60\x00\x51' + '\x80' + '\x60\x01\x01\x60\x00\x52' + \ # '\x61'+chr(jump_num // 256) + chr(jump_num % 256) + '\x11\x60\x00\x57' o = o = { "callcreates": [], "env": { "currentCoinbase": "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", "currentDifficulty": "256", "currentGasLimit": "1000000000", "currentNumber": "257", "currentTimestamp": "1", "previousHash": "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" }, "exec": { "address": "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "caller": "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "code": "0x" + c.encode('hex'), "data": "0xc4ede3d3c49e38e7351405f35621bafce3a2ef3cef0af0a119fe3772ffcc2a8a0aa48ac7dc2bdc26dfad6de18cd9ea15a119bd676f5b3e492f2c2a5cc3ed6f6182041cda117a1fdc958df9e53b3f957d676f15003da9d6792800b612d8f9ec6d85ea7ca5f70789cf04137db582e89c73fcd3fafeb24db17c91ef9950eca6d3c194be97be7ecae7c2892fb915619d4845dcbd9510544a9cb88a54a7baa313d85c196387eeaeaddf8c03d2d0a222bf3b94c87c9ad20180f821db4f85347247e650200bc5b1b045f0da19aee3e94c585bb08bc47586962ec3269f66318ab2356e6a786dc5b0b51af3dc0d7751f22a63301baa9383c2c5e4d953e558b09af532e075", "gas": "100000000", "gasPrice": "100000000000000", "origin": "cd1722f3947def4cf144679da39c4c32bdc35681", "value": "1000000000000000000" }, "pre": { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6": { "balance": "1000000000000000000", "code": "0x36303732363062353031353036306239363062343031353036303861363035", "nonce": "0", "storage": { "0x56": "0x0f5b2ebf118c64ede45e3d5f4436fd219110d1f20442c6f153a22c39a70bf7df" } } }, "gas": "1000000000", "logs": [], "out": "0x" } out[name + str(_subid)] = o _subid += 1 return out
def run_test_vm(params): print params pre = params['pre'] exek = params['exec'] callcreates = params.get('callcreates', []) env = params['env'] post = params.get('post', {}) check_testdata(env.keys(), ['currentGasLimit', 'currentTimestamp', 'previousHash', 'currentCoinbase', 'currentDifficulty', 'currentNumber']) # setup env blk = blocks.Block(db, prevhash=env['previousHash'].decode('hex'), number=int(env['currentNumber']), coinbase=env['currentCoinbase'], difficulty=int(env['currentDifficulty']), gas_limit=int(env['currentGasLimit']), timestamp=int(env['currentTimestamp'])) # code FIXME WHAT TO DO WITH THIS CODE??? # if isinstance(env['code'], str): # continue # else: # addr = 0 # FIXME # blk.set_code(addr, ''.join(map(chr, env['code']))) # setup state for address, h in pre.items(): check_testdata(h.keys(), ['code', 'nonce', 'balance', 'storage']) blk.set_nonce(address, int(h['nonce'])) blk.set_balance(address, int(h['balance'])) blk.set_code(address, h['code'][2:].decode('hex')) for k, v in h['storage'].iteritems(): blk.set_storage_data(address, u.big_endian_to_int(k[2:].decode('hex')), u.big_endian_to_int(v[2:].decode('hex'))) # execute transactions sender = exek['caller'] # a party that originates a call recvaddr = exek['address'] tx = transactions.Transaction( nonce=blk._get_acct_item(exek['caller'], 'nonce'), gasprice=int(exek['gasPrice']), startgas=int(exek['gas']), to=recvaddr, value=int(exek['value']), data=exek['data'][2:].decode('hex')) tx.sender = sender # capture apply_message calls apply_message_calls = [] orig_apply_msg = pb.apply_msg ext = pb.VMExt(blk, tx) def call_wrapper(msg): ext.set_balance(msg.sender, ext.get_balance(msg.sender) - msg.value) hexdata = msg.data.extract_all().encode('hex') apply_message_calls.append(dict(gasLimit=msg.gas, value=msg.value, destination=msg.to, data=hexdata)) return 1, msg.gas, '' def sendmsg_wrapper(msg, code): ext.set_balance(msg.sender, ext.get_balance(msg.sender) - msg.value) hexdata = msg.data.extract_all().encode('hex') apply_message_calls.append(dict(gasLimit=msg.gas, value=msg.value, destination=msg.to, data=hexdata)) return 1, msg.gas, '' def create_wrapper(msg): ext.set_balance(msg.sender, ext.get_balance(msg.sender) - msg.value) sender = msg.sender.decode('hex') if len(msg.sender) == 40 else msg.sender nonce = u.encode_int(ext._block.get_nonce(msg.sender)) addr = u.sha3(rlp.encode([sender, nonce]))[12:].encode('hex') hexdata = msg.data.extract_all().encode('hex') apply_message_calls.append(dict(gasLimit=msg.gas, value=msg.value, destination='', data=hexdata)) return 1, msg.gas, addr ext.sendmsg = sendmsg_wrapper ext.call = call_wrapper ext.create = create_wrapper def blkhash(n): if n >= ext.block_number or n < ext.block_number - 256: return '' else: return u.sha3(str(n)) ext.block_hash = blkhash msg = vm.Message(tx.sender, tx.to, tx.value, tx.startgas, vm.CallData([ord(x) for x in tx.data])) success, gas_remained, output = \ vm.vm_execute(ext, msg, exek['code'][2:].decode('hex')) pb.apply_msg = orig_apply_msg blk.commit_state() """ 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. """ if not success: assert 'gas' not in params assert 'post' not in params return for k in ['gas', 'logs', 'out', 'post', 'callcreates']: assert k in params assert len(callcreates) == len(apply_message_calls) # check against callcreates for i, callcreate in enumerate(callcreates): amc = apply_message_calls[i] assert callcreate['data'] == '0x' + amc['data'] assert callcreate['gasLimit'] == str(amc['gasLimit']) assert callcreate['value'] == str(amc['value']) assert callcreate['destination'] == amc['destination'] if 'out' in params: assert '0x' + ''.join(map(chr, output)).encode('hex') == params['out'] if 'gas' in params: assert str(gas_remained) == params['gas'] if 'logs' in params: """ The logs sections is a mapping between the blooms and their corresponding logentries. Each logentry has the format: address: The address of the logentry. data: The data of the logentry. topics: The topics of the logentry, given as an array of values. """ test_logs = params['logs'] vm_logs = [] for log in tx.logs: vm_logs.append({ "bloom": bloom.b64(bloom.bloom_from_list(log.bloomables())).encode('hex'), "address": log.address, "data": '0x' + log.data.encode('hex'), "topics": [u.zpad(u.int_to_big_endian(t), 32).encode('hex') for t in log.topics] }) assert len(vm_logs) == len(test_logs) assert vm_logs == test_logs # check state for address, data in post.items(): state = blk.account_to_dict(address, for_vmtest=True) state.pop('storage_root', None) # attribute not present in vmtest fixtures assert data == state
def test_reservation(self): data = ['ethereum.bit', '54.200.236.204'] ans = self.sim.tx(self.ALICE, self.contract, 0, data) assert ans == [1] assert self.sim.get_storage_dict(self.contract) == {utils.zpad('ethereum.bit', 32): '54.200.236.204'}