Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move code reference to message #705

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions bindings/go/evmc/evmc.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ static struct evmc_result execute_wrapper(struct evmc_vm* vm,
*value,
{{0}}, // create2_salt: not required for execution
{{0}}, // code_address: not required for execution
0, // code
0, // code_size
code,
code_size,
};

struct evmc_host_context* context = (struct evmc_host_context*)context_index;
return evmc_execute(vm, &evmc_go_host, context, rev, &msg, code, code_size);
return evmc_execute(vm, &evmc_go_host, context, rev, &msg);
}
*/
import "C"
Expand Down
1 change: 0 additions & 1 deletion bindings/rust/evmc-declare-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ impl EvmcVm for FooVM {
fn execute(
&self,
_revision: evmc_sys::evmc_revision,
_code: &[u8],
_message: &ExecutionMessage,
_context: Option<&mut ExecutionContext>,
) -> ExecutionResult {
Expand Down
26 changes: 4 additions & 22 deletions bindings/rust/evmc-declare/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
//! ExampleVM {}
//! }
//!
//! fn execute(&self, revision: evmc_vm::ffi::evmc_revision, code: &[u8], message: &evmc_vm::ExecutionMessage, context: Option<&mut evmc_vm::ExecutionContext>) -> evmc_vm::ExecutionResult {
//! fn execute(&self, revision: evmc_vm::ffi::evmc_revision, message: &evmc_vm::ExecutionMessage, context: Option<&mut evmc_vm::ExecutionContext>) -> evmc_vm::ExecutionResult {
//! evmc_vm::ExecutionResult::success(1337, 0, None)
//! }
//! }
Expand Down Expand Up @@ -395,52 +395,34 @@ fn build_execute_fn(names: &VMNameSet) -> proc_macro2::TokenStream {
host: *const ::evmc_vm::ffi::evmc_host_interface,
context: *mut ::evmc_vm::ffi::evmc_host_context,
revision: ::evmc_vm::ffi::evmc_revision,
msg: *const ::evmc_vm::ffi::evmc_message,
code: *const u8,
code_size: usize
msg: *const ::evmc_vm::ffi::evmc_message
) -> ::evmc_vm::ffi::evmc_result
{
use evmc_vm::EvmcVm;

// TODO: context is optional in case of the "precompiles" capability
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this removed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't able to translate the check easily and also not sure if this check isn't to heavy to be included in the bindings (unless this helps Rust translation somehow).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe TODO is worth to leave? It seems to point to something that is not yet implemented in bindings, but might be useful.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the check for instance/msg null should be removed. This is the place it ensures it won't be null.

if instance.is_null() || msg.is_null() || (code.is_null() && code_size != 0) {
// These are irrecoverable errors that violate the EVMC spec.
std::process::abort();
}

assert!(!instance.is_null());
assert!(!msg.is_null());

let execution_message: ::evmc_vm::ExecutionMessage = unsafe {
msg.as_ref().expect("EVMC message is null").into()
};

let empty_code = [0u8;0];
let code_ref: &[u8] = if code.is_null() {
assert_eq!(code_size, 0);
&empty_code
} else {
unsafe {
::std::slice::from_raw_parts(code, code_size)
}
};

let container = unsafe {
// Acquire ownership from EVMC.
::evmc_vm::EvmcContainer::<#type_name_ident>::from_ffi_pointer(instance)
};

let result = ::std::panic::catch_unwind(|| {
if host.is_null() {
container.execute(revision, code_ref, &execution_message, None)
container.execute(revision, &execution_message, None)
} else {
let mut execution_context = unsafe {
::evmc_vm::ExecutionContext::new(
host.as_ref().expect("EVMC host is null"),
context,
)
};
container.execute(revision, code_ref, &execution_message, Some(&mut execution_context))
container.execute(revision, &execution_message, Some(&mut execution_context))
}
});

Expand Down
5 changes: 0 additions & 5 deletions bindings/rust/evmc-vm/src/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ mod tests {
fn execute(
&self,
_revision: evmc_sys::evmc_revision,
_code: &[u8],
_message: &ExecutionMessage,
_context: Option<&mut ExecutionContext>,
) -> ExecutionResult {
Expand Down Expand Up @@ -120,8 +119,6 @@ mod tests {
set_option: None,
};

let code = [0u8; 0];

let message = ::evmc_sys::evmc_message {
kind: ::evmc_sys::evmc_call_kind::EVMC_CALL,
flags: 0,
Expand Down Expand Up @@ -165,7 +162,6 @@ mod tests {
container
.execute(
evmc_sys::evmc_revision::EVMC_PETERSBURG,
&code,
&message,
Some(&mut context)
)
Expand All @@ -181,7 +177,6 @@ mod tests {
container
.execute(
evmc_sys::evmc_revision::EVMC_PETERSBURG,
&code,
&message,
Some(&mut context)
)
Expand Down
3 changes: 1 addition & 2 deletions bindings/rust/evmc-vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ pub trait EvmcVm {
fn execute<'a>(
&self,
revision: Revision,
code: &'a [u8],
message: &'a ExecutionMessage,
context: Option<&'a mut ExecutionContext<'a>>,
) -> ExecutionResult;
Expand Down Expand Up @@ -368,7 +367,7 @@ impl<'a> ExecutionContext<'a> {
create2_salt: *message.create2_salt(),
code_address: *message.code_address(),
code: code_data,
code_size,
code_size: code_size,
};
unsafe {
assert!((*self.host).call.is_some());
Expand Down
5 changes: 2 additions & 3 deletions examples/example-rust-vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ impl EvmcVm for ExampleRustVM {
fn execute<'a>(
&self,
_revision: Revision,
_code: &'a [u8],
message: &'a ExecutionMessage,
_context: Option<&'a mut ExecutionContext<'a>>,
) -> ExecutionResult {
Expand All @@ -53,7 +52,7 @@ impl EvmcVm for ExampleRustVM {
return ExecutionResult::failure();
}

if _code.is_empty() {
if message.code().unwrap().is_empty() {
return ExecutionResult::failure();
}

Expand All @@ -63,7 +62,7 @@ impl EvmcVm for ExampleRustVM {
0x43, 0x60, 0x00, 0x55, 0x43, 0x60, 0x00, 0x52, 0x59, 0x60, 0x00, 0xf3,
];

if save_return_block_number != _code {
if save_return_block_number != *message.code().unwrap() {
return ExecutionResult::failure();
}

Expand Down
4 changes: 3 additions & 1 deletion examples/example.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 1 addition & 3 deletions examples/example_precompiles_vm/example_precompiles_vm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
12 changes: 5 additions & 7 deletions examples/example_vm/example_vm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<ExampleVM*>(instance);

Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 1 addition & 5 deletions include/evmc/evmc.h
Original file line number Diff line number Diff line change
Expand Up @@ -1056,17 +1056,13 @@ enum evmc_revision
* The VM MUST NOT dereference the pointer.
* @param rev The requested EVM specification revision.
* @param msg The call parameters. See ::evmc_message. This argument MUST NOT be NULL.
* @param code The reference to the code to be executed. This argument MAY be NULL.
* @param code_size The length of the code. If @p code is NULL this argument MUST be 0.
* @return The execution result.
*/
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.
Expand Down
22 changes: 6 additions & 16 deletions include/evmc/evmc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -745,13 +739,9 @@ class VM
/// but without providing the Host context and interface.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update comment above

/// 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.
Expand Down
6 changes: 2 additions & 4 deletions include/evmc/helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
19 changes: 11 additions & 8 deletions lib/tooling/run.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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;

Expand All @@ -50,7 +49,7 @@ auto bench(MockedHost& host,
// Benchmark loop.
const auto num_iterations = std::max(static_cast<int>(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<unit>(bench_time).count() << unit_name
Expand All @@ -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";
Expand All @@ -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";
Expand Down
6 changes: 3 additions & 3 deletions test/unittests/cpp_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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());
Expand All @@ -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);
}
Expand Down
Loading