Skip to content

Commit

Permalink
Add EOFCREATE message support
Browse files Browse the repository at this point in the history
  • Loading branch information
gumb0 committed Feb 29, 2024
1 parent b576474 commit 874a0a7
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 3 deletions.
2 changes: 2 additions & 0 deletions bindings/go/evmc/evmc.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ 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
};
struct evmc_host_context* context = (struct evmc_host_context*)context_index;
Expand Down
1 change: 1 addition & 0 deletions bindings/go/evmc/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const (
CallCode CallKind = C.EVMC_CALLCODE
Create CallKind = C.EVMC_CREATE
Create2 CallKind = C.EVMC_CREATE2
EofCreate CallKind = C.EVMC_EOFCREATE
)

type AccessStatus int
Expand Down
2 changes: 2 additions & 0 deletions bindings/rust/evmc-vm/src/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ mod tests {
value: ::evmc_sys::evmc_uint256be::default(),
create2_salt: ::evmc_sys::evmc_bytes32::default(),
code_address: ::evmc_sys::evmc_address::default(),
code: std::ptr::null(),
code_size: 0,
};
let message: ExecutionMessage = (&message).into();

Expand Down
111 changes: 111 additions & 0 deletions bindings/rust/evmc-vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ pub struct ExecutionMessage {
value: Uint256,
create2_salt: Bytes32,
code_address: Address,
code: Option<Vec<u8>>,
}

