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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion gadgets/src/binary_number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ where
/// - creating expressions (via the Config) that evaluate to 1 when the bits
/// match a specific value and 0 otherwise.
#[derive(Clone, Debug)]
pub struct BinaryNumberChip<F: Field, T, const N: usize> {
pub struct BinaryNumberChip<F, T, const N: usize> {
config: BinaryNumberConfig<T, N>,
_marker: PhantomData<F>,
}
Expand All @@ -122,6 +122,7 @@ where
pub fn configure(
meta: &mut ConstraintSystem<F>,
selector: Column<Fixed>,
value: Option<Column<Advice>>,
) -> BinaryNumberConfig<T, N> {
let bits = [0; N].map(|_| meta.advice_column());
bits.map(|bit| {
Expand All @@ -137,6 +138,17 @@ where
_marker: PhantomData,
};

if let Some(value) = value {
meta.create_gate("binary number value", |meta| {
let selector = meta.query_fixed(selector, Rotation::cur());
vec![
selector
* (config.value(Rotation::cur())(meta)
- meta.query_advice(value, Rotation::cur())),
]
});
}

// Disallow bit patterns (if any) that don't correspond to a variant of T.
let valid_values: BTreeSet<usize> = T::iter().map(|t| from_bits(&t.as_bits())).collect();
let mut invalid_values = (0..1 << N).filter(|i| !valid_values.contains(i)).peekable();
Expand Down
9 changes: 6 additions & 3 deletions zkevm-circuits/src/copy_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -770,9 +770,12 @@ mod tests {
config
.tx_table
.load(&mut layouter, &self.block.txs, self.randomness)?;
config
.rw_table
.load(&mut layouter, &self.block.rws, self.randomness)?;
config.rw_table.load(
&mut layouter,
&self.block.rws.table_assignments(),
self.block.state_circuit_pad_to,
self.randomness,
)?;
config.bytecode_table.load(
&mut layouter,
self.block.bytecodes.values(),
Expand Down
10 changes: 7 additions & 3 deletions zkevm-circuits/src/evm_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,9 +264,13 @@ pub mod test {
config
.tx_table
.load(&mut layouter, &self.block.txs, self.block.randomness)?;
config
.rw_table
.load(&mut layouter, &self.block.rws, self.block.randomness)?;
self.block.rws.check_rw_counter_sanity();
config.rw_table.load(
&mut layouter,
&self.block.rws.table_assignments(),
self.block.state_circuit_pad_to,
self.block.randomness,
)?;
config.bytecode_table.load(
&mut layouter,
self.block.bytecodes.values(),
Expand Down
98 changes: 69 additions & 29 deletions zkevm-circuits/src/evm_circuit/witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ pub struct Block<F> {
pub context: BlockContext,
/// Copy events for the EVM circuit's copy table.
pub copy_events: Vec<CopyEvent>,
/// Length to rw table rows in state circuit
pub state_circuit_pad_to: usize,
}

#[derive(Debug, Default, Clone)]
Expand Down Expand Up @@ -377,7 +379,62 @@ impl std::ops::Index<(RwTableTag, usize)> for RwMap {
&self.0.get(&tag).unwrap()[idx]
}
}

impl RwMap {
/// Check rw_counter is continuous and starting from 1
pub fn check_rw_counter_sanity(&self) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i like this check style !!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case the RWs do not pass the sanity check, do we want to panic (the debug_assert_eq will panic)? Or handle the error before loading the RW table?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are two scenarios that cannot satisfy check_rw_counter_sanity. (1)in evm circuit witness is wrong, it is bug so we debug_assert (2) we manually construct test cases for state circuit where rw_counter may not be continuous.

So i only check_rw_counter_sanity in evm circuit assignment, and let it fail if error happens

for (idx, rw_counter) in self
.0
.values()
.flatten()
.map(|r| r.rw_counter())
.sorted()
.enumerate()
{
debug_assert_eq!(idx, rw_counter - 1);
}
}
/// Calculates the number of Rw::Start rows needed.
/// `target_len` is allowed to be 0 as an "auto" mode,
/// then only 1 Rw::Start row will be prepadded.
pub(crate) fn padding_len(rows: &[Rw], target_len: usize) -> usize {
if target_len > rows.len() {
target_len - rows.len()
} else {
if target_len != 0 {
log::error!(
"RwMap::padding_len overflow, target_len: {}, rows.len(): {}",
target_len,
rows.len()
);
}
1
}
}
/// Prepad Rw::Start rows to target length
pub fn table_assignments_prepad(rows: &[Rw], target_len: usize) -> (Vec<Rw>, usize) {
let padding_length = Self::padding_len(rows, target_len);
let padding = (1..=padding_length).map(|rw_counter| Rw::Start { rw_counter });
(
padding.chain(rows.iter().cloned()).collect(),
padding_length,
)
}
/// Build Rws for assignment
pub fn table_assignments(&self) -> Vec<Rw> {
let mut rows: Vec<Rw> = self.0.values().flatten().cloned().collect();
rows.sort_by_key(|row| {
(
row.tag() as u64,
row.id().unwrap_or_default(),
row.address().unwrap_or_default(),
row.field_tag().unwrap_or_default(),
row.storage_key().unwrap_or_default(),
row.rw_counter(),
)
});
rows
}
}
#[derive(Clone, Copy, Debug)]
pub enum Rw {
Start {
Expand Down Expand Up @@ -476,39 +533,21 @@ pub enum Rw {
value: u64,
},
}
#[derive(Default, Clone, Copy)]
pub struct RwRow<F: FieldExt> {
#[derive(Default, Clone, Copy, Debug)]
pub struct RwRow<F> {
pub rw_counter: F,
pub is_write: F,
pub tag: F,
pub key1: F,
pub key2: F,
pub key3: F,
pub key4: F,
pub id: F,
pub address: F,
pub field_tag: F,
pub storage_key: F,
pub value: F,
pub value_prev: F,
pub aux1: F,
pub aux2: F,
}

impl<F: FieldExt> From<[F; 11]> for RwRow<F> {
fn from(row: [F; 11]) -> Self {
Self {
rw_counter: row[0],
is_write: row[1],
tag: row[2],
key1: row[3],
key2: row[4],
key3: row[5],
key4: row[6],
value: row[7],
value_prev: row[8],
aux1: row[9],
aux2: row[10],
}
}
}

impl Rw {
pub fn tx_access_list_value_pair(&self) -> (bool, bool) {
match self {
Expand Down Expand Up @@ -608,10 +647,10 @@ impl Rw {
rw_counter: F::from(self.rw_counter() as u64),
is_write: F::from(self.is_write() as u64),
tag: F::from(self.tag() as u64),
key1: F::from(self.id().unwrap_or_default() as u64),
key2: self.address().unwrap_or_default().to_scalar().unwrap(),
key3: F::from(self.field_tag().unwrap_or_default() as u64),
key4: RandomLinearCombination::random_linear_combine(
id: F::from(self.id().unwrap_or_default() as u64),
address: self.address().unwrap_or_default().to_scalar().unwrap(),
field_tag: F::from(self.field_tag().unwrap_or_default() as u64),
storage_key: RandomLinearCombination::random_linear_combine(
self.storage_key().unwrap_or_default().to_le_bytes(),
randomness,
),
Expand Down Expand Up @@ -1384,5 +1423,6 @@ pub fn block_convert(
})
.collect(),
copy_events: block.copy_events.clone(),
..Default::default()
}
}
Loading