def test_ADD_1(self): instruction = EVMAsm.disassemble_one(b"\x60\x10") self.assertEqual( EVMAsm.Instruction(0x60, "PUSH", 1, 0, 1, 3, "Place 1 byte item on stack.", 16, 0), instruction) instruction = EVMAsm.assemble_one("PUSH1 0x10") self.assertEqual( instruction, EVMAsm.Instruction(0x60, "PUSH", 1, 0, 1, 3, "Place 1 byte item on stack.", 16, 0)) instructions1 = EVMAsm.disassemble_all(b"\x30\x31") instructions2 = EVMAsm.assemble_all("ADDRESS\nBALANCE") self.assertTrue( all(a == b for a, b in zip(instructions1, instructions2))) # High level simple assembler/disassembler bytecode = EVMAsm.assemble_hex("""PUSH1 0x80 BLOCKHASH MSTORE PUSH1 0x2 PUSH2 0x100 """) self.assertEqual(bytecode, "0x608040526002610100") asmcode = EVMAsm.disassemble_hex("0x608040526002610100") self.assertEqual( asmcode, """PUSH1 0x80\nBLOCKHASH\nMSTORE\nPUSH1 0x2\nPUSH2 0x100""")
def test_ADD_1(self): instruction = EVMAsm.disassemble_one(b'\x60\x10') self.assertEqual( EVMAsm.Instruction(0x60, 'PUSH', 1, 0, 1, 0, 'Place 1 byte item on stack.', 16, 0), instruction) instruction = EVMAsm.assemble_one('PUSH1 0x10') EVMAsm.Instruction(0x60, 'PUSH', 1, 0, 1, 0, 'Place 1 byte item on stack.', 16, 0) instructions1 = EVMAsm.disassemble_all(b'\x30\x31') instructions2 = EVMAsm.assemble_all('ADDRESS\nBALANCE') self.assertTrue( all(a == b for a, b in zip(instructions1, instructions2))) # High level simple assembler/disassembler bytecode = EVMAsm.assemble_hex("""PUSH1 0x80 BLOCKHASH MSTORE PUSH1 0x2 PUSH2 0x100 """) self.assertEqual(bytecode, '0x608040526002610100') asmcode = EVMAsm.disassemble_hex('0x608040526002610100') self.assertEqual( asmcode, '''PUSH1 0x80\nBLOCKHASH\nMSTORE\nPUSH1 0x2\nPUSH2 0x100''')
def test_codehash_contract(self): evm_code = make_evm_ext_code( disassemble_one(bytes.fromhex("3f")), "0x895521964D724c8362A36608AAf09A3D7d0A0445", ) hex_code = assemble_hex(evm_code) code_hash = int.from_bytes(eth_utils.crypto.keccak(hexstr=hex_code), byteorder="big") contract_a = make_contract(evm_code, "uint256") contracts = create_many_contracts(contract_a) vm = create_evm_vm(contracts, True, False) output_handler = create_output_handler(contracts) vm.env.messages = messagestack.addMessage( value.Tuple([]), value.Tuple( make_msg_val( value.Tuple([0, 2345, contract_a.testMethod(0, 0)]) # type # sender )), ) run_until_block(vm, self) self.assertEqual(len(vm.logs), 1) val = vm.logs[0] parsed_out = output_handler(val) self.assertIsInstance(parsed_out, EVMReturn) self.assertEqual(parsed_out.output_values[0], code_hash)
def test_codecopy_contract(self): offset = 30 length = 80 evm_code = make_evm_codecopy_code( offset, length, "0x895521964D724c8362A36608AAf09A3D7d0A0445") hex_code = assemble_hex(evm_code) contract_a = make_contract(evm_code, "bytes") contracts = create_many_contracts(contract_a) vm = create_evm_vm(contracts, True, False) output_handler = create_output_handler(contracts) vm.env.messages = messagestack.addMessage( value.Tuple([]), value.Tuple( make_msg_val( value.Tuple([0, 2345, contract_a.testMethod(0, 0)]) # type # sender )), ) run_until_block(vm, self) self.assertEqual(len(vm.logs), 1) val = vm.logs[0] parsed_out = output_handler(val) self.assertIsInstance(parsed_out, EVMReturn) self.assertEqual( parsed_out.output_values[0].hex(), hex_code[2 + offset * 2:2 + offset * 2 + length * 2], )
def make_contract(evm_code, return_type, address=None): if not address: contract_address = "0x895521964D724c8362A36608AAf09A3D7d0A0445" else: contract_address = address return ContractABI({ "address": contract_address, "abi": [{ "constant": False, "inputs": [], "name": "testMethod", "outputs": [{ "name": "", "type": return_type }], "payable": False, "stateMutability": "view", "type": "function", }], "name": "TestContract", "code": assemble_hex(evm_code), "storage": {}, })
def test_codecopy_succeed(self): offset = 30 length = 80 evm_code = make_evm_codecopy_code( offset, length, "0x895521964D724c8362A36608AAf09A3D7d0A0445") hex_code = assemble_hex(evm_code) contract_a = make_contract(evm_code, "bytes") vm = create_many_contract_vm(contract_a) vm.env.send_message( [make_msg_val(contract_a.testMethod(4)), 2345, 0, 0]) vm.env.deliver_pending() run_until_block(vm, self) self.assertEqual(len(vm.logs), 1) val = vm.logs[0] parsed_out = vm.output_handler(val) self.assertIsInstance(parsed_out, EVMCall) self.assertEqual(parsed_out.output_values[0].hex(), hex_code[2 + offset * 2:2 + offset * 2 + length * 2])
def test_codehash_succeed(self): evm_code = make_evm_ext_code( disassemble_one(bytes.fromhex('3f')), "0x895521964D724c8362A36608AAf09A3D7d0A0445") hex_code = assemble_hex(evm_code) code_hash = int.from_bytes(eth_utils.crypto.keccak(hexstr=hex_code), byteorder="big") contract_a = make_contract(evm_code, "uint256") vm = create_many_contract_vm(contract_a) vm.env.send_message( [make_msg_val(contract_a.testMethod(4)), 2345, 0, 0]) vm.env.deliver_pending() run_until_block(vm, self) self.assertEqual(len(vm.logs), 1) val = vm.logs[0] parsed_out = vm.output_handler(val) self.assertIsInstance(parsed_out, EVMCall) self.assertEqual(parsed_out.output_values[0], code_hash)
def run_benchmark(iut, code, iterations, runs): hex_assembly = assemble_hex(prepare_code(code, iterations)) p = Popen([iut], stdout=PIPE, stdin=PIPE, stderr=PIPE) exec_results = p.communicate( bytes(json.dumps({ 'iterations': runs, 'code': hex_assembly }), encoding='utf-8')) try: results = json.loads(exec_results[0].decode("utf-8")) except json.decoder.JSONDecodeError: print("Unable to read results:") print("STDERR: {0}".format(exec_results[1].decode("utf-8"))) print("STDOUT: {0}".format(exec_results[0].decode("utf-8"))) raise names = {} units = {} hosts = {} df = pd.DataFrame(index=range(0, len(results[0]['values']))) for r in results: df[r['id']] = pd.DataFrame(r['values']) names.update({r['id']: r['name']}) units.update({r['id']: r['unit']}) hosts.update({r['id']: r['hostname']}) # for now we use the gas consumption of the first metric df['gas'] = pd.DataFrame(int(value, 0) for value in results[0]['gas']) names.update({'gas': 'Gas'}) units.update({'gas': 'gwei'}) hosts.update({'gas': results[0]['hostname']}) df['iterations'] = iterations return {'names': names, 'units': units, 'hosts': hosts, 'values': df}
def make_contract(evm_code, return_type): return ArbContract({ "address": "0x895521964D724c8362A36608AAf09A3D7d0A0445", "abi": [{ "constant": False, "inputs": [], "name": "testMethod", "outputs": [{ "name": "", "type": return_type }], "payable": False, "stateMutability": "view", "type": "function" }], "name": "TestContract", "code": assemble_hex(evm_code), "storage": {} })
print("\treads from stack:", instruction.reads_from_stack) print("\twrites to memory:", instruction.writes_to_memory) print("\treads from memory:", instruction.reads_from_memory) print("\twrites to storage:", instruction.writes_to_storage) print("\treads from storage:", instruction.reads_from_storage) print("\tis terminator", instruction.is_terminator) instruction = ea.disassemble_one("\x60\x10") printi(instruction) instruction = ea.assemble_one("PUSH1 0x10") printi(instruction) for instruction in ea.disassemble_all("\x30\x31"): printi(instruction) for instruction in ea.assemble_all("ADDRESS\nBALANCE"): printi(instruction) # High level simple assembler/disassembler print( ea.assemble_hex("""PUSH1 0x60 BLOCKHASH MSTORE PUSH1 0x2 PUSH2 0x100 """)) print(ea.disassemble_hex("0x606040526002610100"))
def assemble_hex(asmcode, pc=0, fork=pyevmasm.DEFAULT_FORK): return pyevmasm.assemble_hex(asmcode, pc, fork)