mirror of https://github.com/status-im/evmc.git
rust: pass ExecutionMessage directly to EvmcVm.execute()
This commit is contained in:
parent
683640bcfb
commit
3d47d3802e
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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::<TestVm>::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::<TestVm>::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
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue