1212mod container;
1313mod types;
1414
15+ use std:: slice;
16+
1517pub use container:: EvmcContainer ;
1618pub use evmc_sys as ffi;
1719pub 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.
76104pub 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
82110impl 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 {
488509extern "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.
496517impl 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 {
517538extern "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+
556612fn 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