plonky2/src/gadgets/random_access.rs

94 lines
3.0 KiB
Rust
Raw Normal View History

2021-08-04 10:58:07 -07:00
use crate::field::extension_field::target::ExtensionTarget;
use crate::field::extension_field::Extendable;
use crate::gates::random_access::RandomAccessGate;
use crate::iop::target::Target;
use crate::plonk::circuit_builder::CircuitBuilder;
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Checks that a `Target` matches a vector at a non-deterministic index.
/// Note: `index` is not range-checked.
pub fn random_access(
&mut self,
access_index: Target,
claimed_element: ExtensionTarget<D>,
2021-08-12 13:56:45 -07:00
v: Vec<ExtensionTarget<D>>,
2021-08-04 10:58:07 -07:00
) {
let gate = RandomAccessGate::new(v.len());
let gate_index = self.add_gate(gate.clone(), vec![]);
v.iter().enumerate().for_each(|(i, &val)| {
self.route_extension(
val,
ExtensionTarget::from_range(gate_index, gate.wires_list_item(i)),
);
});
self.route(
access_index,
2021-08-19 19:41:18 -07:00
Target::wire(gate_index, gate.wire_access_index()),
2021-08-04 10:58:07 -07:00
);
self.route_extension(
claimed_element,
ExtensionTarget::from_range(gate_index, gate.wires_claimed_element()),
);
}
2021-08-12 13:32:49 -07:00
/// Like `random_access`, but first pads `v` to a given minimum length. This can help to avoid
/// having multiple `RandomAccessGate`s with different sizes.
pub fn random_access_padded(
&mut self,
access_index: Target,
claimed_element: ExtensionTarget<D>,
mut v: Vec<ExtensionTarget<D>>,
min_length: usize,
) {
let zero = self.zero_extension();
if v.len() < min_length {
v.resize(8, zero);
}
self.random_access(access_index, claimed_element, v);
}
2021-08-04 10:58:07 -07:00
}
#[cfg(test)]
mod tests {
use anyhow::Result;
use super::*;
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::field_types::Field;
use crate::iop::witness::PartialWitness;
use crate::plonk::circuit_data::CircuitConfig;
use crate::plonk::verifier::verify;
fn test_random_access_given_len(len_log: usize) -> Result<()> {
type F = CrandallField;
type FF = QuarticCrandallField;
let len = 1 << len_log;
let config = CircuitConfig::large_config();
2021-08-20 11:56:57 +02:00
let pw = PartialWitness::new();
2021-08-04 10:58:07 -07:00
let mut builder = CircuitBuilder::<F, 4>::new(config);
2021-08-04 14:19:06 -07:00
let vec = FF::rand_vec(len);
let v: Vec<_> = vec.iter().map(|x| builder.constant_extension(*x)).collect();
2021-08-04 10:58:07 -07:00
for i in 0..len {
let it = builder.constant(F::from_canonical_usize(i));
let elem = builder.constant_extension(vec[i]);
builder.random_access(it, elem, v.clone());
}
let data = builder.build();
2021-08-06 15:14:38 +02:00
let proof = data.prove(pw)?;
2021-08-04 10:58:07 -07:00
verify(proof, &data.verifier_only, &data.common)
}
#[test]
fn test_random_access() -> Result<()> {
for len_log in 1..3 {
test_random_access_given_len(len_log)?;
}
Ok(())
}
}