@@ -12,7 +12,7 @@ use revm::{
1212 context:: LocalContextTr ,
1313 handler:: { EthPrecompiles , PrecompileProvider } ,
1414 interpreter:: { CallInput , Gas , InputsImpl , InstructionResult , InterpreterResult } ,
15- precompile:: { PrecompileError , PrecompileFn , PrecompileId , PrecompileResult , Precompiles } ,
15+ precompile:: { stateful_precompiles :: run_stateful_precompile , PrecompileError , PrecompileFn , PrecompileId , PrecompileResult , Precompiles } ,
1616 Context , Journal ,
1717} ;
1818
@@ -46,13 +46,13 @@ impl PrecompilesMap {
4646 {
4747 let dyn_precompiles = self . ensure_dynamic_precompiles ( ) ;
4848
49- // get the current precompile at the address
50- if let Some ( dyn_precompile) = dyn_precompiles. inner . remove ( address) {
49+ // get the current stateless precompile at the address
50+ if let Some ( dyn_precompile) = dyn_precompiles. stateless . remove ( address) {
5151 // apply the transformation function
5252 let transformed = f ( dyn_precompile) ;
5353
5454 // update the precompile at the address
55- dyn_precompiles. inner . insert ( * address, transformed) ;
55+ dyn_precompiles. stateless . insert ( * address, transformed) ;
5656 }
5757 }
5858
@@ -87,8 +87,8 @@ impl PrecompilesMap {
8787 {
8888 let dyn_precompiles = self . ensure_dynamic_precompiles ( ) ;
8989
90- // apply the transformation to each precompile
91- let entries = dyn_precompiles. inner . drain ( ) ;
90+ // apply the transformation to each stateless precompile
91+ let entries = dyn_precompiles. stateless . drain ( ) ;
9292 let mut new_map =
9393 HashMap :: with_capacity_and_hasher ( entries. size_hint ( ) . 0 , Default :: default ( ) ) ;
9494 for ( addr, precompile) in entries {
@@ -100,7 +100,7 @@ impl PrecompilesMap {
100100 }
101101 }
102102
103- dyn_precompiles. inner = new_map;
103+ dyn_precompiles. stateless = new_map;
104104 }
105105
106106 /// Applies a transformation to the precompile at the given address.
@@ -146,20 +146,20 @@ impl PrecompilesMap {
146146 F : FnOnce ( Option < DynPrecompile > ) -> Option < DynPrecompile > ,
147147 {
148148 let dyn_precompiles = self . ensure_dynamic_precompiles ( ) ;
149- let current = dyn_precompiles. inner . get ( address) . cloned ( ) ;
149+ let current = dyn_precompiles. stateless . get ( address) . cloned ( ) ;
150150
151151 // apply the transformation function
152152 let result = f ( current) ;
153153
154154 match result {
155155 Some ( transformed) => {
156156 // insert the transformed precompile
157- dyn_precompiles. inner . insert ( * address, transformed) ;
157+ dyn_precompiles. stateless . insert ( * address, transformed) ;
158158 dyn_precompiles. addresses . insert ( * address) ;
159159 }
160160 None => {
161161 // remove the precompile if the transformation returned None
162- dyn_precompiles. inner . remove ( address) ;
162+ dyn_precompiles. stateless . remove ( address) ;
163163 dyn_precompiles. addresses . remove ( address) ;
164164 }
165165 }
@@ -280,11 +280,16 @@ impl PrecompilesMap {
280280 Cow :: Owned ( owned) => owned,
281281 } ;
282282
283- for ( & addr, pc) in static_precompiles. inner ( ) . iter ( ) {
284- dynamic. inner . insert ( addr, DynPrecompile :: from ( * pc. precompile ( ) ) ) ;
283+ for ( & addr, pc) in static_precompiles. stateless ( ) . iter ( ) {
284+ dynamic. stateless . insert ( addr, DynPrecompile :: from ( * pc. precompile ( ) ) ) ;
285285 dynamic. addresses . insert ( addr) ;
286286 }
287287
288+ for addr in static_precompiles. stateful ( ) . iter ( ) {
289+ dynamic. stateful . insert ( * addr) ;
290+ dynamic. addresses . insert ( * addr) ;
291+ }
292+
288293 self . precompiles = PrecompilesKind :: Dynamic ( dynamic) ;
289294 }
290295
@@ -308,12 +313,12 @@ impl PrecompilesMap {
308313 ///
309314 /// This method first checks the static precompile map, and if not found,
310315 /// falls back to the dynamic lookup function (if set).
311- pub fn get ( & self , address : & Address ) -> Option < impl Precompile + ' _ > {
316+ pub fn get_stateless ( & self , address : & Address ) -> Option < impl Precompile + ' _ > {
312317 // First check static precompiles
313318 let static_result = match & self . precompiles {
314- PrecompilesKind :: Builtin ( precompiles) => precompiles. get ( address) . map ( Either :: Left ) ,
319+ PrecompilesKind :: Builtin ( precompiles) => precompiles. get_stateless ( address) . map ( Either :: Left ) ,
315320 PrecompilesKind :: Dynamic ( dyn_precompiles) => {
316- dyn_precompiles. inner . get ( address) . map ( Either :: Right )
321+ dyn_precompiles. stateless . get ( address) . map ( Either :: Right )
317322 }
318323 } ;
319324
@@ -326,6 +331,14 @@ impl PrecompilesMap {
326331 let lookup = self . lookup . as_ref ( ) ?;
327332 lookup. lookup ( address) . map ( Either :: Right )
328333 }
334+
335+ /// Check if the given address is stateful precompile.
336+ pub fn is_stateful ( & self , address : & Address ) -> bool {
337+ match & self . precompiles {
338+ PrecompilesKind :: Builtin ( precompiles) => precompiles. is_stateful ( address) ,
339+ PrecompilesKind :: Dynamic ( dyn_precompiles) => dyn_precompiles. stateful . contains ( address) ,
340+ }
341+ }
329342}
330343
331344impl From < EthPrecompiles > for PrecompilesMap {
@@ -365,49 +378,56 @@ where
365378 context : & mut Context < BlockEnv , TxEnv , CfgEnv , DB , Journal < DB > , Chain > ,
366379 address : & Address ,
367380 inputs : & InputsImpl ,
368- _is_static : bool ,
381+ is_static : bool ,
369382 gas_limit : u64 ,
370383 ) -> Result < Option < InterpreterResult > , String > {
371384 // Get the precompile at the address
372- let Some ( precompile) = self . get ( address) else {
385+ let maybe_stateless = self . get_stateless ( address) ;
386+ if maybe_stateless. is_none ( ) && !self . is_stateful ( address) {
373387 return Ok ( None ) ;
374- } ;
388+ }
375389
376390 let mut result = InterpreterResult {
377391 result : InstructionResult :: Return ,
378392 gas : Gas :: new ( gas_limit) ,
379393 output : Bytes :: new ( ) ,
380394 } ;
381395
382- let ( local, journal) = ( & context. local , & mut context. journaled_state ) ;
383-
384396 // Execute the precompile
385- let r;
386397 let input_bytes = match & inputs. input {
387398 CallInput :: SharedBuffer ( range) => {
388399 // `map_or` does not work here as we use `r` to extend lifetime of the slice
389400 // and return it.
390401 #[ allow( clippy:: option_if_let_else) ]
391- if let Some ( slice) = local. shared_memory_buffer_slice ( range. clone ( ) ) {
392- r = slice;
393- & * r
402+ if let Some ( slice) = context. local . shared_memory_buffer_slice ( range. clone ( ) ) {
403+ slice. to_vec ( )
394404 } else {
395- & [ ]
405+ vec ! [ ]
396406 }
397407 }
398- CallInput :: Bytes ( bytes) => bytes. as_ref ( ) ,
408+ CallInput :: Bytes ( bytes) => bytes. 0 . to_vec ( ) ,
399409 } ;
400410
401- let precompile_result = precompile. call ( PrecompileInput {
402- data : input_bytes,
403- gas : gas_limit,
404- caller : inputs. caller_address ,
405- value : inputs. call_value ,
406- internals : EvmInternals :: new ( journal, & context. block ) ,
411+ let precompile_result = match maybe_stateless {
412+ Some ( precompile) => precompile. call ( PrecompileInput {
413+ data : & input_bytes,
414+ gas : gas_limit,
415+ caller : inputs. caller_address ,
416+ value : inputs. call_value ,
417+ internals : EvmInternals :: new ( & mut context. journaled_state , & context. block ) ,
407418 target_address : inputs. target_address ,
408419 bytecode_address : inputs. bytecode_address . expect ( "always set for precompile calls" ) ,
409- } ) ;
410-
420+ } ) ,
421+ None => run_stateful_precompile (
422+ * address,
423+ & input_bytes,
424+ gas_limit,
425+ inputs. caller_address ,
426+ inputs. call_value ,
427+ is_static,
428+ context,
429+ ) ,
430+ } ;
411431 match precompile_result {
412432 Ok ( output) => {
413433 let underflow = result. gas . record_cost ( output. gas_used ) ;
@@ -437,7 +457,7 @@ where
437457 }
438458
439459 fn contains ( & self , address : & Address ) -> bool {
440- self . get ( address) . is_some ( )
460+ self . get_stateless ( address) . is_some ( ) || self . is_stateful ( address )
441461 }
442462}
443463
@@ -493,8 +513,10 @@ impl core::fmt::Debug for DynPrecompile {
493513/// unlike the static `Precompiles` struct from revm.
494514#[ derive( Clone , Default ) ]
495515pub struct DynPrecompiles {
496- /// Precompiles
497- inner : HashMap < Address , DynPrecompile > ,
516+ /// Stateless Precompiles
517+ stateless : HashMap < Address , DynPrecompile > ,
518+ /// Stateful Precompiles
519+ stateful : HashSet < Address > ,
498520 /// Addresses of precompile
499521 addresses : HashSet < Address > ,
500522}
@@ -503,7 +525,7 @@ impl DynPrecompiles {
503525 /// Consumes the type and returns an iterator over the addresses and the corresponding
504526 /// precompile.
505527 pub fn into_precompiles ( self ) -> impl Iterator < Item = ( Address , DynPrecompile ) > {
506- self . inner . into_iter ( )
528+ self . stateless . into_iter ( )
507529 }
508530}
509531
@@ -793,7 +815,7 @@ mod tests {
793815 // using the dynamic precompiles interface
794816 let dyn_precompile = match & spec_precompiles. precompiles {
795817 PrecompilesKind :: Dynamic ( dyn_precompiles) => {
796- dyn_precompiles. inner . get ( & identity_address) . unwrap ( )
818+ dyn_precompiles. stateless . get ( & identity_address) . unwrap ( )
797819 }
798820 _ => panic ! ( "Expected dynamic precompiles" ) ,
799821 } ;
@@ -827,7 +849,7 @@ mod tests {
827849 // get the modified precompile and check it
828850 let dyn_precompile = match & spec_precompiles. precompiles {
829851 PrecompilesKind :: Dynamic ( dyn_precompiles) => {
830- dyn_precompiles. inner . get ( & identity_address) . unwrap ( )
852+ dyn_precompiles. stateless . get ( & identity_address) . unwrap ( )
831853 }
832854 _ => panic ! ( "Expected dynamic precompiles" ) ,
833855 } ;
@@ -931,11 +953,11 @@ mod tests {
931953
932954 // Test that static precompiles still work
933955 let identity_address = address ! ( "0x0000000000000000000000000000000000000004" ) ;
934- assert ! ( spec_precompiles. get ( & identity_address) . is_some( ) ) ;
956+ assert ! ( spec_precompiles. get_stateless ( & identity_address) . is_some( ) ) ;
935957
936958 // Test dynamic lookup for matching address
937959 let dynamic_address = address ! ( "0xDEAD000000000000000000000000000000000001" ) ;
938- let dynamic_precompile = spec_precompiles. get ( & dynamic_address) ;
960+ let dynamic_precompile = spec_precompiles. get_stateless ( & dynamic_address) ;
939961 assert ! ( dynamic_precompile. is_some( ) , "Dynamic precompile should be found" ) ;
940962
941963 // Execute the dynamic precompile
@@ -956,7 +978,7 @@ mod tests {
956978
957979 // Test non-matching address returns None
958980 let non_matching_address = address ! ( "0x1234000000000000000000000000000000000001" ) ;
959- assert ! ( spec_precompiles. get ( & non_matching_address) . is_none( ) ) ;
981+ assert ! ( spec_precompiles. get_stateless ( & non_matching_address) . is_none( ) ) ;
960982 }
961983
962984 #[ test]
@@ -970,7 +992,7 @@ mod tests {
970992 let test_input = Bytes :: from_static ( b"test data" ) ;
971993 let gas_limit = 1000 ;
972994
973- let precompile = spec_precompiles. get ( & identity_address) ;
995+ let precompile = spec_precompiles. get_stateless ( & identity_address) ;
974996 assert ! ( precompile. is_some( ) , "Identity precompile should exist" ) ;
975997
976998 let result = precompile
@@ -989,14 +1011,14 @@ mod tests {
9891011
9901012 let nonexistent_address = address ! ( "0x0000000000000000000000000000000000000099" ) ;
9911013 assert ! (
992- spec_precompiles. get ( & nonexistent_address) . is_none( ) ,
1014+ spec_precompiles. get_stateless ( & nonexistent_address) . is_none( ) ,
9931015 "Non-existent precompile should not be found"
9941016 ) ;
9951017
9961018 let mut dynamic_precompiles = spec_precompiles;
9971019 dynamic_precompiles. ensure_dynamic_precompiles ( ) ;
9981020
999- let dyn_precompile = dynamic_precompiles. get ( & identity_address) ;
1021+ let dyn_precompile = dynamic_precompiles. get_stateless ( & identity_address) ;
10001022 assert ! (
10011023 dyn_precompile. is_some( ) ,
10021024 "Identity precompile should exist after conversion to dynamic"
0 commit comments