@@ -6,8 +6,8 @@ use std::collections::BTreeSet;
66use alloy_consensus:: Header ;
77use alloy_evm:: Evm ;
88use alloy_provider:: { network:: AnyNetwork , Provider } ;
9- use alloy_rpc_types:: { BlockId , BlockNumberOrTag } ;
10- use eyre:: eyre;
9+ use alloy_rpc_types:: BlockId ;
10+ use eyre:: { eyre, Ok } ;
1111use revm:: database:: CacheDB ;
1212use revm_primitives:: { Bytes , B256 , U256 } ;
1313use rsp_mpt:: EthereumState ;
@@ -16,12 +16,16 @@ use rsp_rpc_db::RpcDb;
1616
1717use sp1_cc_client_executor:: { io:: EVMStateSketch , new_evm, ContractInput } ;
1818
19+ pub use rsp_primitives:: genesis:: Genesis ;
20+
1921/// An executor that fetches data from a [`Provider`].
2022///
2123/// This executor keeps track of the state being accessed, and eventually compresses it into an
2224/// [`EVMStateSketch`].
2325#[ derive( Debug , Clone ) ]
2426pub struct HostExecutor < P : Provider < AnyNetwork > + Clone > {
27+ /// The genesis block specification.
28+ pub genesis : Genesis ,
2529 /// The header of the block to execute our view functions on.
2630 pub header : Header ,
2731 /// The [`RpcDb`] used to back the EVM.
@@ -31,28 +35,20 @@ pub struct HostExecutor<P: Provider<AnyNetwork> + Clone> {
3135}
3236
3337impl < P : Provider < AnyNetwork > + Clone > HostExecutor < P > {
34- /// Create a new [`HostExecutor`] with a specific [`Provider`] and [`BlockNumberOrTag`].
35- pub async fn new ( provider : P , block_number : BlockNumberOrTag ) -> eyre:: Result < Self > {
36- let block = provider
37- . get_block_by_number ( block_number)
38- . full ( )
39- . await ?
40- . ok_or ( eyre ! ( "couldn't fetch block: {}" , block_number) ) ?;
41-
42- let rpc_db = RpcDb :: new ( provider. clone ( ) , block. header . number ) ;
43- let header = block
44- . inner
45- . header
46- . inner
47- . clone ( )
48- . try_into_header ( )
49- . map_err ( |_| eyre ! ( "fail to convert header" ) ) ?;
50-
51- Ok ( Self { header, rpc_db, provider } )
38+ /// Creates a new [`HostExecutor`] with a specific [`Provider`] and `block_identifier`
39+ /// on Ethereum Mainnet. For a custom chain, use [`HostExecutor::new_with_genesis`].
40+ pub async fn new < B : Into < BlockId > > ( provider : P , block_identifier : B ) -> eyre:: Result < Self > {
41+ Self :: new_with_genesis ( provider, block_identifier, Genesis :: Mainnet ) . await
5242 }
5343
54- /// Create a new [`HostExecutor`] with a specific [`Provider`] and [`BlockId`].
55- pub async fn new_with_blockid ( provider : P , block_identifier : BlockId ) -> eyre:: Result < Self > {
44+ /// Creates a new [`HostExecutor`] with a specific [`Provider`] and `block_identifier`
45+ /// on a custom chain using the provided [`Genesis`].
46+ pub async fn new_with_genesis < B : Into < BlockId > > (
47+ provider : P ,
48+ block_identifier : B ,
49+ genesis : Genesis ,
50+ ) -> eyre:: Result < Self > {
51+ let block_identifier = block_identifier. into ( ) ;
5652 let block = provider
5753 . get_block ( block_identifier)
5854 . full ( )
@@ -67,15 +63,26 @@ impl<P: Provider<AnyNetwork> + Clone> HostExecutor<P> {
6763 . clone ( )
6864 . try_into_header ( )
6965 . map_err ( |_| eyre ! ( "fail to convert header" ) ) ?;
70- Ok ( Self { header, rpc_db, provider } )
66+
67+ Ok ( Self { genesis, header, rpc_db, provider } )
7168 }
7269
7370 /// Executes the smart contract call with the given [`ContractInput`].
74- pub async fn execute ( & mut self , call : ContractInput ) -> eyre:: Result < Bytes > {
71+ pub async fn execute ( & self , call : ContractInput ) -> eyre:: Result < Bytes > {
7572 let cache_db = CacheDB :: new ( & self . rpc_db ) ;
76- let mut evm = new_evm ( cache_db, & self . header , U256 :: ZERO ) ;
73+ let mut evm = new_evm ( cache_db, & self . header , U256 :: ZERO , & self . genesis ) ;
74+
7775 let output = evm. transact ( & call) ?;
78- let output_bytes = output. result . output ( ) . ok_or ( eyre ! ( "Error getting result" ) ) ?;
76+
77+ let output_bytes = match output. result {
78+ revm:: context:: result:: ExecutionResult :: Success { output, .. } => {
79+ Ok ( output. data ( ) . clone ( ) )
80+ }
81+ revm:: context:: result:: ExecutionResult :: Revert { output, .. } => Ok ( output) ,
82+ revm:: context:: result:: ExecutionResult :: Halt { reason, .. } => {
83+ Err ( eyre ! ( "Execution halted: {reason:?}" ) )
84+ }
85+ } ?;
7986
8087 Ok ( output_bytes. clone ( ) )
8188 }
@@ -124,6 +131,7 @@ impl<P: Provider<AnyNetwork> + Clone> HostExecutor<P> {
124131 }
125132
126133 Ok ( EVMStateSketch {
134+ genesis : self . genesis . clone ( ) ,
127135 header : self . header . clone ( ) ,
128136 ancestor_headers,
129137 state,
0 commit comments