Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add dummy rows to memory trace #42

Merged
merged 1 commit into from
Nov 12, 2024
Merged
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
64 changes: 63 additions & 1 deletion crates/brainfuck_prover/src/components/memory/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,48 @@ impl MemoryTable {
self.table.iter().find(|r| *r == row)
}

/// Sorts in-place the existing [`MemoryTableRow`] rows in the Memory Table by `mp`.
/// Returns a reference to a row in the Memory Table given its index.
///
/// # Arguments
/// * `index` - The [`usize`] index to search for in the table.
///
/// # Returns
/// An `Option` containing a reference to the matching row if found,
/// or `None` if the row does not exist in the table.
pub fn get_row_from_index(&self, index: usize) -> Option<&MemoryTableRow> {
self.table.get(index)
}

/// Sorts in-place the existing [`MemoryTableRow`] rows in the Memory Table by `mp`, then `clk`.
///
/// Having the rows sorted is required to ensure a correct proof generation (such that the
/// constraints can be verified).
pub fn sort(&mut self) {
self.table.sort_by_key(|x| (x.mp, x.clk));
}

/// Fills the jumps in `clk` with dummy rows.
///
/// Required to ensure the correct sorting of the [`MemoryTable`] in the constraints.
pub fn complete_with_dummy_rows(&mut self) {
let mut new_table = Vec::with_capacity(self.table.len());
let mut prev_row = self.get_row_from_index(0).unwrap();

for row in &self.table {
let next_clk = prev_row.clk + BaseField::one();
if row.mp == prev_row.mp && row.clk > next_clk {
let mut clk = next_clk;
while clk < row.clk {
new_table.push(MemoryTableRow::new_dummy(clk, prev_row.mp, prev_row.mv));
clk += BaseField::one();
}
}
new_table.push(row.clone());
prev_row = row;
}
new_table.shrink_to_fit();
self.table = new_table;
}
}

#[cfg(test)]
Expand Down Expand Up @@ -268,4 +306,28 @@ mod tests {

assert_eq!(memory_table, expected_memory_table);
}

#[test]
fn test_complete_wih_dummy_rows() {
let mut memory_table = MemoryTable::new();
let row1 = MemoryTableRow::new(BaseField::zero(), BaseField::zero(), BaseField::zero());
let row2 = MemoryTableRow::new(BaseField::zero(), BaseField::one(), BaseField::zero());
let row3 = MemoryTableRow::new(BaseField::from(5), BaseField::one(), BaseField::one());
memory_table.add_rows(vec![row3.clone(), row1.clone(), row2.clone()]);
memory_table.sort();
memory_table.complete_with_dummy_rows();

let mut expected_memory_table = MemoryTable::new();
expected_memory_table.add_rows(vec![
row1,
row2,
MemoryTableRow::new_dummy(BaseField::from(1), BaseField::one(), BaseField::zero()),
MemoryTableRow::new_dummy(BaseField::from(2), BaseField::one(), BaseField::zero()),
MemoryTableRow::new_dummy(BaseField::from(3), BaseField::one(), BaseField::zero()),
MemoryTableRow::new_dummy(BaseField::from(4), BaseField::one(), BaseField::zero()),
row3,
]);

assert_eq!(memory_table, expected_memory_table);
}
}