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

Commit 4f6e264

Browse files
convert pointers to slices in ExecutionTxContext & make input and code fields of ExecutionMessage slices
1 parent 613889b commit 4f6e264

2 files changed

Lines changed: 100 additions & 47 deletions

File tree

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,7 @@ where
3838
}
3939

4040
/// Convert boxed self into an FFI pointer, surrendering ownership of the heap data.
41-
///
42-
/// # Safety
43-
/// This function will return a valid instance pointer.
44-
pub unsafe fn into_ffi_pointer(boxed: Box<Self>) -> *mut ::evmc_sys::evmc_vm {
41+
pub fn into_ffi_pointer(boxed: Box<Self>) -> *mut ::evmc_sys::evmc_vm {
4542
Box::into_raw(boxed) as *mut ::evmc_sys::evmc_vm
4643
}
4744
}
@@ -175,7 +172,7 @@ mod tests {
175172
::evmc_sys::evmc_status_code::EVMC_FAILURE
176173
);
177174

178-
let ptr = unsafe { EvmcContainer::into_ffi_pointer(container) };
175+
let ptr = EvmcContainer::into_ffi_pointer(container);
179176

180177
let mut context = ExecutionContext::new(&host, host_context);
181178
let container = unsafe { EvmcContainer::<TestVm>::from_ffi_pointer(ptr) };

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

Lines changed: 98 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
mod container;
1313
mod types;
1414

15+
use std::slice;
16+
1517
pub use container::EvmcContainer;
1618
pub use evmc_sys as ffi;
1719
pub use types::*;
@@ -54,29 +56,55 @@ pub struct ExecutionResult {
5456

5557
/// EVMC execution message structure.
5658
#[derive(Debug)]
57-
pub struct ExecutionMessage {
59+
pub struct ExecutionMessage<'a> {
5860
kind: MessageKind,
5961
flags: u32,
6062
depth: i32,
6163
gas: i64,
6264
recipient: Address,
6365
sender: Address,
64-
input: Option<Vec<u8>>,
66+
input: Option<&'a [u8]>,
6567
value: Uint256,
6668
create2_salt: Bytes32,
6769
code_address: Address,
68-
code: Option<Vec<u8>>,
70+
code: Option<&'a [u8]>,
6971
}
7072

7173
/// EVMC transaction context structure.
72-
pub type ExecutionTxContext = ffi::evmc_tx_context;
74+
#[derive(Debug, Copy, Clone, Hash, PartialEq)]
75+
pub struct ExecutionTxContext<'a> {
76+
#[doc = "The transaction gas price."]
77+
pub tx_gas_price: Bytes32,
78+
#[doc = "The transaction origin account."]
79+
pub tx_origin: Address,
80+
#[doc = "The miner of the block."]
81+
pub block_coinbase: Address,
82+
#[doc = "The block number."]
83+
pub block_number: i64,
84+
#[doc = "The block timestamp."]
85+
pub block_timestamp: i64,
86+
#[doc = "The block gas limit."]
87+
pub block_gas_limit: i64,
88+
#[doc = "The block previous RANDAO (EIP-4399)."]
89+
pub block_prev_randao: Bytes32,
90+
#[doc = "The blockchain's ChainID."]
91+
pub chain_id: Bytes32,
92+
#[doc = "The block base fee per gas (EIP-1559, EIP-3198)."]
93+
pub block_base_fee: Bytes32,
94+
#[doc = "The blob base fee (EIP-7516)."]
95+
pub blob_base_fee: Bytes32,
96+
#[doc = "The array of blob hashes (EIP-4844)."]
97+
pub blob_hashes: &'a [Bytes32],
98+
#[doc = "The array of transaction initcodes (TXCREATE)."]
99+
pub initcodes: &'a [ffi::evmc_tx_initcode],
100+
}
73101

74102
/// EVMC context structure. Exposes the EVMC host functions, message data, and transaction context
75103
/// to the executing VM.
76104
pub struct ExecutionContext<'a> {
77105
host: &'a ffi::evmc_host_interface,
78106
context: *mut ffi::evmc_host_context,
79-
tx_context: ExecutionTxContext,
107+
tx_context: ExecutionTxContext<'a>,
80108
}
81109

