@@ -8,7 +8,7 @@ use alloy_rpc_types::{Filter, FilteredParams};
88use alloy_sol_types:: { sol, SolCall , SolEvent } ;
99use alloy_trie:: root:: ordered_trie_root_with_encoder;
1010use eyre:: OptionExt ;
11- use io:: EVMStateSketch ;
11+ use io:: EvmSketchInput ;
1212use reth_chainspec:: ChainSpec ;
1313use reth_evm:: { ConfigureEvm , EvmEnv } ;
1414use reth_evm_ethereum:: { EthEvm , EthEvmConfig } ;
@@ -20,6 +20,9 @@ use revm_primitives::{Address, Bytes, TxKind, B256, U256};
2020use rsp_client_executor:: io:: { TrieDB , WitnessInput } ;
2121use rsp_primitives:: genesis:: Genesis ;
2222
23+ mod anchor;
24+ pub use anchor:: { rebuild_merkle_root, Anchor , BeaconAnchor , HeaderAnchor , BLOCK_HASH_LEAF_INDEX } ;
25+
2326mod errors;
2427pub use errors:: ClientError ;
2528
@@ -100,11 +103,17 @@ impl IntoTxEnv<TxEnv> for &ContractInput {
100103}
101104
102105sol ! {
106+ #[ derive( Debug ) ]
107+ enum AnchorType { BlockHash , BeaconRoot }
108+
103109 /// Public values of a contract call.
104110 ///
105111 /// These outputs can easily be abi-encoded, for use on-chain.
112+ #[ derive( Debug ) ]
106113 struct ContractPublicValues {
107- bytes32 blockHash;
114+ uint256 id;
115+ bytes32 anchorHash;
116+ AnchorType anchorType;
108117 address callerAddress;
109118 address contractAddress;
110119 bytes contractCalldata;
@@ -117,46 +126,65 @@ impl ContractPublicValues {
117126 ///
118127 /// By default, commit the contract input, the output, and the block hash to public values of
119128 /// the proof. More can be committed if necessary.
120- pub fn new ( call : ContractInput , output : Bytes , block_hash : B256 ) -> Self {
129+ pub fn new (
130+ call : ContractInput ,
131+ output : Bytes ,
132+ id : U256 ,
133+ anchor : B256 ,
134+ anchor_type : AnchorType ,
135+ ) -> Self {
121136 Self {
137+ id,
138+ anchorHash : anchor,
139+ anchorType : anchor_type,
122140 contractAddress : call. contract_address ,
123141 callerAddress : call. caller_address ,
124142 contractCalldata : call. calldata . to_bytes ( ) ,
125143 contractOutput : output,
126- blockHash : block_hash,
127144 }
128145 }
129146}
130147
131148/// An executor that executes smart contract calls inside a zkVM.
132149#[ derive( Debug ) ]
133150pub struct ClientExecutor < ' a > {
151+ /// The block anchor.
152+ pub anchor : & ' a Anchor ,
134153 /// The genesis block specification.
135154 pub genesis : & ' a Genesis ,
136155 /// The database that the executor uses to access state.
137156 pub witness_db : TrieDB < ' a > ,
138- /// The block header.
139- pub header : & ' a Header ,
140157 /// All logs in the block.
141158 pub logs : Vec < Log > ,
142159}
143160
144161impl < ' a > ClientExecutor < ' a > {
145162 /// Instantiates a new [`ClientExecutor`]
146- pub fn new ( state_sketch : & ' a EVMStateSketch ) -> Result < Self , ClientError > {
147- if !state_sketch. receipts . is_empty ( ) {
163+ pub fn new ( state_sketch : & ' a EvmSketchInput ) -> Result < Self , ClientError > {
164+ assert_eq ! (
165+ state_sketch. anchor. header( ) . state_root,
166+ state_sketch. state. state_root( ) ,
167+ "State root mismatch"
168+ ) ;
169+
170+ if let Some ( receipts) = & state_sketch. receipts {
148171 // verify the receipts root hash
149- let root =
150- ordered_trie_root_with_encoder ( & state_sketch. receipts , |r, out| r. encode_2718 ( out) ) ;
151- assert_eq ! ( state_sketch. header. receipts_root, root, "Receipts root mismatch" ) ;
172+ let root = ordered_trie_root_with_encoder ( receipts, |r, out| r. encode_2718 ( out) ) ;
173+ assert_eq ! ( state_sketch. anchor. header( ) . receipts_root, root, "Receipts root mismatch" ) ;
152174 }
153175
154- let logs = state_sketch. receipts . iter ( ) . flat_map ( |r| r. logs ( ) . to_vec ( ) ) . collect ( ) ;
176+ let logs = state_sketch
177+ . receipts
178+ . as_ref ( )
179+ . unwrap_or ( & vec ! [ ] )
180+ . iter ( )
181+ . flat_map ( |r| r. logs ( ) . to_vec ( ) )
182+ . collect ( ) ;
155183
156184 Ok ( Self {
185+ anchor : & state_sketch. anchor ,
157186 genesis : & state_sketch. genesis ,
158187 witness_db : state_sketch. witness_db ( ) ?,
159- header : & state_sketch. header ,
160188 logs,
161189 } )
162190 }
@@ -166,10 +194,19 @@ impl<'a> ClientExecutor<'a> {
166194 /// Storage accesses are already validated against the `witness_db`'s state root.
167195 pub fn execute ( & self , call : ContractInput ) -> eyre:: Result < ContractPublicValues > {
168196 let cache_db = CacheDB :: new ( & self . witness_db ) ;
169- let mut evm = new_evm ( cache_db, self . header , U256 :: ZERO , self . genesis ) ;
197+ let mut evm = new_evm ( cache_db, self . anchor . header ( ) , U256 :: ZERO , self . genesis ) ;
170198 let tx_output = evm. transact ( & call) ?;
171199 let tx_output_bytes = tx_output. result . output ( ) . ok_or_eyre ( "Error decoding result" ) ?;
172- Ok ( ContractPublicValues :: new ( call, tx_output_bytes. clone ( ) , self . header . hash_slow ( ) ) )
200+
201+ let public_values = ContractPublicValues :: new (
202+ call,
203+ tx_output_bytes. clone ( ) ,
204+ self . anchor . id ( ) ,
205+ self . anchor . hash ( ) ,
206+ self . anchor . ty ( ) ,
207+ ) ;
208+
209+ Ok ( public_values)
173210 }
174211
175212 /// Returns the decoded logs matching the provided `filter`.
0 commit comments