Skip to content
This repository was archived by the owner on Jul 5, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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(
Comment thread
DreamWuGit marked this conversation as resolved.
&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!(
Comment thread
DreamWuGit marked this conversation as resolved.
[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