diff --git a/zkevm-circuits/src/evm_circuit/table.rs b/zkevm-circuits/src/evm_circuit/table.rs index 200ba85f8df..8c3d12a38ab 100644 --- a/zkevm-circuits/src/evm_circuit/table.rs +++ b/zkevm-circuits/src/evm_circuit/table.rs @@ -142,8 +142,8 @@ pub struct RwValues { pub storage_key: Word>, pub value: Word>, pub value_prev: Word>, - pub aux1: Expression, - pub aux2: Expression, + pub aux1: Expression, // for AccountStorage::tx_id + pub aux2: Word>, // for AccountStorage committed value } impl RwValues { @@ -156,7 +156,7 @@ impl RwValues { value: Word>, value_prev: Word>, aux1: Expression, - aux2: Expression, + aux2: Word>, ) -> Self { Self { id, @@ -338,7 +338,8 @@ impl Lookup { values.value_prev.lo().clone(), values.value_prev.hi().clone(), values.aux1.clone(), - values.aux2.clone(), + values.aux2.lo().clone(), + values.aux2.hi().clone(), ], Self::Bytecode { hash, diff --git a/zkevm-circuits/src/evm_circuit/util/common_gadget.rs b/zkevm-circuits/src/evm_circuit/util/common_gadget.rs index f80da5c26c7..2607f4ca6ea 100644 --- a/zkevm-circuits/src/evm_circuit/util/common_gadget.rs +++ b/zkevm-circuits/src/evm_circuit/util/common_gadget.rs @@ -622,10 +622,10 @@ impl CommonCallGadget let gas_word = cb.query_word32(); let callee_address_word = cb.query_account_address(); let value = cb.query_word32(); - let cd_offset = cb.query_word32(); - let cd_length = cb.query_word32(); - let rd_offset = cb.query_word32(); - let rd_length = cb.query_word32(); + let cd_offset = cb.query_word_unchecked(); + let cd_length = cb.query_memory_address(); + let rd_offset = cb.query_word_unchecked(); + let rd_length = cb.query_memory_address(); let is_success = cb.query_bool(); // Lookup values from stack diff --git a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs index 69e223aa2d8..152089e5c53 100644 --- a/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs +++ b/zkevm-circuits/src/evm_circuit/util/constraint_builder.rs @@ -899,7 +899,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> { value, value_prev, 0.expr(), - 0.expr(), + Word::zero(), ), reversion_info, ); @@ -923,7 +923,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> { value.clone(), value, 0.expr(), - 0.expr(), + Word::zero(), ), ); } @@ -948,7 +948,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> { value, value_prev, 0.expr(), - 0.expr(), + Word::zero(), ), reversion_info, ); @@ -973,7 +973,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> { value.clone(), value, 0.expr(), - 0.expr(), + Word::zero(), ), ); } @@ -993,7 +993,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> { value.clone(), value, 0.expr(), - 0.expr(), + Word::zero(), ), ); } @@ -1016,7 +1016,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> { value, value_prev, 0.expr(), - 0.expr(), + Word::zero(), ), reversion_info, ); @@ -1042,7 +1042,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> { value.clone(), value, 0.expr(), - 0.expr(), + Word::zero(), ), ); } @@ -1066,7 +1066,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> { value, value_prev, 0.expr(), - 0.expr(), + Word::zero(), ), reversion_info, ); @@ -1080,7 +1080,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> { key: Word>, value: Word>, tx_id: Expression, - committed_value: Expression, + committed_value: Word>, ) { self.rw_lookup( "account_storage_read", @@ -1107,7 +1107,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> { value: Word>, value_prev: Word>, tx_id: Expression, - committed_value: Expression, + committed_value: Word>, reversion_info: Option<&mut ReversionInfo>, ) { self.reversible_write( @@ -1175,7 +1175,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> { value, Word::zero(), 0.expr(), - 0.expr(), + Word::zero(), ), ); } @@ -1198,7 +1198,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> { value, Word::zero(), 0.expr(), - 0.expr(), + Word::zero(), ), ); } @@ -1287,7 +1287,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> { value, Word::zero(), 0.expr(), - 0.expr(), + Word::zero(), ), ); } @@ -1314,7 +1314,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> { Word::from_lo_unchecked(byte), Word::zero(), 0.expr(), - 0.expr(), + Word::zero(), ), ); } @@ -1340,7 +1340,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> { Word::from_lo_unchecked(value), Word::zero(), 0.expr(), - 0.expr(), + Word::zero(), ), ); } @@ -1367,7 +1367,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> { Word::from_lo_unchecked(value), Word::zero(), 0.expr(), - 0.expr(), + Word::zero(), ), ); } @@ -1388,7 +1388,7 @@ impl<'a, F: Field> EVMConstraintBuilder<'a, F> { value: Word::zero(), value_prev: Word::zero(), aux1: 0.expr(), - aux2: 0.expr(), + aux2: Word::zero(), }, ); } diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/lt_word.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/lt_word.rs index d4fe7266dea..5466106a810 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/lt_word.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/lt_word.rs @@ -84,7 +84,8 @@ mod tests { fn configure_gadget_container(cb: &mut EVMConstraintBuilder) -> Self { let a = cb.query_word32(); let b = cb.query_word32(); - let ltword_gadget = LtWordGadget::::construct(cb, &a, &b); + let ltword_gadget = + LtWordGadget::, Word32Cell>::construct(cb, a, b); cb.require_equal("a < b", ltword_gadget.expr(), 1.expr()); LtWordTestContainer { ltword_gadget, diff --git a/zkevm-circuits/src/evm_circuit/util/math_gadget/modulo.rs b/zkevm-circuits/src/evm_circuit/util/math_gadget/modulo.rs index 344647e9ce8..833928c9c09 100644 --- a/zkevm-circuits/src/evm_circuit/util/math_gadget/modulo.rs +++ b/zkevm-circuits/src/evm_circuit/util/math_gadget/modulo.rs @@ -40,7 +40,7 @@ impl ModGadget { let a_or_is_zero = IsZeroWordGadget::construct(cb, a_or_zero.clone()); let mul_add_words = MulAddWordsGadget::construct(cb, [&k, n, r, &a_or_zero]); let eq = IsEqualWordGadget::construct(cb, a.clone(), a_or_zero); - let lt = LtWordGadget::construct(cb, r, n); + let lt = LtWordGadget::construct(cb, r.clone(), n.clone()); // Constrain the aux variable a_or_zero to be =a or =0 if n==0: // (a == a_or_zero) ^ (n == 0 & a_or_zero == 0) cb.add_constraint( diff --git a/zkevm-circuits/src/evm_circuit/util/memory_gadget.rs b/zkevm-circuits/src/evm_circuit/util/memory_gadget.rs index 7c84af70dc3..c05b28b63f1 100644 --- a/zkevm-circuits/src/evm_circuit/util/memory_gadget.rs +++ b/zkevm-circuits/src/evm_circuit/util/memory_gadget.rs @@ -1,19 +1,16 @@ -use super::{constraint_builder::ConstrainBuilderCommon, CachedRegion}; +use super::{constraint_builder::ConstrainBuilderCommon, CachedRegion, MemoryAddress}; use crate::{ evm_circuit::{ param::{N_BYTES_GAS, N_BYTES_MEMORY_ADDRESS, N_BYTES_MEMORY_WORD_SIZE}, util::{ constraint_builder::EVMConstraintBuilder, from_bytes, - math_gadget::{ - ConstantDivisionGadget, IsZeroGadget, IsZeroWordGadget, MinMaxGadget, - RangeCheckGadget, - }, + math_gadget::{ConstantDivisionGadget, IsZeroGadget, MinMaxGadget, RangeCheckGadget}, select, sum, Cell, }, }, util::{ - word::{Word, Word32Cell}, + word::{Word, WordCell, WordExpr}, Expr, }, }; @@ -69,21 +66,31 @@ pub(crate) mod address_high { /// the RLC value for `memory_offset` need not match the bytes. #[derive(Clone, Debug)] pub(crate) struct MemoryAddressGadget { - memory_offset: Word32Cell, - memory_length: Word32Cell, - memory_length_is_zero: IsZeroWordGadget>, + memory_offset_bytes: MemoryAddress, + memory_length: MemoryAddress, + memory_length_is_zero: IsZeroGadget, } impl MemoryAddressGadget { pub(crate) fn construct( cb: &mut EVMConstraintBuilder, - memory_offset: Word32Cell, - memory_length: Word32Cell, + memory_offset_word: WordCell, + memory_length: MemoryAddress, ) -> Self { - let memory_length_is_zero = IsZeroWordGadget::construct(cb, memory_length); + let memory_length_is_zero = IsZeroGadget::construct(cb, sum::expr(&memory_length.cells)); + let memory_offset_bytes = cb.query_memory_address(); + + let has_length = 1.expr() - memory_length_is_zero.expr(); + cb.condition(has_length, |cb| { + cb.require_equal_word( + "Offset decomposition into 5 bytes", + Word::from_lo_unchecked(memory_offset_bytes.expr()), + memory_offset_word.to_word(), + ); + }); Self { - memory_offset, + memory_offset_bytes, memory_length, memory_length_is_zero, } @@ -96,27 +103,33 @@ impl MemoryAddressGadget { memory_offset: U256, memory_length: U256, ) -> Result { + let memory_offset_bytes = memory_offset.to_le_bytes(); + let memory_length_bytes = memory_length.to_le_bytes(); let memory_length_is_zero = memory_length.is_zero(); - self.memory_offset.assign( + self.memory_offset_bytes.assign( region, offset, if memory_length_is_zero { - Some([0u8; 32]) + Some([0; 5]) } else { - Some(memory_offset.to_le_bytes()) + memory_offset_bytes[..N_BYTES_MEMORY_ADDRESS] + .try_into() + .ok() }, )?; - - self.memory_length - .assign(region, offset, Some(memory_length.to_le_bytes()))?; - + self.memory_length.assign( + region, + offset, + memory_length_bytes[..N_BYTES_MEMORY_ADDRESS] + .try_into() + .ok(), + )?; self.memory_length_is_zero - .assign(region, offset, Word::from_u256(memory_length))?; + .assign(region, offset, sum::value(&memory_length_bytes))?; Ok(if memory_length_is_zero { 0 } else { - address_low::value(memory_offset.to_le_bytes()) - + address_low::value(memory_length.to_le_bytes()) + address_low::value(memory_offset_bytes) + address_low::value(memory_length_bytes) }) } @@ -205,7 +218,7 @@ impl // The memory size needs to be updated if this memory access // requires expanding the memory. // `next_memory_word_size < 256**MAX_MEMORY_SIZE_IN_BYTES` - let curr_memory_word_size = cb.curr.state.memory_word_size.word_expr(); + let curr_memory_word_size = cb.curr.state.memory_word_size.expr(); let mut next_memory_word_size = curr_memory_word_size.clone(); let max_memory_word_sizes = array_init(|idx| { let max_memory_word_size = MinMaxGadget::construct( diff --git a/zkevm-circuits/src/table.rs b/zkevm-circuits/src/table.rs index 9851acd880d..62da03c3170 100644 --- a/zkevm-circuits/src/table.rs +++ b/zkevm-circuits/src/table.rs @@ -452,7 +452,7 @@ pub struct RwTable { /// Aux1 pub aux1: Column, /// Aux2 (Committed Value) - pub aux2: Column, + pub aux2: word::Word>, } impl LookupTable for RwTable { @@ -471,7 +471,8 @@ impl LookupTable for RwTable { self.value_prev.lo().clone().into(), self.value_prev.hi().clone().into(), self.aux1.into(), - self.aux2.into(), + self.aux2.lo().clone().into(), + self.aux2.hi().clone().into(), ] } @@ -490,7 +491,8 @@ impl LookupTable for RwTable { String::from("value_prev_lo"), String::from("value_prev_hi"), String::from("aux1"), - String::from("aux2"), + String::from("aux2_lo"), + String::from("aux2_hi"), ] } } @@ -510,7 +512,7 @@ impl RwTable { // It seems that aux1 for the moment is not using randomness // TODO check in a future review aux1: meta.advice_column_in(SecondPhase), - aux2: meta.advice_column_in(SecondPhase), + aux2: word::Word::new([meta.advice_column(), meta.advice_column()]), } } fn assign( diff --git a/zkevm-circuits/src/witness/rw.rs b/zkevm-circuits/src/witness/rw.rs index 345a3309931..dc08b59713a 100644 --- a/zkevm-circuits/src/witness/rw.rs +++ b/zkevm-circuits/src/witness/rw.rs @@ -257,11 +257,11 @@ pub struct RwRow { pub(crate) value: word::Word, pub(crate) value_prev: word::Word, pub(crate) aux1: F, - pub(crate) aux2: F, + pub(crate) aux2: word::Word, } impl RwRow { - pub(crate) fn values(&self) -> [F; 14] { + pub(crate) fn values(&self) -> [F; 15] { [ self.rw_counter, self.is_write, @@ -276,7 +276,8 @@ impl RwRow { self.value_prev.lo().clone(), self.value_prev.hi().clone(), self.aux1, - self.aux2, + self.aux2.lo().clone(), + self.aux2.hi().clone(), ] } pub(crate) fn rlc(&self, randomness: F) -> F {