Skip to content
This repository was archived by the owner on Apr 8, 2026. It is now read-only.

Commit 22ed657

Browse files
authored
Merge pull request #353 from ethereum/rust-message
rust: pass ExecutionMessage directly to EvmcVm.execute()
2 parents 683640b + 3d47d38 commit 22ed657

5 files changed

Lines changed: 49 additions & 62 deletions

File tree

bindings/rust/evmc-declare-tests/src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use evmc_declare::evmc_declare_vm;
77
use evmc_vm::EvmcVm;
88
use evmc_vm::ExecutionContext;
9+
use evmc_vm::ExecutionMessage;
910
use evmc_vm::ExecutionResult;
1011

1112
#[evmc_declare_vm("Foo VM", "ewasm, evm", "1.42-alpha.gamma.starship")]
@@ -16,7 +17,12 @@ impl EvmcVm for FooVM {
1617
FooVM {}
1718
}
1819

19-
fn execute(&self, _code: &[u8], _context: &ExecutionContext) -> ExecutionResult {
20+
fn execute(
21+
&self,
22+
_code: &[u8],
23+
_message: &ExecutionMessage,
24+
_context: &ExecutionContext,
25+
) -> ExecutionResult {
2026
ExecutionResult::success(1337, None)
2127
}
2228
}