/// EVMC transaction context structure.
Expand Down Expand Up @@ -149,6 +150,7 @@ impl ExecutionMessage {
value: Uint256,
create2_salt: Bytes32,
code_address: Address,
code: Option<&[u8]>,
) -> Self {
ExecutionMessage {
kind,
Expand All @@ -161,6 +163,7 @@ impl ExecutionMessage {
value,
create2_salt,
code_address,
code: code.map(|s| s.to_vec()),
}
}

Expand Down Expand Up @@ -213,6 +216,11 @@ impl ExecutionMessage {
pub fn code_address(&self) -> &Address {
&self.code_address
}

/// Read the optional init code.
pub fn code(&self) -> Option<&Vec<u8>> {
self.code.as_ref()
}
}

impl<'a> ExecutionContext<'a> {
Expand Down Expand Up @@ -338,6 +346,13 @@ impl<'a> ExecutionContext<'a> {
} else {
std::ptr::null() as *const u8
};
let code = message.code();
let code_size = if let Some(code) = code { code.len() } else { 0 };
let code_data = if let Some(code) = code {
code.as_ptr()
} else {
std::ptr::null() as *const u8
};
// Cannot use a nice from trait here because that complicates memory management,
// evmc_message doesn't have a release() method we could abstract it with.
let message = ffi::evmc_message {
Expand All @@ -352,6 +367,8 @@ impl<'a> ExecutionContext<'a> {
value: *message.value(),
create2_salt: *message.create2_salt(),
code_address: *message.code_address(),
code: code_data,
code_size,
};
unsafe {
assert!((*self.host).call.is_some());
Expand Down Expand Up @@ -524,6 +541,14 @@ impl From<&ffi::evmc_message> for ExecutionMessage {
value: message.value,
create2_salt: message.create2_salt,
code_address: message.code_address,
code: if message.code.is_null() {
assert_eq!(message.code_size, 0);
None
} else if message.code_size == 0 {
None
} else {
Some(from_buf_raw::<u8>(message.code, message.code_size))
},
}
}
}
Expand Down Expand Up @@ -704,6 +729,7 @@ mod tests {
value,
create2_salt,
code_address,
None,
);

assert_eq!(ret.kind(), MessageKind::EVMC_CALL);
Expand All @@ -719,6 +745,42 @@ mod tests {
assert_eq!(*ret.code_address(), code_address);
}

#[test]
fn message_new_with_code() {
let recipient = Address { bytes: [32u8; 20] };
let sender = Address { bytes: [128u8; 20] };
let value = Uint256 { bytes: [0u8; 32] };
let create2_salt = Bytes32 { bytes: [255u8; 32] };
let code_address = Address { bytes: [64u8; 20] };
let code = vec![0x5f, 0x5f, 0xfd];

let ret = ExecutionMessage::new(
MessageKind::EVMC_CALL,
44,
66,
4466,
recipient,
sender,
None,
value,
create2_salt,
code_address,
Some(&code),
);

assert_eq!(ret.kind(), MessageKind::EVMC_CALL);
assert_eq!(ret.flags(), 44);
assert_eq!(ret.depth(), 66);
assert_eq!(ret.gas(), 4466);
assert_eq!(*ret.recipient(), recipient);
assert_eq!(*ret.sender(), sender);
assert_eq!(*ret.value(), value);
assert_eq!(*ret.create2_salt(), create2_salt);
assert_eq!(*ret.code_address(), code_address);
assert!(ret.code().is_some());
assert_eq!(*ret.code().unwrap(), code);
}

#[test]
fn message_from_ffi() {
let recipient = Address { bytes: [32u8; 20] };
Expand All @@ -739,6 +801,8 @@ mod tests {
value,
create2_salt,
code_address,
code: std::ptr::null(),
code_size: 0,
};

let ret: ExecutionMessage = (&msg).into();
Expand All @@ -753,6 +817,7 @@ mod tests {
assert_eq!(*ret.value(), msg.value);
assert_eq!(*ret.create2_salt(), msg.create2_salt);
assert_eq!(*ret.code_address(), msg.code_address);
assert!(ret.code().is_none());
}

#[test]
Expand All @@ -776,6 +841,8 @@ mod tests {
value,
create2_salt,
code_address,
code: std::ptr::null(),
code_size: 0,
};

let ret: ExecutionMessage = (&msg).into();
Expand All @@ -791,6 +858,48 @@ mod tests {
assert_eq!(*ret.value(), msg.value);
assert_eq!(*ret.create2_salt(), msg.create2_salt);
assert_eq!(*ret.code_address(), msg.code_address);
assert!(ret.code().is_none());
}

#[test]
fn message_from_ffi_with_code() {
let recipient = Address { bytes: [32u8; 20] };
let sender = Address { bytes: [128u8; 20] };
let value = Uint256 { bytes: [0u8; 32] };
let create2_salt = Bytes32 { bytes: [255u8; 32] };
let code_address = Address { bytes: [64u8; 20] };
let code = vec![0x5f, 0x5f, 0xfd];

let msg = ffi::evmc_message {
kind: MessageKind::EVMC_CALL,
flags: 44,
depth: 66,
gas: 4466,
recipient,
sender,
input_data: std::ptr::null(),
input_size: 0,
value,
create2_salt,
code_address,
code: code.as_ptr(),
code_size: code.len(),
};

let ret: ExecutionMessage = (&msg).into();

assert_eq!(ret.kind(), msg.kind);
assert_eq!(ret.flags(), msg.flags);
assert_eq!(ret.depth(), msg.depth);
assert_eq!(ret.gas(), msg.gas);
assert_eq!(*ret.recipient(), msg.recipient);
assert_eq!(*ret.sender(), msg.sender);
assert!(ret.input().is_none());
assert_eq!(*ret.value(), msg.value);
assert_eq!(*ret.create2_salt(), msg.create2_salt);
assert_eq!(*ret.code_address(), msg.code_address);
assert!(ret.code().is_some());
assert_eq!(*ret.code().unwrap(), code);
}

unsafe extern "C" fn get_dummy_tx_context(
Expand Down Expand Up @@ -918,6 +1027,7 @@ mod tests {
Uint256::default(),
Bytes32::default(),
test_addr,
None,
);

let b = exe_context.call(&message);
Expand Down Expand Up @@ -950,6 +1060,7 @@ mod tests {
Uint256::default(),
Bytes32::default(),
test_addr,
None,
);

let b = exe_context.call(&message);
Expand Down
5 changes: 5 additions & 0 deletions bindings/rust/evmc-vm/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ mod tests {
ffi::evmc_call_kind::EVMC_DELEGATECALL
);
assert_eq!(MessageKind::EVMC_CREATE, ffi::evmc_call_kind::EVMC_CREATE);
assert_eq!(MessageKind::EVMC_CREATE2, ffi::evmc_call_kind::EVMC_CREATE2);
assert_eq!(
MessageKind::EVMC_EOFCREATE,
ffi::evmc_call_kind::EVMC_EOFCREATE
);
}

#[test]
Expand Down
13 changes: 12 additions & 1 deletion include/evmc/evmc.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ enum evmc_call_kind
The value param ignored. */
EVMC_CALLCODE = 2, /**< Request CALLCODE. */
EVMC_CREATE = 3, /**< Request CREATE. */
EVMC_CREATE2 = 4 /**< Request CREATE2. Valid since Constantinople.*/
EVMC_CREATE2 = 4, /**< Request CREATE2. Valid since Constantinople.*/
EVMC_EOFCREATE = 5 /**< Request EOFCREATE. Valid since Prague.*/
};

/** The flags for ::evmc_message. */
Expand Down Expand Up @@ -187,6 +188,16 @@ struct evmc_message
* Defined as `c` in the Yellow Paper.
*/
evmc_address code_address;

/**
* The code to be executed.
*/
const uint8_t* code;

/**
* The length of the code to be executed.
*/
size_t code_size;
};


Expand Down
8 changes: 6 additions & 2 deletions tools/vmtester/tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ TEST_F(evmc_vm_test, execute_create)
0,
evmc_uint256be{},
evmc_bytes32{},
evmc_address{}};
evmc_address{},
nullptr,
0};
std::array<uint8_t, 2> code = {{0xfe, 0x00}};

const evmc_result result =
Expand Down Expand Up @@ -188,7 +190,9 @@ TEST_F(evmc_vm_test, precompile_test)
0,
evmc_uint256be{},
evmc_bytes32{},
addr};
addr,
nullptr,
0};

const evmc_result result =
vm->execute(vm, nullptr, nullptr, EVMC_MAX_REVISION, &msg, nullptr, 0);
Expand Down

0 comments on commit 874a0a7

Please sign in to comment.