Skip to content

Commit

Permalink
rust: pass ExecutionMessage directly to EvmcVm.execute()
Browse files Browse the repository at this point in the history
  • Loading branch information
axic committed Jul 8, 2019
1 parent 683640b commit 8b04f3f
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 44 deletions.
8 changes: 7 additions & 1 deletion bindings/rust/evmc-declare-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand All @@ -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)
}
}
11 changes: 5 additions & 6 deletions bindings/rust/evmc-declare/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
//! }
//! }
Expand Down Expand Up @@ -342,11 +342,10 @@ 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().unwrap().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];
Expand All @@ -364,7 +363,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() {
Expand Down
9 changes: 7 additions & 2 deletions bindings/rust/evmc-vm/src/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}
Expand Down
44 changes: 11 additions & 33 deletions bindings/rust/evmc-vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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,
}
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -806,46 +805,29 @@ mod tests {

#[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) };

assert_eq!(a.block_gas_limit, b.block_gas_limit);
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);
Expand All @@ -857,12 +839,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,
Expand Down Expand Up @@ -892,12 +872,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];

Expand Down
9 changes: 7 additions & 2 deletions examples/example-rust-vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down

0 comments on commit 8b04f3f

Please sign in to comment.