Skip to content
This repository was archived by the owner on Jul 5, 2024. It is now read-only.

Commit 2a0c179

Browse files
[Opcode] Jumpdest (#143)
* implement jumpdest code * fix fmt * change format * mark _step Co-authored-by: Dream Wu <[email protected]>
1 parent 197b41d commit 2a0c179

File tree

3 files changed

+153
-0
lines changed

3 files changed

+153
-0
lines changed

bus-mapping/src/evm.rs

+2
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,8 @@ pub struct GasCost(u64);
268268
impl GasCost {
269269
/// Constant cost for free step
270270
pub const ZERO: Self = Self(0);
271+
/// Constant cost for jumpdest step, only it takes one gas
272+
pub const ONE: Self = Self(1);
271273
/// Constant cost for quick step
272274
pub const QUICK: Self = Self(2);
273275
/// Constant cost for fastest step

zkevm-circuits/src/evm_circuit/op_execution.rs

+13
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ mod arithmetic;
1818
mod byte;
1919
mod comparator;
2020
mod dup;
21+
mod jumpdest;
2122
mod pc;
2223
mod pop;
2324
mod push;
@@ -29,6 +30,7 @@ use arithmetic::AddGadget;
2930
use byte::ByteGadget;
3031
use comparator::ComparatorGadget;
3132
use dup::DupGadget;
33+
use jumpdest::JumpdestGadget;
3234
use pc::PcGadget;
3335
use pop::PopGadget;
3436
use push::PushGadget;
@@ -229,6 +231,7 @@ pub(crate) struct OpExecutionGadget<F> {
229231
pc_gadget: PcGadget<F>,
230232
signextend_gadget: SignextendGadget<F>,
231233
swap_gadget: SwapGadget<F>,
234+
jumpdest_gadget: JumpdestGadget<F>,
232235
}
233236

234237
impl<F: FieldExt> OpExecutionGadget<F> {
@@ -291,6 +294,7 @@ impl<F: FieldExt> OpExecutionGadget<F> {
291294
construct_op_gadget!(pc_gadget);
292295
construct_op_gadget!(signextend_gadget);
293296
construct_op_gadget!(swap_gadget);
297+
construct_op_gadget!(jumpdest_gadget);
294298
let _ = qs_op_idx;
295299

296300
for constraint in constraints.into_iter() {
@@ -335,6 +339,7 @@ impl<F: FieldExt> OpExecutionGadget<F> {
335339
pc_gadget,
336340
signextend_gadget,
337341
swap_gadget,
342+
jumpdest_gadget,
338343
}
339344
}
340345

@@ -603,6 +608,14 @@ impl<F: FieldExt> OpExecutionGadget<F> {
603608
(_, _, _, OpcodeId::SIGNEXTEND) => self
604609
.signextend_gadget
605610
.assign(region, offset, core_state, execution_step)?,
611+
612+
(_, _, _, OpcodeId::JUMPDEST) => self.jumpdest_gadget.assign(
613+
region,
614+
offset,
615+
core_state,
616+
execution_step,
617+
)?,
618+
606619
_ => unimplemented!(),
607620
}
608621
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
use super::super::{Case, Cell, Constraint, ExecutionStep};
2+
use super::utils;
3+
use super::utils::common_cases::OutOfGasCase;
4+
use super::utils::constraint_builder::ConstraintBuilder;
5+
use super::{
6+
CaseAllocation, CaseConfig, CoreStateInstance, OpExecutionState, OpGadget,
7+
};
8+
use crate::impl_op_gadget;
9+
use crate::util::Expr;
10+
use bus_mapping::evm::{GasCost, OpcodeId};
11+
use halo2::plonk::Error;
12+
use halo2::{arithmetic::FieldExt, circuit::Region};
13+
use std::convert::TryInto;
14+
15+
const GC_DELTA: usize = 0;
16+
const PC_DELTA: usize = 1;
17+
const SP_DELTA: usize = 0;
18+
const GAS: GasCost = GasCost::ONE;
19+
20+
impl_op_gadget!(
21+
[JUMPDEST]
22+
JumpdestGadget {
23+
JumpdestSuccessCase(),
24+
OutOfGasCase(GAS.as_usize()),
25+
}
26+
);
27+
28+
#[derive(Clone, Debug)]
29+
struct JumpdestSuccessCase<F> {
30+
case_selector: Cell<F>,
31+
}
32+
33+
impl<F: FieldExt> JumpdestSuccessCase<F> {
34+
pub(crate) const CASE_CONFIG: &'static CaseConfig = &CaseConfig {
35+
case: Case::Success,
36+
num_word: 0,
37+
num_cell: 0,
38+
will_halt: false,
39+
};
40+
41+
pub(crate) fn construct(alloc: &mut CaseAllocation<F>) -> Self {
42+
Self {
43+
case_selector: alloc.selector.clone(),
44+
}
45+
}
46+
47+
pub(crate) fn constraint(
48+
&self,
49+
state_curr: &OpExecutionState<F>,
50+
state_next: &OpExecutionState<F>,
51+
name: &'static str,
52+
) -> Constraint<F> {
53+
let mut cb = ConstraintBuilder::default();
54+
// State transitions
55+
utils::StateTransitions {
56+
gc_delta: Some(GC_DELTA.expr()),
57+
sp_delta: Some(SP_DELTA.expr()),
58+
pc_delta: Some(PC_DELTA.expr()),
59+
gas_delta: Some(GAS.expr()),
60+
}
61+
.constraints(&mut cb, state_curr, state_next);
62+
63+
// Generate the constraint
64+
cb.constraint(self.case_selector.expr(), name)
65+
}
66+
67+
fn assign(
68+
&self,
69+
region: &mut Region<'_, F>,
70+
offset: usize,
71+
state: &mut CoreStateInstance,
72+
_step: &ExecutionStep,
73+
) -> Result<(), Error> {
74+
state.global_counter += GC_DELTA;
75+
state.program_counter += PC_DELTA;
76+
state.stack_pointer += SP_DELTA;
77+
state.gas_counter += GAS.as_usize();
78+
79+
self.case_selector
80+
.assign(region, offset, Some(F::from_u64(1)))
81+
.unwrap();
82+
Ok(())
83+
}
84+
}
85+
86+
#[cfg(test)]
87+
mod test {
88+
use super::super::super::{
89+
test::TestCircuit, Case, ExecutionStep, Operation,
90+
};
91+
use bus_mapping::{evm::OpcodeId, operation::Target};
92+
use halo2::{arithmetic::FieldExt, dev::MockProver};
93+
use num::BigUint;
94+
use pasta_curves::pallas::Base;
95+
96+
macro_rules! try_test_circuit {
97+
($execution_steps:expr, $operations:expr, $result:expr) => {{
98+
let circuit =
99+
TestCircuit::<Base>::new($execution_steps, $operations);
100+
let prover = MockProver::<Base>::run(10, &circuit, vec![]).unwrap();
101+
assert_eq!(prover.verify(), $result);
102+
}};
103+
}
104+
105+
#[test]
106+
fn jumpdest_gadget() {
107+
try_test_circuit!(
108+
vec![
109+
ExecutionStep {
110+
opcode: OpcodeId::PUSH2,
111+
case: Case::Success,
112+
values: vec![
113+
BigUint::from(0x02_03u64),
114+
BigUint::from(0x01_01u64),
115+
],
116+
},
117+
ExecutionStep {
118+
// jumpdest
119+
opcode: OpcodeId::JUMPDEST,
120+
case: Case::Success,
121+
values: vec![],
122+
}
123+
],
124+
vec![Operation {
125+
gc: 1,
126+
target: Target::Stack,
127+
is_write: true,
128+
values: [
129+
Base::zero(),
130+
Base::from_u64(1023),
131+
Base::from_u64(2 + 3),
132+
Base::zero(),
133+
]
134+
}],
135+
Ok(())
136+
);
137+
}
138+
}

0 commit comments

Comments
 (0)