Skip to content

Commit

Permalink
add non static call constraint for sstore (privacy-scaling-exploratio…
Browse files Browse the repository at this point in the history
…ns#467)

* add non static call constraint

* assert CallcontextOp in test

Co-authored-by: Zhang Zhuo <[email protected]>
  • Loading branch information
DreamWuGit and lispc authored May 3, 2022
1 parent 1642b95 commit a0cc988
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 9 deletions.
52 changes: 49 additions & 3 deletions bus-mapping/src/evm/opcodes/sstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ impl Opcode for Sstore {
value: Word::from(state.tx_ctx.id()),
},
);
state.push_op(
&mut exec_step,
RW::READ,
CallContextOp {
call_id: state.call()?.call_id,
field: CallContextField::IsStatic,
value: Word::from(state.call()?.is_static as u8),
},
);
state.push_op(
&mut exec_step,
RW::READ,
Expand Down Expand Up @@ -187,7 +196,44 @@ mod sstore_tests {
.unwrap();

assert_eq!(
[4, 5]
[0, 1, 2, 3, 4]
.map(|idx| &builder.block.container.call_context
[step.bus_mapping_instance[idx].as_usize()])
.map(|operation| (operation.rw(), operation.op())),
[
(
RW::READ,
&CallContextOp::new(1, CallContextField::TxId, Word::from(0x01)),
),
(
RW::READ,
&CallContextOp::new(1, CallContextField::IsStatic, Word::from(0x00)),
),
(
RW::READ,
&CallContextOp::new(
1,
CallContextField::RwCounterEndOfReversion,
Word::from(0x00)
),
),
(
RW::READ,
&CallContextOp::new(1, CallContextField::IsPersistent, Word::from(0x01)),
),
(
RW::READ,
&CallContextOp::new(
1,
CallContextField::CalleeAddress,
MOCK_ACCOUNTS[0].to_word(),
),
),
]
);

assert_eq!(
[5, 6]
.map(|idx| &builder.block.container.stack[step.bus_mapping_instance[idx].as_usize()])
.map(|operation| (operation.rw(), operation.op())),
[
Expand All @@ -202,7 +248,7 @@ mod sstore_tests {
]
);

let storage_op = &builder.block.container.storage[step.bus_mapping_instance[6].as_usize()];
let storage_op = &builder.block.container.storage[step.bus_mapping_instance[7].as_usize()];
assert_eq!(
(storage_op.rw(), storage_op.op()),
(
Expand All @@ -217,7 +263,7 @@ mod sstore_tests {
)
)
);
let refund_op = &builder.block.container.tx_refund[step.bus_mapping_instance[8].as_usize()];
let refund_op = &builder.block.container.tx_refund[step.bus_mapping_instance[9].as_usize()];
assert_eq!(
(refund_op.rw(), refund_op.op()),
(
Expand Down
28 changes: 27 additions & 1 deletion bus-mapping/src/operation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ impl fmt::Debug for StackOp {
}

impl StackOp {
/// Create a new instance of a `MemoryOp` from it's components.
/// Create a new instance of a `StackOp` from it's components.
pub const fn new(call_id: usize, address: StackAddress, value: Word) -> StackOp {
StackOp {
call_id,
Expand Down Expand Up @@ -734,6 +734,32 @@ impl Op for CallContextOp {
}
}

impl CallContextOp {
/// Create a new instance of a `CallContextOp` from it's components.
pub const fn new(call_id: usize, field: CallContextField, value: Word) -> CallContextOp {
CallContextOp {
call_id,
field,
value,
}
}

/// Returns the [`Target`] (operation type) of this operation.
pub const fn target(&self) -> Target {
Target::CallContext
}

/// Returns the call id associated to this Operation.
pub const fn call_id(&self) -> usize {
self.call_id
}

/// Returns the [`Word`] read or written by this operation.
pub const fn value(&self) -> &Word {
&self.value
}
}

/// Generic enum that wraps over all the operation types possible.
/// In particular [`StackOp`], [`MemoryOp`] and [`StorageOp`].
#[derive(Debug, Clone)]
Expand Down
19 changes: 14 additions & 5 deletions zkevm-circuits/src/evm_circuit/execution/sstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use halo2_proofs::{
pub(crate) struct SstoreGadget<F> {
same_context: SameContextGadget<F>,
tx_id: Cell<F>,
is_static: Cell<F>,
reversion_info: ReversionInfo<F>,
callee_address: Cell<F>,
key: Cell<F>,
Expand All @@ -47,6 +48,11 @@ impl<F: Field> ExecutionGadget<F> for SstoreGadget<F> {
let opcode = cb.query_cell();

let tx_id = cb.call_context(None, CallContextFieldTag::TxId);

// constrain not in static call
let is_static = cb.call_context(None, CallContextFieldTag::IsStatic);
cb.require_zero("is_static is false", is_static.expr());

let mut reversion_info = cb.reversion_info(None);
let callee_address = cb.call_context(None, CallContextFieldTag::CalleeAddress);

Expand Down Expand Up @@ -104,7 +110,7 @@ impl<F: Field> ExecutionGadget<F> for SstoreGadget<F> {
);

let step_state_transition = StepStateTransition {
rw_counter: Delta(9.expr()),
rw_counter: Delta(10.expr()),
program_counter: Delta(1.expr()),
stack_pointer: Delta(2.expr()),
reversible_write_counter: Delta(3.expr()),
Expand All @@ -116,6 +122,7 @@ impl<F: Field> ExecutionGadget<F> for SstoreGadget<F> {
Self {
same_context,
tx_id,
is_static,
reversion_info,
callee_address,
key,
Expand All @@ -142,6 +149,8 @@ impl<F: Field> ExecutionGadget<F> for SstoreGadget<F> {

self.tx_id
.assign(region, offset, Some(F::from(tx.id as u64)))?;
self.is_static
.assign(region, offset, Some(F::from(call.is_static as u64)))?;
self.reversion_info.assign(
region,
offset,
Expand All @@ -152,7 +161,7 @@ impl<F: Field> ExecutionGadget<F> for SstoreGadget<F> {
.assign(region, offset, call.callee_address.to_scalar())?;

let [key, value] =
[step.rw_indices[4], step.rw_indices[5]].map(|idx| block.rws[idx].stack_value());
[step.rw_indices[5], step.rw_indices[6]].map(|idx| block.rws[idx].stack_value());
self.key.assign(
region,
offset,
Expand All @@ -170,7 +179,7 @@ impl<F: Field> ExecutionGadget<F> for SstoreGadget<F> {
)),
)?;

let (_, value_prev, _, original_value) = block.rws[step.rw_indices[6]].storage_value_aux();
let (_, value_prev, _, original_value) = block.rws[step.rw_indices[7]].storage_value_aux();
self.value_prev.assign(
region,
offset,
Expand All @@ -188,11 +197,11 @@ impl<F: Field> ExecutionGadget<F> for SstoreGadget<F> {
)),
)?;

let (_, is_warm) = block.rws[step.rw_indices[7]].tx_access_list_value_pair();
let (_, is_warm) = block.rws[step.rw_indices[8]].tx_access_list_value_pair();
self.is_warm
.assign(region, offset, Some(F::from(is_warm as u64)))?;

let (tx_refund, tx_refund_prev) = block.rws[step.rw_indices[8]].tx_refund_value_pair();
let (tx_refund, tx_refund_prev) = block.rws[step.rw_indices[9]].tx_refund_value_pair();
self.tx_refund_prev
.assign(region, offset, Some(F::from(tx_refund_prev)))?;

Expand Down

0 comments on commit a0cc988

Please sign in to comment.