From f00aaee5b091a0dff623041b64e8e96d822a2231 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Sun, 13 Feb 2022 16:44:19 +0800 Subject: [PATCH 01/39] update --- zkevm-circuits/src/evm_circuit/execution.rs | 5 + .../src/evm_circuit/execution/storage.rs | 3 + .../evm_circuit/execution/storage/sload.rs | 385 ++++++++++++++++++ .../evm_circuit/util/constraint_builder.rs | 53 +++ zkevm-circuits/src/evm_circuit/witness.rs | 82 ++++ 5 files changed, 528 insertions(+) create mode 100644 zkevm-circuits/src/evm_circuit/execution/storage.rs create mode 100644 zkevm-circuits/src/evm_circuit/execution/storage/sload.rs diff --git a/zkevm-circuits/src/evm_circuit/execution.rs b/zkevm-circuits/src/evm_circuit/execution.rs index 4db5031865..a6cc84df17 100644 --- a/zkevm-circuits/src/evm_circuit/execution.rs +++ b/zkevm-circuits/src/evm_circuit/execution.rs @@ -37,6 +37,7 @@ mod push; mod signed_comparator; mod signextend; mod stop; +mod storage; mod swap; mod timestamp; @@ -61,6 +62,7 @@ use push::PushGadget; use signed_comparator::SignedComparatorGadget; use signextend::SignextendGadget; use stop::StopGadget; +use storage::SloadGadget; use swap::SwapGadget; use timestamp::TimestampGadget; @@ -111,6 +113,7 @@ pub(crate) struct ExecutionConfig { msize_gadget: MsizeGadget, coinbase_gadget: CoinbaseGadget, timestamp_gadget: TimestampGadget, + sload_gadget: SloadGadget, } impl ExecutionConfig { @@ -239,6 +242,7 @@ impl ExecutionConfig { msize_gadget: configure_gadget!(), coinbase_gadget: configure_gadget!(), timestamp_gadget: configure_gadget!(), + sload_gadget: configure_gadget!(), step: step_curr, presets_map, }; @@ -489,6 +493,7 @@ impl ExecutionConfig { ExecutionState::TIMESTAMP => { assign_exec_step!(self.timestamp_gadget) } + ExecutionState::SLOAD => assign_exec_step!(self.sload_gadget), ExecutionState::ErrorOutOfGasPureMemory => { assign_exec_step!(self.error_oog_pure_memory_gadget) } diff --git a/zkevm-circuits/src/evm_circuit/execution/storage.rs b/zkevm-circuits/src/evm_circuit/execution/storage.rs new file mode 100644 index 0000000000..b93c20808e --- /dev/null +++ b/zkevm-circuits/src/evm_circuit/execution/storage.rs @@ -0,0 +1,3 @@ +mod sload; + +pub(crate) use sload::SloadGadget; diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs new file mode 100644 index 0000000000..843169a4a4 --- /dev/null +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs @@ -0,0 +1,385 @@ +use crate::{ + evm_circuit::{ + execution::ExecutionGadget, + param::STACK_CAPACITY, + step::ExecutionState, + table::{AccountFieldTag, CallContextFieldTag, TxContextFieldTag}, + util::{ + common_gadget::{SameContextGadget, TransferWithGasFeeGadget}, + constraint_builder::{ + ConstraintBuilder, StepStateTransition, + Transition::{Delta, To}, + }, + math_gadget::{MulWordByU64Gadget, RangeCheckGadget}, + select, Cell, RandomLinearCombination, Word, + }, + witness::{Block, Call, ExecStep, Transaction}, + }, + util::Expr, +}; +use eth_types::{evm_types::GasCost, ToLittleEndian, ToScalar}; +use halo2::{ + arithmetic::FieldExt, + circuit::Region, + plonk::{Error, Expression}, +}; + +#[derive(Clone, Debug)] +pub(crate) struct SloadGadget { + same_context: SameContextGadget, + call_id: Cell, + tx_id: Cell, + rw_counter_end_of_reversion: Cell, + is_persistent: Cell, + callee_address: Cell, + key: Word, + value: Word, + committed_value: Word, + is_warm: Cell, +} + +impl ExecutionGadget for SloadGadget { + const NAME: &'static str = "SLOAD"; + + const EXECUTION_STATE: ExecutionState = ExecutionState::SLOAD; + + fn configure(cb: &mut ConstraintBuilder) -> Self { + let opcode = cb.query_cell(); + + let call_id = cb.query_cell(); + let [tx_id, rw_counter_end_of_reversion, is_persistent, callee_address] = [ + CallContextFieldTag::TxId, + CallContextFieldTag::RwCounterEndOfReversion, + CallContextFieldTag::IsPersistent, + CallContextFieldTag::CalleeAddress, + ] + .map(|field_tag| cb.call_context(Some(call_id.expr()), field_tag)); + + let key = cb.query_word(); + // Pop the key from the stack + cb.stack_pop(key.expr()); + + let value = cb.query_word(); + let committed_value = cb.query_word(); + cb.account_storage_read( + callee_address.expr(), + key.expr(), + value.expr(), + tx_id.expr(), + committed_value.expr(), + ); + + let is_warm = cb.query_bool(); + cb.account_storage_access_list_write_with_reversion( + tx_id.expr(), + callee_address.expr(), + key.expr(), + true.expr(), + is_warm.expr(), + is_persistent.expr(), + rw_counter_end_of_reversion.expr(), + ); + + cb.stack_push(value.expr()); + + let step_state_transition = StepStateTransition { + rw_counter: Delta(8.expr()), + program_counter: Delta(1.expr()), + state_write_counter: To(1.expr()), + ..Default::default() + }; + let gas_cost = SloadGasGadget::construct(cb, is_warm.expr()); + let same_context = + SameContextGadget::construct(cb, opcode, step_state_transition, Some(gas_cost.expr())); + + Self { + same_context: same_context, + call_id: call_id, + tx_id: tx_id, + rw_counter_end_of_reversion: rw_counter_end_of_reversion, + is_persistent: is_persistent, + callee_address: callee_address, + key: key, + value: value, + committed_value: committed_value, + is_warm: is_warm, + } + } + + fn assign_exec_step( + &self, + region: &mut Region<'_, F>, + offset: usize, + block: &Block, + tx: &Transaction, + call: &Call, + step: &ExecStep, + ) -> Result<(), Error> { + self.same_context.assign_exec_step(region, offset, step)?; + + self.call_id + .assign(region, offset, Some(F::from(call.id as u64)))?; + + self.tx_id + .assign(region, offset, Some(F::from(tx.id as u64)))?; + self.rw_counter_end_of_reversion.assign( + region, + offset, + Some(F::from(call.rw_counter_end_of_reversion as u64)), + )?; + self.is_persistent + .assign(region, offset, Some(F::from(call.is_persistent as u64)))?; + self.callee_address + .assign(region, offset, call.callee_address.to_scalar())?; + + let [key, value] = + [step.rw_indices[4], step.rw_indices[7]].map(|idx| block.rws[idx].stack_value()); + self.key.assign(region, offset, Some(key.to_le_bytes()))?; + self.value + .assign(region, offset, Some(value.to_le_bytes()))?; + + let (_, committed_value) = block.rws[step.rw_indices[5]].aux_pair(); + self.committed_value + .assign(region, offset, Some(committed_value.to_le_bytes()))?; + + let (_, is_warm) = block.rws[step.rw_indices[6]].accesslist_value_pair(); + self.is_warm + .assign(region, offset, Some(F::from(is_warm as u64)))?; + + Ok(()) + } +} + +#[derive(Clone, Debug)] +pub(crate) struct SloadGasGadget { + is_warm: Expression, + gas_cost: Expression, +} + +impl SloadGasGadget { + pub(crate) fn construct(cb: &mut ConstraintBuilder, is_warm: Expression) -> Self { + let gas_cost = select::expr( + is_warm.expr(), + GasCost::WARM_STORAGE_READ_COST.expr(), + GasCost::COLD_SLOAD_COST.expr(), + ); + + Self { + is_warm: is_warm, + gas_cost: gas_cost, + } + } + + pub(crate) fn expr(&self) -> Expression { + // Return the gas cost + self.gas_cost.clone() + } +} + +#[cfg(test)] +mod test { + use crate::evm_circuit::{ + param::STACK_CAPACITY, + step::ExecutionState, + table::CallContextFieldTag, + test::{rand_fp, rand_word, run_test_circuit_incomplete_fixed_table}, + util::RandomLinearCombination, + witness::{self, Block, Bytecode, Call, ExecStep, Rw, Transaction}, + }; + use crate::test_util::run_test_circuits; + use bus_mapping::evm::OpcodeId; + use eth_types::{address, bytecode, evm_types::GasCost, Address, ToLittleEndian, ToWord, Word}; + use std::convert::TryInto; + + fn test_ok(tx: eth_types::Transaction, key: Word, value: Word, is_warm: bool, result: bool) { + let rw_counter_end_of_reversion = if result { 0 } else { 19 }; + + let call_data_gas_cost = tx + .input + .0 + .iter() + .fold(0, |acc, byte| acc + if *byte == 0 { 4 } else { 16 }); + + let randomness = rand_fp(); + let bytecode = Bytecode::from(&bytecode! { + // TODO: SSTORE first + PUSH32(key) + #[start] + SLOAD + STOP + }); + let block = Block { + randomness, + txs: vec![Transaction { + id: 1, + nonce: tx.nonce.try_into().unwrap(), + gas: tx.gas.try_into().unwrap(), + gas_price: tx.gas_price.unwrap_or_else(Word::zero), + caller_address: tx.from, + callee_address: tx.to.unwrap_or_else(Address::zero), + is_create: tx.to.is_none(), + value: tx.value, + call_data: tx.input.to_vec(), + call_data_length: tx.input.0.len(), + call_data_gas_cost, + calls: vec![Call { + id: 1, + is_root: true, + is_create: false, + opcode_source: RandomLinearCombination::random_linear_combine( + bytecode.hash.to_le_bytes(), + randomness, + ), + result: Word::from(result as usize), + rw_counter_end_of_reversion, + is_persistent: result, + callee_address: tx.to.unwrap_or_else(Address::zero), + ..Default::default() + }], + steps: vec![ + ExecStep { + rw_indices: (0..8 + if result { 0 } else { 2 }).collect(), + execution_state: ExecutionState::SLOAD, + rw_counter: 9, + program_counter: 33, + stack_pointer: STACK_CAPACITY, + gas_left: if is_warm { + GasCost::WARM_STORAGE_READ_COST.as_u64() + } else { + GasCost::COLD_SLOAD_COST.as_u64() + }, + gas_cost: if is_warm { + GasCost::WARM_STORAGE_READ_COST.as_u64() + } else { + GasCost::COLD_SLOAD_COST.as_u64() + }, + opcode: Some(OpcodeId::SLOAD), + ..Default::default() + }, + ExecStep { + execution_state: ExecutionState::STOP, + rw_counter: 17, + program_counter: 34, + stack_pointer: STACK_CAPACITY, + gas_left: 0, + opcode: Some(OpcodeId::STOP), + state_write_counter: 1, + ..Default::default() + }, + ], + }], + rws: [ + vec![ + Rw::CallContext { + rw_counter: 9, + is_write: false, + call_id: 1, + field_tag: CallContextFieldTag::TxId, + value: Word::one(), + }, + Rw::CallContext { + rw_counter: 10, + is_write: false, + call_id: 1, + field_tag: CallContextFieldTag::RwCounterEndOfReversion, + value: Word::from(rw_counter_end_of_reversion), + }, + Rw::CallContext { + rw_counter: 11, + is_write: false, + call_id: 1, + field_tag: CallContextFieldTag::IsPersistent, + value: Word::from(result as u64), + }, + Rw::CallContext { + rw_counter: 12, + is_write: false, + call_id: 1, + field_tag: CallContextFieldTag::CalleeAddress, + value: tx.to.unwrap().to_word(), + }, + Rw::Stack { + rw_counter: 13, + is_write: false, + call_id: 1, + stack_pointer: STACK_CAPACITY, + value: key, + }, + Rw::AccountStorage { + rw_counter: 14, + is_write: false, + address: tx.to.unwrap(), + key: key, + value: value, + value_prev: value, + tx_id: 1, + committed_value: Word::zero(), + }, + Rw::TxAccessListAccountStorage { + rw_counter: 15, + is_write: true, + tx_id: 1, + address: tx.to.unwrap(), + key: key, + value: true, + value_prev: is_warm, + }, + Rw::Stack { + rw_counter: 16, + is_write: true, + call_id: 1, + stack_pointer: STACK_CAPACITY, + value: value, + }, + ], + if result { + vec![] + } else { + vec![Rw::TxAccessListAccountStorage { + rw_counter: 19, + is_write: true, + tx_id: 1usize, + address: tx.to.unwrap_or_else(Address::zero), + key: key, + value: is_warm, + value_prev: true, + }] + }, + ] + .concat(), + bytecodes: vec![bytecode], + ..Default::default() + }; + + assert_eq!(run_test_circuit_incomplete_fixed_table(block), Ok(())); + } + + fn mock_tx() -> eth_types::Transaction { + let from = address!("0x00000000000000000000000000000000000000fe"); + let to = address!("0x00000000000000000000000000000000000000ff"); + let minimal_gas = Word::from(21000); + eth_types::Transaction { + from, + to: Some(to), + ..Default::default() + } + } + + #[test] + fn sload_gadget_simple() { + test_ok(mock_tx(), 0x030201.into(), 0x060504.into(), true, true); + test_ok(mock_tx(), 0x030201.into(), 0x060504.into(), true, false); + test_ok(mock_tx(), 0x030201.into(), 0x060504.into(), false, true); + test_ok(mock_tx(), 0x030201.into(), 0x060504.into(), false, false); + } + + #[test] + fn sload_gadget_rand() { + let key = rand_word(); + let value = rand_word(); + test_ok(mock_tx(), key, value, true, true); + test_ok(mock_tx(), key, value, true, false); + test_ok(mock_tx(), key, value, false, true); + test_ok(mock_tx(), key, value, false, false); + } +} diff --git a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs index 8c72f21b72..b08b412078 100644 --- a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs +++ b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs @@ -536,6 +536,33 @@ impl<'a, F: FieldExt> ConstraintBuilder<'a, F> { ); } + pub(crate) fn account_storage_access_list_write_with_reversion( + &mut self, + tx_id: Expression, + account_address: Expression, + key: Expression, + value: Expression, + value_prev: Expression, + is_persistent: Expression, + rw_counter_end_of_reversion: Expression, + ) { + self.state_write_with_reversion( + "account_storage_access_list_write_with_reversion", + RwTableTag::TxAccessListAccountStorage, + [ + tx_id, + account_address, + key, + value, + value_prev, + 0.expr(), + 0.expr(), + ], + is_persistent, + rw_counter_end_of_reversion, + ); + } + // Account pub(crate) fn account_read( @@ -609,6 +636,32 @@ impl<'a, F: FieldExt> ConstraintBuilder<'a, F> { ); } + // Account Storage + + pub(crate) fn account_storage_read( + &mut self, + account_address: Expression, + key: Expression, + value: Expression, + tx_id: Expression, + committed_value: Expression, + ) { + self.rw_lookup( + "account_storage_read", + false.expr(), + RwTableTag::AccountStorage, + [ + account_address, + key, + 0.expr(), + value.clone(), + value, + tx_id, + committed_value, + ], + ); + } + // Call context pub(crate) fn call_context( diff --git a/zkevm-circuits/src/evm_circuit/witness.rs b/zkevm-circuits/src/evm_circuit/witness.rs index 7c5bdb69ab..fbb775aceb 100644 --- a/zkevm-circuits/src/evm_circuit/witness.rs +++ b/zkevm-circuits/src/evm_circuit/witness.rs @@ -377,6 +377,11 @@ pub enum Rw { TxAccessListAccountStorage { rw_counter: usize, is_write: bool, + tx_id: usize, + address: Address, + key: Word, + value: bool, + value_prev: bool, }, TxRefund { rw_counter: usize, @@ -393,6 +398,12 @@ pub enum Rw { AccountStorage { rw_counter: usize, is_write: bool, + address: Address, + key: Word, + value: Word, + value_prev: Word, + tx_id: usize, + committed_value: Word, }, AccountDestructed { rw_counter: usize, @@ -422,6 +433,18 @@ pub enum Rw { } impl Rw { + pub fn accesslist_value_pair(&self) -> (bool, bool) { + match self { + Self::TxAccessListAccount { + value, value_prev, .. + } => (*value, *value_prev), + Self::TxAccessListAccountStorage { + value, value_prev, .. + } => (*value, *value_prev), + _ => unreachable!(), + } + } + pub fn account_value_pair(&self) -> (Word, Word) { match self { Self::Account { @@ -431,6 +454,17 @@ impl Rw { } } + pub fn aux_pair(&self) -> (usize, Word) { + match self { + Self::AccountStorage { + tx_id, + committed_value, + .. + } => (*tx_id, *committed_value), + _ => unreachable!(), + } + } + pub fn stack_value(&self) -> Word { match self { Self::Stack { value, .. } => *value, @@ -459,6 +493,26 @@ impl Rw { F::zero(), F::zero(), ], + Self::TxAccessListAccountStorage { + rw_counter, + is_write, + tx_id, + address, + key, + value, + value_prev, + } => [ + F::from(*rw_counter as u64), + F::from(*is_write as u64), + F::from(RwTableTag::TxAccessListAccountStorage as u64), + F::from(*tx_id as u64), + address.to_scalar().unwrap(), + RandomLinearCombination::random_linear_combine(key.to_le_bytes(), randomness), + F::from(*value as u64), + F::from(*value_prev as u64), + F::zero(), + F::zero(), + ], Self::Account { rw_counter, is_write, @@ -487,6 +541,33 @@ impl Rw { F::zero(), ] } + Self::AccountStorage { + rw_counter, + is_write, + address, + key, + value, + value_prev, + tx_id, + committed_value, + } => [ + F::from(*rw_counter as u64), + F::from(*is_write as u64), + F::from(RwTableTag::AccountStorage as u64), + address.to_scalar().unwrap(), + RandomLinearCombination::random_linear_combine(key.to_le_bytes(), randomness), + F::zero(), + RandomLinearCombination::random_linear_combine(value.to_le_bytes(), randomness), + RandomLinearCombination::random_linear_combine( + value_prev.to_le_bytes(), + randomness, + ), + F::from(*tx_id as u64), + RandomLinearCombination::random_linear_combine( + committed_value.to_le_bytes(), + randomness, + ), + ], Self::CallContext { rw_counter, is_write, @@ -596,6 +677,7 @@ impl From<&bus_mapping::circuit_input_builder::ExecStep> for ExecutionState { OpcodeId::COINBASE => ExecutionState::COINBASE, OpcodeId::TIMESTAMP => ExecutionState::TIMESTAMP, OpcodeId::GAS => ExecutionState::GAS, + OpcodeId::SLOAD => ExecutionState::SLOAD, _ => unimplemented!("unimplemented opcode {:?}", step.op), } } From afcde83f6f1f5b6aa498cfe0cfa2bb5908d7d524 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Sun, 13 Feb 2022 16:47:20 +0800 Subject: [PATCH 02/39] fix clippy --- .../evm_circuit/execution/storage/sload.rs | 49 +++++++++---------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs index 843169a4a4..54a57af314 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs @@ -1,17 +1,15 @@ use crate::{ evm_circuit::{ execution::ExecutionGadget, - param::STACK_CAPACITY, step::ExecutionState, - table::{AccountFieldTag, CallContextFieldTag, TxContextFieldTag}, + table::CallContextFieldTag, util::{ - common_gadget::{SameContextGadget, TransferWithGasFeeGadget}, + common_gadget::SameContextGadget, constraint_builder::{ ConstraintBuilder, StepStateTransition, Transition::{Delta, To}, }, - math_gadget::{MulWordByU64Gadget, RangeCheckGadget}, - select, Cell, RandomLinearCombination, Word, + select, Cell, Word, }, witness::{Block, Call, ExecStep, Transaction}, }, @@ -93,16 +91,16 @@ impl ExecutionGadget for SloadGadget { SameContextGadget::construct(cb, opcode, step_state_transition, Some(gas_cost.expr())); Self { - same_context: same_context, - call_id: call_id, - tx_id: tx_id, - rw_counter_end_of_reversion: rw_counter_end_of_reversion, - is_persistent: is_persistent, - callee_address: callee_address, - key: key, - value: value, - committed_value: committed_value, - is_warm: is_warm, + same_context, + call_id, + tx_id, + rw_counter_end_of_reversion, + is_persistent, + callee_address, + key, + value, + committed_value, + is_warm, } } @@ -157,7 +155,7 @@ pub(crate) struct SloadGasGadget { } impl SloadGasGadget { - pub(crate) fn construct(cb: &mut ConstraintBuilder, is_warm: Expression) -> Self { + pub(crate) fn construct(_cb: &mut ConstraintBuilder, is_warm: Expression) -> Self { let gas_cost = select::expr( is_warm.expr(), GasCost::WARM_STORAGE_READ_COST.expr(), @@ -165,8 +163,8 @@ impl SloadGasGadget { ); Self { - is_warm: is_warm, - gas_cost: gas_cost, + is_warm, + gas_cost, } } @@ -184,9 +182,9 @@ mod test { table::CallContextFieldTag, test::{rand_fp, rand_word, run_test_circuit_incomplete_fixed_table}, util::RandomLinearCombination, - witness::{self, Block, Bytecode, Call, ExecStep, Rw, Transaction}, + witness::{Block, Bytecode, Call, ExecStep, Rw, Transaction}, }; - use crate::test_util::run_test_circuits; + use bus_mapping::evm::OpcodeId; use eth_types::{address, bytecode, evm_types::GasCost, Address, ToLittleEndian, ToWord, Word}; use std::convert::TryInto; @@ -309,8 +307,8 @@ mod test { rw_counter: 14, is_write: false, address: tx.to.unwrap(), - key: key, - value: value, + key, + value, value_prev: value, tx_id: 1, committed_value: Word::zero(), @@ -320,7 +318,7 @@ mod test { is_write: true, tx_id: 1, address: tx.to.unwrap(), - key: key, + key, value: true, value_prev: is_warm, }, @@ -329,7 +327,7 @@ mod test { is_write: true, call_id: 1, stack_pointer: STACK_CAPACITY, - value: value, + value, }, ], if result { @@ -340,7 +338,7 @@ mod test { is_write: true, tx_id: 1usize, address: tx.to.unwrap_or_else(Address::zero), - key: key, + key, value: is_warm, value_prev: true, }] @@ -357,7 +355,6 @@ mod test { fn mock_tx() -> eth_types::Transaction { let from = address!("0x00000000000000000000000000000000000000fe"); let to = address!("0x00000000000000000000000000000000000000ff"); - let minimal_gas = Word::from(21000); eth_types::Transaction { from, to: Some(to), From 20de4a74e302a861b14e1c34f08ad560388f1620 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Sun, 13 Feb 2022 16:51:43 +0800 Subject: [PATCH 03/39] clean up --- zkevm-circuits/src/evm_circuit/execution/storage/sload.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs index 54a57af314..7f2586393b 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs @@ -200,7 +200,6 @@ mod test { let randomness = rand_fp(); let bytecode = Bytecode::from(&bytecode! { - // TODO: SSTORE first PUSH32(key) #[start] SLOAD From ef434f4b989877e4ad07c7927004e6198f6959af Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Sun, 13 Feb 2022 16:53:22 +0800 Subject: [PATCH 04/39] cargo fmt --- zkevm-circuits/src/evm_circuit/execution/storage/sload.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs index 7f2586393b..3e33e7591f 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs @@ -162,10 +162,7 @@ impl SloadGasGadget { GasCost::COLD_SLOAD_COST.expr(), ); - Self { - is_warm, - gas_cost, - } + Self { is_warm, gas_cost } } pub(crate) fn expr(&self) -> Expression { @@ -184,7 +181,7 @@ mod test { util::RandomLinearCombination, witness::{Block, Bytecode, Call, ExecStep, Rw, Transaction}, }; - + use bus_mapping::evm::OpcodeId; use eth_types::{address, bytecode, evm_types::GasCost, Address, ToLittleEndian, ToWord, Word}; use std::convert::TryInto; From 958aa408edcd89c60c26b2e68dbfa569ff14fe69 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Sun, 13 Feb 2022 16:54:10 +0800 Subject: [PATCH 05/39] cargo clippy --- zkevm-circuits/src/evm_circuit/util/constraint_builder.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs index b08b412078..66c61ecbc2 100644 --- a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs +++ b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs @@ -536,6 +536,7 @@ impl<'a, F: FieldExt> ConstraintBuilder<'a, F> { ); } + #[allow(clippy::too_many_arguments)] pub(crate) fn account_storage_access_list_write_with_reversion( &mut self, tx_id: Expression, From 29a59f9b8c5ca9d8c2c94b600a7629a7798c528c Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Mon, 14 Feb 2022 14:05:37 +0800 Subject: [PATCH 06/39] minor --- zkevm-circuits/src/evm_circuit/execution/storage/sload.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs index 3e33e7591f..cae855dae2 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs @@ -183,7 +183,7 @@ mod test { }; use bus_mapping::evm::OpcodeId; - use eth_types::{address, bytecode, evm_types::GasCost, Address, ToLittleEndian, ToWord, Word}; + use eth_types::{address, bytecode, evm_types::GasCost, ToLittleEndian, ToWord, Word}; use std::convert::TryInto; fn test_ok(tx: eth_types::Transaction, key: Word, value: Word, is_warm: bool, result: bool) { @@ -210,7 +210,7 @@ mod test { gas: tx.gas.try_into().unwrap(), gas_price: tx.gas_price.unwrap_or_else(Word::zero), caller_address: tx.from, - callee_address: tx.to.unwrap_or_else(Address::zero), + callee_address: tx.to.unwrap(), is_create: tx.to.is_none(), value: tx.value, call_data: tx.input.to_vec(), @@ -227,7 +227,7 @@ mod test { result: Word::from(result as usize), rw_counter_end_of_reversion, is_persistent: result, - callee_address: tx.to.unwrap_or_else(Address::zero), + callee_address: tx.to.unwrap(), ..Default::default() }], steps: vec![ @@ -333,7 +333,7 @@ mod test { rw_counter: 19, is_write: true, tx_id: 1usize, - address: tx.to.unwrap_or_else(Address::zero), + address: tx.to.unwrap(), key, value: is_warm, value_prev: true, From 6555051f4421a75d2c52c0ea55339949568ae558 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Mon, 21 Feb 2022 14:46:42 +0800 Subject: [PATCH 07/39] minor --- zkevm-circuits/src/evm_circuit/execution/storage/sload.rs | 2 +- zkevm-circuits/src/evm_circuit/witness.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs index 7c86f3b4f1..ba03397780 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs @@ -140,7 +140,7 @@ impl ExecutionGadget for SloadGadget { self.committed_value .assign(region, offset, Some(committed_value.to_le_bytes()))?; - let (_, is_warm) = block.rws[step.rw_indices[6]].accesslist_value_pair(); + let (_, is_warm) = block.rws[step.rw_indices[6]].tx_access_list_value_pair(); self.is_warm .assign(region, offset, Some(F::from(is_warm as u64)))?; diff --git a/zkevm-circuits/src/evm_circuit/witness.rs b/zkevm-circuits/src/evm_circuit/witness.rs index 965fa0598c..5515d63864 100644 --- a/zkevm-circuits/src/evm_circuit/witness.rs +++ b/zkevm-circuits/src/evm_circuit/witness.rs @@ -463,7 +463,7 @@ pub enum Rw { } impl Rw { - pub fn accesslist_value_pair(&self) -> (bool, bool) { + pub fn tx_access_list_value_pair(&self) -> (bool, bool) { match self { Self::TxAccessListAccount { value, value_prev, .. From 8541fe98b9a0ed0f2b3206b1e705bb56c992af98 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Mon, 21 Feb 2022 14:46:52 +0800 Subject: [PATCH 08/39] cargo fmt --- zkevm-circuits/src/evm_circuit/witness.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/zkevm-circuits/src/evm_circuit/witness.rs b/zkevm-circuits/src/evm_circuit/witness.rs index 5515d63864..f90fb4af53 100644 --- a/zkevm-circuits/src/evm_circuit/witness.rs +++ b/zkevm-circuits/src/evm_circuit/witness.rs @@ -595,7 +595,10 @@ impl Rw { F::from(*is_write as u64), F::from(RwTableTag::AccountStorage as u64), account_address.to_scalar().unwrap(), - RandomLinearCombination::random_linear_combine(storage_key.to_le_bytes(), randomness), + RandomLinearCombination::random_linear_combine( + storage_key.to_le_bytes(), + randomness, + ), F::zero(), RandomLinearCombination::random_linear_combine(value.to_le_bytes(), randomness), RandomLinearCombination::random_linear_combine( From 9a53e704abd64d5108a937615b0cb84bf56531fa Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Mon, 21 Feb 2022 15:00:27 +0800 Subject: [PATCH 09/39] add more to StorageOp --- bus-mapping/src/operation.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/bus-mapping/src/operation.rs b/bus-mapping/src/operation.rs index be5f0f54ef..303103518d 100644 --- a/bus-mapping/src/operation.rs +++ b/bus-mapping/src/operation.rs @@ -286,14 +286,18 @@ pub struct StorageOp { pub value: Word, /// Storage Value before the operation pub value_prev: Word, + /// Transaction ID: Transaction index in the block starting at 1. + pub tx_id: usize, + /// Storage Value before the transaction + pub committed_value: Word, } impl fmt::Debug for StorageOp { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("StorageOp { ")?; f.write_fmt(format_args!( - "addr: {:?}, key: {:?}, val_prev: 0x{:x}, val: 0x{:x}", - self.address, self.key, self.value_prev, self.value, + "tx_id: {:?}, addr: {:?}, key: {:?}, committed_val: 0x{:x}, val_prev: 0x{:x}, val: 0x{:x}", + self.tx_id, self.address, self.key, self.committed_value, self.value_prev, self.value ))?; f.write_str(" }") } @@ -301,12 +305,21 @@ impl fmt::Debug for StorageOp { impl StorageOp { /// Create a new instance of a `StorageOp` from it's components. - pub const fn new(address: Address, key: Word, value: Word, value_prev: Word) -> StorageOp { + pub const fn new( + address: Address, + key: Word, + value: Word, + value_prev: Word, + tx_id: usize, + committed_value: Word, + ) -> StorageOp { StorageOp { address, key, value, value_prev, + tx_id, + committed_value, } } From a438997e98ec0ea9c8f67532de4d68f65ef2e0b7 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Mon, 21 Feb 2022 15:19:02 +0800 Subject: [PATCH 10/39] skip for now --- bus-mapping/src/evm/opcodes/sload.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bus-mapping/src/evm/opcodes/sload.rs b/bus-mapping/src/evm/opcodes/sload.rs index aa04230f93..88f7593a23 100644 --- a/bus-mapping/src/evm/opcodes/sload.rs +++ b/bus-mapping/src/evm/opcodes/sload.rs @@ -35,6 +35,8 @@ impl Opcode for Sload { stack_value_read, storage_value_read, storage_value_read, + 1usize, // TODO: tx_id. read from call_context + storage_value_read, // TODO: committed_value ), ); From 167b1c3e0a4f631ae6808e230830573961577064 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Mon, 21 Feb 2022 15:23:03 +0800 Subject: [PATCH 11/39] cargo fmt --- bus-mapping/src/evm/opcodes/sload.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bus-mapping/src/evm/opcodes/sload.rs b/bus-mapping/src/evm/opcodes/sload.rs index 88f7593a23..8ed8e49c71 100644 --- a/bus-mapping/src/evm/opcodes/sload.rs +++ b/bus-mapping/src/evm/opcodes/sload.rs @@ -35,7 +35,7 @@ impl Opcode for Sload { stack_value_read, storage_value_read, storage_value_read, - 1usize, // TODO: tx_id. read from call_context + 1usize, // TODO: tx_id. read from call_context storage_value_read, // TODO: committed_value ), ); From 2473e5bb617278c55b922c9d891750eb3effb2b0 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Mon, 21 Feb 2022 16:15:54 +0800 Subject: [PATCH 12/39] minor --- bus-mapping/src/evm/opcodes/sload.rs | 2 ++ bus-mapping/src/operation/container.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/bus-mapping/src/evm/opcodes/sload.rs b/bus-mapping/src/evm/opcodes/sload.rs index 8ed8e49c71..82448266db 100644 --- a/bus-mapping/src/evm/opcodes/sload.rs +++ b/bus-mapping/src/evm/opcodes/sload.rs @@ -102,6 +102,8 @@ mod sload_tests { Word::from(0x0u32), Word::from(0x6fu32), Word::from(0x6fu32), + 1usize, + Word::from(0x6fu32), ), ); // Add StackOp associated to the stack push. diff --git a/bus-mapping/src/operation/container.rs b/bus-mapping/src/operation/container.rs index e1d673faad..90a4310018 100644 --- a/bus-mapping/src/operation/container.rs +++ b/bus-mapping/src/operation/container.rs @@ -191,6 +191,8 @@ mod container_test { Word::default(), Word::from(0x1), Word::default(), + 1usize, + Word::default(), ), ); let stack_ref = operation_container.insert(stack_operation.clone()); From e087cf90b40a9ccbb656f4fdb069399785bda3f1 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Mon, 21 Feb 2022 16:56:41 +0800 Subject: [PATCH 13/39] minor --- .../src/evm_circuit/execution/storage/sload.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs index ba03397780..c91efb6fb3 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs @@ -302,8 +302,8 @@ mod test { Rw::AccountStorage { rw_counter: 14, is_write: false, - address: tx.to.unwrap(), - key, + account_address: tx.to.unwrap(), + storage_key: key, value, value_prev: value, tx_id: 1, @@ -313,8 +313,8 @@ mod test { rw_counter: 15, is_write: true, tx_id: 1, - address: tx.to.unwrap(), - key, + account_address: tx.to.unwrap(), + storage_key: key, value: true, value_prev: is_warm, }, @@ -333,8 +333,8 @@ mod test { rw_counter: 19, is_write: true, tx_id: 1usize, - address: tx.to.unwrap(), - key, + account_address: tx.to.unwrap(), + storage_key: key, value: is_warm, value_prev: true, }] From 43bee1eb57d60f76b4f04569db543faf97ae0118 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Mon, 21 Feb 2022 17:02:25 +0800 Subject: [PATCH 14/39] minor --- .../src/evm_circuit/execution/storage/sload.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs index c91efb6fb3..1000f7731d 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs @@ -179,7 +179,7 @@ mod test { table::CallContextFieldTag, test::{rand_fp, rand_word, run_test_circuit_incomplete_fixed_table}, util::RandomLinearCombination, - witness::{Block, Bytecode, Call, ExecStep, Rw, Transaction}, + witness::{Block, Bytecode, Call, CodeSource, ExecStep, Rw, Transaction}, }; use bus_mapping::evm::OpcodeId; @@ -220,13 +220,10 @@ mod test { id: 1, is_root: true, is_create: false, - opcode_source: RandomLinearCombination::random_linear_combine( - bytecode.hash.to_le_bytes(), - randomness, - ), - result: Word::from(result as usize), + code_source: CodeSource::Account(bytecode.hash), rw_counter_end_of_reversion, is_persistent: result, + is_success: result, callee_address: tx.to.unwrap(), ..Default::default() }], From 191c86fbe0cddf8f37d808b74ccdfa3380fa9ca1 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Mon, 21 Feb 2022 20:47:38 +0800 Subject: [PATCH 15/39] minor --- zkevm-circuits/src/state_circuit/state.rs | 30 +++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/zkevm-circuits/src/state_circuit/state.rs b/zkevm-circuits/src/state_circuit/state.rs index 7963311c88..218582e7fb 100644 --- a/zkevm-circuits/src/state_circuit/state.rs +++ b/zkevm-circuits/src/state_circuit/state.rs @@ -1362,6 +1362,8 @@ mod tests { Word::from(0x40), Word::from(32), Word::from(0), + 1usize, + Word::from(0), ), ); let storage_op_1 = Operation::new( @@ -1372,6 +1374,8 @@ mod tests { Word::from(0x40), Word::from(32), Word::from(32), + 1usize, + Word::from(32), ), ); let storage_op_2 = Operation::new( @@ -1382,6 +1386,8 @@ mod tests { Word::from(0x40), Word::from(32), Word::from(32), + 1usize, + Word::from(32), ), ); @@ -1520,6 +1526,8 @@ mod tests { Word::from(0x40), Word::from(32), Word::from(0), + 1usize, + Word::from(0), ), ); let storage_op_1 = Operation::new( @@ -1532,6 +1540,8 @@ mod tests { Word::from(0x41), Word::from(32), Word::from(0), + 1usize, + Word::from(0), ), ); @@ -1547,6 +1557,8 @@ mod tests { have two conditions met. */ Word::from(32), Word::from(0), + 1usize, + Word::from(0), ), ); @@ -1741,6 +1753,8 @@ mod tests { Word::from(0x40), Word::from(32), Word::from(0), + 1usize, + Word::from(0), ), ); let storage_op_1 = Operation::new( @@ -1751,6 +1765,8 @@ mod tests { Word::from(0x40), Word::from(32), Word::from(0), + 1usize, + Word::from(0), ), ); let storage_op_2 = Operation::new( @@ -1764,6 +1780,8 @@ mod tests { Word::from(0x40), Word::from(32), Word::from(0), + 1usize, + Word::from(0), ), ); let storage_op_3 = Operation::new( @@ -1776,6 +1794,8 @@ mod tests { Word::from(0x41), Word::from(32), Word::from(32), + 1usize, + Word::from(32), ), ); @@ -1790,6 +1810,8 @@ mod tests { Word::from(0x41), Word::from(32), Word::from(0), + 1usize, + Word::from(0), ), ); @@ -1882,6 +1904,8 @@ mod tests { Word::from(0x40), Word::from(32), Word::from(0), + 1usize, + Word::from(0), ), ); let storage_op_1 = Operation::new( @@ -1895,6 +1919,8 @@ mod tests { * value as in the previous * row. */ Word::from(0), + 1usize, + Word::from(0), ), ); let storage_op_2 = Operation::new( @@ -1907,6 +1933,8 @@ mod tests { Word::from(0), /* Fails because not the same * as value in the previous row - note: this * is WRITE. */ + 1usize, + Word::from(0), ), ); let storage_op_3 = Operation::new( @@ -1919,6 +1947,8 @@ mod tests { Word::from(1), /* Fails because not the same * as value_prev in the previous row - note: * this is READ. */ + 1usize, + Word::from(1), ), ); From 5250724822f4a8688cf728a0ca4000decd9b5b89 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Mon, 21 Feb 2022 21:10:04 +0800 Subject: [PATCH 16/39] minor --- .../evm_circuit/execution/storage/sload.rs | 277 +++++++++++++----- 1 file changed, 196 insertions(+), 81 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs index 1000f7731d..e1024cf6da 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs @@ -176,10 +176,10 @@ mod test { use crate::evm_circuit::{ param::STACK_CAPACITY, step::ExecutionState, - table::CallContextFieldTag, + table::{CallContextFieldTag, RwTableTag}, test::{rand_fp, rand_word, run_test_circuit_incomplete_fixed_table}, util::RandomLinearCombination, - witness::{Block, Bytecode, Call, CodeSource, ExecStep, Rw, Transaction}, + witness::{Block, Bytecode, Call, CodeSource, ExecStep, Rw, RwMap, Transaction}, }; use bus_mapping::evm::OpcodeId; @@ -259,85 +259,200 @@ mod test { }, ], }], - rws: [ - vec![ - Rw::CallContext { - rw_counter: 9, - is_write: false, - call_id: 1, - field_tag: CallContextFieldTag::TxId, - value: Word::one(), - }, - Rw::CallContext { - rw_counter: 10, - is_write: false, - call_id: 1, - field_tag: CallContextFieldTag::RwCounterEndOfReversion, - value: Word::from(rw_counter_end_of_reversion), - }, - Rw::CallContext { - rw_counter: 11, - is_write: false, - call_id: 1, - field_tag: CallContextFieldTag::IsPersistent, - value: Word::from(result as u64), - }, - Rw::CallContext { - rw_counter: 12, - is_write: false, - call_id: 1, - field_tag: CallContextFieldTag::CalleeAddress, - value: tx.to.unwrap().to_word(), - }, - Rw::Stack { - rw_counter: 13, - is_write: false, - call_id: 1, - stack_pointer: STACK_CAPACITY, - value: key, - }, - Rw::AccountStorage { - rw_counter: 14, - is_write: false, - account_address: tx.to.unwrap(), - storage_key: key, - value, - value_prev: value, - tx_id: 1, - committed_value: Word::zero(), - }, - Rw::TxAccessListAccountStorage { - rw_counter: 15, - is_write: true, - tx_id: 1, - account_address: tx.to.unwrap(), - storage_key: key, - value: true, - value_prev: is_warm, - }, - Rw::Stack { - rw_counter: 16, - is_write: true, - call_id: 1, - stack_pointer: STACK_CAPACITY, - value, - }, - ], - if result { - vec![] - } else { - vec![Rw::TxAccessListAccountStorage { - rw_counter: 19, - is_write: true, - tx_id: 1usize, - account_address: tx.to.unwrap(), - storage_key: key, - value: is_warm, - value_prev: true, - }] - }, - ] - .concat(), + rws: RwMap( + [ + ( + RwTableTag::TxAccessListAccount, + vec![ + // Rw::TxAccessListAccount { + // rw_counter: 5, + // is_write: true, + // tx_id: 1, + // account_address: tx.from, + // value: true, + // value_prev: false, + // }, + // Rw::TxAccessListAccount { + // rw_counter: 6, + // is_write: true, + // tx_id: 1, + // account_address: tx.to.unwrap(), + // value: true, + // value_prev: false, + // }, + ], + ), + ( + RwTableTag::Account, + [ + vec![ + // Rw::Account { + // rw_counter: 4, + // is_write: true, + // account_address: tx.from, + // field_tag: AccountFieldTag::Nonce, + // value: tx.nonce + Word::one(), + // value_prev: tx.nonce, + // }, + // Rw::Account { + // rw_counter: 7, + // is_write: true, + // account_address: tx.from, + // field_tag: AccountFieldTag::Balance, + // value: from_balance, + // value_prev: from_balance_prev, + // }, + // Rw::Account { + // rw_counter: 8, + // is_write: true, + // account_address: tx.to.unwrap_or_else(Address::zero), + // field_tag: AccountFieldTag::Balance, + // value: to_balance, + // value_prev: to_balance_prev, + // }, + // Rw::Account { + // rw_counter: 9, + // is_write: false, + // account_address: tx.to.unwrap_or_else(Address::zero), + // field_tag: AccountFieldTag::CodeHash, + // value: bytecode.hash, + // value_prev: bytecode.hash, + // }, + ], + if result { + vec![] + } else { + vec![ + // Rw::Account { + // rw_counter: rw_counter_end_of_reversion - 1, + // is_write: true, + // account_address: tx.to.unwrap_or_else(Address::zero), + // field_tag: AccountFieldTag::Balance, + // value: to_balance_prev, + // value_prev: to_balance, + // }, + // Rw::Account { + // rw_counter: rw_counter_end_of_reversion, + // is_write: true, + // account_address: tx.from, + // field_tag: AccountFieldTag::Balance, + // value: from_balance_prev, + // value_prev: from_balance, + // }, + ] + }, + ] + .concat(), + ), + ( + RwTableTag::CallContext, + vec![ + Rw::CallContext { + rw_counter: 1, + is_write: false, + call_id: 1, + field_tag: CallContextFieldTag::TxId, + value: Word::one(), + }, + Rw::CallContext { + rw_counter: 2, + is_write: false, + call_id: 1, + field_tag: CallContextFieldTag::RwCounterEndOfReversion, + value: Word::from(rw_counter_end_of_reversion), + }, + Rw::CallContext { + rw_counter: 3, + is_write: false, + call_id: 1, + field_tag: CallContextFieldTag::IsPersistent, + value: Word::from(result as u64), + }, + ], + ), + ] + .into(), + ), + + // rws: [ + // vec![ + // Rw::CallContext { + // rw_counter: 9, + // is_write: false, + // call_id: 1, + // field_tag: CallContextFieldTag::TxId, + // value: Word::one(), + // }, + // Rw::CallContext { + // rw_counter: 10, + // is_write: false, + // call_id: 1, + // field_tag: CallContextFieldTag::RwCounterEndOfReversion, + // value: Word::from(rw_counter_end_of_reversion), + // }, + // Rw::CallContext { + // rw_counter: 11, + // is_write: false, + // call_id: 1, + // field_tag: CallContextFieldTag::IsPersistent, + // value: Word::from(result as u64), + // }, + // Rw::CallContext { + // rw_counter: 12, + // is_write: false, + // call_id: 1, + // field_tag: CallContextFieldTag::CalleeAddress, + // value: tx.to.unwrap().to_word(), + // }, + // Rw::Stack { + // rw_counter: 13, + // is_write: false, + // call_id: 1, + // stack_pointer: STACK_CAPACITY, + // value: key, + // }, + // Rw::AccountStorage { + // rw_counter: 14, + // is_write: false, + // account_address: tx.to.unwrap(), + // storage_key: key, + // value, + // value_prev: value, + // tx_id: 1, + // committed_value: Word::zero(), + // }, + // Rw::TxAccessListAccountStorage { + // rw_counter: 15, + // is_write: true, + // tx_id: 1, + // account_address: tx.to.unwrap(), + // storage_key: key, + // value: true, + // value_prev: is_warm, + // }, + // Rw::Stack { + // rw_counter: 16, + // is_write: true, + // call_id: 1, + // stack_pointer: STACK_CAPACITY, + // value, + // }, + // ], + // if result { + // vec![] + // } else { + // vec![Rw::TxAccessListAccountStorage { + // rw_counter: 19, + // is_write: true, + // tx_id: 1usize, + // account_address: tx.to.unwrap(), + // storage_key: key, + // value: is_warm, + // value_prev: true, + // }] + // }, + // ] + // .concat(), bytecodes: vec![bytecode], ..Default::default() }; From bb21899df26e54c294eaf847fa3ad334a847e943 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Mon, 21 Feb 2022 21:29:31 +0800 Subject: [PATCH 17/39] minor --- .../evm_circuit/execution/storage/sload.rs | 212 +++++------------- 1 file changed, 59 insertions(+), 153 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs index e1024cf6da..5643fa9073 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs @@ -262,84 +262,63 @@ mod test { rws: RwMap( [ ( - RwTableTag::TxAccessListAccount, + RwTableTag::Stack, vec![ - // Rw::TxAccessListAccount { - // rw_counter: 5, - // is_write: true, - // tx_id: 1, - // account_address: tx.from, - // value: true, - // value_prev: false, - // }, - // Rw::TxAccessListAccount { - // rw_counter: 6, - // is_write: true, - // tx_id: 1, - // account_address: tx.to.unwrap(), - // value: true, - // value_prev: false, - // }, + Rw::Stack { + rw_counter: 13, + is_write: false, + call_id: 1, + stack_pointer: STACK_CAPACITY, + value: key, + }, + Rw::Stack { + rw_counter: 16, + is_write: true, + call_id: 1, + stack_pointer: STACK_CAPACITY, + value, + }, + ], + ), + ( + RwTableTag::AccountStorage, + vec![ + Rw::AccountStorage { + rw_counter: 14, + is_write: false, + account_address: tx.to.unwrap(), + storage_key: key, + value, + value_prev: value, + tx_id: 1, + committed_value: Word::zero(), + }, ], ), ( - RwTableTag::Account, + RwTableTag::TxAccessListAccountStorage, [ - vec![ - // Rw::Account { - // rw_counter: 4, - // is_write: true, - // account_address: tx.from, - // field_tag: AccountFieldTag::Nonce, - // value: tx.nonce + Word::one(), - // value_prev: tx.nonce, - // }, - // Rw::Account { - // rw_counter: 7, - // is_write: true, - // account_address: tx.from, - // field_tag: AccountFieldTag::Balance, - // value: from_balance, - // value_prev: from_balance_prev, - // }, - // Rw::Account { - // rw_counter: 8, - // is_write: true, - // account_address: tx.to.unwrap_or_else(Address::zero), - // field_tag: AccountFieldTag::Balance, - // value: to_balance, - // value_prev: to_balance_prev, - // }, - // Rw::Account { - // rw_counter: 9, - // is_write: false, - // account_address: tx.to.unwrap_or_else(Address::zero), - // field_tag: AccountFieldTag::CodeHash, - // value: bytecode.hash, - // value_prev: bytecode.hash, - // }, - ], + vec![Rw::TxAccessListAccountStorage { + rw_counter: 15, + is_write: true, + tx_id: 1, + account_address: tx.to.unwrap(), + storage_key: key, + value: true, + value_prev: is_warm, + }], if result { vec![] } else { - vec![ - // Rw::Account { - // rw_counter: rw_counter_end_of_reversion - 1, - // is_write: true, - // account_address: tx.to.unwrap_or_else(Address::zero), - // field_tag: AccountFieldTag::Balance, - // value: to_balance_prev, - // value_prev: to_balance, - // }, - // Rw::Account { - // rw_counter: rw_counter_end_of_reversion, - // is_write: true, - // account_address: tx.from, - // field_tag: AccountFieldTag::Balance, - // value: from_balance_prev, - // value_prev: from_balance, - // }, - ] + vec![Rw::TxAccessListAccountStorage { + rw_counter: rw_counter_end_of_reversion, + is_write: true, + tx_id: 1usize, + account_address: tx.to.unwrap(), + storage_key: key, + value: is_warm, + value_prev: true, + }] }, ] .concat(), @@ -348,111 +327,38 @@ mod test { RwTableTag::CallContext, vec![ Rw::CallContext { - rw_counter: 1, + rw_counter: 9, is_write: false, call_id: 1, field_tag: CallContextFieldTag::TxId, value: Word::one(), }, Rw::CallContext { - rw_counter: 2, + rw_counter: 10, is_write: false, call_id: 1, field_tag: CallContextFieldTag::RwCounterEndOfReversion, value: Word::from(rw_counter_end_of_reversion), }, Rw::CallContext { - rw_counter: 3, + rw_counter: 11, is_write: false, call_id: 1, field_tag: CallContextFieldTag::IsPersistent, value: Word::from(result as u64), }, + Rw::CallContext { + rw_counter: 12, + is_write: false, + call_id: 1, + field_tag: CallContextFieldTag::CalleeAddress, + value: tx.to.unwrap().to_word(), + }, ], ), ] .into(), ), - - // rws: [ - // vec![ - // Rw::CallContext { - // rw_counter: 9, - // is_write: false, - // call_id: 1, - // field_tag: CallContextFieldTag::TxId, - // value: Word::one(), - // }, - // Rw::CallContext { - // rw_counter: 10, - // is_write: false, - // call_id: 1, - // field_tag: CallContextFieldTag::RwCounterEndOfReversion, - // value: Word::from(rw_counter_end_of_reversion), - // }, - // Rw::CallContext { - // rw_counter: 11, - // is_write: false, - // call_id: 1, - // field_tag: CallContextFieldTag::IsPersistent, - // value: Word::from(result as u64), - // }, - // Rw::CallContext { - // rw_counter: 12, - // is_write: false, - // call_id: 1, - // field_tag: CallContextFieldTag::CalleeAddress, - // value: tx.to.unwrap().to_word(), - // }, - // Rw::Stack { - // rw_counter: 13, - // is_write: false, - // call_id: 1, - // stack_pointer: STACK_CAPACITY, - // value: key, - // }, - // Rw::AccountStorage { - // rw_counter: 14, - // is_write: false, - // account_address: tx.to.unwrap(), - // storage_key: key, - // value, - // value_prev: value, - // tx_id: 1, - // committed_value: Word::zero(), - // }, - // Rw::TxAccessListAccountStorage { - // rw_counter: 15, - // is_write: true, - // tx_id: 1, - // account_address: tx.to.unwrap(), - // storage_key: key, - // value: true, - // value_prev: is_warm, - // }, - // Rw::Stack { - // rw_counter: 16, - // is_write: true, - // call_id: 1, - // stack_pointer: STACK_CAPACITY, - // value, - // }, - // ], - // if result { - // vec![] - // } else { - // vec![Rw::TxAccessListAccountStorage { - // rw_counter: 19, - // is_write: true, - // tx_id: 1usize, - // account_address: tx.to.unwrap(), - // storage_key: key, - // value: is_warm, - // value_prev: true, - // }] - // }, - // ] - // .concat(), bytecodes: vec![bytecode], ..Default::default() }; From c14aa0740923b6f94efdea0877c67326459e6561 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Tue, 22 Feb 2022 10:43:04 +0800 Subject: [PATCH 18/39] minor --- bus-mapping/src/evm/opcodes/sload.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bus-mapping/src/evm/opcodes/sload.rs b/bus-mapping/src/evm/opcodes/sload.rs index 82448266db..76b65a869b 100644 --- a/bus-mapping/src/evm/opcodes/sload.rs +++ b/bus-mapping/src/evm/opcodes/sload.rs @@ -35,7 +35,7 @@ impl Opcode for Sload { stack_value_read, storage_value_read, storage_value_read, - 1usize, // TODO: tx_id. read from call_context + state.tx_ctx.id(), storage_value_read, // TODO: committed_value ), ); From 69a97a0097b98a2273eef3437b74945e021cd9f0 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Tue, 22 Feb 2022 11:17:09 +0800 Subject: [PATCH 19/39] minor --- .../evm_circuit/execution/storage/sload.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs index 5643fa9073..3d688c63e5 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs @@ -229,7 +229,24 @@ mod test { }], steps: vec![ ExecStep { - rw_indices: (0..8 + if result { 0 } else { 2 }).collect(), + rw_indices: [ + vec![ + (RwTableTag::CallContext, 0), + (RwTableTag::CallContext, 1), + (RwTableTag::CallContext, 2), + (RwTableTag::CallContext, 3), + (RwTableTag::Stack, 0), + (RwTableTag::AccountStorage, 0), + (RwTableTag::Stack, 1), + (RwTableTag::TxAccessListAccountStorage, 0), + ], + if result { + vec![] + } else { + vec![(RwTableTag::TxAccessListAccountStorage, 1)] + }, + ] + .concat(), execution_state: ExecutionState::SLOAD, rw_counter: 9, program_counter: 33, From d0c03a00cf18e2ab66c2d211fc0c7603b39645e6 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Tue, 22 Feb 2022 14:22:35 +0800 Subject: [PATCH 20/39] update --- zkevm-circuits/src/evm_circuit/execution/storage/sload.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs index 3d688c63e5..ff7cc8659f 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs @@ -67,6 +67,8 @@ impl ExecutionGadget for SloadGadget { committed_value.expr(), ); + cb.stack_push(value.expr()); + let is_warm = cb.query_bool(); cb.account_storage_access_list_write_with_reversion( tx_id.expr(), @@ -78,8 +80,6 @@ impl ExecutionGadget for SloadGadget { rw_counter_end_of_reversion.expr(), ); - cb.stack_push(value.expr()); - let step_state_transition = StepStateTransition { rw_counter: Delta(8.expr()), program_counter: Delta(1.expr()), @@ -131,7 +131,7 @@ impl ExecutionGadget for SloadGadget { .assign(region, offset, call.callee_address.to_scalar())?; let [key, value] = - [step.rw_indices[4], step.rw_indices[7]].map(|idx| block.rws[idx].stack_value()); + [step.rw_indices[4], step.rw_indices[6]].map(|idx| block.rws[idx].stack_value()); self.key.assign(region, offset, Some(key.to_le_bytes()))?; self.value .assign(region, offset, Some(value.to_le_bytes()))?; @@ -140,7 +140,7 @@ impl ExecutionGadget for SloadGadget { self.committed_value .assign(region, offset, Some(committed_value.to_le_bytes()))?; - let (_, is_warm) = block.rws[step.rw_indices[6]].tx_access_list_value_pair(); + let (_, is_warm) = block.rws[step.rw_indices[7]].tx_access_list_value_pair(); self.is_warm .assign(region, offset, Some(F::from(is_warm as u64)))?; From be6fe59675cfc708ee2edd56f86cb3453c824ec9 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Tue, 22 Feb 2022 20:14:31 +0800 Subject: [PATCH 21/39] fix --- zkevm-circuits/src/evm_circuit/execution/storage/sload.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs index ff7cc8659f..0614770378 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs @@ -289,7 +289,7 @@ mod test { value: key, }, Rw::Stack { - rw_counter: 16, + rw_counter: 15, is_write: true, call_id: 1, stack_pointer: STACK_CAPACITY, @@ -316,7 +316,7 @@ mod test { RwTableTag::TxAccessListAccountStorage, [ vec![Rw::TxAccessListAccountStorage { - rw_counter: 15, + rw_counter: 16, is_write: true, tx_id: 1, account_address: tx.to.unwrap(), From d4de9bd687a0425f6792ec9042746738647035bc Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Tue, 22 Feb 2022 20:14:50 +0800 Subject: [PATCH 22/39] cargo fmt --- .../evm_circuit/execution/storage/sload.rs | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs index 0614770378..62592336c4 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs @@ -299,18 +299,16 @@ mod test { ), ( RwTableTag::AccountStorage, - vec![ - Rw::AccountStorage { - rw_counter: 14, - is_write: false, - account_address: tx.to.unwrap(), - storage_key: key, - value, - value_prev: value, - tx_id: 1, - committed_value: Word::zero(), - }, - ], + vec![Rw::AccountStorage { + rw_counter: 14, + is_write: false, + account_address: tx.to.unwrap(), + storage_key: key, + value, + value_prev: value, + tx_id: 1, + committed_value: Word::zero(), + }], ), ( RwTableTag::TxAccessListAccountStorage, From bf791940cc8f0107b7fbb6a2d4b3c9fab17a6361 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Tue, 22 Feb 2022 20:16:00 +0800 Subject: [PATCH 23/39] cargo clippy --- zkevm-circuits/src/evm_circuit/execution/storage/sload.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs index 62592336c4..2eba4034c1 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs @@ -178,12 +178,11 @@ mod test { step::ExecutionState, table::{CallContextFieldTag, RwTableTag}, test::{rand_fp, rand_word, run_test_circuit_incomplete_fixed_table}, - util::RandomLinearCombination, witness::{Block, Bytecode, Call, CodeSource, ExecStep, Rw, RwMap, Transaction}, }; use bus_mapping::evm::OpcodeId; - use eth_types::{address, bytecode, evm_types::GasCost, ToLittleEndian, ToWord, Word}; + use eth_types::{address, bytecode, evm_types::GasCost, ToWord, Word}; use std::convert::TryInto; fn test_ok(tx: eth_types::Transaction, key: Word, value: Word, is_warm: bool, result: bool) { From 2283e9700ceb5bfc6fd8f004d1f6ffe1596bc8b4 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Wed, 23 Feb 2022 13:05:18 +0800 Subject: [PATCH 24/39] fix --- zkevm-circuits/src/evm_circuit/witness.rs | 39 ++++------------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/witness.rs b/zkevm-circuits/src/evm_circuit/witness.rs index 05f586807e..8507e4b7ce 100644 --- a/zkevm-circuits/src/evm_circuit/witness.rs +++ b/zkevm-circuits/src/evm_circuit/witness.rs @@ -676,36 +676,6 @@ impl Rw { ] .into() } - Self::AccountStorage { - rw_counter, - is_write, - account_address, - storage_key, - value, - value_prev, - tx_id, - committed_value, - } => [ - F::from(*rw_counter as u64), - F::from(*is_write as u64), - F::from(RwTableTag::AccountStorage as u64), - account_address.to_scalar().unwrap(), - RandomLinearCombination::random_linear_combine( - storage_key.to_le_bytes(), - randomness, - ), - F::zero(), - RandomLinearCombination::random_linear_combine(value.to_le_bytes(), randomness), - RandomLinearCombination::random_linear_combine( - value_prev.to_le_bytes(), - randomness, - ), - F::from(*tx_id as u64), - RandomLinearCombination::random_linear_combine( - committed_value.to_le_bytes(), - randomness, - ), - ], Self::CallContext { rw_counter, is_write, @@ -779,6 +749,8 @@ impl Rw { storage_key, value, value_prev, + tx_id, + committed_value, } => [ F::from(*rw_counter as u64), F::from(*is_write as u64), @@ -794,8 +766,11 @@ impl Rw { value_prev.to_le_bytes(), randomness, ), - F::zero(), // TODO: txid - F::zero(), // TODO: committed_value + F::from(*tx_id as u64), + RandomLinearCombination::random_linear_combine( + committed_value.to_le_bytes(), + randomness, + ), ] .into(), _ => unimplemented!(), From ecaac3d971f60db61e014deeb01b47628b9b0003 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Sun, 27 Feb 2022 10:01:31 +0800 Subject: [PATCH 25/39] merge and fix conflicts --- .../src/evm_circuit/execution/storage/sload.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs index 2eba4034c1..ddc84ef964 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sload.rs @@ -15,9 +15,8 @@ use crate::{ }, util::Expr, }; -use eth_types::{evm_types::GasCost, ToLittleEndian, ToScalar}; -use halo2::{ - arithmetic::FieldExt, +use eth_types::{evm_types::GasCost, Field, ToLittleEndian, ToScalar}; +use halo2_proofs::{ circuit::Region, plonk::{Error, Expression}, }; @@ -36,7 +35,7 @@ pub(crate) struct SloadGadget { is_warm: Cell, } -impl ExecutionGadget for SloadGadget { +impl ExecutionGadget for SloadGadget { const NAME: &'static str = "SLOAD"; const EXECUTION_STATE: ExecutionState = ExecutionState::SLOAD; @@ -154,7 +153,7 @@ pub(crate) struct SloadGasGadget { gas_cost: Expression, } -impl SloadGasGadget { +impl SloadGasGadget { pub(crate) fn construct(_cb: &mut ConstraintBuilder, is_warm: Expression) -> Self { let gas_cost = select::expr( is_warm.expr(), From 3d44162d0ef6717221d8984fdc8d76807d824e22 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Sun, 27 Feb 2022 10:04:47 +0800 Subject: [PATCH 26/39] update eth-types/src/evm_types.rs --- eth-types/src/evm_types.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/eth-types/src/evm_types.rs b/eth-types/src/evm_types.rs index 29ffa3272d..f1e7cef7b2 100644 --- a/eth-types/src/evm_types.rs +++ b/eth-types/src/evm_types.rs @@ -103,6 +103,16 @@ impl GasCost { pub const COLD_ACCOUNT_ACCESS_COST: Self = Self(2600); /// Constant cost for a warm storage read pub const WARM_STORAGE_READ_COST: Self = Self(100); + + /// Constant cost for a warm storage read XXXXXX + pub const SLOAD_GAS: Self = Self(100); + /// Constant cost for a warm storage read XXXXXX + pub const SSTORE_SET_GAS: Self = Self(20000); + /// Constant cost for a warm storage read XXXXXX + pub const SSTORE_RESET_GAS: Self = Self(2900); + /// Constant cost for a warm storage read XXXXXX + pub const SSTORE_CLEARS_SCHEDULE: Self = Self(15000); + /// Constant cost for a non-creation transaction pub const TX: Self = Self(21000); /// Constant cost for creation transaction From 29f0ff9b1414fcbbac3c6aab3e540de1d0a2b3ca Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Sun, 27 Feb 2022 10:06:45 +0800 Subject: [PATCH 27/39] update zkevm-circuits/src/evm_circuit/execution.rs --- zkevm-circuits/src/evm_circuit/execution.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zkevm-circuits/src/evm_circuit/execution.rs b/zkevm-circuits/src/evm_circuit/execution.rs index 9cb4c5a45b..dcafdacf8a 100644 --- a/zkevm-circuits/src/evm_circuit/execution.rs +++ b/zkevm-circuits/src/evm_circuit/execution.rs @@ -76,6 +76,7 @@ use signed_comparator::SignedComparatorGadget; use signextend::SignextendGadget; use stop::StopGadget; use storage::SloadGadget; +use storage::SstoreGadget; use swap::SwapGadget; use timestamp::TimestampGadget; @@ -133,6 +134,7 @@ pub(crate) struct ExecutionConfig { timestamp_gadget: TimestampGadget, selfbalance_gadget: SelfbalanceGadget, sload_gadget: SloadGadget, + sstore_gadget: SstoreGadget, } impl ExecutionConfig { @@ -268,6 +270,7 @@ impl ExecutionConfig { coinbase_gadget: configure_gadget!(), timestamp_gadget: configure_gadget!(), sload_gadget: configure_gadget!(), + sstore_gadget: configure_gadget!(), step: step_curr, presets_map, }; @@ -524,6 +527,7 @@ impl ExecutionConfig { } ExecutionState::SELFBALANCE => assign_exec_step!(self.selfbalance_gadget), ExecutionState::SLOAD => assign_exec_step!(self.sload_gadget), + ExecutionState::SSTORE => assign_exec_step!(self.sstore_gadget), ExecutionState::CALLDATACOPY => { assign_exec_step!(self.calldatacopy_gadget) } From a6de4895c936daafc302834f776d7ce594815764 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Sun, 27 Feb 2022 10:07:13 +0800 Subject: [PATCH 28/39] update zkevm-circuits/src/evm_circuit/execution/storage.rs --- zkevm-circuits/src/evm_circuit/execution/storage.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage.rs b/zkevm-circuits/src/evm_circuit/execution/storage.rs index b93c20808e..e49059947d 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage.rs @@ -1,3 +1,4 @@ mod sload; pub(crate) use sload::SloadGadget; +pub(crate) use sstore::SstoreGadget; From 652da7147de40630730d37a99a4f2f9f25ec2f05 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Sun, 27 Feb 2022 10:09:35 +0800 Subject: [PATCH 29/39] update zkevm-circuits/src/evm_circuit/witness.rs --- zkevm-circuits/src/evm_circuit/witness.rs | 24 +++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/zkevm-circuits/src/evm_circuit/witness.rs b/zkevm-circuits/src/evm_circuit/witness.rs index 194158317d..adf9258bd9 100644 --- a/zkevm-circuits/src/evm_circuit/witness.rs +++ b/zkevm-circuits/src/evm_circuit/witness.rs @@ -560,6 +560,15 @@ impl Rw { } } + pub fn tx_refund_value_pair(&self) -> (Word, Word) { + match self { + Self::TxRefund { + value, value_prev, .. + } => (*value, *value_prev), + _ => unreachable!(), + } + } + pub fn account_value_pair(&self) -> (Word, Word) { match self { Self::Account { @@ -580,6 +589,20 @@ impl Rw { } } + // TODO: merge with aux_pair + pub fn storage_value_aux(&self) -> (Word, Word, usize, Word) { + match self { + Self::AccountStorage { + value, + value_prev, + tx_id, + committed_value, + .. + } => (*value, *value_prev, *tx_id, *committed_value), + _ => unreachable!(), + } + } + pub fn call_context_value(&self) -> Word { match self { Self::CallContext { value, .. } => *value, @@ -1053,6 +1076,7 @@ impl From<&bus_mapping::circuit_input_builder::ExecStep> for ExecutionState { OpcodeId::GAS => ExecutionState::GAS, OpcodeId::SELFBALANCE => ExecutionState::SELFBALANCE, OpcodeId::SLOAD => ExecutionState::SLOAD, + OpcodeId::SSTORE => ExecutionState::SSTORE, _ => unimplemented!("unimplemented opcode {:?}", step.op), } } From 71b38748c253d950f16bc5b01759faf30a63aee6 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Sun, 27 Feb 2022 10:12:55 +0800 Subject: [PATCH 30/39] update zkevm-circuits/src/evm_circuit/util/constraint_builder.rs --- .../evm_circuit/util/constraint_builder.rs | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs index 74acbea7d9..c9c87373d8 100644 --- a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs +++ b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs @@ -704,6 +704,33 @@ impl<'a, F: FieldExt> ConstraintBuilder<'a, F> { ); } + // TxRefund + + pub(crate) fn tx_refund_write_with_reversion( + &mut self, + tx_id: Expression, + value: Expression, + value_prev: Expression, + is_persistent: Expression, + rw_counter_end_of_reversion: Expression, + ) { + self.state_write_with_reversion( + "tx_refund_write_with_reversion", + RwTableTag::TxRefund, + [ + tx_id, + 0.expr(), + 0.expr(), + value, + value_prev, + 0.expr(), + 0.expr(), + ], + is_persistent, + rw_counter_end_of_reversion, + ); + } + // Account pub(crate) fn account_read( @@ -803,6 +830,34 @@ impl<'a, F: FieldExt> ConstraintBuilder<'a, F> { ); } + pub(crate) fn account_storage_write_with_reversion( + &mut self, + account_address: Expression, + key: Expression, + value: Expression, + value_prev: Expression, + tx_id: Expression, + committed_value: Expression, + is_persistent: Expression, + rw_counter_end_of_reversion: Expression, + ) { + self.state_write_with_reversion( + "account_storage_write_with_reversion", + RwTableTag::AccountStorage, + [ + account_address, + key, + 0.expr(), + value, + value_prev, + tx_id, + committed_value, + ], + is_persistent, + rw_counter_end_of_reversion, + ); + } + // Call context pub(crate) fn call_context( From 2837d403fd888ca0be0fd6852b2bab5b59c13f09 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Sun, 27 Feb 2022 10:20:00 +0800 Subject: [PATCH 31/39] update zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs --- .../src/evm_circuit/execution/storage.rs | 1 + .../evm_circuit/execution/storage/sstore.rs | 544 ++++++++++++++++++ 2 files changed, 545 insertions(+) create mode 100644 zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs diff --git a/zkevm-circuits/src/evm_circuit/execution/storage.rs b/zkevm-circuits/src/evm_circuit/execution/storage.rs index e49059947d..0d2be98ac9 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage.rs @@ -1,4 +1,5 @@ mod sload; +mod sstore; pub(crate) use sload::SloadGadget; pub(crate) use sstore::SstoreGadget; diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs new file mode 100644 index 0000000000..2128d8fff2 --- /dev/null +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs @@ -0,0 +1,544 @@ +use crate::{ + evm_circuit::{ + execution::ExecutionGadget, + step::ExecutionState, + table::CallContextFieldTag, + util::{ + common_gadget::SameContextGadget, + constraint_builder::{ + ConstraintBuilder, StepStateTransition, + Transition::{Delta, To}, + }, + select, Cell, Word, + }, + witness::{Block, Call, ExecStep, Transaction}, + }, + util::Expr, +}; +use eth_types::{evm_types::GasCost, Field, ToLittleEndian, ToScalar}; +use halo2_proofs::{ + circuit::Region, + plonk::{Error, Expression}, +}; + +#[derive(Clone, Debug)] +pub(crate) struct SstoreGadget { + same_context: SameContextGadget, + call_id: Cell, + tx_id: Cell, + rw_counter_end_of_reversion: Cell, + is_persistent: Cell, + callee_address: Cell, + key: Word, + value: Word, + value_prev: Word, + committed_value: Word, + is_warm: Cell, + tx_refund_prev: Word, +} + +impl ExecutionGadget for SstoreGadget { + const NAME: &'static str = "SSTORE"; + + const EXECUTION_STATE: ExecutionState = ExecutionState::SSTORE; + + fn configure(cb: &mut ConstraintBuilder) -> Self { + let opcode = cb.query_cell(); + + let call_id = cb.query_cell(); + let [tx_id, rw_counter_end_of_reversion, is_persistent, callee_address] = [ + CallContextFieldTag::TxId, + CallContextFieldTag::RwCounterEndOfReversion, + CallContextFieldTag::IsPersistent, + CallContextFieldTag::CalleeAddress, + ] + .map(|field_tag| cb.call_context(Some(call_id.expr()), field_tag)); + + let key = cb.query_word(); + // Pop the key from the stack + cb.stack_pop(key.expr()); + + let value = cb.query_word(); + // Pop the value from the stack + cb.stack_pop(value.expr()); // TODO: 79 + + let value_prev = cb.query_word(); + let committed_value = cb.query_word(); + cb.account_storage_write_with_reversion( + callee_address.expr(), + key.expr(), + value.expr(), + value_prev.expr(), + tx_id.expr(), + committed_value.expr(), + is_persistent.expr(), + rw_counter_end_of_reversion.expr(), + ); + + let is_warm = cb.query_bool(); + cb.account_storage_access_list_write_with_reversion( + tx_id.expr(), + callee_address.expr(), + key.expr(), + true.expr(), + is_warm.expr(), + is_persistent.expr(), + rw_counter_end_of_reversion.expr(), + ); + + let gas_cost = SstoreGasGadget::construct( + cb, + value.expr(), + value_prev.expr(), + committed_value.expr(), + is_warm.expr(), + ); + + // TODO: TxRefund + let tx_refund_prev = cb.query_word(); + let tx_refund = cb.query_word(); + cb.tx_refund_write_with_reversion( + tx_id.expr(), + tx_refund.expr(), + tx_refund_prev.expr(), + is_persistent.expr(), + rw_counter_end_of_reversion.expr(), + ); + + let step_state_transition = StepStateTransition { + rw_counter: Delta(9.expr()), + program_counter: Delta(1.expr()), + stack_pointer: Delta(-2.expr()), + state_write_counter: To(3.expr()), + ..Default::default() + }; + let same_context = + SameContextGadget::construct(cb, opcode, step_state_transition, Some(gas_cost.expr())); + + Self { + same_context, + call_id, + tx_id, + rw_counter_end_of_reversion, + is_persistent, + callee_address, + key, + value, + value_prev, + committed_value, + is_warm, + tx_refund_prev, + } + } + + fn assign_exec_step( + &self, + region: &mut Region<'_, F>, + offset: usize, + block: &Block, + tx: &Transaction, + call: &Call, + step: &ExecStep, + ) -> Result<(), Error> { + self.same_context.assign_exec_step(region, offset, step)?; + + self.call_id + .assign(region, offset, Some(F::from(call.id as u64)))?; + + self.tx_id + .assign(region, offset, Some(F::from(tx.id as u64)))?; + self.rw_counter_end_of_reversion.assign( + region, + offset, + Some(F::from(call.rw_counter_end_of_reversion as u64)), + )?; + self.is_persistent + .assign(region, offset, Some(F::from(call.is_persistent as u64)))?; + self.callee_address + .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()); + self.key.assign(region, offset, Some(key.to_le_bytes()))?; + self.value + .assign(region, offset, Some(value.to_le_bytes()))?; + + let (_, value_prev, _, committed_value) = block.rws[step.rw_indices[6]].storage_value_aux(); + self.value_prev + .assign(region, offset, Some(value_prev.to_le_bytes()))?; + self.committed_value + .assign(region, offset, Some(committed_value.to_le_bytes()))?; + + let (_, is_warm) = block.rws[step.rw_indices[7]].tx_access_list_value_pair(); + self.is_warm + .assign(region, offset, Some(F::from(is_warm as u64)))?; + + let (_, tx_refund_prev) = block.rws[step.rw_indices[8]].tx_refund_value_pair(); + self.tx_refund_prev + .assign(region, offset, Some(tx_refund_prev.to_le_bytes()))?; + + Ok(()) + } +} + +// TODO: +#[derive(Clone, Debug)] +pub(crate) struct SstoreGasGadget { + value: Expression, + value_prev: Expression, + committed_value: Expression, + is_warm: Expression, + gas_cost: Expression, +} + +// TODO: +impl SstoreGasGadget { + pub(crate) fn construct( + _cb: &mut ConstraintBuilder, + _value: Expression, + _value_prev: Expression, + _committed_value: Expression, + is_warm: Expression, + ) -> Self { + let gas_cost = select::expr( + is_warm.expr(), + GasCost::WARM_STORAGE_READ_COST.expr(), + GasCost::COLD_SLOAD_COST.expr(), + ); + + Self { + value: _value, + value_prev: _value_prev, + committed_value: _committed_value, + is_warm, + gas_cost, + } + } + + pub(crate) fn expr(&self) -> Expression { + // Return the gas cost + self.gas_cost.clone() + } +} + +// TODO: +#[derive(Clone, Debug)] +pub(crate) struct SstoreTxRefundGadget { + value: Expression, + value_prev: Expression, + committed_value: Expression, + is_warm: Expression, + tx_refund_old: Expression, + tx_refund_new: Expression, +} + +// TODO: +impl SstoreTxRefundGadget { + pub(crate) fn construct( + _cb: &mut ConstraintBuilder, + _value: Expression, + _value_prev: Expression, + _committed_value: Expression, + tx_refund_old: Expression, + is_warm: Expression, + ) -> Self { + let tx_refund_new = select::expr( + is_warm.expr(), + GasCost::WARM_STORAGE_READ_COST.expr(), + GasCost::COLD_SLOAD_COST.expr(), + ); + + Self { + value: _value, + value_prev: _value_prev, + committed_value: _committed_value, + is_warm, + tx_refund_old, + tx_refund_new, + } + } + + pub(crate) fn expr(&self) -> Expression { + // Return the new tx_refund + self.tx_refund_new.clone() + } +} + +#[cfg(test)] +mod test { + use crate::evm_circuit::{ + param::STACK_CAPACITY, + step::ExecutionState, + table::CallContextFieldTag, + test::{rand_fp, rand_word, run_test_circuit_incomplete_fixed_table}, + util::RandomLinearCombination, + witness::{Block, Bytecode, Call, ExecStep, Rw, Transaction}, + }; + + use bus_mapping::evm::OpcodeId; + use eth_types::{address, bytecode, evm_types::GasCost, Address, ToLittleEndian, ToWord, Word}; + use std::convert::TryInto; + + fn calc_expected_gas_cost( + value: Word, + value_prev: Word, + committed_value: Word, + is_warm: bool, + ) -> u64 { + if is_warm { + return GasCost::WARM_STORAGE_READ_COST.as_u64(); + } else { + return GasCost::COLD_SLOAD_COST.as_u64(); + } + } + + fn test_ok( + tx: eth_types::Transaction, + key: Word, + value: Word, + value_prev: Word, + committed_value: Word, + is_warm: bool, + result: bool, + ) { + let gas = calc_expected_gas_cost(value, value_prev, committed_value, is_warm); + let rw_counter_end_of_reversion = if result { 0 } else { 14 }; + + let call_data_gas_cost = tx + .input + .0 + .iter() + .fold(0, |acc, byte| acc + if *byte == 0 { 4 } else { 16 }); + + let randomness = rand_fp(); + let bytecode = Bytecode::from(&bytecode! { + PUSH32(value) + PUSH32(key) + #[start] + SSTORE + STOP + }); + let block = Block { + randomness, + txs: vec![Transaction { + id: 1, + nonce: tx.nonce.try_into().unwrap(), + gas: tx.gas.try_into().unwrap(), + gas_price: tx.gas_price.unwrap_or_else(Word::zero), + caller_address: tx.from, + callee_address: tx.to.unwrap(), + is_create: tx.to.is_none(), + value: tx.value, + call_data: tx.input.to_vec(), + call_data_length: tx.input.0.len(), + call_data_gas_cost, + calls: vec![Call { + id: 1, + is_root: true, + is_create: false, + opcode_source: RandomLinearCombination::random_linear_combine( + bytecode.hash.to_le_bytes(), + randomness, + ), + result: Word::from(result as usize), + rw_counter_end_of_reversion, + is_persistent: result, + callee_address: tx.to.unwrap(), + ..Default::default() + }], + steps: vec![ + ExecStep { + rw_indices: (0..9 + if result { 0 } else { 2 }).collect(), + execution_state: ExecutionState::SSTORE, + rw_counter: 1, + program_counter: 66, + stack_pointer: STACK_CAPACITY, + gas_left: gas, + gas_cost: gas, + opcode: Some(OpcodeId::SSTORE), + ..Default::default() + }, + ExecStep { + execution_state: ExecutionState::STOP, + rw_counter: 10, + program_counter: 67, + stack_pointer: STACK_CAPACITY - 2, + gas_left: 0, + opcode: Some(OpcodeId::STOP), + state_write_counter: 3, + ..Default::default() + }, + ], + }], + rws: [ + vec![ + Rw::CallContext { + rw_counter: 1, + is_write: false, + call_id: 1, + field_tag: CallContextFieldTag::TxId, + value: Word::one(), + }, + Rw::CallContext { + rw_counter: 2, + is_write: false, + call_id: 1, + field_tag: CallContextFieldTag::RwCounterEndOfReversion, + value: Word::from(rw_counter_end_of_reversion), + }, + Rw::CallContext { + rw_counter: 3, + is_write: false, + call_id: 1, + field_tag: CallContextFieldTag::IsPersistent, + value: Word::from(result as u64), + }, + Rw::CallContext { + rw_counter: 4, + is_write: false, + call_id: 1, + field_tag: CallContextFieldTag::CalleeAddress, + value: tx.to.unwrap().to_word(), + }, + Rw::Stack { + rw_counter: 5, + is_write: false, + call_id: 1, + stack_pointer: STACK_CAPACITY, + value: key, + }, + Rw::Stack { + rw_counter: 6, + is_write: false, + call_id: 1, + stack_pointer: STACK_CAPACITY + 1, + value: value, + }, + Rw::AccountStorage { + rw_counter: 7, + is_write: true, + address: tx.to.unwrap(), + key, + value: value, + value_prev: value_prev, + tx_id: 1usize, + committed_value: committed_value, + }, + Rw::TxAccessListAccountStorage { + rw_counter: 8, + is_write: true, + tx_id: 1usize, + address: tx.to.unwrap(), + key, + value: true, + value_prev: is_warm, + }, + Rw::TxRefund { + rw_counter: 9, + is_write: true, + tx_id: 1usize, + value: Word::from(0), // TODO: + value_prev: Word::from(998), + }, + ], + if result { + vec![] + } else { + vec![ + Rw::TxRefund { + rw_counter: 12, + is_write: true, + tx_id: 1usize, + value: Word::from(998), + value_prev: Word::from(0), // TODO: + }, + Rw::TxAccessListAccountStorage { + rw_counter: 13, + is_write: true, + tx_id: 1usize, + address: tx.to.unwrap(), + key, + value: is_warm, + value_prev: true, + }, + Rw::AccountStorage { + rw_counter: 14, + is_write: true, + address: tx.to.unwrap(), + key, + value: value, + value_prev: value_prev, + tx_id: 1usize, + committed_value: committed_value, + }, + ] + }, + ] + .concat(), + bytecodes: vec![bytecode], + ..Default::default() + }; + + assert_eq!(run_test_circuit_incomplete_fixed_table(block), Ok(())); + } + + fn mock_tx() -> eth_types::Transaction { + let from = address!("0x00000000000000000000000000000000000000fe"); + let to = address!("0x00000000000000000000000000000000000000ff"); + eth_types::Transaction { + from, + to: Some(to), + ..Default::default() + } + } + + #[test] + fn sstore_gadget_warm() { + // persist cases + test_ok( + mock_tx(), + 0x030201.into(), + 0x060504.into(), + 0x060504.into(), + 0x060504.into(), + true, + true, + ); + + // revert cases + test_ok( + mock_tx(), + 0x030201.into(), + 0x060504.into(), + 0x060504.into(), + 0x060504.into(), + true, + false, + ); + } + + #[test] + fn sstore_gadget_cold() { + // persist cases + test_ok( + mock_tx(), + 0x030201.into(), + 0x060504.into(), + 0x060504.into(), + 0x060504.into(), + false, + true, + ); + + // revert cases + test_ok( + mock_tx(), + 0x030201.into(), + 0x060504.into(), + 0x060504.into(), + 0x060504.into(), + false, + false, + ); + } +} From 501c8687d559391087e1fc231ba525c746f09659 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Sun, 27 Feb 2022 10:54:23 +0800 Subject: [PATCH 32/39] update --- .../evm_circuit/execution/storage/sstore.rs | 279 +++++++++++------- 1 file changed, 166 insertions(+), 113 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs index 2128d8fff2..32a0e10070 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs @@ -269,10 +269,10 @@ mod test { use crate::evm_circuit::{ param::STACK_CAPACITY, step::ExecutionState, - table::CallContextFieldTag, + table::{CallContextFieldTag, RwTableTag}, test::{rand_fp, rand_word, run_test_circuit_incomplete_fixed_table}, util::RandomLinearCombination, - witness::{Block, Bytecode, Call, ExecStep, Rw, Transaction}, + witness::{Block, Bytecode, Call, CodeSource, ExecStep, Rw, RwMap, Transaction}, }; use bus_mapping::evm::OpcodeId; @@ -336,19 +336,38 @@ mod test { id: 1, is_root: true, is_create: false, - opcode_source: RandomLinearCombination::random_linear_combine( - bytecode.hash.to_le_bytes(), - randomness, - ), - result: Word::from(result as usize), + code_source: CodeSource::Account(bytecode.hash), rw_counter_end_of_reversion, is_persistent: result, + is_success: result, callee_address: tx.to.unwrap(), ..Default::default() }], steps: vec![ ExecStep { - rw_indices: (0..9 + if result { 0 } else { 2 }).collect(), + rw_indices: [ + vec![ + (RwTableTag::CallContext, 0), + (RwTableTag::CallContext, 1), + (RwTableTag::CallContext, 2), + (RwTableTag::CallContext, 3), + (RwTableTag::Stack, 0), + (RwTableTag::Stack, 1), + (RwTableTag::AccountStorage, 0), + (RwTableTag::TxAccessListAccountStorage, 0), + (RwTableTag::TxRefund, 0), + ], + if result { + vec![] + } else { + vec![ + (RwTableTag::TxRefund, 1), + (RwTableTag::TxAccessListAccountStorage, 1), + (RwTableTag::AccountStorage, 1), + ] + }, + ] + .concat(), execution_state: ExecutionState::SSTORE, rw_counter: 1, program_counter: 66, @@ -370,111 +389,145 @@ mod test { }, ], }], - rws: [ - vec![ - Rw::CallContext { - rw_counter: 1, - is_write: false, - call_id: 1, - field_tag: CallContextFieldTag::TxId, - value: Word::one(), - }, - Rw::CallContext { - rw_counter: 2, - is_write: false, - call_id: 1, - field_tag: CallContextFieldTag::RwCounterEndOfReversion, - value: Word::from(rw_counter_end_of_reversion), - }, - Rw::CallContext { - rw_counter: 3, - is_write: false, - call_id: 1, - field_tag: CallContextFieldTag::IsPersistent, - value: Word::from(result as u64), - }, - Rw::CallContext { - rw_counter: 4, - is_write: false, - call_id: 1, - field_tag: CallContextFieldTag::CalleeAddress, - value: tx.to.unwrap().to_word(), - }, - Rw::Stack { - rw_counter: 5, - is_write: false, - call_id: 1, - stack_pointer: STACK_CAPACITY, - value: key, - }, - Rw::Stack { - rw_counter: 6, - is_write: false, - call_id: 1, - stack_pointer: STACK_CAPACITY + 1, - value: value, - }, - Rw::AccountStorage { - rw_counter: 7, - is_write: true, - address: tx.to.unwrap(), - key, - value: value, - value_prev: value_prev, - tx_id: 1usize, - committed_value: committed_value, - }, - Rw::TxAccessListAccountStorage { - rw_counter: 8, - is_write: true, - tx_id: 1usize, - address: tx.to.unwrap(), - key, - value: true, - value_prev: is_warm, - }, - Rw::TxRefund { - rw_counter: 9, - is_write: true, - tx_id: 1usize, - value: Word::from(0), // TODO: - value_prev: Word::from(998), - }, - ], - if result { - vec![] - } else { - vec![ - Rw::TxRefund { - rw_counter: 12, - is_write: true, - tx_id: 1usize, - value: Word::from(998), - value_prev: Word::from(0), // TODO: - }, - Rw::TxAccessListAccountStorage { - rw_counter: 13, - is_write: true, - tx_id: 1usize, - address: tx.to.unwrap(), - key, - value: is_warm, - value_prev: true, - }, - Rw::AccountStorage { - rw_counter: 14, - is_write: true, - address: tx.to.unwrap(), - key, - value: value, - value_prev: value_prev, - tx_id: 1usize, - committed_value: committed_value, - }, - ] - }, - ] - .concat(), + rws: RwMap( + [ + ( + RwTableTag::Stack, + vec![ + Rw::Stack { + rw_counter: 5, + is_write: false, + call_id: 1, + stack_pointer: STACK_CAPACITY, + value: key, + }, + Rw::Stack { + rw_counter: 6, + is_write: false, + call_id: 1, + stack_pointer: STACK_CAPACITY + 1, + value, + }, + ], + ), + ( + RwTableTag::AccountStorage, + [ + vec![Rw::AccountStorage { + rw_counter: 7, + is_write: true, + account_address: tx.to.unwrap(), + storage_key: key, + value: value, + value_prev: value_prev, + tx_id: 1usize, + committed_value: committed_value, + }], + if result { + vec![] + } else { + vec![Rw::AccountStorage { + rw_counter: rw_counter_end_of_reversion, + is_write: true, + account_address: tx.to.unwrap(), + storage_key: key, + value: value_prev, + value_prev: value, + tx_id: 1usize, + committed_value: committed_value, + }] + }, + ] + .concat(), + ), + ( + RwTableTag::TxAccessListAccountStorage, + [ + vec![Rw::TxAccessListAccountStorage { + rw_counter: 8, + is_write: true, + tx_id: 1usize, + account_address: tx.to.unwrap(), + storage_key: key, + value: true, + value_prev: is_warm, + }], + if result { + vec![] + } else { + vec![Rw::TxAccessListAccountStorage { + rw_counter: rw_counter_end_of_reversion - 1, + is_write: true, + tx_id: 1usize, + account_address: tx.to.unwrap(), + storage_key: key, + value: is_warm, + value_prev: true, + }] + }, + ] + .concat(), + ), + ( + RwTableTag::TxRefund, + [ + vec![Rw::TxRefund { + rw_counter: 9, + is_write: true, + tx_id: 1usize, + value: Word::from(0), // TODO: + value_prev: Word::from(998), + }], + if result { + vec![] + } else { + vec![Rw::TxRefund { + rw_counter: rw_counter_end_of_reversion - 2, + is_write: true, + tx_id: 1usize, + value: Word::from(998), + value_prev: Word::from(0), // TODO: + }] + }, + ] + .concat(), + ), + ( + RwTableTag::CallContext, + vec![ + Rw::CallContext { + rw_counter: 1, + is_write: false, + call_id: 1, + field_tag: CallContextFieldTag::TxId, + value: Word::one(), + }, + Rw::CallContext { + rw_counter: 2, + is_write: false, + call_id: 1, + field_tag: CallContextFieldTag::RwCounterEndOfReversion, + value: Word::from(rw_counter_end_of_reversion), + }, + Rw::CallContext { + rw_counter: 3, + is_write: false, + call_id: 1, + field_tag: CallContextFieldTag::IsPersistent, + value: Word::from(result as u64), + }, + Rw::CallContext { + rw_counter: 4, + is_write: false, + call_id: 1, + field_tag: CallContextFieldTag::CalleeAddress, + value: tx.to.unwrap().to_word(), + }, + ], + ), + ] + .into(), + ), bytecodes: vec![bytecode], ..Default::default() }; From 4b1edead031d86a07c50f7e53d0ea4c75dd7565a Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Sun, 27 Feb 2022 13:40:51 +0800 Subject: [PATCH 33/39] fix zkevm-circuits/src/evm_circuit/witness.rs --- zkevm-circuits/src/evm_circuit/witness.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/zkevm-circuits/src/evm_circuit/witness.rs b/zkevm-circuits/src/evm_circuit/witness.rs index adf9258bd9..eb5b54bc92 100644 --- a/zkevm-circuits/src/evm_circuit/witness.rs +++ b/zkevm-circuits/src/evm_circuit/witness.rs @@ -670,6 +670,28 @@ impl Rw { F::zero(), ] .into(), + Self::TxRefund { + rw_counter, + is_write, + tx_id, + value, + value_prev, + } => [ + F::from(*rw_counter as u64), + F::from(*is_write as u64), + F::from(RwTableTag::TxRefund as u64), + F::from(*tx_id as u64), + F::zero(), + F::zero(), + RandomLinearCombination::random_linear_combine(value.to_le_bytes(), randomness), + RandomLinearCombination::random_linear_combine( + value_prev.to_le_bytes(), + randomness, + ), + F::zero(), + F::zero(), + ] + .into(), Self::Account { rw_counter, is_write, From 5c00a90bc61c0b7c1cb6a38b35d0cea5e8aaebbc Mon Sep 17 00:00:00 2001 From: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com> Date: Sun, 27 Feb 2022 20:33:44 +0800 Subject: [PATCH 34/39] implement gas (#108) --- .../evm_circuit/execution/storage/sstore.rs | 279 +++++++++++++++--- .../evm_circuit/util/constraint_builder.rs | 1 + 2 files changed, 244 insertions(+), 36 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs index 32a0e10070..87dc3c672d 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs @@ -9,6 +9,7 @@ use crate::{ ConstraintBuilder, StepStateTransition, Transition::{Delta, To}, }, + math_gadget::{IsEqualGadget, IsZeroGadget}, select, Cell, Word, }, witness::{Block, Call, ExecStep, Transaction}, @@ -35,6 +36,7 @@ pub(crate) struct SstoreGadget { committed_value: Word, is_warm: Cell, tx_refund_prev: Word, + gas_cost: SstoreGasGadget, } impl ExecutionGadget for SstoreGadget { @@ -88,10 +90,10 @@ impl ExecutionGadget for SstoreGadget { let gas_cost = SstoreGasGadget::construct( cb, - value.expr(), - value_prev.expr(), - committed_value.expr(), - is_warm.expr(), + value.clone(), + value_prev.clone(), + committed_value.clone(), + is_warm.clone(), ); // TODO: TxRefund @@ -108,7 +110,7 @@ impl ExecutionGadget for SstoreGadget { let step_state_transition = StepStateTransition { rw_counter: Delta(9.expr()), program_counter: Delta(1.expr()), - stack_pointer: Delta(-2.expr()), + stack_pointer: Delta(-(2.expr())), state_write_counter: To(3.expr()), ..Default::default() }; @@ -128,6 +130,7 @@ impl ExecutionGadget for SstoreGadget { committed_value, is_warm, tx_refund_prev, + gas_cost, } } @@ -177,41 +180,72 @@ impl ExecutionGadget for SstoreGadget { self.tx_refund_prev .assign(region, offset, Some(tx_refund_prev.to_le_bytes()))?; + self.gas_cost.assign( + region, + offset, + value, + value_prev, + committed_value, + is_warm, + block.randomness, + )?; + Ok(()) } } -// TODO: #[derive(Clone, Debug)] pub(crate) struct SstoreGasGadget { - value: Expression, - value_prev: Expression, - committed_value: Expression, - is_warm: Expression, + value: Word, + value_prev: Word, + committed_value: Word, + is_warm: Cell, gas_cost: Expression, + value_eq_prev: IsEqualGadget, + original_eq_prev: IsEqualGadget, + original_is_zero: IsZeroGadget, } -// TODO: impl SstoreGasGadget { pub(crate) fn construct( - _cb: &mut ConstraintBuilder, - _value: Expression, - _value_prev: Expression, - _committed_value: Expression, - is_warm: Expression, + cb: &mut ConstraintBuilder, + value: Word, + value_prev: Word, + committed_value: Word, + is_warm: Cell, ) -> Self { + let value_eq_prev = IsEqualGadget::construct(cb, value.expr(), value_prev.expr()); + let original_eq_prev = + IsEqualGadget::construct(cb, committed_value.expr(), value_prev.expr()); + let original_is_zero = IsZeroGadget::construct(cb, committed_value.expr()); + let warm_case_gas = select::expr( + value_eq_prev.expr(), + GasCost::SLOAD_GAS.expr(), + select::expr( + original_eq_prev.expr(), + select::expr( + original_is_zero.expr(), + GasCost::SSTORE_SET_GAS.expr(), + GasCost::SSTORE_RESET_GAS.expr(), + ), + GasCost::SLOAD_GAS.expr(), + ), + ); let gas_cost = select::expr( is_warm.expr(), - GasCost::WARM_STORAGE_READ_COST.expr(), - GasCost::COLD_SLOAD_COST.expr(), + warm_case_gas.expr(), + warm_case_gas + GasCost::COLD_SLOAD_COST.expr(), ); Self { - value: _value, - value_prev: _value_prev, - committed_value: _committed_value, + value, + value_prev, + committed_value, is_warm, gas_cost, + value_eq_prev, + original_eq_prev, + original_is_zero, } } @@ -219,6 +253,45 @@ impl SstoreGasGadget { // Return the gas cost self.gas_cost.clone() } + + #[allow(clippy::too_many_arguments)] + pub(crate) fn assign( + &self, + region: &mut Region<'_, F>, + offset: usize, + value: eth_types::Word, + value_prev: eth_types::Word, + committed_value: eth_types::Word, + is_warm: bool, + randomness: F, + ) -> Result<(), Error> { + self.value + .assign(region, offset, Some(value.to_le_bytes()))?; + self.value_prev + .assign(region, offset, Some(value_prev.to_le_bytes()))?; + self.committed_value + .assign(region, offset, Some(committed_value.to_le_bytes()))?; + self.is_warm + .assign(region, offset, Some(F::from(is_warm as u64)))?; + self.value_eq_prev.assign( + region, + offset, + Word::random_linear_combine(value.to_le_bytes(), randomness), + Word::random_linear_combine(value_prev.to_le_bytes(), randomness), + )?; + self.original_eq_prev.assign( + region, + offset, + Word::random_linear_combine(committed_value.to_le_bytes(), randomness), + Word::random_linear_combine(value_prev.to_le_bytes(), randomness), + )?; + self.original_is_zero.assign( + region, + offset, + Word::random_linear_combine(committed_value.to_le_bytes(), randomness), + )?; + Ok(()) + } } // TODO: @@ -236,9 +309,9 @@ pub(crate) struct SstoreTxRefundGadget { impl SstoreTxRefundGadget { pub(crate) fn construct( _cb: &mut ConstraintBuilder, - _value: Expression, - _value_prev: Expression, - _committed_value: Expression, + value: Expression, + value_prev: Expression, + committed_value: Expression, tx_refund_old: Expression, is_warm: Expression, ) -> Self { @@ -249,9 +322,9 @@ impl SstoreTxRefundGadget { ); Self { - value: _value, - value_prev: _value_prev, - committed_value: _committed_value, + value, + value_prev, + committed_value, is_warm, tx_refund_old, tx_refund_new, @@ -270,13 +343,12 @@ mod test { param::STACK_CAPACITY, step::ExecutionState, table::{CallContextFieldTag, RwTableTag}, - test::{rand_fp, rand_word, run_test_circuit_incomplete_fixed_table}, - util::RandomLinearCombination, + test::{rand_fp, run_test_circuit_incomplete_fixed_table}, witness::{Block, Bytecode, Call, CodeSource, ExecStep, Rw, RwMap, Transaction}, }; use bus_mapping::evm::OpcodeId; - use eth_types::{address, bytecode, evm_types::GasCost, Address, ToLittleEndian, ToWord, Word}; + use eth_types::{address, bytecode, evm_types::GasCost, ToWord, Word}; use std::convert::TryInto; fn calc_expected_gas_cost( @@ -285,10 +357,21 @@ mod test { committed_value: Word, is_warm: bool, ) -> u64 { + let warm_case_gas = if value_prev == value { + GasCost::SLOAD_GAS + } else if committed_value == value_prev { + if committed_value == Word::from(0) { + GasCost::SSTORE_SET_GAS + } else { + GasCost::SSTORE_RESET_GAS + } + } else { + GasCost::SLOAD_GAS + }; if is_warm { - return GasCost::WARM_STORAGE_READ_COST.as_u64(); + warm_case_gas.as_u64() } else { - return GasCost::COLD_SLOAD_COST.as_u64(); + warm_case_gas.as_u64() + GasCost::COLD_SLOAD_COST.as_u64() } } @@ -418,10 +501,10 @@ mod test { is_write: true, account_address: tx.to.unwrap(), storage_key: key, - value: value, - value_prev: value_prev, + value, + value_prev, tx_id: 1usize, - committed_value: committed_value, + committed_value, }], if result { vec![] @@ -434,7 +517,7 @@ mod test { value: value_prev, value_prev: value, tx_id: 1usize, - committed_value: committed_value, + committed_value, }] }, ] @@ -548,6 +631,7 @@ mod test { #[test] fn sstore_gadget_warm() { // persist cases + // value_prev == value test_ok( mock_tx(), 0x030201.into(), @@ -557,13 +641,74 @@ mod test { true, true, ); + // value_prev != value, original_value == value_prev, original_value != 0 + test_ok( + mock_tx(), + 0x030201.into(), + 0x060504.into(), + 0x060505.into(), + 0x060505.into(), + true, + true, + ); + // value_prev != value, original_value == value_prev, original_value == 0 + test_ok( + mock_tx(), + 0x030201.into(), + 0x060504.into(), + 0.into(), + 0.into(), + true, + true, + ); + // value_prev != value, original_value != value_prev + test_ok( + mock_tx(), + 0x030201.into(), + 0x060504.into(), + 0x060505.into(), + 0x060504.into(), + true, + true, + ); // revert cases + // value_prev == value + test_ok( + mock_tx(), + 0x030201.into(), + 0x060504.into(), + 0x060504.into(), + 0x060504.into(), + true, + false, + ); + // value_prev != value, original_value == value_prev, original_value != 0 + test_ok( + mock_tx(), + 0x030201.into(), + 0x060504.into(), + 0x060505.into(), + 0x060505.into(), + true, + false, + ); + // value_prev != value, original_value == value_prev, original_value == 0 test_ok( mock_tx(), 0x030201.into(), 0x060504.into(), + 0.into(), + 0.into(), + true, + false, + ); + // value_prev != value, original_value != value_prev + test_ok( + mock_tx(), + 0x030201.into(), 0x060504.into(), + 0x060505.into(), 0x060504.into(), true, false, @@ -573,6 +718,7 @@ mod test { #[test] fn sstore_gadget_cold() { // persist cases + // value_prev == value test_ok( mock_tx(), 0x030201.into(), @@ -582,8 +728,39 @@ mod test { false, true, ); + // value_prev != value, original_value == value_prev, original_value != 0 + test_ok( + mock_tx(), + 0x030201.into(), + 0x060504.into(), + 0x060505.into(), + 0x060505.into(), + false, + true, + ); + // value_prev != value, original_value == value_prev, original_value == 0 + test_ok( + mock_tx(), + 0x030201.into(), + 0x060504.into(), + 0.into(), + 0.into(), + false, + true, + ); + // value_prev != value, original_value != value_prev + test_ok( + mock_tx(), + 0x030201.into(), + 0x060504.into(), + 0x060505.into(), + 0x060504.into(), + false, + true, + ); // revert cases + // value_prev == value test_ok( mock_tx(), 0x030201.into(), @@ -593,5 +770,35 @@ mod test { false, false, ); + // value_prev != value, original_value == value_prev, original_value != 0 + test_ok( + mock_tx(), + 0x030201.into(), + 0x060504.into(), + 0x060505.into(), + 0x060505.into(), + false, + false, + ); + // value_prev != value, original_value == value_prev, original_value == 0 + test_ok( + mock_tx(), + 0x030201.into(), + 0x060504.into(), + 0.into(), + 0.into(), + false, + false, + ); + // value_prev != value, original_value != value_prev + test_ok( + mock_tx(), + 0x030201.into(), + 0x060504.into(), + 0x060505.into(), + 0x060504.into(), + false, + false, + ); } } diff --git a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs index c9c87373d8..d22a60d068 100644 --- a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs +++ b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs @@ -830,6 +830,7 @@ impl<'a, F: FieldExt> ConstraintBuilder<'a, F> { ); } + #[allow(clippy::too_many_arguments)] pub(crate) fn account_storage_write_with_reversion( &mut self, account_address: Expression, From 7eb85252f918964112a8dc5c3a25e6bdea0c6ab4 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Sun, 27 Feb 2022 20:39:41 +0800 Subject: [PATCH 35/39] minor --- .../src/evm_circuit/execution/storage/sstore.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs index 87dc3c672d..03412a4927 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs @@ -629,8 +629,7 @@ mod test { } #[test] - fn sstore_gadget_warm() { - // persist cases + fn sstore_gadget_warm_persist() { // value_prev == value test_ok( mock_tx(), @@ -671,8 +670,9 @@ mod test { true, true, ); + } - // revert cases + fn sstore_gadget_warm_revert() { // value_prev == value test_ok( mock_tx(), @@ -716,8 +716,7 @@ mod test { } #[test] - fn sstore_gadget_cold() { - // persist cases + fn sstore_gadget_cold_persist() { // value_prev == value test_ok( mock_tx(), @@ -758,8 +757,10 @@ mod test { false, true, ); + } - // revert cases + #[test] + fn sstore_gadget_cold_revert() { // value_prev == value test_ok( mock_tx(), From 9f627dbf36a547acaf17ff421a893bfdadaf859a Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Mon, 28 Feb 2022 08:43:34 +0800 Subject: [PATCH 36/39] update test cases --- .../evm_circuit/execution/storage/sstore.rs | 48 +++++++++++++++++-- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs b/zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs index 03412a4927..7b5fc90518 100644 --- a/zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs +++ b/zkevm-circuits/src/evm_circuit/execution/storage/sstore.rs @@ -660,7 +660,17 @@ mod test { true, true, ); - // value_prev != value, original_value != value_prev + // value_prev != value, original_value != value_prev, value != original_value + test_ok( + mock_tx(), + 0x030201.into(), + 0x060504.into(), + 0x060505.into(), + 0x060506.into(), + true, + true, + ); + // value_prev != value, original_value != value_prev, value == original_value test_ok( mock_tx(), 0x030201.into(), @@ -703,7 +713,17 @@ mod test { true, false, ); - // value_prev != value, original_value != value_prev + // value_prev != value, original_value != value_prev, value != original_value + test_ok( + mock_tx(), + 0x030201.into(), + 0x060504.into(), + 0x060505.into(), + 0x060506.into(), + true, + false, + ); + // value_prev != value, original_value != value_prev, value == original_value test_ok( mock_tx(), 0x030201.into(), @@ -747,7 +767,17 @@ mod test { false, true, ); - // value_prev != value, original_value != value_prev + // value_prev != value, original_value != value_prev, value != original_value + test_ok( + mock_tx(), + 0x030201.into(), + 0x060504.into(), + 0x060505.into(), + 0x060506.into(), + false, + true, + ); + // value_prev != value, original_value != value_prev, value == original_value test_ok( mock_tx(), 0x030201.into(), @@ -791,7 +821,17 @@ mod test { false, false, ); - // value_prev != value, original_value != value_prev + // value_prev != value, original_value != value_prev, value != original_value + test_ok( + mock_tx(), + 0x030201.into(), + 0x060504.into(), + 0x060505.into(), + 0x060506.into(), + false, + false, + ); + // value_prev != value, original_value != value_prev, value == original_value test_ok( mock_tx(), 0x030201.into(), From 43d22011f32792ea8183004559e724d7a1f3b7e4 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Wed, 9 Mar 2022 09:02:20 +0800 Subject: [PATCH 37/39] cargo fmt --- zkevm-circuits/src/evm_circuit/execution.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution.rs b/zkevm-circuits/src/evm_circuit/execution.rs index a83b2f1862..23988bfc25 100644 --- a/zkevm-circuits/src/evm_circuit/execution.rs +++ b/zkevm-circuits/src/evm_circuit/execution.rs @@ -44,8 +44,8 @@ mod selfbalance; mod signed_comparator; mod signextend; mod sload; -mod stop; mod sstore; +mod stop; mod swap; mod timestamp; @@ -76,8 +76,8 @@ use selfbalance::SelfbalanceGadget; use signed_comparator::SignedComparatorGadget; use signextend::SignextendGadget; use sload::SloadGadget; -use stop::StopGadget; use sstore::SstoreGadget; +use stop::StopGadget; use swap::SwapGadget; use timestamp::TimestampGadget; From 936e1e4c7598890a8fdfd2aff128d66bc2851d44 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Wed, 9 Mar 2022 09:16:22 +0800 Subject: [PATCH 38/39] use cell --- .../src/evm_circuit/execution/sstore.rs | 112 ++++++++++++------ 1 file changed, 79 insertions(+), 33 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/sstore.rs b/zkevm-circuits/src/evm_circuit/execution/sstore.rs index 7b5fc90518..a8c3cf3166 100644 --- a/zkevm-circuits/src/evm_circuit/execution/sstore.rs +++ b/zkevm-circuits/src/evm_circuit/execution/sstore.rs @@ -30,12 +30,12 @@ pub(crate) struct SstoreGadget { rw_counter_end_of_reversion: Cell, is_persistent: Cell, callee_address: Cell, - key: Word, - value: Word, - value_prev: Word, - committed_value: Word, + key: Cell, + value: Cell, + value_prev: Cell, + committed_value: Cell, is_warm: Cell, - tx_refund_prev: Word, + tx_refund_prev: Cell, gas_cost: SstoreGasGadget, } @@ -56,16 +56,16 @@ impl ExecutionGadget for SstoreGadget { ] .map(|field_tag| cb.call_context(Some(call_id.expr()), field_tag)); - let key = cb.query_word(); + let key = cb.query_cell(); // Pop the key from the stack cb.stack_pop(key.expr()); - let value = cb.query_word(); + let value = cb.query_cell(); // Pop the value from the stack - cb.stack_pop(value.expr()); // TODO: 79 + cb.stack_pop(value.expr()); - let value_prev = cb.query_word(); - let committed_value = cb.query_word(); + let value_prev = cb.query_cell(); + let committed_value = cb.query_cell(); cb.account_storage_write_with_reversion( callee_address.expr(), key.expr(), @@ -97,8 +97,8 @@ impl ExecutionGadget for SstoreGadget { ); // TODO: TxRefund - let tx_refund_prev = cb.query_word(); - let tx_refund = cb.query_word(); + let tx_refund_prev = cb.query_cell(); + let tx_refund = cb.query_cell(); cb.tx_refund_write_with_reversion( tx_id.expr(), tx_refund.expr(), @@ -162,23 +162,54 @@ impl ExecutionGadget for SstoreGadget { let [key, value] = [step.rw_indices[4], step.rw_indices[5]].map(|idx| block.rws[idx].stack_value()); - self.key.assign(region, offset, Some(key.to_le_bytes()))?; - self.value - .assign(region, offset, Some(value.to_le_bytes()))?; + self.key.assign( + region, + offset, + Some(Word::random_linear_combine( + key.to_le_bytes(), + block.randomness, + )), + )?; + self.value.assign( + region, + offset, + Some(Word::random_linear_combine( + value.to_le_bytes(), + block.randomness, + )), + )?; let (_, value_prev, _, committed_value) = block.rws[step.rw_indices[6]].storage_value_aux(); - self.value_prev - .assign(region, offset, Some(value_prev.to_le_bytes()))?; - self.committed_value - .assign(region, offset, Some(committed_value.to_le_bytes()))?; + self.value_prev.assign( + region, + offset, + Some(Word::random_linear_combine( + value_prev.to_le_bytes(), + block.randomness, + )), + )?; + self.committed_value.assign( + region, + offset, + Some(Word::random_linear_combine( + committed_value.to_le_bytes(), + block.randomness, + )), + )?; let (_, is_warm) = block.rws[step.rw_indices[7]].tx_access_list_value_pair(); self.is_warm .assign(region, offset, Some(F::from(is_warm as u64)))?; let (_, tx_refund_prev) = block.rws[step.rw_indices[8]].tx_refund_value_pair(); - self.tx_refund_prev - .assign(region, offset, Some(tx_refund_prev.to_le_bytes()))?; + self.tx_refund_prev.assign( + region, + offset, + Some(Word::random_linear_combine( + tx_refund_prev.to_le_bytes(), + block.randomness, + )), + )?; self.gas_cost.assign( region, @@ -196,9 +227,9 @@ impl ExecutionGadget for SstoreGadget { #[derive(Clone, Debug)] pub(crate) struct SstoreGasGadget { - value: Word, - value_prev: Word, - committed_value: Word, + value: Cell, + value_prev: Cell, + committed_value: Cell, is_warm: Cell, gas_cost: Expression, value_eq_prev: IsEqualGadget, @@ -209,9 +240,9 @@ pub(crate) struct SstoreGasGadget { impl SstoreGasGadget { pub(crate) fn construct( cb: &mut ConstraintBuilder, - value: Word, - value_prev: Word, - committed_value: Word, + value: Cell, + value_prev: Cell, + committed_value: Cell, is_warm: Cell, ) -> Self { let value_eq_prev = IsEqualGadget::construct(cb, value.expr(), value_prev.expr()); @@ -265,12 +296,27 @@ impl SstoreGasGadget { is_warm: bool, randomness: F, ) -> Result<(), Error> { - self.value - .assign(region, offset, Some(value.to_le_bytes()))?; - self.value_prev - .assign(region, offset, Some(value_prev.to_le_bytes()))?; - self.committed_value - .assign(region, offset, Some(committed_value.to_le_bytes()))?; + self.value.assign( + region, + offset, + Some(Word::random_linear_combine(value.to_le_bytes(), randomness)), + )?; + self.value_prev.assign( + region, + offset, + Some(Word::random_linear_combine( + value_prev.to_le_bytes(), + randomness, + )), + )?; + self.committed_value.assign( + region, + offset, + Some(Word::random_linear_combine( + committed_value.to_le_bytes(), + randomness, + )), + )?; self.is_warm .assign(region, offset, Some(F::from(is_warm as u64)))?; self.value_eq_prev.assign( From 92b90f03c9b23e9129a41966b92327be0a6a7097 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ Date: Wed, 9 Mar 2022 10:16:38 +0800 Subject: [PATCH 39/39] fix fix fix --- zkevm-circuits/src/evm_circuit/execution/sstore.rs | 10 ++-------- zkevm-circuits/src/evm_circuit/witness.rs | 7 ++----- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/zkevm-circuits/src/evm_circuit/execution/sstore.rs b/zkevm-circuits/src/evm_circuit/execution/sstore.rs index a8c3cf3166..7515146c23 100644 --- a/zkevm-circuits/src/evm_circuit/execution/sstore.rs +++ b/zkevm-circuits/src/evm_circuit/execution/sstore.rs @@ -202,14 +202,8 @@ impl ExecutionGadget for SstoreGadget { .assign(region, offset, Some(F::from(is_warm as u64)))?; let (_, tx_refund_prev) = block.rws[step.rw_indices[8]].tx_refund_value_pair(); - self.tx_refund_prev.assign( - region, - offset, - Some(Word::random_linear_combine( - tx_refund_prev.to_le_bytes(), - block.randomness, - )), - )?; + self.tx_refund_prev + .assign(region, offset, Some(F::from(tx_refund_prev.as_u64())))?; self.gas_cost.assign( region, diff --git a/zkevm-circuits/src/evm_circuit/witness.rs b/zkevm-circuits/src/evm_circuit/witness.rs index eb5b54bc92..40bd25f4ce 100644 --- a/zkevm-circuits/src/evm_circuit/witness.rs +++ b/zkevm-circuits/src/evm_circuit/witness.rs @@ -683,11 +683,8 @@ impl Rw { F::from(*tx_id as u64), F::zero(), F::zero(), - RandomLinearCombination::random_linear_combine(value.to_le_bytes(), randomness), - RandomLinearCombination::random_linear_combine( - value_prev.to_le_bytes(), - randomness, - ), + F::from(value.as_u64()), + F::from(value_prev.as_u64()), F::zero(), F::zero(), ]