Skip to content

Commit 270256f

Browse files
committed
Implement JumpDest fetching from RPC.
Automated testing missing.
1 parent 0e55293 commit 270256f

File tree

24 files changed

+525
-37
lines changed

24 files changed

+525
-37
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ eth_trie = "0.4.0"
6363
ethereum-types = "0.14.1"
6464
futures = "0.3.30"
6565
hashbrown = "0.14.5"
66-
hex = "0.4.3"
66+
hex = { version = "0.4.3", features = ["serde"] }
6767
hex-literal = "0.4.1"
6868
impl-codec = "0.6.0"
6969
impl-num-traits = "0.1.2"

evm_arithmetization/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ homepage.workspace = true
1515
keywords.workspace = true
1616

1717
[dependencies]
18+
__compat_primitive_types = { workspace = true }
1819
anyhow = { workspace = true }
1920
bytes = { workspace = true }
2021
env_logger = { workspace = true }
2122
ethereum-types = { workspace = true }
22-
hex = { workspace = true, optional = true }
23+
hex = { workspace = true }
2324
hex-literal = { workspace = true }
2425
itertools = { workspace = true }
2526
keccak-hash = { workspace = true }
@@ -55,7 +56,6 @@ ripemd = { workspace = true }
5556

5657
[features]
5758
default = ["parallel"]
58-
asmtools = ["hex"]
5959
parallel = [
6060
"plonky2/parallel",
6161
"plonky2_maybe_rayon/parallel",

evm_arithmetization/benches/fibonacci_25m_gas.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ fn prepare_setup() -> anyhow::Result<GenerationInputs> {
194194
prev_hashes: vec![H256::default(); 256],
195195
cur_hash: H256::default(),
196196
},
197+
jumpdest_table: Default::default(),
197198
})
198199
}
199200

evm_arithmetization/src/cpu/kernel/interpreter.rs

Lines changed: 76 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
//! jumpdest table, before the actual CPU carries on with contract execution.
77
88
use std::collections::{BTreeSet, HashMap};
9+
use std::str::FromStr;
910

1011
use anyhow::anyhow;
11-
use ethereum_types::{BigEndianHash, U256};
12+
use ethereum_types::{BigEndianHash, H256, U256};
1213
use log::Level;
1314
use mpt_trie::partial_trie::PartialTrie;
1415
use plonky2::field::types::Field;
@@ -19,6 +20,10 @@ use crate::cpu::kernel::aggregator::KERNEL;
1920
use crate::cpu::kernel::constants::global_metadata::GlobalMetadata;
2021
use crate::generation::debug_inputs;
2122
use crate::generation::mpt::load_all_mpts;
23+
use crate::generation::prover_input::{
24+
get_proofs_and_jumpdests, CodeDb, ContextJumpDests, JumpDestTableProcessed,
25+
JumpDestTableWitness,
26+
};
2227
use crate::generation::rlp::all_rlp_prover_inputs_reversed;
2328
use 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.
6569
pub(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+
93146
impl<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();

evm_arithmetization/src/cpu/kernel/tests/add11.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ fn test_add11_yml() {
195195
prev_hashes: vec![H256::default(); 256],
196196
cur_hash: H256::default(),
197197
},
198+
jumpdest_table: Default::default(),
198199
};
199200

200201
let initial_stack = vec![];
@@ -376,6 +377,7 @@ fn test_add11_yml_with_exception() {
376377
prev_hashes: vec![H256::default(); 256],
377378
cur_hash: H256::default(),
378379
},
380+
jumpdest_table: Default::default(),
379381
};
380382

381383
let initial_stack = vec![];

evm_arithmetization/src/generation/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use plonky2::field::types::Field;
1010
use plonky2::hash::hash_types::RichField;
1111
use plonky2::timed;
1212
use plonky2::util::timing::TimingTree;
13+
use prover_input::JumpDestTableWitness;
1314
use serde::{Deserialize, Serialize};
1415
use starky::config::StarkConfig;
1516
use GlobalMetadata::{
@@ -78,6 +79,9 @@ pub struct GenerationInputs {
7879
/// The hash of the current block, and a list of the 256 previous block
7980
/// hashes.
8081
pub block_hashes: BlockHashes,
82+
83+
/// A jumptable describing each JUMPDEST reached.
84+
pub jumpdest_table: JumpDestTableWitness,
8185
}
8286

8387
#[derive(Clone, Debug, Deserialize, Serialize, Default)]

0 commit comments

Comments
 (0)