Skip to content

Commit

Permalink
WIP: attempt to use hashmap? Not sure it is good.
Browse files Browse the repository at this point in the history
I have been thinking about a memory that has to be initialized first, and use
some interface like RAMlookup to access values, and the protocol is simply
different.
  • Loading branch information
dannywillems committed Sep 23, 2024
1 parent f0e189b commit 0881882
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 10 deletions.
2 changes: 1 addition & 1 deletion arrabiata/src/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ impl<Fp: PrimeField> InterpreterEnv for Env<Fp> {
unimplemented!("TODO")
}

fn load_value(&mut self, _pos: Self::Position) -> Self::Variable {
fn load_value(&mut self, _row: usize, _pos: Self::Position) -> Self::Variable {
unimplemented!("TODO")
}
}
2 changes: 1 addition & 1 deletion arrabiata/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ pub trait InterpreterEnv {
fn save_value(&mut self, pos: Self::Position) -> Self::Variable;

/// Load the latest value saved in the CPU cache for the position [pos].
fn load_value(&mut self, pos: Self::Position) -> Self::Variable;
fn load_value(&mut self, row: usize, pos: Self::Position) -> Self::Variable;
}

/// Run the application
Expand Down
67 changes: 59 additions & 8 deletions arrabiata/src/witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ use num_integer::Integer;
use o1_utils::field_helpers::FieldHelpers;
use poly_commitment::{commitment::CommitmentCurve, srs::SRS, PolyComm, SRS as _};
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use std::time::Instant;
use std::{
collections::{hash_map::Entry, HashMap},
time::Instant,
};

use crate::{
columns::{Column, Gadget},
interpreter::{Instruction, InterpreterEnv, Side},
poseidon_3_60_0_5_5_fp, poseidon_3_60_0_5_5_fq, BIT_DECOMPOSITION_NUMBER_OF_CHUNKS,
MAXIMUM_FIELD_SIZE_IN_BITS, NUMBER_OF_COLUMNS, NUMBER_OF_PUBLIC_INPUTS, NUMBER_OF_SELECTORS,
NUMBER_OF_VALUES_TO_ABSORB_PUBLIC_IO, POSEIDON_ALPHA, POSEIDON_ROUNDS_FULL,
POSEIDON_STATE_SIZE,
MAXIMUM_FIELD_SIZE_IN_BITS, NUMBER_OF_COLUMNS, NUMBER_OF_PERMUTATION_COLUMNS,
NUMBER_OF_PUBLIC_INPUTS, NUMBER_OF_SELECTORS, NUMBER_OF_VALUES_TO_ABSORB_PUBLIC_IO,
POSEIDON_ALPHA, POSEIDON_ROUNDS_FULL, POSEIDON_STATE_SIZE,
};

pub const IVC_STARTING_INSTRUCTION: Instruction = Instruction::Poseidon(0);
Expand Down Expand Up @@ -93,6 +96,20 @@ pub struct Env<
// FIXME: I don't like this design. Feel free to suggest a better solution
pub public_state: [BigInt; NUMBER_OF_PUBLIC_INPUTS],

/// Keep track of the permutations
/// Each value of the array represents a mapping i -> x_i, where i in [n] and
/// x_i is the value at the previous step i.
///
/// When a value is "saved" at step `i`, the mapping from `i` is created,
/// but set to `None`, meaning it has to be "loaded" later.
///
/// TODO: The permutation itself should be part of a setup phase, where we
/// keep track of the the time we accessed the value.
///
/// The permutations are supposed to be on the first
/// [NUMBER_OF_PERMUTATION_COLUMNS], and are only valid on the same column.
pub permutations: [HashMap<usize, (BigInt, Option<usize>)>; NUMBER_OF_PERMUTATION_COLUMNS],

/// Selectors to activate the gadgets.
/// The size of the outer vector must be equal to the number of gadgets in
/// the circuit.
Expand Down Expand Up @@ -800,12 +817,45 @@ where
(x3, y3)
}

fn save_value(&mut self, _pos: Self::Position) -> Self::Variable {
unimplemented!("TODO")
fn save_value(&mut self, pos: Self::Position) -> Self::Variable {
let (Column::X(idx), _) = pos else {
panic!("The 'cache' can only be used on private columns. To load public values, use a lookup argument")
};
assert!(idx < NUMBER_OF_PERMUTATION_COLUMNS, "The permutation argument only works on the first {NUMBER_OF_PERMUTATION_COLUMNS} columns");
let permutation = &mut self.permutations[idx];
// This should never happen as we build from top to bottom, but we never
// know...
if let Entry::Vacant(e) = permutation.entry(idx) {
let v = self.state[idx].clone();
e.insert((v, None));
} else {
panic!("It seems that the index {idx} is already in the permutation, which should never happen has the execution trace is built from top to bottom")
};
self.state[idx].clone()
}

fn load_value(&mut self, _pos: Self::Position) -> Self::Variable {
unimplemented!("TODO")
fn load_value(&mut self, row: usize, pos: Self::Position) -> Self::Variable {
let (Column::X(idx), _) = pos else {
panic!("The 'cache' can only be used on private columns. To load public values, use a lookup argument")
};
assert!(idx < NUMBER_OF_PERMUTATION_COLUMNS, "The permutation argument only works on the first {NUMBER_OF_PERMUTATION_COLUMNS} columns");
if let Some(v) = self.permutations[idx].get_mut(&row) {
match v {
(_, Some(row_prime)) => {
panic!("It seems that the value saved at row {row} has been already read at step {row_prime}")
}
(res, None) => {
let output = (*res).clone();
*v = (output, Some(row))
}
}
} else {
panic!(
"No value has been saved at row {row} for the position {:?}",
pos
)
};
self.permutations[idx].get(&row).unwrap().0.clone()
}
}

Expand Down Expand Up @@ -918,6 +968,7 @@ impl<
state: std::array::from_fn(|_| BigInt::from(0_usize)),
next_state: std::array::from_fn(|_| BigInt::from(0_usize)),
public_state: std::array::from_fn(|_| BigInt::from(0_usize)),
permutations: std::array::from_fn(|_| HashMap::new()),
selectors,
challenges,
current_instruction: IVC_STARTING_INSTRUCTION,
Expand Down

0 comments on commit 0881882

Please sign in to comment.