66//! jumpdest table, before the actual CPU carries on with contract execution.
77
88use std:: collections:: { BTreeSet , HashMap } ;
9+ use std:: str:: FromStr ;
910
1011use anyhow:: anyhow;
11- use ethereum_types:: { BigEndianHash , U256 } ;
12+ use ethereum_types:: { BigEndianHash , H256 , U256 } ;
1213use log:: Level ;
1314use mpt_trie:: partial_trie:: PartialTrie ;
1415use plonky2:: field:: types:: Field ;
@@ -19,6 +20,10 @@ use crate::cpu::kernel::aggregator::KERNEL;
1920use crate :: cpu:: kernel:: constants:: global_metadata:: GlobalMetadata ;
2021use crate :: generation:: debug_inputs;
2122use crate :: generation:: mpt:: load_all_mpts;
23+ use crate :: generation:: prover_input:: {
24+ get_proofs_and_jumpdests, CodeDb , ContextJumpDests , JumpDestTableProcessed ,
25+ JumpDestTableWitness ,
26+ } ;
2227use crate :: generation:: rlp:: all_rlp_prover_inputs_reversed;
2328use crate :: generation:: state:: {
2429 all_withdrawals_prover_inputs_reversed, GenerationState , GenerationStateCheckpoint ,
@@ -52,6 +57,7 @@ pub(crate) struct Interpreter<F: Field> {
5257 /// Counts the number of appearances of each opcode. For debugging purposes.
5358 #[ allow( unused) ]
5459 pub ( crate ) opcode_count : [ usize ; 0x100 ] ,
60+ /// A table of contexts and their reached JUMPDESTs.
5561 jumpdest_table : HashMap < usize , BTreeSet < usize > > ,
5662 /// `true` if the we are currently carrying out a jumpdest analysis.
5763 pub ( crate ) is_jumpdest_analysis : bool ,
@@ -60,14 +66,15 @@ pub(crate) struct Interpreter<F: Field> {
6066 pub ( crate ) clock : usize ,
6167}
6268
63- /// Simulates the CPU execution from `state` until the program counter reaches
64- /// `final_label` in the current context.
6569pub ( crate ) fn simulate_cpu_and_get_user_jumps < F : Field > (
6670 final_label : & str ,
6771 state : & GenerationState < F > ,
68- ) -> Option < HashMap < usize , Vec < usize > > > {
72+ ) -> (
73+ Option < HashMap < usize , Vec < usize > > > ,
74+ HashMap < usize , BTreeSet < usize > > ,
75+ ) {
6976 match state. jumpdest_table {
70- Some ( _) => None ,
77+ Some ( _) => ( None , Default :: default ( ) ) ,
7178 None => {
7279 let halt_pc = KERNEL . global_labels [ final_label] ;
7380 let initial_context = state. registers . context ;
@@ -82,14 +89,60 @@ pub(crate) fn simulate_cpu_and_get_user_jumps<F: Field>(
8289
8390 interpreter
8491 . generation_state
85- . set_jumpdest_analysis_inputs ( interpreter. jumpdest_table ) ;
92+ . set_jumpdest_analysis_inputs ( interpreter. jumpdest_table . clone ( ) ) ;
8693
8794 log:: debug!( "Simulated CPU for jumpdest analysis halted." ) ;
88- interpreter. generation_state . jumpdest_table
95+ (
96+ interpreter. generation_state . jumpdest_table ,
97+ interpreter. jumpdest_table ,
98+ )
8999 }
90100 }
91101}
92102
103+ /// Computes the JUMPDEST proofs for each context.
104+ ///
105+ /// # Arguments
106+ ///
107+ /// - `jumpdest_table_rpc`: The raw table received from RPC.
108+ /// - `code_db`: The corresponding database of contract code used in the trace.
109+ pub ( crate ) fn set_jumpdest_analysis_inputs_rpc (
110+ jumpdest_table_rpc : & JumpDestTableWitness ,
111+ code_db : & CodeDb ,
112+ ) -> JumpDestTableProcessed {
113+ let ctx_proofs = jumpdest_table_rpc
114+ . 0
115+ . iter ( )
116+ . flat_map ( |( code_addr, ctx_jumpdests) | {
117+ prove_context_jumpdests ( & code_db[ code_addr] , ctx_jumpdests)
118+ } )
119+ . collect ( ) ;
120+ JumpDestTableProcessed ( ctx_proofs)
121+ }
122+
123+ /// Orchestrates the proving of all contexts in a specific bytecode.
124+ ///
125+ /// # Arguments
126+ ///
127+ /// - `ctx_jumpdests`: Map from `ctx` to its list of offsets to reached
128+ /// `JUMPDEST`s.
129+ /// - `code`: The bytecode for the contexts. This is the same for all contexts.
130+ fn prove_context_jumpdests (
131+ code : & [ u8 ] ,
132+ ctx_jumpdests : & ContextJumpDests ,
133+ ) -> HashMap < usize , Vec < usize > > {
134+ ctx_jumpdests
135+ . 0
136+ . iter ( )
137+ . map ( |( & ctx, jumpdests) | {
138+ let proofs = jumpdests. last ( ) . map_or ( Vec :: default ( ) , |& largest_address| {
139+ get_proofs_and_jumpdests ( code, largest_address, jumpdests. clone ( ) )
140+ } ) ;
141+ ( ctx, proofs)
142+ } )
143+ . collect ( )
144+ }
145+
93146impl < F : Field > Interpreter < F > {
94147 /// Returns an instance of `Interpreter` given `GenerationInputs`, and
95148 /// assuming we are initializing with the `KERNEL` code.
@@ -508,14 +561,29 @@ impl<F: Field> State<F> for Interpreter<F> {
508561
509562 let op = decode ( registers, opcode) ?;
510563
564+ // log here
511565 fill_op_flag ( op, & mut row) ;
512566
513567 self . fill_stack_fields ( & mut row) ?;
514568
515569 if registers. is_kernel {
516570 log_kernel_instruction ( self , op) ;
517571 } else {
518- self . log_debug ( format ! ( "User instruction: {:?}" , op) ) ;
572+ //self.log_debug(format!("User instruction: {:?} CTX {:?}", op,
573+ let hash = "0xc02ea02af1da253b9cf3d1de648c3355211f490cf4b8641b3146e69450870ba6" ;
574+ let debug_tx = H256 :: from_str ( hash) . unwrap ( ) ;
575+ let curr_tx =
576+ keccak_hash:: keccak ( self . generation_state . inputs . signed_txn . as_ref ( ) . unwrap ( ) ) ;
577+
578+ if curr_tx == debug_tx {
579+ log:: info!(
580+ "JMP: {:<5} TX: {:?} CTX: {:<2} OP: {:<10?}" ,
581+ self . is_jumpdest_analysis,
582+ curr_tx,
583+ registers. code_context( ) ,
584+ op
585+ ) ;
586+ }
519587 }
520588
521589 let generation_state = self . get_mut_generation_state ( ) ;
0 commit comments