bindings/rust/evmc-declare/src/lib.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
//! ExampleVM {}
2323
//! }
2424
//!
25-
//! fn execute(&self, code: &[u8], context: &evmc_vm::ExecutionContext) -> evmc_vm::ExecutionResult {
25+
//! fn execute(&self, code: &[u8], message: &evmc_vm::ExecutionMessage, context: &evmc_vm::ExecutionContext) -> evmc_vm::ExecutionResult {
2626
//! evmc_vm::ExecutionResult::success(1337, None)
2727
//! }
2828
//! }
@@ -342,11 +342,12 @@ fn build_execute_fn(names: &VMNameSet) -> proc_macro2::TokenStream {
342342
assert!(!context.is_null());
343343
assert!(!msg.is_null());
344344

345+
let execution_message: ::evmc_vm::ExecutionMessage = unsafe {
346+
msg.as_ref().expect("EVMC message is null").into()
347+
};
348+
345349
let execution_context = unsafe {
346-
::evmc_vm::ExecutionContext::new(
347-
msg.as_ref().expect("EVMC message is null"),
348-
context.as_mut().expect("EVMC context is null")
349-
)
350+
::evmc_vm::ExecutionContext::new(context.as_mut().expect("EVMC context is null"))
350351
};
351352

352353
let empty_code = [0u8;0];
@@ -364,7 +365,7 @@ fn build_execute_fn(names: &VMNameSet) -> proc_macro2::TokenStream {
364365
};
365366

366367
let result = ::std::panic::catch_unwind(|| {
367-
container.execute(code_ref, &execution_context)
368+
container.execute(code_ref, &execution_message, &execution_context)
368369
});
369370

370371
let result = if result.is_err() {

bindings/rust/evmc-vm/src/container.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,19 @@ where
5050
mod tests {
5151
use super::*;
5252
use crate::types::*;
53-
use crate::{ExecutionContext, ExecutionResult};
53+
use crate::{ExecutionContext, ExecutionMessage, ExecutionResult};
5454

5555
struct TestVm {}
5656
impl EvmcVm for TestVm {
5757
fn init() -> Self {
5858
TestVm {}
5959
}
60-
fn execute(&self, _code: &[u8], _context: &ExecutionContext) -> ExecutionResult {
60+
fn execute(
61+
&self,
62+
_code: &[u8],
63+
_message: &ExecutionMessage,
64+
_context: &ExecutionContext,
65+
) -> ExecutionResult {
6166
ExecutionResult::failure()
6267
}
6368
}
@@ -90,6 +95,7 @@ mod tests {
9095
};
9196

9297
let code = [0u8; 0];
98+
9399
let message = ::evmc_sys::evmc_message {
94100
kind: ::evmc_sys::evmc_call_kind::EVMC_CALL,
95101
flags: 0,
@@ -102,6 +108,8 @@ mod tests {
102108
value: ::evmc_sys::evmc_uint256be::default(),
103109
create2_salt: ::evmc_sys::evmc_bytes32::default(),
104110
};
111+
let message: ExecutionMessage = (&message).into();
112+
105113
let host = ::evmc_sys::evmc_host_interface {
106114
account_exists: None,
107115
get_storage: None,
@@ -117,19 +125,23 @@ mod tests {
117125
emit_log: None,
118126
};
119127
let mut backing_context = ::evmc_sys::evmc_context { host: &host };
120-
let context = ExecutionContext::new(&message, &mut backing_context);
128+
let context = ExecutionContext::new(&mut backing_context);
121129

122130
let container = EvmcContainer::<TestVm>::new(instance);
123131
assert_eq!(
124-
container.execute(&code, &context).get_status_code(),
132+
container
133+
.execute(&code, &message, &context)
134+
.get_status_code(),
125135
::evmc_sys::evmc_status_code::EVMC_FAILURE
126136
);
127137

128138
let ptr = unsafe { EvmcContainer::into_ffi_pointer(Box::new(container)) };
129139

130140
let container = unsafe { EvmcContainer::<TestVm>::from_ffi_pointer(ptr) };
131141
assert_eq!(
132-
container.execute(&code, &context).get_status_code(),
142+
container
143+
.execute(&code, &message, &context)
144+
.get_status_code(),
133145
::evmc_sys::evmc_status_code::EVMC_FAILURE
134146
);
135147
}

bindings/rust/evmc-vm/src/lib.rs

Lines changed: 11 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ pub use types::*;
1717

1818
pub trait EvmcVm {
1919
fn init() -> Self;
20-
fn execute(&self, code: &[u8], context: &ExecutionContext) -> ExecutionResult;
20+
fn execute(
21+
&self,
22+
code: &[u8],
23+
message: &ExecutionMessage,
24+
context: &ExecutionContext,
25+
) -> ExecutionResult;
2126
}
2227

2328
/// EVMC result structure.
@@ -44,7 +49,6 @@ pub struct ExecutionMessage {
4449
/// EVMC context structure. Exposes the EVMC host functions, message data, and transaction context
4550
/// to the executing VM.
4651
pub struct ExecutionContext<'a> {
47-
message: ExecutionMessage,
4852
context: &'a mut ffi::evmc_context,
4953
tx_context: ffi::evmc_tx_context,
5054
}
@@ -159,23 +163,18 @@ impl ExecutionMessage {
159163
}
160164

161165
impl<'a> ExecutionContext<'a> {
162-
pub fn new(_message: &'a ffi::evmc_message, _context: &'a mut ffi::evmc_context) -> Self {
166+
pub fn new(_context: &'a mut ffi::evmc_context) -> Self {
163167
let _tx_context = unsafe {
164168
assert!((*(_context.host)).get_tx_context.is_some());
165169
(*(_context.host)).get_tx_context.unwrap()(_context as *mut ffi::evmc_context)
166170
};
167171

168172
ExecutionContext {
169-
message: _message.into(),
170173
context: _context,
171174
tx_context: _tx_context,
172175
}
173176
}
174177

175-
pub fn get_message(&self) -> &ExecutionMessage {
176-
&self.message
177-
}
178-
179178
pub fn get_tx_context(&mut self) -> &ffi::evmc_tx_context {
180179
&self.tx_context
181180
}
@@ -789,63 +788,31 @@ mod tests {
789788
}
790789
}
791790

792-
fn get_dummy_message() -> ffi::evmc_message {
793-
ffi::evmc_message {
794-
kind: ffi::evmc_call_kind::EVMC_CALL,
795-
flags: 0,
796-
depth: 123,
797-
gas: 105023,
798-
destination: Address { bytes: [0u8; 20] },
799-
sender: Address { bytes: [0u8; 20] },
800-
input_data: std::ptr::null() as *const u8,
801-
input_size: 0,
802-
value: Uint256 { bytes: [0u8; 32] },
803-
create2_salt: Uint256 { bytes: [0u8; 32] },
804-
}
805-
}
806-
807791
#[test]
808792
fn execution_context() {
809-
let msg = get_dummy_message();
810793
let mut context_raw = get_dummy_context();
811794
// Make a copy here so we don't let get_dummy_context() go out of scope when called again
812795
// in get_dummy_tx_context() and cause LLVM
813796
// sanitizers to complain
814797
let mut context_raw_copy = context_raw.clone();
815798

816-
let mut exe_context = ExecutionContext::new(&msg, &mut context_raw);
799+
let mut exe_context = ExecutionContext::new(&mut context_raw);
817800
let a = exe_context.get_tx_context();
818801
let b = unsafe { get_dummy_tx_context(&mut context_raw_copy as *mut ffi::evmc_context) };
819802

820803
assert_eq!(a.block_gas_limit, b.block_gas_limit);
821804
assert_eq!(a.block_timestamp, b.block_timestamp);
822805
assert_eq!(a.block_number, b.block_number);
823806

824-
let c = exe_context.get_message();
825-
let d = get_dummy_message();
826-
827-
assert_eq!(c.kind, d.kind);
828-
assert_eq!(c.flags, d.flags);
829-
assert_eq!(c.depth, d.depth);
830-
assert_eq!(c.gas, d.gas);
831-
if d.input_data.is_null() {
832-
assert!(c.input().is_none());
833-
} else {
834-
assert!(c.input().is_some());
835-
assert_eq!(c.input().unwrap().len(), d.input_size);
836-
}
837-
838807
dummy_context_dispose(context_raw);
839808
}
840809

841810
#[test]
842811
fn get_code_size() {
843-
let msg = get_dummy_message();
844-
845812
// This address is useless. Just a dummy parameter for the interface function.
846813
let test_addr = Address { bytes: [0u8; 20] };
847814
let mut context_raw = get_dummy_context();
848-
let mut exe_context = ExecutionContext::new(&msg, &mut context_raw);
815+
let mut exe_context = ExecutionContext::new(&mut context_raw);
849816

850817
let a: usize = 105023;
851818
let b = exe_context.get_code_size(&test_addr);
@@ -857,12 +824,10 @@ mod tests {
857824

858825
#[test]
859826
fn test_call_empty_data() {
860-
let msg = get_dummy_message();
861-
862827
// This address is useless. Just a dummy parameter for the interface function.
863828
let test_addr = ffi::evmc_address { bytes: [0u8; 20] };
864829
let mut context_raw = get_dummy_context();
865-
let mut exe_context = ExecutionContext::new(&msg, &mut context_raw);
830+
let mut exe_context = ExecutionContext::new(&mut context_raw);
866831

867832
let message = ExecutionMessage::new(
868833
ffi::evmc_call_kind::EVMC_CALL,
@@ -892,12 +857,10 @@ mod tests {
892857

893858
#[test]
894859
fn test_call_with_data() {
895-
let msg = get_dummy_message();
896-
897860
// This address is useless. Just a dummy parameter for the interface function.
898861
let test_addr = ffi::evmc_address { bytes: [0u8; 20] };
899862
let mut context_raw = get_dummy_context();
900-
let mut exe_context = ExecutionContext::new(&msg, &mut context_raw);
863+
let mut exe_context = ExecutionContext::new(&mut context_raw);
901864

902865
let data = vec![0xc0, 0xff, 0xfe];
903866

examples/example-rust-vm/src/lib.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,13 @@ impl EvmcVm for ExampleRustVM {
1414
ExampleRustVM {}
1515
}
1616

17-
fn execute(&self, _code: &[u8], context: &ExecutionContext) -> ExecutionResult {
18-
let is_create = context.get_message().kind() == evmc_sys::evmc_call_kind::EVMC_CREATE;
17+
fn execute(
18+
&self,
19+
_code: &[u8],
20+
message: &ExecutionMessage,
21+
_context: &ExecutionContext,
22+
) -> ExecutionResult {
23+
let is_create = message.kind() == evmc_sys::evmc_call_kind::EVMC_CREATE;
1924

2025
if is_create {
2126
ExecutionResult::failure()

0 commit comments

Comments
 (0)