Add constants to the RAM gate

This commit is contained in:
wborgeaud 2022-03-31 08:29:05 +02:00
parent e50e668f7e
commit e2de88d145
5 changed files with 46 additions and 22 deletions

View File

@ -86,7 +86,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let min_wires = random_access.num_wires().max(interpolation_wires);
let min_routed_wires = random_access
.num_routed_wires()
.num_ram_wires()
.max(interpolation_routed_wires);
assert!(

View File

@ -159,7 +159,7 @@ mod tests {
#[test]
fn low_degree() {
let num_consts = CircuitConfig::standard_recursion_config().constant_gate_size;
let num_consts = CircuitConfig::standard_recursion_config().num_constants;
let gate = ConstantGate { num_consts };
test_low_degree::<GoldilocksField, _, 2>(gate)
}
@ -169,7 +169,7 @@ mod tests {
const D: usize = 2;
type C = PoseidonGoldilocksConfig;
type F = <C as GenericConfig<D>>::F;
let num_consts = CircuitConfig::standard_recursion_config().constant_gate_size;
let num_consts = CircuitConfig::standard_recursion_config().num_constants;
let gate = ConstantGate { num_consts };
test_eval_fns::<F, C, _, D>(gate)
}

View File

@ -26,14 +26,16 @@ use crate::plonk::vars::{
pub(crate) struct RandomAccessGate<F: RichField + Extendable<D>, const D: usize> {
pub bits: usize,
pub num_copies: usize,
pub num_extra_constants: usize,
_phantom: PhantomData<F>,
}
impl<F: RichField + Extendable<D>, const D: usize> RandomAccessGate<F, D> {
fn new(num_copies: usize, bits: usize) -> Self {
fn new(num_copies: usize, bits: usize, num_extra_constants: usize) -> Self {
Self {
bits,
num_copies,
num_extra_constants,
_phantom: PhantomData,
}
}
@ -45,7 +47,7 @@ impl<F: RichField + Extendable<D>, const D: usize> RandomAccessGate<F, D> {
// Need `(2 + vec_size + bits) * num_copies` wires
config.num_wires / (2 + vec_size + bits),
);
Self::new(max_copies, bits)
Self::new(max_copies, bits, config.num_constants)
}
fn vec_size(&self) -> usize {
@ -68,12 +70,17 @@ impl<F: RichField + Extendable<D>, const D: usize> RandomAccessGate<F, D> {
(2 + self.vec_size()) * copy + 2 + i
}
fn start_of_intermediate_wires(&self) -> usize {
pub(crate) fn num_ram_wires(&self) -> usize {
(2 + self.vec_size()) * self.num_copies
}
pub(crate) fn num_routed_wires(&self) -> usize {
self.start_of_intermediate_wires()
fn wire_extra_constant(&self, i: usize) -> usize {
debug_assert!(i < self.num_extra_constants);
self.num_ram_wires() + i
}
fn num_routed_wires(&self) -> usize {
self.num_ram_wires() + self.num_extra_constants
}
/// An intermediate wire where the prover gives the (purported) binary decomposition of the
@ -81,7 +88,7 @@ impl<F: RichField + Extendable<D>, const D: usize> RandomAccessGate<F, D> {
pub fn wire_bit(&self, i: usize, copy: usize) -> usize {
debug_assert!(i < self.bits);
debug_assert!(copy < self.num_copies);
self.start_of_intermediate_wires() + copy * self.bits + i
self.num_routed_wires() + copy * self.bits + i
}
}
@ -129,6 +136,11 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for RandomAccessGa
constraints.push(list_items[0] - claimed_element);
}
constraints.extend(
(0..self.num_extra_constants)
.map(|i| vars.local_constants[i] - vars.local_wires[self.wire_extra_constant(i)]),
);
constraints
}
@ -189,14 +201,22 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for RandomAccessGa
constraints.push(builder.sub_extension(list_items[0], claimed_element));
}
constraints.extend((0..self.num_extra_constants).map(|i| {
builder.sub_extension(
vars.local_constants[i],
vars.local_wires[self.wire_extra_constant(i)],
)
}));
constraints
}
fn generators(
&self,
gate_index: usize,
_local_constants: &[F],
local_constants: &[F],
) -> Vec<Box<dyn WitnessGenerator<F>>> {
let constants = local_constants[..self.num_extra_constants].to_vec();
(0..self.num_copies)
.map(|copy| {
let g: Box<dyn WitnessGenerator<F>> = Box::new(
@ -204,6 +224,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for RandomAccessGa
gate_index,
gate: *self,
copy,
constants: constants.to_vec(),
}
.adapter(),
);
@ -270,6 +291,10 @@ impl<F: RichField + Extendable<D>, const D: usize> PackedEvaluableBase<F, D>
debug_assert_eq!(list_items.len(), 1);
yield_constr.one(list_items[0] - claimed_element);
}
yield_constr.many(
(0..self.num_extra_constants)
.map(|i| vars.local_constants[i] - vars.local_wires[self.wire_extra_constant(i)]),
);
}
}
@ -278,6 +303,7 @@ struct RandomAccessGenerator<F: RichField + Extendable<D>, const D: usize> {
gate_index: usize,
gate: RandomAccessGate<F, D>,
copy: usize,
constants: Vec<F>,
}
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
@ -323,6 +349,10 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
let bit = F::from_bool(((access_index >> i) & 1) != 0);
set_local_wire(self.gate.wire_bit(i, copy), bit);
}
for (i, &c) in self.constants.iter().enumerate() {
set_local_wire(self.gate.wire_extra_constant(i), c);
}
}
}
@ -344,7 +374,7 @@ mod tests {
#[test]
fn low_degree() {
test_low_degree::<GoldilocksField, _, 4>(RandomAccessGate::new(4, 4));
test_low_degree::<GoldilocksField, _, 4>(RandomAccessGate::new(4, 4, 1));
}
#[test]
@ -352,7 +382,7 @@ mod tests {
const D: usize = 2;
type C = PoseidonGoldilocksConfig;
type F = <C as GenericConfig<D>>::F;
test_eval_fns::<F, C, _, D>(RandomAccessGate::new(4, 4))
test_eval_fns::<F, C, _, D>(RandomAccessGate::new(4, 4, 1))
}
#[test]
@ -404,6 +434,7 @@ mod tests {
let gate = RandomAccessGate::<F, D> {
bits,
num_copies,
num_extra_constants: 1,
_phantom: PhantomData,
};

View File

@ -321,14 +321,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
return target;
}
let num_consts = self.config.constant_gate_size;
// We will fill this `ConstantGate` with zero constants initially.
// These will be overwritten by `constant` as the gate instances are filled.
let gate = ConstantGate { num_consts };
let (gate, instance) = self.find_slot(gate, &[], &vec![F::ZERO; num_consts]);
let target = Target::wire(gate, instance);
self.gate_instances[gate].constants[instance] = c;
let target = self.add_virtual_target();
self.constants_to_targets.insert(c, target);
self.targets_to_constants.insert(target, c);

View File

@ -33,7 +33,7 @@ use crate::util::timing::TimingTree;
pub struct CircuitConfig {
pub num_wires: usize,
pub num_routed_wires: usize,
pub constant_gate_size: usize,
pub num_constants: usize,
/// Whether to use a dedicated gate for base field arithmetic, rather than using a single gate
/// for both base field and extension field arithmetic.
pub use_base_arithmetic_gate: bool,
@ -64,7 +64,7 @@ impl CircuitConfig {
Self {
num_wires: 135,
num_routed_wires: 80,
constant_gate_size: 5,
num_constants: 5,
use_base_arithmetic_gate: true,
security_bits: 100,
num_challenges: 2,