diff --git a/examples/example.c b/examples/example.c index 5b9f2148d..07ca13199 100644 --- a/examples/example.c +++ b/examples/example.c @@ -58,8 +58,10 @@ int main(int argc, char* argv[]) .input_size = sizeof(input), .gas = gas, .depth = 0, + .code = code, + .code_size = code_size, }; - struct evmc_result result = evmc_execute(vm, host, ctx, EVMC_HOMESTEAD, &msg, code, code_size); + struct evmc_result result = evmc_execute(vm, host, ctx, EVMC_HOMESTEAD, &msg); printf("Execution result:\n"); int exit_code = 0; if (result.status_code != EVMC_SUCCESS) diff --git a/examples/example_precompiles_vm/example_precompiles_vm.cpp b/examples/example_precompiles_vm/example_precompiles_vm.cpp index 8c6cf3e38..b705fb519 100644 --- a/examples/example_precompiles_vm/example_precompiles_vm.cpp +++ b/examples/example_precompiles_vm/example_precompiles_vm.cpp @@ -52,9 +52,7 @@ evmc_result execute(evmc_vm* /*vm*/, const evmc_host_interface* /*host*/, evmc_host_context* /*context*/, enum evmc_revision rev, - const evmc_message* msg, - const uint8_t* /*code*/, - size_t /*code_size*/) + const evmc_message* msg) { // The EIP-1352 (https://eips.ethereum.org/EIPS/eip-1352) defines // the range 0 - 0xffff (2 bytes) of addresses reserved for precompiled contracts. diff --git a/examples/example_vm/example_vm.cpp b/examples/example_vm/example_vm.cpp index ecb99c8fc..43bb0b5ce 100644 --- a/examples/example_vm/example_vm.cpp +++ b/examples/example_vm/example_vm.cpp @@ -163,9 +163,7 @@ evmc_result execute(evmc_vm* instance, const evmc_host_interface* host, evmc_host_context* context, enum evmc_revision rev, - const evmc_message* msg, - const uint8_t* code, - size_t code_size) + const evmc_message* msg) { auto* vm = static_cast(instance); @@ -176,14 +174,14 @@ evmc_result execute(evmc_vm* instance, Stack stack; Memory memory; - for (size_t pc = 0; pc < code_size; ++pc) + for (size_t pc = 0; pc < msg->code_size; ++pc) { // Check remaining gas, assume each instruction costs 1. gas_left -= 1; if (gas_left < 0) return evmc_make_result(EVMC_OUT_OF_GAS, 0, 0, nullptr, 0); - switch (code[pc]) + switch (msg->code[pc]) { default: return evmc_make_result(EVMC_UNDEFINED_INSTRUCTION, 0, 0, nullptr, 0); @@ -296,9 +294,9 @@ evmc_result execute(evmc_vm* instance, case OP_PUSH32: { evmc_uint256be value = {}; - size_t num_push_bytes = size_t{code[pc]} - OP_PUSH1 + 1; + size_t num_push_bytes = size_t{msg->code[pc]} - OP_PUSH1 + 1; size_t offset = sizeof(value) - num_push_bytes; - std::memcpy(&value.bytes[offset], &code[pc + 1], num_push_bytes); + std::memcpy(&value.bytes[offset], &msg->code[pc + 1], num_push_bytes); pc += num_push_bytes; stack.push(value); break; diff --git a/include/evmc/evmc.h b/include/evmc/evmc.h index f8558902c..18ac7f952 100644 --- a/include/evmc/evmc.h +++ b/include/evmc/evmc.h @@ -1064,9 +1064,7 @@ typedef struct evmc_result (*evmc_execute_fn)(struct evmc_vm* vm, const struct evmc_host_interface* host, struct evmc_host_context* context, enum evmc_revision rev, - const struct evmc_message* msg, - uint8_t const* code, - size_t code_size); + const struct evmc_message* msg); /** * Possible capabilities of a VM. diff --git a/include/evmc/evmc.hpp b/include/evmc/evmc.hpp index 91386c46f..ab16312f7 100644 --- a/include/evmc/evmc.hpp +++ b/include/evmc/evmc.hpp @@ -720,21 +720,15 @@ class VM Result execute(const evmc_host_interface& host, evmc_host_context* ctx, evmc_revision rev, - const evmc_message& msg, - const uint8_t* code, - size_t code_size) noexcept + const evmc_message& msg) noexcept { - return Result{m_instance->execute(m_instance, &host, ctx, rev, &msg, code, code_size)}; + return Result{m_instance->execute(m_instance, &host, ctx, rev, &msg)}; } /// Convenient variant of the VM::execute() that takes reference to evmc::Host class. - Result execute(Host& host, - evmc_revision rev, - const evmc_message& msg, - const uint8_t* code, - size_t code_size) noexcept + Result execute(Host& host, evmc_revision rev, const evmc_message& msg) noexcept { - return execute(Host::get_interface(), host.to_context(), rev, msg, code, code_size); + return execute(Host::get_interface(), host.to_context(), rev, msg); } /// Executes code without the Host context. @@ -745,13 +739,9 @@ class VM /// but without providing the Host context and interface. /// This method is for experimental precompiles support where execution is /// guaranteed not to require any Host access. - Result execute(evmc_revision rev, - const evmc_message& msg, - const uint8_t* code, - size_t code_size) noexcept + Result execute(evmc_revision rev, const evmc_message& msg) noexcept { - return Result{ - m_instance->execute(m_instance, nullptr, nullptr, rev, &msg, code, code_size)}; + return Result{m_instance->execute(m_instance, nullptr, nullptr, rev, &msg)}; } /// Returns the pointer to C EVMC struct representing the VM. diff --git a/include/evmc/helpers.h b/include/evmc/helpers.h index 683567ef1..e50a569ab 100644 --- a/include/evmc/helpers.h +++ b/include/evmc/helpers.h @@ -93,11 +93,9 @@ static inline struct evmc_result evmc_execute(struct evmc_vm* vm, const struct evmc_host_interface* host, struct evmc_host_context* context, enum evmc_revision rev, - const struct evmc_message* msg, - uint8_t const* code, - size_t code_size) + const struct evmc_message* msg) { - return vm->execute(vm, host, context, rev, msg, code, code_size); + return vm->execute(vm, host, context, rev, msg); } /// The evmc_result release function using free() for releasing the memory. diff --git a/lib/tooling/run.cpp b/lib/tooling/run.cpp index ce8be55e1..eef3255b1 100644 --- a/lib/tooling/run.cpp +++ b/lib/tooling/run.cpp @@ -23,7 +23,6 @@ auto bench(MockedHost& host, evmc::VM& vm, evmc_revision rev, const evmc_message& msg, - bytes_view code, const evmc::Result& expected_result, std::ostream& out) { @@ -37,7 +36,7 @@ auto bench(MockedHost& host, // Probe run: execute once again the already warm code to estimate a single run time. const auto probe_start = clock::now(); - const auto result = vm.execute(host, rev, msg, code.data(), code.size()); + const auto result = vm.execute(host, rev, msg); const auto bench_start = clock::now(); const auto probe_time = bench_start - probe_start; @@ -50,7 +49,7 @@ auto bench(MockedHost& host, // Benchmark loop. const auto num_iterations = std::max(static_cast(target_bench_time / probe_time), 1); for (int i = 0; i < num_iterations; ++i) - vm.execute(host, rev, msg, code.data(), code.size()); + vm.execute(host, rev, msg); const auto bench_time = (clock::now() - bench_start) / num_iterations; out << "Time: " << std::chrono::duration_cast(bench_time).count() << unit_name @@ -77,16 +76,19 @@ int run(VM& vm, msg.gas = gas; msg.input_data = input.data(); msg.input_size = input.size(); + msg.code = code.data(); + msg.code_size = code.size(); - bytes_view exec_code = code; if (create) { evmc_message create_msg{}; create_msg.kind = EVMC_CREATE; create_msg.recipient = create_address; create_msg.gas = create_gas; + create_msg.code = code.data(); + create_msg.code_size = code.size(); - const auto create_result = vm.execute(host, rev, create_msg, code.data(), code.size()); + const auto create_result = vm.execute(host, rev, create_msg); if (create_result.status_code != EVMC_SUCCESS) { out << "Contract creation failed: " << create_result.status_code << "\n"; @@ -97,14 +99,15 @@ int run(VM& vm, created_account.code = bytes(create_result.output_data, create_result.output_size); msg.recipient = create_address; - exec_code = created_account.code; + msg.code = created_account.code.data(); + msg.code_size = created_account.code.size(); } out << "\n"; - const auto result = vm.execute(host, rev, msg, exec_code.data(), exec_code.size()); + const auto result = vm.execute(host, rev, msg); if (bench) - tooling::bench(host, vm, rev, msg, exec_code, result, out); + tooling::bench(host, vm, rev, msg, result, out); const auto gas_used = msg.gas - result.gas_left; out << "Result: " << result.status_code << "\nGas used: " << gas_used << "\n"; diff --git a/test/unittests/cpp_test.cpp b/test/unittests/cpp_test.cpp index 942487a3e..904528d86 100644 --- a/test/unittests/cpp_test.cpp +++ b/test/unittests/cpp_test.cpp @@ -495,7 +495,7 @@ TEST(cpp, vm) const auto host = evmc_host_interface{}; auto msg = evmc_message{}; msg.gas = 1; - auto res = vm.execute(host, nullptr, EVMC_MAX_REVISION, msg, nullptr, 0); + auto res = vm.execute(host, nullptr, EVMC_MAX_REVISION, msg); EXPECT_EQ(res.status_code, EVMC_SUCCESS); EXPECT_EQ(res.gas_left, 1); } @@ -616,7 +616,7 @@ TEST(cpp, vm_execute_precompiles) msg.input_size = input.size(); msg.gas = 18; - auto res = vm.execute(EVMC_MAX_REVISION, msg, nullptr, 0); + auto res = vm.execute(EVMC_MAX_REVISION, msg); EXPECT_EQ(res.status_code, EVMC_SUCCESS); EXPECT_EQ(res.gas_left, 0); ASSERT_EQ(res.output_size, input.size()); @@ -632,7 +632,7 @@ TEST(cpp, vm_execute_with_null_host) auto vm = evmc::VM{evmc_create_example_vm()}; const evmc_message msg{}; - auto res = vm.execute(host, EVMC_FRONTIER, msg, nullptr, 0); + auto res = vm.execute(host, EVMC_FRONTIER, msg); EXPECT_EQ(res.status_code, EVMC_SUCCESS); EXPECT_EQ(res.gas_left, 0); } diff --git a/test/unittests/example_vm_test.cpp b/test/unittests/example_vm_test.cpp index 801d711b2..e8b428957 100644 --- a/test/unittests/example_vm_test.cpp +++ b/test/unittests/example_vm_test.cpp @@ -51,8 +51,10 @@ class example_vm : public testing::Test msg.gas = gas; msg.input_data = input.data(); msg.input_size = input.size(); + msg.code = code.data(); + msg.code_size = code.size(); - return vm.execute(host, rev, msg, code.data(), code.size()); + return vm.execute(host, rev, msg); } }; diff --git a/tools/vmtester/tests.cpp b/tools/vmtester/tests.cpp index dbd903f6d..df7b37652 100644 --- a/tools/vmtester/tests.cpp +++ b/tools/vmtester/tests.cpp @@ -55,12 +55,13 @@ TEST_F(evmc_vm_test, capabilities) TEST_F(evmc_vm_test, execute_call) { evmc::MockedHost mockedHost; - const evmc_message msg{}; + evmc_message msg{}; std::array code = {{0xfe, 0x00}}; + msg.code = code.data(); + msg.code_size = code.size(); - const evmc_result result = - vm->execute(vm, &evmc::MockedHost::get_interface(), mockedHost.to_context(), - EVMC_MAX_REVISION, &msg, code.data(), code.size()); + const evmc_result result = vm->execute(vm, &evmc::MockedHost::get_interface(), + mockedHost.to_context(), EVMC_MAX_REVISION, &msg); // Validate some constraints if (result.status_code != EVMC_SUCCESS && result.status_code != EVMC_REVERT) @@ -86,6 +87,7 @@ TEST_F(evmc_vm_test, execute_call) TEST_F(evmc_vm_test, execute_create) { + std::array code = {{0xfe, 0x00}}; evmc::MockedHost mockedHost; const evmc_message msg{EVMC_CREATE, 0, @@ -98,13 +100,11 @@ TEST_F(evmc_vm_test, execute_create) evmc_uint256be{}, evmc_bytes32{}, evmc_address{}, - nullptr, - 0}; - std::array code = {{0xfe, 0x00}}; + code.data(), + code.size()}; - const evmc_result result = - vm->execute(vm, &evmc::MockedHost::get_interface(), mockedHost.to_context(), - EVMC_MAX_REVISION, &msg, code.data(), code.size()); + const evmc_result result = vm->execute(vm, &evmc::MockedHost::get_interface(), + mockedHost.to_context(), EVMC_MAX_REVISION, &msg); // Validate some constraints if (result.status_code != EVMC_SUCCESS && result.status_code != EVMC_REVERT) @@ -194,8 +194,7 @@ TEST_F(evmc_vm_test, precompile_test) nullptr, 0}; - const evmc_result result = - vm->execute(vm, nullptr, nullptr, EVMC_MAX_REVISION, &msg, nullptr, 0); + const evmc_result result = vm->execute(vm, nullptr, nullptr, EVMC_MAX_REVISION, &msg); // Validate some constraints