Merge remote-tracking branch 'origin/main' into codex

# Conflicts:
#	plonky2/src/gates/lookup.rs
This commit is contained in:
Balazs Komuves 2025-01-30 19:55:27 +01:00
commit d682f58af5
No known key found for this signature in database
GPG Key ID: F63B7AEF18435562
14 changed files with 94 additions and 44 deletions

View File

@ -369,7 +369,7 @@ pub trait Field:
let mut product = Self::ONE;
for j in 0..bits_u64(power) {
if (power >> j & 1) != 0 {
if ((power >> j) & 1) != 0 {
product *= current;
}
current = current.square();

View File

@ -1,7 +1,7 @@
[package]
name = "plonky2"
description = "Recursive SNARKs based on PLONK and FRI"
version = "1.0.0"
version = "1.0.1"
authors = ["Daniel Lubarov <daniel@lubarov.com>", "William Borgeaud <williamborgeaud@gmail.com>", "Nicholas Ward <npward@berkeley.edu>"]
readme = "README.md"
edition.workspace = true

View File

@ -16,7 +16,8 @@ use plonky2::plonk::verifier::{VerifierOptions, HashStatisticsPrintLevel};
use env_logger;
pub const N_PRIMES: usize = 512;
pub const N_PRIMES: usize = 512;
pub const TABLE_SIZE: usize = 512; // 19*26;
// table of the first 512 prime numbers
pub const PRIMES_TABLE: [u16; N_PRIMES] = [
@ -101,8 +102,8 @@ fn main() -> Result<()> {
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let indices: [u16; N_PRIMES] = core::array::from_fn( |i| i as u16 );
let my_lut_index = builder.add_lookup_table_from_table( &PRIMES_TABLE , &indices );
let indices: [u16; TABLE_SIZE] = core::array::from_fn( |i| i as u16 );
let my_lut_index = builder.add_lookup_table_from_table( &PRIMES_TABLE[..TABLE_SIZE] , &indices );
// The arithmetic circuit.
let the_a = builder.add_virtual_target();
@ -147,15 +148,13 @@ fn main() -> Result<()> {
};
let proof = data.prove_with_options(pw, &prover_opts)?;
/*
// serialize circuit into JSON
let common_circuit_data_serialized = serde_json::to_string(&data.common ).unwrap();
let verifier_only_circuit_data_serialized = serde_json::to_string(&data.verifier_only).unwrap();
let proof_serialized = serde_json::to_string(&proof ).unwrap();
fs::write("lookup_common_circuit_data.json" , common_circuit_data_serialized) .expect("Unable to write file");
fs::write("lookup_verifier_only_circuit_data.json", verifier_only_circuit_data_serialized).expect("Unable to write file");
fs::write("lookup_proof_with_public_inputs.json" , proof_serialized) .expect("Unable to write file");
*/
fs::write("lookup_common.json" , common_circuit_data_serialized) .expect("Unable to write file");
fs::write("lookup_vkey.json" , verifier_only_circuit_data_serialized).expect("Unable to write file");
fs::write("lookup_proof.json" , proof_serialized) .expect("Unable to write file");
println!("the arithmetic progression `q[i] := {}*i + {}` for 0<=i<{} are all primes!",proof.public_inputs[0],proof.public_inputs[1],nn);
println!("sum of the indices of these primes = {}",proof.public_inputs[2]);

View File

@ -470,7 +470,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
if j != 0 {
current = self.square_extension(current);
}
if (exponent >> j & 1) != 0 {
if ((exponent >> j) & 1) != 0 {
product = self.mul_extension(product, current);
}
}

View File

@ -198,9 +198,9 @@ impl<F: RichField + Extendable<D>, const B: usize, const D: usize> SimpleGenerat
) -> Result<()> {
let sum_value = witness
.get_target(Target::wire(self.row, BaseSumGate::<B>::WIRE_SUM))
.to_canonical_u64() as usize;
.to_canonical_u64();
debug_assert_eq!(
(0..self.num_limbs).fold(sum_value, |acc, _| acc / B),
(0..self.num_limbs).fold(sum_value, |acc, _| acc / (B as u64)),
0,
"Integer too large to fit in given number of limbs"
);
@ -209,9 +209,9 @@ impl<F: RichField + Extendable<D>, const B: usize, const D: usize> SimpleGenerat
.map(|i| Target::wire(self.row, i));
let limbs_value = (0..self.num_limbs)
.scan(sum_value, |acc, _| {
let tmp = *acc % B;
*acc /= B;
Some(F::from_canonical_usize(tmp))
let tmp = *acc % (B as u64);
*acc /= B as u64;
Some(F::from_canonical_u64(tmp))
})
.collect::<Vec<_>>();

View File

@ -81,7 +81,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for LookupGate {
fn short_id(&self) -> String {
format!("LookupGate:{}",self.num_slots)
}
fn serialize(&self, dst: &mut Vec<u8>, common_data: &CommonCircuitData<F, D>) -> IoResult<()> {
dst.write_usize(self.num_slots)?;
for (i, lut) in common_data.luts.iter().enumerate() {
@ -201,14 +201,10 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for Loo
let get_wire = |wire: usize| -> F { witness.get_target(Target::wire(self.row, wire)) };
let input_val = get_wire(LookupGate::wire_ith_looking_inp(self.slot_nb));
let idx_candidate: usize = input_val.to_canonical_u64() as usize;
let ((input, output), ok) = if idx_candidate < self.lut.len() {
(self.lut[idx_candidate], true)
}
else {
((0,0), false)
};
if ok && (input_val == F::from_canonical_u16(input)) {
if (input_val.to_canonical_u64() as usize) < self.lut.len()
&& input_val == F::from_canonical_u16(self.lut[input_val.to_canonical_u64() as usize].0)
{
let (_, output) = self.lut[input_val.to_canonical_u64() as usize];
let output_val = F::from_canonical_u16(output);
let out_wire = Target::wire(self.row, LookupGate::wire_ith_looking_out(self.slot_nb));

View File

@ -228,9 +228,11 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F, D> for Loo
out_buffer.set_target(slot_input_target, F::from_canonical_usize(input as usize))?;
out_buffer.set_target(slot_output_target, F::from_canonical_usize(output as usize))
} else {
// Pad with zeros.
out_buffer.set_target(slot_input_target, F::ZERO)?;
out_buffer.set_target(slot_output_target, F::ZERO)
// Pad with first element in the LUT.
assert!(!self.lut.is_empty(), "Empty LUTs are not supported.");
let (input, output) = self.lut[0];
out_buffer.set_target(slot_input_target, F::from_canonical_usize(input as usize))?;
out_buffer.set_target(slot_output_target, F::from_canonical_usize(output as usize))
}
}

View File

@ -1,7 +1,9 @@
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use core::fmt;
use anyhow::ensure;
use serde::de::{self, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::field::goldilocks_field::GoldilocksField;
@ -193,19 +195,52 @@ impl<F: RichField, const N: usize> GenericHashOut<F> for BytesHash<N> {
}
impl<const N: usize> Serialize for BytesHash<N> {
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
todo!()
serializer.serialize_bytes(&self.0)
}
}
struct ByteHashVisitor<const N: usize>;
impl<'de, const N: usize> Visitor<'de> for ByteHashVisitor<N> {
type Value = BytesHash<N>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "an array containing exactly {} bytes", N)
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: de::SeqAccess<'de>,
{
let mut bytes = [0u8; N];
for i in 0..N {
let next_element = seq.next_element()?;
match next_element {
Some(value) => bytes[i] = value,
None => return Err(de::Error::invalid_length(i, &self)),
}
}
Ok(BytesHash(bytes))
}
fn visit_bytes<E>(self, s: &[u8]) -> Result<Self::Value, E>
where
E: de::Error,
{
let bytes = s.try_into().unwrap();
Ok(BytesHash(bytes))
}
}
impl<'de, const N: usize> Deserialize<'de> for BytesHash<N> {
fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
todo!()
deserializer.deserialize_seq(ByteHashVisitor::<N>)
}
}

View File

@ -36,10 +36,17 @@ pub(crate) fn get_lut_poly<F: RichField + Extendable<D>, const D: usize>(
let b = deltas[LookupChallenges::ChallengeB as usize];
let mut coeffs = Vec::with_capacity(common_data.luts[lut_index].len());
let n = common_data.luts[lut_index].len();
let nb_padded_elts = LookupTableGate::num_slots(&common_data.config)
- n % LookupTableGate::num_slots(&common_data.config);
let (padding_inp, padding_out) = common_data.luts[lut_index][0];
for (input, output) in common_data.luts[lut_index].iter() {
coeffs.push(F::from_canonical_u16(*input) + b * F::from_canonical_u16(*output));
}
coeffs.append(&mut vec![F::ZERO; degree - n]);
// Padding with the first element of the LUT.
for _ in 0..nb_padded_elts {
coeffs.push(F::from_canonical_u16(padding_inp) + b * F::from_canonical_u16(padding_out));
}
coeffs.append(&mut vec![F::ZERO; degree - (n + nb_padded_elts)]);
coeffs.reverse();
PolynomialCoeffs::new(coeffs)
}
@ -756,6 +763,9 @@ pub(crate) fn get_lut_poly_circuit<F: RichField + Extendable<D>, const D: usize>
let b = deltas[LookupChallenges::ChallengeB as usize];
let delta = deltas[LookupChallenges::ChallengeDelta as usize];
let n = common_data.luts[lut_index].len();
let nb_padded_elts = LookupTableGate::num_slots(&common_data.config)
- n % LookupTableGate::num_slots(&common_data.config);
let (padding_inp, padding_out) = common_data.luts[lut_index][0];
let mut coeffs: Vec<Target> = common_data.luts[lut_index]
.iter()
.map(|(input, output)| {
@ -763,7 +773,14 @@ pub(crate) fn get_lut_poly_circuit<F: RichField + Extendable<D>, const D: usize>
builder.add_const(temp, F::from_canonical_u16(*input))
})
.collect();
for _ in n..degree {
// Padding with the first element of the LUT.
for _ in 0..nb_padded_elts {
let temp = builder.mul_const(F::from_canonical_u16(padding_out), b);
let temp = builder.add_const(temp, F::from_canonical_u16(padding_inp));
coeffs.push(temp);
}
for _ in (n + nb_padded_elts)..degree {
coeffs.push(builder.zero());
}
coeffs.reverse();

View File

@ -1,10 +1,11 @@
//! A module to help with GateRef serialization
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
pub use alloc::vec::Vec;
#[cfg(feature = "std")]
use std::vec::Vec; // For macros below
pub use std::vec::Vec; // For macros below
pub use log;
use plonky2_field::extension::Extendable;
use crate::gates::gate::GateRef;
@ -51,8 +52,8 @@ macro_rules! get_gate_tag_impl {
Ok(tag)
} else)*
{
log::log!(
log::Level::Error,
$crate::util::serialization::gate_serialization::log::log!(
$crate::util::serialization::gate_serialization::log::Level::Error,
"attempted to serialize gate with id `{}` which is unsupported by this gate serializer",
$gate.0.id()
);

View File

@ -1,7 +1,7 @@
[package]
name = "starky"
description = "Implementation of STARKs"
version = "1.0.0"
version = "1.0.1"
authors = ["Daniel Lubarov <daniel@lubarov.com>", "William Borgeaud <williamborgeaud@gmail.com>"]
readme = "README.md"
edition.workspace = true
@ -27,7 +27,7 @@ serde = { workspace = true, features = ["rc"] }
num-bigint = { version = "0.4.3", default-features = false }
# Local dependencies
plonky2 = { version = "1.0.0", path = "../plonky2", default-features = false }
plonky2 = { version = "1.0.1", path = "../plonky2", default-features = false }
plonky2_maybe_rayon = { version = "1.0.0", path = "../maybe_rayon", default-features = false }
plonky2_util = { version = "1.0.0", path = "../util", default-features = false }

View File

@ -14,8 +14,8 @@
window.onload = function() {
console.log("onload!");
// let fname = "json/fibonacci_witness.json";
// let fname = "json/lookup_witness.json";
let fname = "json/multi_lookup_witness.json";
let fname = "json/lookup_witness.json";
// let fname = "json/multi_lookup_witness.json";
load_witness(fname);
}
</script>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long