From 3d47d3802e9afeaf7e6aef5863acb9bdc5a4068f Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 4 Jul 2019 14:21:15 +0100 Subject: [PATCH] rust: pass ExecutionMessage directly to EvmcVm.execute() --- bindings/rust/evmc-declare-tests/src/lib.rs | 8 ++- bindings/rust/evmc-declare/src/lib.rs | 13 ++--- bindings/rust/evmc-vm/src/container.rs | 22 ++++++-- bindings/rust/evmc-vm/src/lib.rs | 59 ++++----------------- examples/example-rust-vm/src/lib.rs | 9 +++- 5 files changed, 49 insertions(+), 62 deletions(-) diff --git a/bindings/rust/evmc-declare-tests/src/lib.rs b/bindings/rust/evmc-declare-tests/src/lib.rs index 01c88a641..38fd2f3e7 100644 --- a/bindings/rust/evmc-declare-tests/src/lib.rs +++ b/bindings/rust/evmc-declare-tests/src/lib.rs @@ -6,6 +6,7 @@ use evmc_declare::evmc_declare_vm; use evmc_vm::EvmcVm; use evmc_vm::ExecutionContext; +use evmc_vm::ExecutionMessage; use evmc_vm::ExecutionResult; #[evmc_declare_vm("Foo VM", "ewasm, evm", "1.42-alpha.gamma.starship")] @@ -16,7 +17,12 @@ impl EvmcVm for FooVM { FooVM {} } - fn execute(&self, _code: &[u8], _context: &ExecutionContext) -> ExecutionResult { + fn execute( + &self, + _code: &[u8], + _message: &ExecutionMessage, + _context: &ExecutionContext, + ) -> ExecutionResult { ExecutionResult::success(1337, None) } } diff --git a/bindings/rust/evmc-declare/src/lib.rs b/bindings/rust/evmc-declare/src/lib.rs index ae4083207..f70e2c809 100644 --- a/bindings/rust/evmc-declare/src/lib.rs +++ b/bindings/rust/evmc-declare/src/lib.rs @@ -22,7 +22,7 @@ //! ExampleVM {} //! } //! -//! fn execute(&self, code: &[u8], context: &evmc_vm::ExecutionContext) -> evmc_vm::ExecutionResult { +//! fn execute(&self, code: &[u8], message: &evmc_vm::ExecutionMessage, context: &evmc_vm::ExecutionContext) -> evmc_vm::ExecutionResult { //! evmc_vm::ExecutionResult::success(1337, None) //! } //! } @@ -342,11 +342,12 @@ fn build_execute_fn(names: &VMNameSet) -> proc_macro2::TokenStream { assert!(!context.is_null()); assert!(!msg.is_null()); + let execution_message: ::evmc_vm::ExecutionMessage = unsafe { + msg.as_ref().expect("EVMC message is null").into() + }; + let execution_context = unsafe { - ::evmc_vm::ExecutionContext::new( - msg.as_ref().expect("EVMC message is null"), - context.as_mut().expect("EVMC context is null") - ) + ::evmc_vm::ExecutionContext::new(context.as_mut().expect("EVMC context is null")) }; let empty_code = [0u8;0]; @@ -364,7 +365,7 @@ fn build_execute_fn(names: &VMNameSet) -> proc_macro2::TokenStream { }; let result = ::std::panic::catch_unwind(|| { - container.execute(code_ref, &execution_context) + container.execute(code_ref, &execution_message, &execution_context) }); let result = if result.is_err() { diff --git a/bindings/rust/evmc-vm/src/container.rs b/bindings/rust/evmc-vm/src/container.rs index f2975d23c..89f40f222 100644 --- a/bindings/rust/evmc-vm/src/container.rs +++ b/bindings/rust/evmc-vm/src/container.rs @@ -50,14 +50,19 @@ where mod tests { use super::*; use crate::types::*; - use crate::{ExecutionContext, ExecutionResult}; + use crate::{ExecutionContext, ExecutionMessage, ExecutionResult}; struct TestVm {} impl EvmcVm for TestVm { fn init() -> Self { TestVm {} } - fn execute(&self, _code: &[u8], _context: &ExecutionContext) -> ExecutionResult { + fn execute( + &self, + _code: &[u8], + _message: &ExecutionMessage, + _context: &ExecutionContext, + ) -> ExecutionResult { ExecutionResult::failure() } } @@ -90,6 +95,7 @@ mod tests { }; let code = [0u8; 0]; + let message = ::evmc_sys::evmc_message { kind: ::evmc_sys::evmc_call_kind::EVMC_CALL, flags: 0, @@ -102,6 +108,8 @@ mod tests { value: ::evmc_sys::evmc_uint256be::default(), create2_salt: ::evmc_sys::evmc_bytes32::default(), }; + let message: ExecutionMessage = (&message).into(); + let host = ::evmc_sys::evmc_host_interface { account_exists: None, get_storage: None, @@ -117,11 +125,13 @@ mod tests { emit_log: None, }; let mut backing_context = ::evmc_sys::evmc_context { host: &host }; - let context = ExecutionContext::new(&message, &mut backing_context); + let context = ExecutionContext::new(&mut backing_context); let container = EvmcContainer::::new(instance); assert_eq!( - container.execute(&code, &context).get_status_code(), + container + .execute(&code, &message, &context) + .get_status_code(), ::evmc_sys::evmc_status_code::EVMC_FAILURE ); @@ -129,7 +139,9 @@ mod tests { let container = unsafe { EvmcContainer::::from_ffi_pointer(ptr) }; assert_eq!( - container.execute(&code, &context).get_status_code(), + container + .execute(&code, &message, &context) + .get_status_code(), ::evmc_sys::evmc_status_code::EVMC_FAILURE ); } diff --git a/bindings/rust/evmc-vm/src/lib.rs b/bindings/rust/evmc-vm/src/lib.rs index 5b7c55faf..fc63ae678 100644 --- a/bindings/rust/evmc-vm/src/lib.rs +++ b/bindings/rust/evmc-vm/src/lib.rs @@ -17,7 +17,12 @@ pub use types::*; pub trait EvmcVm { fn init() -> Self; - fn execute(&self, code: &[u8], context: &ExecutionContext) -> ExecutionResult; + fn execute( + &self, + code: &[u8], + message: &ExecutionMessage, + context: &ExecutionContext, + ) -> ExecutionResult; } /// EVMC result structure. @@ -44,7 +49,6 @@ pub struct ExecutionMessage { /// EVMC context structure. Exposes the EVMC host functions, message data, and transaction context /// to the executing VM. pub struct ExecutionContext<'a> { - message: ExecutionMessage, context: &'a mut ffi::evmc_context, tx_context: ffi::evmc_tx_context, } @@ -159,23 +163,18 @@ impl ExecutionMessage { } impl<'a> ExecutionContext<'a> { - pub fn new(_message: &'a ffi::evmc_message, _context: &'a mut ffi::evmc_context) -> Self { + pub fn new(_context: &'a mut ffi::evmc_context) -> Self { let _tx_context = unsafe { assert!((*(_context.host)).get_tx_context.is_some()); (*(_context.host)).get_tx_context.unwrap()(_context as *mut ffi::evmc_context) }; ExecutionContext { - message: _message.into(), context: _context, tx_context: _tx_context, } } - pub fn get_message(&self) -> &ExecutionMessage { - &self.message - } - pub fn get_tx_context(&mut self) -> &ffi::evmc_tx_context { &self.tx_context } @@ -789,31 +788,15 @@ mod tests { } } - fn get_dummy_message() -> ffi::evmc_message { - ffi::evmc_message { - kind: ffi::evmc_call_kind::EVMC_CALL, - flags: 0, - depth: 123, - gas: 105023, - destination: Address { bytes: [0u8; 20] }, - sender: Address { bytes: [0u8; 20] }, - input_data: std::ptr::null() as *const u8, - input_size: 0, - value: Uint256 { bytes: [0u8; 32] }, - create2_salt: Uint256 { bytes: [0u8; 32] }, - } - } - #[test] fn execution_context() { - let msg = get_dummy_message(); let mut context_raw = get_dummy_context(); // Make a copy here so we don't let get_dummy_context() go out of scope when called again // in get_dummy_tx_context() and cause LLVM // sanitizers to complain let mut context_raw_copy = context_raw.clone(); - let mut exe_context = ExecutionContext::new(&msg, &mut context_raw); + let mut exe_context = ExecutionContext::new(&mut context_raw); let a = exe_context.get_tx_context(); let b = unsafe { get_dummy_tx_context(&mut context_raw_copy as *mut ffi::evmc_context) }; @@ -821,31 +804,15 @@ mod tests { assert_eq!(a.block_timestamp, b.block_timestamp); assert_eq!(a.block_number, b.block_number); - let c = exe_context.get_message(); - let d = get_dummy_message(); - - assert_eq!(c.kind, d.kind); - assert_eq!(c.flags, d.flags); - assert_eq!(c.depth, d.depth); - assert_eq!(c.gas, d.gas); - if d.input_data.is_null() { - assert!(c.input().is_none()); - } else { - assert!(c.input().is_some()); - assert_eq!(c.input().unwrap().len(), d.input_size); - } - dummy_context_dispose(context_raw); } #[test] fn get_code_size() { - let msg = get_dummy_message(); - // This address is useless. Just a dummy parameter for the interface function. let test_addr = Address { bytes: [0u8; 20] }; let mut context_raw = get_dummy_context(); - let mut exe_context = ExecutionContext::new(&msg, &mut context_raw); + let mut exe_context = ExecutionContext::new(&mut context_raw); let a: usize = 105023; let b = exe_context.get_code_size(&test_addr); @@ -857,12 +824,10 @@ mod tests { #[test] fn test_call_empty_data() { - let msg = get_dummy_message(); - // This address is useless. Just a dummy parameter for the interface function. let test_addr = ffi::evmc_address { bytes: [0u8; 20] }; let mut context_raw = get_dummy_context(); - let mut exe_context = ExecutionContext::new(&msg, &mut context_raw); + let mut exe_context = ExecutionContext::new(&mut context_raw); let message = ExecutionMessage::new( ffi::evmc_call_kind::EVMC_CALL, @@ -892,12 +857,10 @@ mod tests { #[test] fn test_call_with_data() { - let msg = get_dummy_message(); - // This address is useless. Just a dummy parameter for the interface function. let test_addr = ffi::evmc_address { bytes: [0u8; 20] }; let mut context_raw = get_dummy_context(); - let mut exe_context = ExecutionContext::new(&msg, &mut context_raw); + let mut exe_context = ExecutionContext::new(&mut context_raw); let data = vec![0xc0, 0xff, 0xfe]; diff --git a/examples/example-rust-vm/src/lib.rs b/examples/example-rust-vm/src/lib.rs index cb64e94b6..5ddacec8b 100644 --- a/examples/example-rust-vm/src/lib.rs +++ b/examples/example-rust-vm/src/lib.rs @@ -14,8 +14,13 @@ impl EvmcVm for ExampleRustVM { ExampleRustVM {} } - fn execute(&self, _code: &[u8], context: &ExecutionContext) -> ExecutionResult { - let is_create = context.get_message().kind() == evmc_sys::evmc_call_kind::EVMC_CREATE; + fn execute( + &self, + _code: &[u8], + message: &ExecutionMessage, + _context: &ExecutionContext, + ) -> ExecutionResult { + let is_create = message.kind() == evmc_sys::evmc_call_kind::EVMC_CREATE; if is_create { ExecutionResult::failure()