82110
impl ExecutionResult {
@@ -138,19 +166,19 @@ impl ExecutionResult {
138166
}
139167
}
140168

141-
impl ExecutionMessage {
169+
impl<'a> ExecutionMessage<'a> {
142170
pub fn new(
143171
kind: MessageKind,
144172
flags: u32,
145173
depth: i32,
146174
gas: i64,
147175
recipient: Address,
148176
sender: Address,
149-
input: Option<&[u8]>,
177+
input: Option<&'a [u8]>,
150178
value: Uint256,
151179
create2_salt: Bytes32,
152180
code_address: Address,
153-
code: Option<&[u8]>,
181+
code: Option<&'a [u8]>,
154182
) -> Self {
155183
ExecutionMessage {
156184
kind,
@@ -159,11 +187,11 @@ impl ExecutionMessage {
159187
gas,
160188
recipient,
161189
sender,
162-
input: input.map(|s| s.to_vec()),
190+
input,
163191
value,
164192
create2_salt,
165193
code_address,
166-
code: code.map(|s| s.to_vec()),
194+
code,
167195
}
168196
}
169197

@@ -198,8 +226,8 @@ impl ExecutionMessage {
198226
}
199227

200228
/// Read the optional input message.
201-
pub fn input(&self) -> Option<&Vec<u8>> {
202-
self.input.as_ref()
229+
pub fn input(&self) -> Option<&[u8]> {
230+
self.input
203231
}
204232

205233
/// Read the value of the message.
@@ -218,8 +246,8 @@ impl ExecutionMessage {
218246
}
219247

220248
/// Read the optional init code.
221-
pub fn code(&self) -> Option<&Vec<u8>> {
222-
self.code.as_ref()
249+
pub fn code(&self) -> Option<&[u8]> {
250+
self.code
223251
}
224252
}
225253

@@ -233,7 +261,7 @@ impl<'a> ExecutionContext<'a> {
233261
ExecutionContext {
234262
host,
235263
context: _context,
236-
tx_context: _tx_context,
264+
tx_context: _tx_context.into(),
237265
}
238266
}
239267

@@ -450,28 +478,21 @@ impl From<ffi::evmc_result> for ExecutionResult {
450478
}
451479
}
452480

453-
fn allocate_output_data(output: Option<&Vec<u8>>) -> (*const u8, usize) {
454-
if let Some(buf) = output {
455-
let buf_len = buf.len();
456-
457-
// Manually allocate heap memory for the new home of the output buffer.
458-
let memlayout = std::alloc::Layout::from_size_align(buf_len, 1).expect("Bad layout");
459-
let new_buf = unsafe { std::alloc::alloc(memlayout) };
460-
unsafe {
461-
// Copy the data into the allocated buffer.
462-
std::ptr::copy(buf.as_ptr(), new_buf, buf_len);
481+
fn vec_into_boxed_slice_into_raw<T>(v: Option<Vec<T>>) -> (*const T, usize) {
482+
match v {
483+
Some(v) => {
484+
let slice = Box::into_raw(v.into_boxed_slice());
485+
(slice as *const T, slice.len())
463486
}
464-
465-
(new_buf as *const u8, buf_len)
466-
} else {
467-
(std::ptr::null(), 0)
487+
None => (std::ptr::null(), 0),
468488
}
469489
}
470490

471-
unsafe fn deallocate_output_data(ptr: *const u8, size: usize) {
472-
if !ptr.is_null() {
473-
let buf_layout = std::alloc::Layout::from_size_align(size, 1).expect("Bad layout");
474-
std::alloc::dealloc(ptr as *mut u8, buf_layout);
491+
fn boxed_slice_from_raw_parts<T>(ptr: *const T, len: usize) -> Option<Box<[T]>> {
492+
if ptr.is_null() {
493+
None
494+
} else {
495+
Some(unsafe { Box::<[T]>::from_raw(slice::from_raw_parts_mut(ptr as *mut T, len)) })
475496
}
476497
}
477498

@@ -488,20 +509,20 @@ impl From<ExecutionResult> for *const ffi::evmc_result {
488509
extern "C" fn release_heap_result(result: *const ffi::evmc_result) {
489510
unsafe {
490511
let tmp = Box::from_raw(result as *mut ffi::evmc_result);
491-
deallocate_output_data(tmp.output_data, tmp.output_size);
512+
drop(boxed_slice_from_raw_parts(tmp.output_data, tmp.output_size));
492513
}
493514
}
494515

495516
/// Returns a pointer to a stack-allocated evmc_result.
496517
impl From<ExecutionResult> for ffi::evmc_result {
497518
fn from(value: ExecutionResult) -> Self {
498-
let (buffer, len) = allocate_output_data(value.output.as_ref());
519+
let (output_data, output_size) = vec_into_boxed_slice_into_raw(value.output);
499520
Self {
500521
status_code: value.status_code,
501522
gas_left: value.gas_left,
502523
gas_refund: value.gas_refund,
503-
output_data: buffer,
504-
output_size: len,
524+
output_data,
525+
output_size,
505526
release: Some(release_stack_result),
506527
create_address: if value.create_address.is_some() {
507528
value.create_address.unwrap()
@@ -517,12 +538,12 @@ impl From<ExecutionResult> for ffi::evmc_result {
517538
extern "C" fn release_stack_result(result: *const ffi::evmc_result) {
518539
unsafe {
519540
let tmp = *result;
520-
deallocate_output_data(tmp.output_data, tmp.output_size);
541+
drop(boxed_slice_from_raw_parts(tmp.output_data, tmp.output_size));
521542
}
522543
}
523544

524-
impl From<&ffi::evmc_message> for ExecutionMessage {
525-
fn from(message: &ffi::evmc_message) -> Self {
545+
impl<'a> From<&'a ffi::evmc_message> for ExecutionMessage<'a> {
546+
fn from(message: &'a ffi::evmc_message) -> Self {
526547
ExecutionMessage {
527548
kind: message.kind,
528549
flags: message.flags,
@@ -536,7 +557,9 @@ impl From<&ffi::evmc_message> for ExecutionMessage {
536557
} else if message.input_size == 0 {
537558
None
538559
} else {
539-
Some(from_buf_raw::<u8>(message.input_data, message.input_size))
560+
Some(unsafe {
561+
slice::from_raw_parts_mut(message.input_data as *mut u8, message.input_size)
562+
})
540563
},
541564
value: message.value,
542565
create2_salt: message.create2_salt,
@@ -547,12 +570,45 @@ impl From<&ffi::evmc_message> for ExecutionMessage {
547570
} else if message.code_size == 0 {
548571
None
549572
} else {
550-
Some(from_buf_raw::<u8>(message.code, message.code_size))
573+
Some(unsafe {
574+
slice::from_raw_parts_mut(message.code as *mut u8, message.code_size)
575+
})
551576
},
552577
}
553578
}
554579
}
555580

581+
impl<'a> From<ffi::evmc_tx_context> for ExecutionTxContext<'a> {
582+
fn from(message: ffi::evmc_tx_context) -> Self {
583+
let blob_hashes = if message.blob_hashes.is_null() {
584+
&[]
585+
} else {
586+
assert_ne!(message.blob_hashes_count, 0);
587+
unsafe { slice::from_raw_parts(message.blob_hashes, message.blob_hashes_count) }
588+
};
589+
let initcodes = if message.initcodes.is_null() {
590+
&[]
591+
} else {
592+
assert_ne!(message.initcodes_count, 0);
593+
unsafe { slice::from_raw_parts(message.initcodes, message.initcodes_count) }
594+
};
595+
ExecutionTxContext {
596+
tx_gas_price: message.tx_gas_price,
597+
tx_origin: message.tx_origin,
598+
block_coinbase: message.block_coinbase,
599+
block_number: message.block_number,
600+
block_timestamp: message.block_timestamp,
601+
block_gas_limit: message.block_gas_limit,
602+
block_prev_randao: message.block_prev_randao,
603+
chain_id: message.chain_id,
604+
block_base_fee: message.block_base_fee,
605+
blob_base_fee: message.blob_base_fee,
606+
blob_hashes,
607+
initcodes,
608+
}
609+
}
610+
}
611+
556612
fn from_buf_raw<T>(ptr: *const T, size: usize) -> Vec<T> {
557613
// Pre-allocate a vector.
558614
let mut buf = Vec::with_capacity(size);

0 commit comments

Comments
 (0)