mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-06 15:53:10 +00:00
Fix merge conflicts
This commit is contained in:
parent
bdbc8b6931
commit
288a0b7cf8
@ -1,4 +1,3 @@
|
||||
use crate::field::field_types::{Field, PrimeField};
|
||||
use std::convert::TryInto;
|
||||
|
||||
use crate::field::field_types::{Field, RichField};
|
||||
|
||||
@ -13,7 +13,6 @@ use crate::iop::challenger::RecursiveChallenger;
|
||||
use crate::iop::target::{BoolTarget, Target};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::circuit_data::{CircuitConfig, CommonCircuitData};
|
||||
use crate::plonk::circuit_data::CommonCircuitData;
|
||||
use crate::plonk::config::{AlgebraicConfig, AlgebraicHasher, GenericConfig};
|
||||
use crate::plonk::plonk_common::PlonkPolynomials;
|
||||
use crate::plonk::proof::OpeningSetTarget;
|
||||
@ -24,14 +23,14 @@ use crate::with_context;
|
||||
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
/// Computes P'(x^arity) from {P(x*g^i)}_(i=0..arity), where g is a `arity`-th root of unity
|
||||
/// and P' is the FRI reduced polynomial.
|
||||
fn compute_evaluation(
|
||||
fn compute_evaluation<C: GenericConfig<D, F = F>>(
|
||||
&mut self,
|
||||
x: Target,
|
||||
x_index_within_coset_bits: &[BoolTarget],
|
||||
arity_bits: usize,
|
||||
evals: &[ExtensionTarget<D>],
|
||||
beta: ExtensionTarget<D>,
|
||||
common_data: &CommonCircuitData<F, D>,
|
||||
common_data: &CommonCircuitData<F, C, D>,
|
||||
) -> ExtensionTarget<D> {
|
||||
let arity = 1 << arity_bits;
|
||||
debug_assert_eq!(evals.len(), arity);
|
||||
@ -70,10 +69,10 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
/// Make sure we have enough wires and routed wires to do the FRI checks efficiently. This check
|
||||
/// isn't required -- without it we'd get errors elsewhere in the stack -- but just gives more
|
||||
/// helpful errors.
|
||||
fn check_recursion_config(
|
||||
fn check_recursion_config<C: GenericConfig<D, F = F>>(
|
||||
&self,
|
||||
max_fri_arity_bits: usize,
|
||||
common_data: &CommonCircuitData<F, D>,
|
||||
common_data: &CommonCircuitData<F, C, D>,
|
||||
) {
|
||||
let random_access = RandomAccessGate::<F, D>::new_from_config(
|
||||
&self.config,
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use std::borrow::Borrow;
|
||||
|
||||
use crate::field::extension_field::Extendable;
|
||||
use crate::gates::arithmetic::ArithmeticExtensionGate;
|
||||
use crate::field::field_types::{PrimeField, RichField};
|
||||
use crate::gates::arithmetic_base::ArithmeticGate;
|
||||
use crate::gates::exponentiation::ExponentiationGate;
|
||||
|
||||
@ -4,8 +4,6 @@ use crate::field::extension_field::{Extendable, OEF};
|
||||
use crate::field::field_types::{Field, PrimeField, RichField};
|
||||
use crate::gates::arithmetic_extension::ArithmeticExtensionGate;
|
||||
use crate::gates::multiplication_extension::MulExtensionGate;
|
||||
use crate::field::field_types::{Field, PrimeField};
|
||||
use crate::gates::arithmetic::ArithmeticExtensionGate;
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
|
||||
use crate::iop::target::Target;
|
||||
use crate::iop::witness::{PartitionWitness, Witness};
|
||||
|
||||
@ -248,6 +248,7 @@ mod tests {
|
||||
use rand::Rng;
|
||||
|
||||
use crate::iop::witness::Witness;
|
||||
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||
use crate::{
|
||||
field::goldilocks_field::GoldilocksField,
|
||||
iop::witness::PartialWitness,
|
||||
@ -256,16 +257,19 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_biguint_add() -> Result<()> {
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
type FF = <C as GenericConfig<D>>::FE;
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let x_value = BigUint::from_u128(rng.gen()).unwrap();
|
||||
let y_value = BigUint::from_u128(rng.gen()).unwrap();
|
||||
let expected_z_value = &x_value + &y_value;
|
||||
|
||||
type F = GoldilocksField;
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
let mut pw = PartialWitness::new();
|
||||
let mut builder = CircuitBuilder::<F, 4>::new(config);
|
||||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||
|
||||
let x = builder.add_virtual_biguint_target(x_value.to_u32_digits().len());
|
||||
let y = builder.add_virtual_biguint_target(y_value.to_u32_digits().len());
|
||||
@ -277,13 +281,17 @@ mod tests {
|
||||
pw.set_biguint_target(&y, &y_value);
|
||||
pw.set_biguint_target(&expected_z, &expected_z_value);
|
||||
|
||||
let data = builder.build();
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_biguint_sub() -> Result<()> {
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
type FF = <C as GenericConfig<D>>::FE;
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let mut x_value = BigUint::from_u128(rng.gen()).unwrap();
|
||||
@ -293,10 +301,9 @@ mod tests {
|
||||
}
|
||||
let expected_z_value = &x_value - &y_value;
|
||||
|
||||
type F = GoldilocksField;
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
let pw = PartialWitness::new();
|
||||
let mut builder = CircuitBuilder::<F, 4>::new(config);
|
||||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||
|
||||
let x = builder.constant_biguint(&x_value);
|
||||
let y = builder.constant_biguint(&y_value);
|
||||
@ -305,23 +312,26 @@ mod tests {
|
||||
|
||||
builder.connect_biguint(&z, &expected_z);
|
||||
|
||||
let data = builder.build();
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_biguint_mul() -> Result<()> {
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
type FF = <C as GenericConfig<D>>::FE;
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let x_value = BigUint::from_u128(rng.gen()).unwrap();
|
||||
let y_value = BigUint::from_u128(rng.gen()).unwrap();
|
||||
let expected_z_value = &x_value * &y_value;
|
||||
|
||||
type F = GoldilocksField;
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
let mut pw = PartialWitness::new();
|
||||
let mut builder = CircuitBuilder::<F, 4>::new(config);
|
||||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||
|
||||
let x = builder.add_virtual_biguint_target(x_value.to_u32_digits().len());
|
||||
let y = builder.add_virtual_biguint_target(y_value.to_u32_digits().len());
|
||||
@ -333,22 +343,25 @@ mod tests {
|
||||
pw.set_biguint_target(&y, &y_value);
|
||||
pw.set_biguint_target(&expected_z, &expected_z_value);
|
||||
|
||||
let data = builder.build();
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_biguint_cmp() -> Result<()> {
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
type FF = <C as GenericConfig<D>>::FE;
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let x_value = BigUint::from_u128(rng.gen()).unwrap();
|
||||
let y_value = BigUint::from_u128(rng.gen()).unwrap();
|
||||
|
||||
type F = GoldilocksField;
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
let pw = PartialWitness::new();
|
||||
let mut builder = CircuitBuilder::<F, 4>::new(config);
|
||||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||
|
||||
let x = builder.constant_biguint(&x_value);
|
||||
let y = builder.constant_biguint(&y_value);
|
||||
@ -357,13 +370,17 @@ mod tests {
|
||||
|
||||
builder.connect(cmp.target, expected_cmp.target);
|
||||
|
||||
let data = builder.build();
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_biguint_div_rem() -> Result<()> {
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
type FF = <C as GenericConfig<D>>::FE;
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let mut x_value = BigUint::from_u128(rng.gen()).unwrap();
|
||||
@ -373,10 +390,9 @@ mod tests {
|
||||
}
|
||||
let (expected_div_value, expected_rem_value) = x_value.div_rem(&y_value);
|
||||
|
||||
type F = GoldilocksField;
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
let pw = PartialWitness::new();
|
||||
let mut builder = CircuitBuilder::<F, 4>::new(config);
|
||||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||
|
||||
let x = builder.constant_biguint(&x_value);
|
||||
let y = builder.constant_biguint(&y_value);
|
||||
@ -388,7 +404,7 @@ mod tests {
|
||||
builder.connect_biguint(&div, &expected_div);
|
||||
builder.connect_biguint(&rem, &expected_rem);
|
||||
|
||||
let data = builder.build();
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
}
|
||||
|
||||
@ -186,12 +186,15 @@ mod tests {
|
||||
use crate::iop::witness::PartialWitness;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::circuit_data::CircuitConfig;
|
||||
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||
use crate::plonk::verifier::verify;
|
||||
|
||||
#[test]
|
||||
fn test_curve_point_is_valid() -> Result<()> {
|
||||
type F = GoldilocksField;
|
||||
const D: usize = 4;
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
type FF = <C as GenericConfig<D>>::FE;
|
||||
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
|
||||
@ -205,7 +208,7 @@ mod tests {
|
||||
builder.curve_assert_valid(&g_target);
|
||||
builder.curve_assert_valid(&neg_g_target);
|
||||
|
||||
let data = builder.build();
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
@ -214,8 +217,10 @@ mod tests {
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_curve_point_is_not_valid() {
|
||||
type F = GoldilocksField;
|
||||
const D: usize = 4;
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
type FF = <C as GenericConfig<D>>::FE;
|
||||
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
|
||||
@ -232,7 +237,7 @@ mod tests {
|
||||
|
||||
builder.curve_assert_valid(¬_g_target);
|
||||
|
||||
let data = builder.build();
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
|
||||
verify(proof, &data.verifier_only, &data.common).unwrap();
|
||||
@ -240,8 +245,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_curve_double() -> Result<()> {
|
||||
type F = GoldilocksField;
|
||||
const D: usize = 4;
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
type FF = <C as GenericConfig<D>>::FE;
|
||||
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
|
||||
@ -268,7 +275,7 @@ mod tests {
|
||||
builder.connect_affine_point(&double_g_expected, &double_g_actual);
|
||||
builder.connect_affine_point(&double_neg_g_expected, &double_neg_g_actual);
|
||||
|
||||
let data = builder.build();
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
@ -276,8 +283,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_curve_add() -> Result<()> {
|
||||
type F = GoldilocksField;
|
||||
const D: usize = 4;
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
type FF = <C as GenericConfig<D>>::FE;
|
||||
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
|
||||
@ -297,7 +306,7 @@ mod tests {
|
||||
|
||||
builder.connect_affine_point(&g_plus_2g_expected, &g_plus_2g_actual);
|
||||
|
||||
let data = builder.build();
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
@ -306,8 +315,10 @@ mod tests {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_curve_mul() -> Result<()> {
|
||||
type F = GoldilocksField;
|
||||
const D: usize = 4;
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
type FF = <C as GenericConfig<D>>::FE;
|
||||
|
||||
let config = CircuitConfig {
|
||||
num_routed_wires: 33,
|
||||
@ -331,7 +342,7 @@ mod tests {
|
||||
|
||||
builder.connect_affine_point(&five_g_expected, &five_g_actual);
|
||||
|
||||
let data = builder.build();
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
@ -340,8 +351,10 @@ mod tests {
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_curve_random() -> Result<()> {
|
||||
type F = GoldilocksField;
|
||||
const D: usize = 4;
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
type FF = <C as GenericConfig<D>>::FE;
|
||||
|
||||
let config = CircuitConfig {
|
||||
num_routed_wires: 33,
|
||||
@ -360,7 +373,7 @@ mod tests {
|
||||
let randot_times_two = builder.curve_scalar_mul(&randot, &two_target);
|
||||
builder.connect_affine_point(&randot_doubled, &randot_times_two);
|
||||
|
||||
let data = builder.build();
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
|
||||
@ -4,7 +4,6 @@ use crate::field::extension_field::target::ExtensionTarget;
|
||||
use crate::field::extension_field::Extendable;
|
||||
use crate::field::field_types::RichField;
|
||||
use crate::gates::gate::Gate;
|
||||
use crate::gates::interpolation::InterpolationGate;
|
||||
use crate::iop::target::Target;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
|
||||
@ -113,6 +112,8 @@ mod tests {
|
||||
use crate::field::extension_field::FieldExtension;
|
||||
use crate::field::field_types::Field;
|
||||
use crate::field::interpolation::interpolant;
|
||||
use crate::gates::interpolation::HighDegreeInterpolationGate;
|
||||
use crate::gates::low_degree_interpolation::LowDegreeInterpolationGate;
|
||||
use crate::iop::witness::PartialWitness;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::circuit_data::CircuitConfig;
|
||||
|
||||
@ -76,13 +76,17 @@ mod tests {
|
||||
use crate::iop::witness::PartialWitness;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::circuit_data::CircuitConfig;
|
||||
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||
use crate::plonk::verifier::verify;
|
||||
|
||||
fn test_list_le(size: usize, num_bits: usize) -> Result<()> {
|
||||
type F = GoldilocksField;
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
type FF = <C as GenericConfig<D>>::FE;
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
let pw = PartialWitness::new();
|
||||
let mut builder = CircuitBuilder::<F, 4>::new(config);
|
||||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
@ -120,7 +124,7 @@ mod tests {
|
||||
let expected_result = builder.constant_bool(a_biguint <= b_biguint);
|
||||
builder.connect(result.target, expected_result.target);
|
||||
|
||||
let data = builder.build();
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
}
|
||||
|
||||
@ -219,19 +219,22 @@ mod tests {
|
||||
use crate::iop::witness::PartialWitness;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::circuit_data::CircuitConfig;
|
||||
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||
use crate::plonk::verifier::verify;
|
||||
|
||||
#[test]
|
||||
fn test_nonnative_add() -> Result<()> {
|
||||
type FF = Secp256K1Base;
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
let x_ff = FF::rand();
|
||||
let y_ff = FF::rand();
|
||||
let sum_ff = x_ff + y_ff;
|
||||
|
||||
type F = GoldilocksField;
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
let pw = PartialWitness::new();
|
||||
let mut builder = CircuitBuilder::<F, 4>::new(config);
|
||||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||
|
||||
let x = builder.constant_nonnative(x_ff);
|
||||
let y = builder.constant_nonnative(y_ff);
|
||||
@ -240,7 +243,7 @@ mod tests {
|
||||
let sum_expected = builder.constant_nonnative(sum_ff);
|
||||
builder.connect_nonnative(&sum, &sum_expected);
|
||||
|
||||
let data = builder.build();
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
}
|
||||
@ -248,6 +251,9 @@ mod tests {
|
||||
#[test]
|
||||
fn test_nonnative_sub() -> Result<()> {
|
||||
type FF = Secp256K1Base;
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
let x_ff = FF::rand();
|
||||
let mut y_ff = FF::rand();
|
||||
while y_ff.to_biguint() > x_ff.to_biguint() {
|
||||
@ -255,10 +261,9 @@ mod tests {
|
||||
}
|
||||
let diff_ff = x_ff - y_ff;
|
||||
|
||||
type F = GoldilocksField;
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
let pw = PartialWitness::new();
|
||||
let mut builder = CircuitBuilder::<F, 4>::new(config);
|
||||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||
|
||||
let x = builder.constant_nonnative(x_ff);
|
||||
let y = builder.constant_nonnative(y_ff);
|
||||
@ -267,7 +272,7 @@ mod tests {
|
||||
let diff_expected = builder.constant_nonnative(diff_ff);
|
||||
builder.connect_nonnative(&diff, &diff_expected);
|
||||
|
||||
let data = builder.build();
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
}
|
||||
@ -275,14 +280,16 @@ mod tests {
|
||||
#[test]
|
||||
fn test_nonnative_mul() -> Result<()> {
|
||||
type FF = Secp256K1Base;
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
let x_ff = FF::rand();
|
||||
let y_ff = FF::rand();
|
||||
let product_ff = x_ff * y_ff;
|
||||
|
||||
type F = GoldilocksField;
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
let pw = PartialWitness::new();
|
||||
let mut builder = CircuitBuilder::<F, 4>::new(config);
|
||||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||
|
||||
let x = builder.constant_nonnative(x_ff);
|
||||
let y = builder.constant_nonnative(y_ff);
|
||||
@ -291,7 +298,7 @@ mod tests {
|
||||
let product_expected = builder.constant_nonnative(product_ff);
|
||||
builder.connect_nonnative(&product, &product_expected);
|
||||
|
||||
let data = builder.build();
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
}
|
||||
@ -299,13 +306,15 @@ mod tests {
|
||||
#[test]
|
||||
fn test_nonnative_neg() -> Result<()> {
|
||||
type FF = Secp256K1Base;
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
let x_ff = FF::rand();
|
||||
let neg_x_ff = -x_ff;
|
||||
|
||||
type F = GoldilocksField;
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
let pw = PartialWitness::new();
|
||||
let mut builder = CircuitBuilder::<F, 4>::new(config);
|
||||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||
|
||||
let x = builder.constant_nonnative(x_ff);
|
||||
let neg_x = builder.neg_nonnative(&x);
|
||||
@ -313,7 +322,7 @@ mod tests {
|
||||
let neg_x_expected = builder.constant_nonnative(neg_x_ff);
|
||||
builder.connect_nonnative(&neg_x, &neg_x_expected);
|
||||
|
||||
let data = builder.build();
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
}
|
||||
@ -321,13 +330,15 @@ mod tests {
|
||||
#[test]
|
||||
fn test_nonnative_inv() -> Result<()> {
|
||||
type FF = Secp256K1Base;
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
let x_ff = FF::rand();
|
||||
let inv_x_ff = x_ff.inverse();
|
||||
|
||||
type F = GoldilocksField;
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
let pw = PartialWitness::new();
|
||||
let mut builder = CircuitBuilder::<F, 4>::new(config);
|
||||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||
|
||||
let x = builder.constant_nonnative(x_ff);
|
||||
let inv_x = builder.inv_nonnative(&x);
|
||||
@ -335,7 +346,7 @@ mod tests {
|
||||
let inv_x_expected = builder.constant_nonnative(inv_x_ff);
|
||||
builder.connect_nonnative(&inv_x, &inv_x_expected);
|
||||
|
||||
let data = builder.build();
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw).unwrap();
|
||||
verify(proof, &data.verifier_only, &data.common)
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ impl<const D: usize> PolynomialCoeffsExtAlgebraTarget<D> {
|
||||
powers: &[ExtensionAlgebraTarget<D>],
|
||||
) -> ExtensionAlgebraTarget<D>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
F: Extendable<D>,
|
||||
{
|
||||
debug_assert_eq!(self.0.len(), powers.len() + 1);
|
||||
let acc = self.0[0];
|
||||
|
||||
@ -5,7 +5,6 @@ use itertools::izip;
|
||||
use crate::field::extension_field::Extendable;
|
||||
use crate::field::field_types::{Field, RichField};
|
||||
use crate::gates::assert_le::AssertLessThanGate;
|
||||
use crate::field::field_types::Field;
|
||||
use crate::gates::comparison::ComparisonGate;
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
|
||||
use crate::iop::target::{BoolTarget, Target};
|
||||
|
||||
@ -197,6 +197,7 @@ mod tests {
|
||||
use crate::gates::arithmetic_base::ArithmeticGate;
|
||||
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
|
||||
use crate::plonk::circuit_data::CircuitConfig;
|
||||
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||
|
||||
#[test]
|
||||
fn low_degree() {
|
||||
@ -206,7 +207,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn eval_fns() -> Result<()> {
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
let gate = ArithmeticGate::new_from_config(&CircuitConfig::standard_recursion_config());
|
||||
test_eval_fns::<GoldilocksField, _, 4>(gate)
|
||||
test_eval_fns::<GoldilocksField, C, _, D>(gate)
|
||||
}
|
||||
}
|
||||
|
||||
@ -344,7 +344,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn eval_fns() -> Result<()> {
|
||||
test_eval_fns::<GoldilocksField, _, 4>(U32ArithmeticGate::<GoldilocksField, 4> {
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
test_eval_fns::<GoldilocksField, C, _, D>(U32ArithmeticGate::<GoldilocksField, D> {
|
||||
num_ops: 3,
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
|
||||
@ -439,6 +439,7 @@ mod tests {
|
||||
use crate::gates::gate::Gate;
|
||||
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
|
||||
use crate::hash::hash_types::HashOut;
|
||||
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||
use crate::plonk::vars::EvaluationVars;
|
||||
|
||||
#[test]
|
||||
@ -480,10 +481,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn eval_fns() -> Result<()> {
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
|
||||
let num_bits = 20;
|
||||
let num_chunks = 4;
|
||||
|
||||
test_eval_fns::<GoldilocksField, _, 4>(AssertLessThanGate::<_, 4>::new(
|
||||
test_eval_fns::<GoldilocksField, C, _, D>(AssertLessThanGate::<_, D>::new(
|
||||
num_bits, num_chunks,
|
||||
))
|
||||
}
|
||||
|
||||
@ -227,7 +227,6 @@ mod tests {
|
||||
use crate::field::goldilocks_field::GoldilocksField;
|
||||
use crate::gadgets::interpolation::InterpolationGate;
|
||||
use crate::gates::arithmetic_extension::ArithmeticExtensionGate;
|
||||
use crate::gates::arithmetic::ArithmeticExtensionGate;
|
||||
use crate::gates::base_sum::BaseSumGate;
|
||||
use crate::gates::constant::ConstantGate;
|
||||
use crate::gates::gmimc::GMiMCGate;
|
||||
|
||||
@ -19,7 +19,7 @@ use crate::polynomial::PolynomialCoeffs;
|
||||
/// Interpolation gate with constraints of degree at most `1<<subgroup_bits`.
|
||||
/// `eval_unfiltered_recursively` uses less gates than `LowDegreeInterpolationGate`.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) struct HighDegreeInterpolationGate<F: RichField + Extendable<D>, const D: usize> {
|
||||
pub(crate) struct HighDegreeInterpolationGate<F: Extendable<D>, const D: usize> {
|
||||
pub subgroup_bits: usize,
|
||||
_phantom: PhantomData<F>,
|
||||
}
|
||||
@ -39,7 +39,7 @@ impl<F: Extendable<D>, const D: usize> InterpolationGate<F, D>
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> HighDegreeInterpolationGate<F, D> {
|
||||
impl<F: Extendable<D>, const D: usize> HighDegreeInterpolationGate<F, D> {
|
||||
/// End of wire indices, exclusive.
|
||||
fn end(&self) -> usize {
|
||||
self.start_coeffs() + self.num_points() * D
|
||||
@ -78,9 +78,7 @@ impl<F: RichField + Extendable<D>, const D: usize> HighDegreeInterpolationGate<F
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Extendable<D>, const D: usize> Gate<F, D>
|
||||
for HighDegreeInterpolationGate<F, D>
|
||||
{
|
||||
impl<F: Extendable<D>, const D: usize> Gate<F, D> for HighDegreeInterpolationGate<F, D> {
|
||||
fn id(&self) -> String {
|
||||
format!("{:?}<D={}>", self, D)
|
||||
}
|
||||
|
||||
@ -392,6 +392,7 @@ mod tests {
|
||||
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
|
||||
use crate::gates::low_degree_interpolation::LowDegreeInterpolationGate;
|
||||
use crate::hash::hash_types::HashOut;
|
||||
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||
use crate::plonk::vars::EvaluationVars;
|
||||
use crate::polynomial::PolynomialCoeffs;
|
||||
|
||||
@ -402,7 +403,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn eval_fns() -> Result<()> {
|
||||
test_eval_fns::<GoldilocksField, _, 4>(LowDegreeInterpolationGate::new(4))
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
test_eval_fns::<GoldilocksField, C, _, D>(LowDegreeInterpolationGate::new(4))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@ -189,6 +189,7 @@ mod tests {
|
||||
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
|
||||
use crate::gates::multiplication_extension::MulExtensionGate;
|
||||
use crate::plonk::circuit_data::CircuitConfig;
|
||||
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||
|
||||
#[test]
|
||||
fn low_degree() {
|
||||
@ -198,7 +199,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn eval_fns() -> Result<()> {
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
let gate = MulExtensionGate::new_from_config(&CircuitConfig::standard_recursion_config());
|
||||
test_eval_fns::<GoldilocksField, _, 4>(gate)
|
||||
test_eval_fns::<GoldilocksField, C, _, D>(gate)
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@ impl<F: Extendable<D>, const D: usize> PoseidonGate<F, D> {
|
||||
/// is useful for ordering hashes in Merkle proofs. Otherwise, this should be set to 0.
|
||||
pub const WIRE_SWAP: usize = 2 * SPONGE_WIDTH;
|
||||
|
||||
const START_DELTA: usize = 2 * WIDTH + 1;
|
||||
const START_DELTA: usize = 2 * SPONGE_WIDTH + 1;
|
||||
|
||||
/// A wire which stores `swap * (input[i + 4] - input[i])`; used to compute the swapped inputs.
|
||||
fn wire_delta(i: usize) -> usize {
|
||||
@ -64,11 +64,12 @@ impl<F: Extendable<D>, const D: usize> PoseidonGate<F, D> {
|
||||
"First round S-box inputs are not stored as wires"
|
||||
);
|
||||
debug_assert!(round < poseidon::HALF_N_FULL_ROUNDS);
|
||||
debug_assert!(i < WIDTH);
|
||||
Self::START_FULL_0 + WIDTH * (round - 1) + i
|
||||
debug_assert!(i < SPONGE_WIDTH);
|
||||
Self::START_FULL_0 + SPONGE_WIDTH * (round - 1) + i
|
||||
}
|
||||
|
||||
const START_PARTIAL: usize = Self::START_FULL_0 + WIDTH * (poseidon::HALF_N_FULL_ROUNDS - 1);
|
||||
const START_PARTIAL: usize =
|
||||
Self::START_FULL_0 + SPONGE_WIDTH * (poseidon::HALF_N_FULL_ROUNDS - 1);
|
||||
|
||||
/// A wire which stores the input of the S-box of the `round`-th round of the partial rounds.
|
||||
fn wire_partial_sbox(round: usize) -> usize {
|
||||
@ -82,23 +83,19 @@ impl<F: Extendable<D>, const D: usize> PoseidonGate<F, D> {
|
||||
/// of full rounds.
|
||||
fn wire_full_sbox_1(round: usize, i: usize) -> usize {
|
||||
debug_assert!(round < poseidon::HALF_N_FULL_ROUNDS);
|
||||
debug_assert!(i < WIDTH);
|
||||
Self::START_FULL_1 + WIDTH * round + i
|
||||
debug_assert!(i < SPONGE_WIDTH);
|
||||
Self::START_FULL_1 + SPONGE_WIDTH * round + i
|
||||
}
|
||||
|
||||
/// End of wire indices, exclusive.
|
||||
fn end() -> usize {
|
||||
Self::START_FULL_1 + WIDTH * poseidon::HALF_N_FULL_ROUNDS
|
||||
Self::START_FULL_1 + SPONGE_WIDTH * poseidon::HALF_N_FULL_ROUNDS
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D> + Poseidon<WIDTH>, const D: usize, const WIDTH: usize> Gate<F, D>
|
||||
for PoseidonGate<F, D, WIDTH>
|
||||
where
|
||||
[(); WIDTH - 1]:,
|
||||
{
|
||||
impl<F: Extendable<D>, const D: usize> Gate<F, D> for PoseidonGate<F, D> {
|
||||
fn id(&self) -> String {
|
||||
format!("{:?}<WIDTH={}>", self, WIDTH)
|
||||
format!("{:?}<WIDTH={}>", self, SPONGE_WIDTH)
|
||||
}
|
||||
|
||||
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
|
||||
@ -117,7 +114,7 @@ where
|
||||
}
|
||||
|
||||
// Compute the possibly-swapped input layer.
|
||||
let mut state = [F::Extension::ZERO; WIDTH];
|
||||
let mut state = [F::Extension::ZERO; SPONGE_WIDTH];
|
||||
for i in 0..4 {
|
||||
let delta_i = vars.local_wires[Self::wire_delta(i)];
|
||||
let input_lhs = Self::wire_input(i);
|
||||
@ -125,7 +122,7 @@ where
|
||||
state[i] = vars.local_wires[input_lhs] + delta_i;
|
||||
state[i + 4] = vars.local_wires[input_rhs] - delta_i;
|
||||
}
|
||||
for i in 8..WIDTH {
|
||||
for i in 8..SPONGE_WIDTH {
|
||||
state[i] = vars.local_wires[Self::wire_input(i)];
|
||||
}
|
||||
|
||||
@ -133,54 +130,51 @@ where
|
||||
|
||||
// First set of full rounds.
|
||||
for r in 0..poseidon::HALF_N_FULL_ROUNDS {
|
||||
<F as Poseidon<WIDTH>>::constant_layer_field(&mut state, round_ctr);
|
||||
<F as Poseidon>::constant_layer_field(&mut state, round_ctr);
|
||||
if r != 0 {
|
||||
for i in 0..WIDTH {
|
||||
for i in 0..SPONGE_WIDTH {
|
||||
let sbox_in = vars.local_wires[Self::wire_full_sbox_0(r, i)];
|
||||
constraints.push(state[i] - sbox_in);
|
||||
state[i] = sbox_in;
|
||||
}
|
||||
}
|
||||
<F as Poseidon<WIDTH>>::sbox_layer_field(&mut state);
|
||||
state = <F as Poseidon<WIDTH>>::mds_layer_field(&state);
|
||||
<F as Poseidon>::sbox_layer_field(&mut state);
|
||||
state = <F as Poseidon>::mds_layer_field(&state);
|
||||
round_ctr += 1;
|
||||
}
|
||||
|
||||
// Partial rounds.
|
||||
<F as Poseidon<WIDTH>>::partial_first_constant_layer(&mut state);
|
||||
state = <F as Poseidon<WIDTH>>::mds_partial_layer_init(&state);
|
||||
<F as Poseidon>::partial_first_constant_layer(&mut state);
|
||||
state = <F as Poseidon>::mds_partial_layer_init(&state);
|
||||
for r in 0..(poseidon::N_PARTIAL_ROUNDS - 1) {
|
||||
let sbox_in = vars.local_wires[Self::wire_partial_sbox(r)];
|
||||
constraints.push(state[0] - sbox_in);
|
||||
state[0] = <F as Poseidon<WIDTH>>::sbox_monomial(sbox_in);
|
||||
state[0] += F::Extension::from_canonical_u64(
|
||||
<F as Poseidon<WIDTH>>::FAST_PARTIAL_ROUND_CONSTANTS[r],
|
||||
);
|
||||
state = <F as Poseidon<WIDTH>>::mds_partial_layer_fast_field(&state, r);
|
||||
state[0] = <F as Poseidon>::sbox_monomial(sbox_in);
|
||||
state[0] +=
|
||||
F::Extension::from_canonical_u64(<F as Poseidon>::FAST_PARTIAL_ROUND_CONSTANTS[r]);
|
||||
state = <F as Poseidon>::mds_partial_layer_fast_field(&state, r);
|
||||
}
|
||||
let sbox_in = vars.local_wires[Self::wire_partial_sbox(poseidon::N_PARTIAL_ROUNDS - 1)];
|
||||
constraints.push(state[0] - sbox_in);
|
||||
state[0] = <F as Poseidon<WIDTH>>::sbox_monomial(sbox_in);
|
||||
state = <F as Poseidon<WIDTH>>::mds_partial_layer_fast_field(
|
||||
&state,
|
||||
poseidon::N_PARTIAL_ROUNDS - 1,
|
||||
);
|
||||
state[0] = <F as Poseidon>::sbox_monomial(sbox_in);
|
||||
state =
|
||||
<F as Poseidon>::mds_partial_layer_fast_field(&state, poseidon::N_PARTIAL_ROUNDS - 1);
|
||||
round_ctr += poseidon::N_PARTIAL_ROUNDS;
|
||||
|
||||
// Second set of full rounds.
|
||||
for r in 0..poseidon::HALF_N_FULL_ROUNDS {
|
||||
<F as Poseidon<WIDTH>>::constant_layer_field(&mut state, round_ctr);
|
||||
for i in 0..WIDTH {
|
||||
<F as Poseidon>::constant_layer_field(&mut state, round_ctr);
|
||||
for i in 0..SPONGE_WIDTH {
|
||||
let sbox_in = vars.local_wires[Self::wire_full_sbox_1(r, i)];
|
||||
constraints.push(state[i] - sbox_in);
|
||||
state[i] = sbox_in;
|
||||
}
|
||||
<F as Poseidon<WIDTH>>::sbox_layer_field(&mut state);
|
||||
state = <F as Poseidon<WIDTH>>::mds_layer_field(&state);
|
||||
<F as Poseidon>::sbox_layer_field(&mut state);
|
||||
state = <F as Poseidon>::mds_layer_field(&state);
|
||||
round_ctr += 1;
|
||||
}
|
||||
|
||||
for i in 0..WIDTH {
|
||||
for i in 0..SPONGE_WIDTH {
|
||||
constraints.push(state[i] - vars.local_wires[Self::wire_output(i)]);
|
||||
}
|
||||
|
||||
@ -203,7 +197,7 @@ where
|
||||
}
|
||||
|
||||
// Compute the possibly-swapped input layer.
|
||||
let mut state = [F::ZERO; WIDTH];
|
||||
let mut state = [F::ZERO; SPONGE_WIDTH];
|
||||
for i in 0..4 {
|
||||
let delta_i = vars.local_wires[Self::wire_delta(i)];
|
||||
let input_lhs = Self::wire_input(i);
|
||||
@ -211,7 +205,7 @@ where
|
||||
state[i] = vars.local_wires[input_lhs] + delta_i;
|
||||
state[i + 4] = vars.local_wires[input_rhs] - delta_i;
|
||||
}
|
||||
for i in 8..WIDTH {
|
||||
for i in 8..SPONGE_WIDTH {
|
||||
state[i] = vars.local_wires[Self::wire_input(i)];
|
||||
}
|
||||
|
||||
@ -219,51 +213,49 @@ where
|
||||
|
||||
// First set of full rounds.
|
||||
for r in 0..poseidon::HALF_N_FULL_ROUNDS {
|
||||
<F as Poseidon<WIDTH>>::constant_layer(&mut state, round_ctr);
|
||||
<F as Poseidon>::constant_layer(&mut state, round_ctr);
|
||||
if r != 0 {
|
||||
for i in 0..WIDTH {
|
||||
for i in 0..SPONGE_WIDTH {
|
||||
let sbox_in = vars.local_wires[Self::wire_full_sbox_0(r, i)];
|
||||
constraints.push(state[i] - sbox_in);
|
||||
state[i] = sbox_in;
|
||||
}
|
||||
}
|
||||
<F as Poseidon<WIDTH>>::sbox_layer(&mut state);
|
||||
state = <F as Poseidon<WIDTH>>::mds_layer(&state);
|
||||
<F as Poseidon>::sbox_layer(&mut state);
|
||||
state = <F as Poseidon>::mds_layer(&state);
|
||||
round_ctr += 1;
|
||||
}
|
||||
|
||||
// Partial rounds.
|
||||
<F as Poseidon<WIDTH>>::partial_first_constant_layer(&mut state);
|
||||
state = <F as Poseidon<WIDTH>>::mds_partial_layer_init(&state);
|
||||
<F as Poseidon>::partial_first_constant_layer(&mut state);
|
||||
state = <F as Poseidon>::mds_partial_layer_init(&state);
|
||||
for r in 0..(poseidon::N_PARTIAL_ROUNDS - 1) {
|
||||
let sbox_in = vars.local_wires[Self::wire_partial_sbox(r)];
|
||||
constraints.push(state[0] - sbox_in);
|
||||
state[0] = <F as Poseidon<WIDTH>>::sbox_monomial(sbox_in);
|
||||
state[0] +=
|
||||
F::from_canonical_u64(<F as Poseidon<WIDTH>>::FAST_PARTIAL_ROUND_CONSTANTS[r]);
|
||||
state = <F as Poseidon<WIDTH>>::mds_partial_layer_fast(&state, r);
|
||||
state[0] = <F as Poseidon>::sbox_monomial(sbox_in);
|
||||
state[0] += F::from_canonical_u64(<F as Poseidon>::FAST_PARTIAL_ROUND_CONSTANTS[r]);
|
||||
state = <F as Poseidon>::mds_partial_layer_fast(&state, r);
|
||||
}
|
||||
let sbox_in = vars.local_wires[Self::wire_partial_sbox(poseidon::N_PARTIAL_ROUNDS - 1)];
|
||||
constraints.push(state[0] - sbox_in);
|
||||
state[0] = <F as Poseidon<WIDTH>>::sbox_monomial(sbox_in);
|
||||
state =
|
||||
<F as Poseidon<WIDTH>>::mds_partial_layer_fast(&state, poseidon::N_PARTIAL_ROUNDS - 1);
|
||||
state[0] = <F as Poseidon>::sbox_monomial(sbox_in);
|
||||
state = <F as Poseidon>::mds_partial_layer_fast(&state, poseidon::N_PARTIAL_ROUNDS - 1);
|
||||
round_ctr += poseidon::N_PARTIAL_ROUNDS;
|
||||
|
||||
// Second set of full rounds.
|
||||
for r in 0..poseidon::HALF_N_FULL_ROUNDS {
|
||||
<F as Poseidon<WIDTH>>::constant_layer(&mut state, round_ctr);
|
||||
for i in 0..WIDTH {
|
||||
<F as Poseidon>::constant_layer(&mut state, round_ctr);
|
||||
for i in 0..SPONGE_WIDTH {
|
||||
let sbox_in = vars.local_wires[Self::wire_full_sbox_1(r, i)];
|
||||
constraints.push(state[i] - sbox_in);
|
||||
state[i] = sbox_in;
|
||||
}
|
||||
<F as Poseidon<WIDTH>>::sbox_layer(&mut state);
|
||||
state = <F as Poseidon<WIDTH>>::mds_layer(&state);
|
||||
<F as Poseidon>::sbox_layer(&mut state);
|
||||
state = <F as Poseidon>::mds_layer(&state);
|
||||
round_ctr += 1;
|
||||
}
|
||||
|
||||
for i in 0..WIDTH {
|
||||
for i in 0..SPONGE_WIDTH {
|
||||
constraints.push(state[i] - vars.local_wires[Self::wire_output(i)]);
|
||||
}
|
||||
|
||||
@ -277,7 +269,7 @@ where
|
||||
) -> Vec<ExtensionTarget<D>> {
|
||||
// The naive method is more efficient if we have enough routed wires for PoseidonMdsGate.
|
||||
let use_mds_gate =
|
||||
builder.config.num_routed_wires >= PoseidonMdsGate::<F, D, WIDTH>::new().num_wires();
|
||||
builder.config.num_routed_wires >= PoseidonMdsGate::<F, D>::new().num_wires();
|
||||
|
||||
let mut constraints = Vec::with_capacity(self.num_constraints());
|
||||
|
||||
@ -295,7 +287,7 @@ where
|
||||
}
|
||||
|
||||
// Compute the possibly-swapped input layer.
|
||||
let mut state = [builder.zero_extension(); WIDTH];
|
||||
let mut state = [builder.zero_extension(); SPONGE_WIDTH];
|
||||
for i in 0..4 {
|
||||
let delta_i = vars.local_wires[Self::wire_delta(i)];
|
||||
let input_lhs = vars.local_wires[Self::wire_input(i)];
|
||||
@ -303,7 +295,7 @@ where
|
||||
state[i] = builder.add_extension(input_lhs, delta_i);
|
||||
state[i + 4] = builder.sub_extension(input_rhs, delta_i);
|
||||
}
|
||||
for i in 8..WIDTH {
|
||||
for i in 8..SPONGE_WIDTH {
|
||||
state[i] = vars.local_wires[Self::wire_input(i)];
|
||||
}
|
||||
|
||||
@ -311,47 +303,46 @@ where
|
||||
|
||||
// First set of full rounds.
|
||||
for r in 0..poseidon::HALF_N_FULL_ROUNDS {
|
||||
<F as Poseidon<WIDTH>>::constant_layer_recursive(builder, &mut state, round_ctr);
|
||||
<F as Poseidon>::constant_layer_recursive(builder, &mut state, round_ctr);
|
||||
if r != 0 {
|
||||
for i in 0..WIDTH {
|
||||
for i in 0..SPONGE_WIDTH {
|
||||
let sbox_in = vars.local_wires[Self::wire_full_sbox_0(r, i)];
|
||||
constraints.push(builder.sub_extension(state[i], sbox_in));
|
||||
state[i] = sbox_in;
|
||||
}
|
||||
}
|
||||
<F as Poseidon<WIDTH>>::sbox_layer_recursive(builder, &mut state);
|
||||
state = <F as Poseidon<WIDTH>>::mds_layer_recursive(builder, &state);
|
||||
<F as Poseidon>::sbox_layer_recursive(builder, &mut state);
|
||||
state = <F as Poseidon>::mds_layer_recursive(builder, &state);
|
||||
round_ctr += 1;
|
||||
}
|
||||
|
||||
// Partial rounds.
|
||||
if use_mds_gate {
|
||||
for r in 0..poseidon::N_PARTIAL_ROUNDS {
|
||||
<F as Poseidon<WIDTH>>::constant_layer_recursive(builder, &mut state, round_ctr);
|
||||
<F as Poseidon>::constant_layer_recursive(builder, &mut state, round_ctr);
|
||||
let sbox_in = vars.local_wires[Self::wire_partial_sbox(r)];
|
||||
constraints.push(builder.sub_extension(state[0], sbox_in));
|
||||
state[0] = <F as Poseidon<WIDTH>>::sbox_monomial_recursive(builder, sbox_in);
|
||||
state = <F as Poseidon<WIDTH>>::mds_layer_recursive(builder, &state);
|
||||
state[0] = <F as Poseidon>::sbox_monomial_recursive(builder, sbox_in);
|
||||
state = <F as Poseidon>::mds_layer_recursive(builder, &state);
|
||||
round_ctr += 1;
|
||||
}
|
||||
} else {
|
||||
<F as Poseidon<WIDTH>>::partial_first_constant_layer_recursive(builder, &mut state);
|
||||
state = <F as Poseidon<WIDTH>>::mds_partial_layer_init_recursive(builder, &state);
|
||||
<F as Poseidon>::partial_first_constant_layer_recursive(builder, &mut state);
|
||||
state = <F as Poseidon>::mds_partial_layer_init_recursive(builder, &state);
|
||||
for r in 0..(poseidon::N_PARTIAL_ROUNDS - 1) {
|
||||
let sbox_in = vars.local_wires[Self::wire_partial_sbox(r)];
|
||||
constraints.push(builder.sub_extension(state[0], sbox_in));
|
||||
state[0] = <F as Poseidon<WIDTH>>::sbox_monomial_recursive(builder, sbox_in);
|
||||
let c = <F as Poseidon<WIDTH>>::FAST_PARTIAL_ROUND_CONSTANTS[r];
|
||||
state[0] = <F as Poseidon>::sbox_monomial_recursive(builder, sbox_in);
|
||||
let c = <F as Poseidon>::FAST_PARTIAL_ROUND_CONSTANTS[r];
|
||||
let c = F::Extension::from_canonical_u64(c);
|
||||
let c = builder.constant_extension(c);
|
||||
state[0] = builder.add_extension(state[0], c);
|
||||
state =
|
||||
<F as Poseidon<WIDTH>>::mds_partial_layer_fast_recursive(builder, &state, r);
|
||||
state = <F as Poseidon>::mds_partial_layer_fast_recursive(builder, &state, r);
|
||||
}
|
||||
let sbox_in = vars.local_wires[Self::wire_partial_sbox(poseidon::N_PARTIAL_ROUNDS - 1)];
|
||||
constraints.push(builder.sub_extension(state[0], sbox_in));
|
||||
state[0] = <F as Poseidon<WIDTH>>::sbox_monomial_recursive(builder, sbox_in);
|
||||
state = <F as Poseidon<WIDTH>>::mds_partial_layer_fast_recursive(
|
||||
state[0] = <F as Poseidon>::sbox_monomial_recursive(builder, sbox_in);
|
||||
state = <F as Poseidon>::mds_partial_layer_fast_recursive(
|
||||
builder,
|
||||
&state,
|
||||
poseidon::N_PARTIAL_ROUNDS - 1,
|
||||
@ -361,18 +352,18 @@ where
|
||||
|
||||
// Second set of full rounds.
|
||||
for r in 0..poseidon::HALF_N_FULL_ROUNDS {
|
||||
<F as Poseidon<WIDTH>>::constant_layer_recursive(builder, &mut state, round_ctr);
|
||||
for i in 0..WIDTH {
|
||||
<F as Poseidon>::constant_layer_recursive(builder, &mut state, round_ctr);
|
||||
for i in 0..SPONGE_WIDTH {
|
||||
let sbox_in = vars.local_wires[Self::wire_full_sbox_1(r, i)];
|
||||
constraints.push(builder.sub_extension(state[i], sbox_in));
|
||||
state[i] = sbox_in;
|
||||
}
|
||||
<F as Poseidon<WIDTH>>::sbox_layer_recursive(builder, &mut state);
|
||||
state = <F as Poseidon<WIDTH>>::mds_layer_recursive(builder, &state);
|
||||
<F as Poseidon>::sbox_layer_recursive(builder, &mut state);
|
||||
state = <F as Poseidon>::mds_layer_recursive(builder, &state);
|
||||
round_ctr += 1;
|
||||
}
|
||||
|
||||
for i in 0..WIDTH {
|
||||
for i in 0..SPONGE_WIDTH {
|
||||
constraints
|
||||
.push(builder.sub_extension(state[i], vars.local_wires[Self::wire_output(i)]));
|
||||
}
|
||||
@ -385,7 +376,7 @@ where
|
||||
gate_index: usize,
|
||||
_local_constants: &[F],
|
||||
) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
let gen = PoseidonGenerator::<F, D, WIDTH> {
|
||||
let gen = PoseidonGenerator::<F, D> {
|
||||
gate_index,
|
||||
_phantom: PhantomData,
|
||||
};
|
||||
@ -405,31 +396,27 @@ where
|
||||
}
|
||||
|
||||
fn num_constraints(&self) -> usize {
|
||||
WIDTH * (poseidon::N_FULL_ROUNDS_TOTAL - 1) + poseidon::N_PARTIAL_ROUNDS + WIDTH + 1 + 4
|
||||
SPONGE_WIDTH * (poseidon::N_FULL_ROUNDS_TOTAL - 1)
|
||||
+ poseidon::N_PARTIAL_ROUNDS
|
||||
+ SPONGE_WIDTH
|
||||
+ 1
|
||||
+ 4
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PoseidonGenerator<
|
||||
F: RichField + Extendable<D> + Poseidon<WIDTH>,
|
||||
const D: usize,
|
||||
const WIDTH: usize,
|
||||
> where
|
||||
[(); WIDTH - 1]:,
|
||||
{
|
||||
struct PoseidonGenerator<F: RichField + Extendable<D> + Poseidon, const D: usize> {
|
||||
gate_index: usize,
|
||||
_phantom: PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D> + Poseidon<WIDTH>, const D: usize, const WIDTH: usize>
|
||||
SimpleGenerator<F> for PoseidonGenerator<F, D, WIDTH>
|
||||
where
|
||||
[(); WIDTH - 1]:,
|
||||
impl<F: RichField + Extendable<D> + Poseidon, const D: usize> SimpleGenerator<F>
|
||||
for PoseidonGenerator<F, D>
|
||||
{
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
(0..WIDTH)
|
||||
.map(|i| PoseidonGate::<F, D, WIDTH>::wire_input(i))
|
||||
.chain(Some(PoseidonGate::<F, D, WIDTH>::WIRE_SWAP))
|
||||
(0..SPONGE_WIDTH)
|
||||
.map(|i| PoseidonGate::<F, D>::wire_input(i))
|
||||
.chain(Some(PoseidonGate::<F, D>::WIRE_SWAP))
|
||||
.map(|input| Target::wire(self.gate_index, input))
|
||||
.collect()
|
||||
}
|
||||
@ -440,19 +427,16 @@ where
|
||||
input,
|
||||
};
|
||||
|
||||
let mut state = (0..WIDTH)
|
||||
.map(|i| witness.get_wire(local_wire(PoseidonGate::<F, D, WIDTH>::wire_input(i))))
|
||||
let mut state = (0..SPONGE_WIDTH)
|
||||
.map(|i| witness.get_wire(local_wire(PoseidonGate::<F, D>::wire_input(i))))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let swap_value = witness.get_wire(local_wire(PoseidonGate::<F, D, WIDTH>::WIRE_SWAP));
|
||||
let swap_value = witness.get_wire(local_wire(PoseidonGate::<F, D>::WIRE_SWAP));
|
||||
debug_assert!(swap_value == F::ZERO || swap_value == F::ONE);
|
||||
|
||||
for i in 0..4 {
|
||||
let delta_i = swap_value * (state[i + 4] - state[i]);
|
||||
out_buffer.set_wire(
|
||||
local_wire(PoseidonGate::<F, D, WIDTH>::wire_delta(i)),
|
||||
delta_i,
|
||||
);
|
||||
out_buffer.set_wire(local_wire(PoseidonGate::<F, D>::wire_delta(i)), delta_i);
|
||||
}
|
||||
|
||||
if swap_value == F::ONE {
|
||||
@ -461,67 +445,61 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
let mut state: [F; WIDTH] = state.try_into().unwrap();
|
||||
let mut state: [F; SPONGE_WIDTH] = state.try_into().unwrap();
|
||||
let mut round_ctr = 0;
|
||||
|
||||
for r in 0..poseidon::HALF_N_FULL_ROUNDS {
|
||||
<F as Poseidon<WIDTH>>::constant_layer_field(&mut state, round_ctr);
|
||||
<F as Poseidon>::constant_layer_field(&mut state, round_ctr);
|
||||
if r != 0 {
|
||||
for i in 0..WIDTH {
|
||||
for i in 0..SPONGE_WIDTH {
|
||||
out_buffer.set_wire(
|
||||
local_wire(PoseidonGate::<F, D, WIDTH>::wire_full_sbox_0(r, i)),
|
||||
local_wire(PoseidonGate::<F, D>::wire_full_sbox_0(r, i)),
|
||||
state[i],
|
||||
);
|
||||
}
|
||||
}
|
||||
<F as Poseidon<WIDTH>>::sbox_layer_field(&mut state);
|
||||
state = <F as Poseidon<WIDTH>>::mds_layer_field(&state);
|
||||
<F as Poseidon>::sbox_layer_field(&mut state);
|
||||
state = <F as Poseidon>::mds_layer_field(&state);
|
||||
round_ctr += 1;
|
||||
}
|
||||
|
||||
<F as Poseidon<WIDTH>>::partial_first_constant_layer(&mut state);
|
||||
state = <F as Poseidon<WIDTH>>::mds_partial_layer_init(&state);
|
||||
<F as Poseidon>::partial_first_constant_layer(&mut state);
|
||||
state = <F as Poseidon>::mds_partial_layer_init(&state);
|
||||
for r in 0..(poseidon::N_PARTIAL_ROUNDS - 1) {
|
||||
out_buffer.set_wire(
|
||||
local_wire(PoseidonGate::<F, D, WIDTH>::wire_partial_sbox(r)),
|
||||
local_wire(PoseidonGate::<F, D>::wire_partial_sbox(r)),
|
||||
state[0],
|
||||
);
|
||||
state[0] = <F as Poseidon<WIDTH>>::sbox_monomial(state[0]);
|
||||
state[0] +=
|
||||
F::from_canonical_u64(<F as Poseidon<WIDTH>>::FAST_PARTIAL_ROUND_CONSTANTS[r]);
|
||||
state = <F as Poseidon<WIDTH>>::mds_partial_layer_fast_field(&state, r);
|
||||
state[0] = <F as Poseidon>::sbox_monomial(state[0]);
|
||||
state[0] += F::from_canonical_u64(<F as Poseidon>::FAST_PARTIAL_ROUND_CONSTANTS[r]);
|
||||
state = <F as Poseidon>::mds_partial_layer_fast_field(&state, r);
|
||||
}
|
||||
out_buffer.set_wire(
|
||||
local_wire(PoseidonGate::<F, D, WIDTH>::wire_partial_sbox(
|
||||
local_wire(PoseidonGate::<F, D>::wire_partial_sbox(
|
||||
poseidon::N_PARTIAL_ROUNDS - 1,
|
||||
)),
|
||||
state[0],
|
||||
);
|
||||
state[0] = <F as Poseidon<WIDTH>>::sbox_monomial(state[0]);
|
||||
state = <F as Poseidon<WIDTH>>::mds_partial_layer_fast_field(
|
||||
&state,
|
||||
poseidon::N_PARTIAL_ROUNDS - 1,
|
||||
);
|
||||
state[0] = <F as Poseidon>::sbox_monomial(state[0]);
|
||||
state =
|
||||
<F as Poseidon>::mds_partial_layer_fast_field(&state, poseidon::N_PARTIAL_ROUNDS - 1);
|
||||
round_ctr += poseidon::N_PARTIAL_ROUNDS;
|
||||
|
||||
for r in 0..poseidon::HALF_N_FULL_ROUNDS {
|
||||
<F as Poseidon<WIDTH>>::constant_layer_field(&mut state, round_ctr);
|
||||
for i in 0..WIDTH {
|
||||
<F as Poseidon>::constant_layer_field(&mut state, round_ctr);
|
||||
for i in 0..SPONGE_WIDTH {
|
||||
out_buffer.set_wire(
|
||||
local_wire(PoseidonGate::<F, D, WIDTH>::wire_full_sbox_1(r, i)),
|
||||
local_wire(PoseidonGate::<F, D>::wire_full_sbox_1(r, i)),
|
||||
state[i],
|
||||
);
|
||||
}
|
||||
<F as Poseidon<WIDTH>>::sbox_layer_field(&mut state);
|
||||
state = <F as Poseidon<WIDTH>>::mds_layer_field(&state);
|
||||
<F as Poseidon>::sbox_layer_field(&mut state);
|
||||
state = <F as Poseidon>::mds_layer_field(&state);
|
||||
round_ctr += 1;
|
||||
}
|
||||
|
||||
for i in 0..WIDTH {
|
||||
out_buffer.set_wire(
|
||||
local_wire(PoseidonGate::<F, D, WIDTH>::wire_output(i)),
|
||||
state[i],
|
||||
);
|
||||
for i in 0..SPONGE_WIDTH {
|
||||
out_buffer.set_wire(local_wire(PoseidonGate::<F, D>::wire_output(i)), state[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -546,8 +524,7 @@ mod tests {
|
||||
#[test]
|
||||
fn wire_indices() {
|
||||
type F = GoldilocksField;
|
||||
const WIDTH: usize = 12;
|
||||
type Gate = PoseidonGate<F, 4, WIDTH>;
|
||||
type Gate = PoseidonGate<F, 4>;
|
||||
|
||||
assert_eq!(Gate::wire_input(0), 0);
|
||||
assert_eq!(Gate::wire_input(11), 11);
|
||||
|
||||
@ -7,6 +7,7 @@ use crate::field::extension_field::Extendable;
|
||||
use crate::field::extension_field::FieldExtension;
|
||||
use crate::field::field_types::{Field, RichField};
|
||||
use crate::gates::gate::Gate;
|
||||
use crate::hash::hashing::SPONGE_WIDTH;
|
||||
use crate::hash::poseidon::Poseidon;
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator};
|
||||
use crate::iop::target::Target;
|
||||
@ -15,21 +16,11 @@ use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PoseidonMdsGate<
|
||||
F: RichField + Extendable<D> + Poseidon<WIDTH>,
|
||||
const D: usize,
|
||||
const WIDTH: usize,
|
||||
> where
|
||||
[(); WIDTH - 1]:,
|
||||
{
|
||||
pub struct PoseidonMdsGate<F: RichField + Extendable<D> + Poseidon, const D: usize> {
|
||||
_phantom: PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D> + Poseidon<WIDTH>, const D: usize, const WIDTH: usize>
|
||||
PoseidonMdsGate<F, D, WIDTH>
|
||||
where
|
||||
[(); WIDTH - 1]:,
|
||||
{
|
||||
impl<F: RichField + Extendable<D> + Poseidon, const D: usize> PoseidonMdsGate<F, D> {
|
||||
pub fn new() -> Self {
|
||||
PoseidonMdsGate {
|
||||
_phantom: PhantomData,
|
||||
@ -37,13 +28,13 @@ where
|
||||
}
|
||||
|
||||
pub fn wires_input(i: usize) -> Range<usize> {
|
||||
assert!(i < WIDTH);
|
||||
assert!(i < SPONGE_WIDTH);
|
||||
i * D..(i + 1) * D
|
||||
}
|
||||
|
||||
pub fn wires_output(i: usize) -> Range<usize> {
|
||||
assert!(i < WIDTH);
|
||||
(WIDTH + i) * D..(WIDTH + i + 1) * D
|
||||
assert!(i < SPONGE_WIDTH);
|
||||
(SPONGE_WIDTH + i) * D..(SPONGE_WIDTH + i + 1) * D
|
||||
}
|
||||
|
||||
// Following are methods analogous to ones in `Poseidon`, but for extension algebras.
|
||||
@ -51,15 +42,14 @@ where
|
||||
/// Same as `mds_row_shf` for an extension algebra of `F`.
|
||||
fn mds_row_shf_algebra(
|
||||
r: usize,
|
||||
v: &[ExtensionAlgebra<F::Extension, D>; WIDTH],
|
||||
v: &[ExtensionAlgebra<F::Extension, D>; SPONGE_WIDTH],
|
||||
) -> ExtensionAlgebra<F::Extension, D> {
|
||||
debug_assert!(r < WIDTH);
|
||||
debug_assert!(r < SPONGE_WIDTH);
|
||||
let mut res = ExtensionAlgebra::ZERO;
|
||||
|
||||
for i in 0..WIDTH {
|
||||
let coeff =
|
||||
F::Extension::from_canonical_u64(1 << <F as Poseidon<WIDTH>>::MDS_MATRIX_EXPS[i]);
|
||||
res += v[(i + r) % WIDTH].scalar_mul(coeff);
|
||||
for i in 0..SPONGE_WIDTH {
|
||||
let coeff = F::Extension::from_canonical_u64(1 << <F as Poseidon>::MDS_MATRIX_EXPS[i]);
|
||||
res += v[(i + r) % SPONGE_WIDTH].scalar_mul(coeff);
|
||||
}
|
||||
|
||||
res
|
||||
@ -69,16 +59,16 @@ where
|
||||
fn mds_row_shf_algebra_recursive(
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
r: usize,
|
||||
v: &[ExtensionAlgebraTarget<D>; WIDTH],
|
||||
v: &[ExtensionAlgebraTarget<D>; SPONGE_WIDTH],
|
||||
) -> ExtensionAlgebraTarget<D> {
|
||||
debug_assert!(r < WIDTH);
|
||||
debug_assert!(r < SPONGE_WIDTH);
|
||||
let mut res = builder.zero_ext_algebra();
|
||||
|
||||
for i in 0..WIDTH {
|
||||
for i in 0..SPONGE_WIDTH {
|
||||
let coeff = builder.constant_extension(F::Extension::from_canonical_u64(
|
||||
1 << <F as Poseidon<WIDTH>>::MDS_MATRIX_EXPS[i],
|
||||
1 << <F as Poseidon>::MDS_MATRIX_EXPS[i],
|
||||
));
|
||||
res = builder.scalar_mul_add_ext_algebra(coeff, v[(i + r) % WIDTH], res);
|
||||
res = builder.scalar_mul_add_ext_algebra(coeff, v[(i + r) % SPONGE_WIDTH], res);
|
||||
}
|
||||
|
||||
res
|
||||
@ -86,11 +76,11 @@ where
|
||||
|
||||
/// Same as `mds_layer` for an extension algebra of `F`.
|
||||
fn mds_layer_algebra(
|
||||
state: &[ExtensionAlgebra<F::Extension, D>; WIDTH],
|
||||
) -> [ExtensionAlgebra<F::Extension, D>; WIDTH] {
|
||||
let mut result = [ExtensionAlgebra::ZERO; WIDTH];
|
||||
state: &[ExtensionAlgebra<F::Extension, D>; SPONGE_WIDTH],
|
||||
) -> [ExtensionAlgebra<F::Extension, D>; SPONGE_WIDTH] {
|
||||
let mut result = [ExtensionAlgebra::ZERO; SPONGE_WIDTH];
|
||||
|
||||
for r in 0..WIDTH {
|
||||
for r in 0..SPONGE_WIDTH {
|
||||
result[r] = Self::mds_row_shf_algebra(r, state);
|
||||
}
|
||||
|
||||
@ -100,11 +90,11 @@ where
|
||||
/// Same as `mds_layer_recursive` for an extension algebra of `F`.
|
||||
fn mds_layer_algebra_recursive(
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
state: &[ExtensionAlgebraTarget<D>; WIDTH],
|
||||
) -> [ExtensionAlgebraTarget<D>; WIDTH] {
|
||||
let mut result = [builder.zero_ext_algebra(); WIDTH];
|
||||
state: &[ExtensionAlgebraTarget<D>; SPONGE_WIDTH],
|
||||
) -> [ExtensionAlgebraTarget<D>; SPONGE_WIDTH] {
|
||||
let mut result = [builder.zero_ext_algebra(); SPONGE_WIDTH];
|
||||
|
||||
for r in 0..WIDTH {
|
||||
for r in 0..SPONGE_WIDTH {
|
||||
result[r] = Self::mds_row_shf_algebra_recursive(builder, r, state);
|
||||
}
|
||||
|
||||
@ -112,17 +102,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D> + Poseidon<WIDTH>, const D: usize, const WIDTH: usize> Gate<F, D>
|
||||
for PoseidonMdsGate<F, D, WIDTH>
|
||||
where
|
||||
[(); WIDTH - 1]:,
|
||||
{
|
||||
impl<F: RichField + Extendable<D> + Poseidon, const D: usize> Gate<F, D> for PoseidonMdsGate<F, D> {
|
||||
fn id(&self) -> String {
|
||||
format!("{:?}<WIDTH={}>", self, WIDTH)
|
||||
format!("{:?}<WIDTH={}>", self, SPONGE_WIDTH)
|
||||
}
|
||||
|
||||
fn eval_unfiltered(&self, vars: EvaluationVars<F, D>) -> Vec<F::Extension> {
|
||||
let inputs: [_; WIDTH] = (0..WIDTH)
|
||||
let inputs: [_; SPONGE_WIDTH] = (0..SPONGE_WIDTH)
|
||||
.map(|i| vars.get_local_ext_algebra(Self::wires_input(i)))
|
||||
.collect::<Vec<_>>()
|
||||
.try_into()
|
||||
@ -130,7 +116,7 @@ where
|
||||
|
||||
let computed_outputs = Self::mds_layer_algebra(&inputs);
|
||||
|
||||
(0..WIDTH)
|
||||
(0..SPONGE_WIDTH)
|
||||
.map(|i| vars.get_local_ext_algebra(Self::wires_output(i)))
|
||||
.zip(computed_outputs)
|
||||
.flat_map(|(out, computed_out)| (out - computed_out).to_basefield_array())
|
||||
@ -138,7 +124,7 @@ where
|
||||
}
|
||||
|
||||
fn eval_unfiltered_base(&self, vars: EvaluationVarsBase<F>) -> Vec<F> {
|
||||
let inputs: [_; WIDTH] = (0..WIDTH)
|
||||
let inputs: [_; SPONGE_WIDTH] = (0..SPONGE_WIDTH)
|
||||
.map(|i| vars.get_local_ext(Self::wires_input(i)))
|
||||
.collect::<Vec<_>>()
|
||||
.try_into()
|
||||
@ -146,7 +132,7 @@ where
|
||||
|
||||
let computed_outputs = F::mds_layer_field(&inputs);
|
||||
|
||||
(0..WIDTH)
|
||||
(0..SPONGE_WIDTH)
|
||||
.map(|i| vars.get_local_ext(Self::wires_output(i)))
|
||||
.zip(computed_outputs)
|
||||
.flat_map(|(out, computed_out)| (out - computed_out).to_basefield_array())
|
||||
@ -158,7 +144,7 @@ where
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
vars: EvaluationTargets<D>,
|
||||
) -> Vec<ExtensionTarget<D>> {
|
||||
let inputs: [_; WIDTH] = (0..WIDTH)
|
||||
let inputs: [_; SPONGE_WIDTH] = (0..SPONGE_WIDTH)
|
||||
.map(|i| vars.get_local_ext_algebra(Self::wires_input(i)))
|
||||
.collect::<Vec<_>>()
|
||||
.try_into()
|
||||
@ -166,7 +152,7 @@ where
|
||||
|
||||
let computed_outputs = Self::mds_layer_algebra_recursive(builder, &inputs);
|
||||
|
||||
(0..WIDTH)
|
||||
(0..SPONGE_WIDTH)
|
||||
.map(|i| vars.get_local_ext_algebra(Self::wires_output(i)))
|
||||
.zip(computed_outputs)
|
||||
.flat_map(|(out, computed_out)| {
|
||||
@ -182,12 +168,12 @@ where
|
||||
gate_index: usize,
|
||||
_local_constants: &[F],
|
||||
) -> Vec<Box<dyn WitnessGenerator<F>>> {
|
||||
let gen = PoseidonMdsGenerator::<D, WIDTH> { gate_index };
|
||||
let gen = PoseidonMdsGenerator::<D> { gate_index };
|
||||
vec![Box::new(gen.adapter())]
|
||||
}
|
||||
|
||||
fn num_wires(&self) -> usize {
|
||||
2 * D * WIDTH
|
||||
2 * D * SPONGE_WIDTH
|
||||
}
|
||||
|
||||
fn num_constants(&self) -> usize {
|
||||
@ -199,30 +185,22 @@ where
|
||||
}
|
||||
|
||||
fn num_constraints(&self) -> usize {
|
||||
WIDTH * D
|
||||
SPONGE_WIDTH * D
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct PoseidonMdsGenerator<const D: usize, const WIDTH: usize>
|
||||
where
|
||||
[(); WIDTH - 1]:,
|
||||
{
|
||||
struct PoseidonMdsGenerator<const D: usize> {
|
||||
gate_index: usize,
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D> + Poseidon<WIDTH>, const D: usize, const WIDTH: usize>
|
||||
SimpleGenerator<F> for PoseidonMdsGenerator<D, WIDTH>
|
||||
where
|
||||
[(); WIDTH - 1]:,
|
||||
impl<F: RichField + Extendable<D> + Poseidon, const D: usize> SimpleGenerator<F>
|
||||
for PoseidonMdsGenerator<D>
|
||||
{
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
(0..WIDTH)
|
||||
(0..SPONGE_WIDTH)
|
||||
.flat_map(|i| {
|
||||
Target::wires_from_range(
|
||||
self.gate_index,
|
||||
PoseidonMdsGate::<F, D, WIDTH>::wires_input(i),
|
||||
)
|
||||
Target::wires_from_range(self.gate_index, PoseidonMdsGate::<F, D>::wires_input(i))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
@ -233,8 +211,8 @@ where
|
||||
let get_local_ext =
|
||||
|wire_range| witness.get_extension_target(get_local_get_target(wire_range));
|
||||
|
||||
let inputs: [_; WIDTH] = (0..WIDTH)
|
||||
.map(|i| get_local_ext(PoseidonMdsGate::<F, D, WIDTH>::wires_input(i)))
|
||||
let inputs: [_; SPONGE_WIDTH] = (0..SPONGE_WIDTH)
|
||||
.map(|i| get_local_ext(PoseidonMdsGate::<F, D>::wires_input(i)))
|
||||
.collect::<Vec<_>>()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
@ -243,7 +221,7 @@ where
|
||||
|
||||
for (i, &out) in outputs.iter().enumerate() {
|
||||
out_buffer.set_extension_target(
|
||||
get_local_get_target(PoseidonMdsGate::<F, D, WIDTH>::wires_output(i)),
|
||||
get_local_get_target(PoseidonMdsGate::<F, D>::wires_output(i)),
|
||||
out,
|
||||
);
|
||||
}
|
||||
@ -256,18 +234,23 @@ mod tests {
|
||||
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
|
||||
use crate::gates::poseidon_mds::PoseidonMdsGate;
|
||||
use crate::hash::hashing::SPONGE_WIDTH;
|
||||
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||
|
||||
#[test]
|
||||
fn low_degree() {
|
||||
type F = GoldilocksField;
|
||||
let gate = PoseidonMdsGate::<F, 4, SPONGE_WIDTH>::new();
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
let gate = PoseidonMdsGate::<F, D>::new();
|
||||
test_low_degree(gate)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eval_fns() -> anyhow::Result<()> {
|
||||
type F = GoldilocksField;
|
||||
let gate = PoseidonMdsGate::<F, 4, SPONGE_WIDTH>::new();
|
||||
test_eval_fns(gate)
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
let gate = PoseidonMdsGate::<F, D>::new();
|
||||
test_eval_fns::<F, C, _, D>(gate)
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,13 +16,13 @@ use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase};
|
||||
|
||||
/// A gate for checking that a particular element of a list matches a given value.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) struct RandomAccessGate<F: Extendable<D>, const D: usize> {
|
||||
pub(crate) struct RandomAccessGate<F: Extendable<D>, const D: usize> {
|
||||
pub bits: usize,
|
||||
pub num_copies: usize,
|
||||
_phantom: PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<F: Extendable<D>, const D: usize> RandomAccessGate<F, D> {
|
||||
impl<F: Extendable<D>, const D: usize> RandomAccessGate<F, D> {
|
||||
fn new(num_copies: usize, bits: usize) -> Self {
|
||||
Self {
|
||||
bits,
|
||||
|
||||
@ -209,6 +209,7 @@ mod tests {
|
||||
use crate::field::goldilocks_field::GoldilocksField;
|
||||
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
|
||||
use crate::gates::reducing_extension::ReducingExtensionGate;
|
||||
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||
|
||||
#[test]
|
||||
fn low_degree() {
|
||||
@ -217,6 +218,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn eval_fns() -> Result<()> {
|
||||
test_eval_fns::<GoldilocksField, _, 4>(ReducingExtensionGate::new(22))
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
test_eval_fns::<GoldilocksField, C, _, D>(ReducingExtensionGate::new(22))
|
||||
}
|
||||
}
|
||||
|
||||
@ -321,6 +321,7 @@ mod tests {
|
||||
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
|
||||
use crate::gates::subtraction_u32::U32SubtractionGate;
|
||||
use crate::hash::hash_types::HashOut;
|
||||
use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||
use crate::plonk::vars::EvaluationVars;
|
||||
|
||||
#[test]
|
||||
@ -333,7 +334,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn eval_fns() -> Result<()> {
|
||||
test_eval_fns::<GoldilocksField, _, 4>(U32SubtractionGate::<GoldilocksField, 4> {
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
test_eval_fns::<GoldilocksField, C, _, D>(U32SubtractionGate::<GoldilocksField, D> {
|
||||
num_ops: 3,
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
|
||||
@ -53,7 +53,7 @@ const fn check_mds_matrix() -> bool {
|
||||
let mut i = 0;
|
||||
let wanted_matrix_exps = [0, 0, 1, 0, 3, 5, 1, 8, 12, 3, 16, 10];
|
||||
while i < WIDTH {
|
||||
if <GoldilocksField as Poseidon<12>>::MDS_MATRIX_EXPS[i] != wanted_matrix_exps[i] {
|
||||
if <GoldilocksField as Poseidon>::MDS_MATRIX_EXPS[i] != wanted_matrix_exps[i] {
|
||||
return false;
|
||||
}
|
||||
i += 1;
|
||||
@ -68,7 +68,7 @@ const fn mds_matrix_inf_norm() -> u64 {
|
||||
let mut cumul = 0;
|
||||
let mut i = 0;
|
||||
while i < WIDTH {
|
||||
cumul += 1 << <GoldilocksField as Poseidon<12>>::MDS_MATRIX_EXPS[i];
|
||||
cumul += 1 << <GoldilocksField as Poseidon>::MDS_MATRIX_EXPS[i];
|
||||
i += 1;
|
||||
}
|
||||
cumul
|
||||
|
||||
@ -130,7 +130,7 @@ pub fn hash_n_to_m<F: RichField, P: PlonkyPermutation<F>>(
|
||||
// Absorb all input chunks.
|
||||
for input_chunk in inputs.chunks(SPONGE_RATE) {
|
||||
state[..input_chunk.len()].copy_from_slice(input_chunk);
|
||||
state = permute(state);
|
||||
state = P::permute(state);
|
||||
}
|
||||
|
||||
// Squeeze until we have the desired number of outputs.
|
||||
|
||||
@ -93,7 +93,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
proof: &MerkleProofTarget,
|
||||
) {
|
||||
let zero = self.zero();
|
||||
let mut state:HashOutTarget = self.hash_or_noop(leaf_data);
|
||||
let mut state: HashOutTarget = self.hash_or_noop::<H>(leaf_data);
|
||||
|
||||
for (&bit, &sibling) in leaf_index_bits.iter().zip(&proof.siblings) {
|
||||
let mut perm_inputs = [zero; SPONGE_WIDTH];
|
||||
|
||||
@ -450,7 +450,7 @@ pub trait Poseidon: PrimeField {
|
||||
s0,
|
||||
);
|
||||
for i in 1..WIDTH {
|
||||
let t = <Self as Poseidon<WIDTH>>::FAST_PARTIAL_ROUND_W_HATS[r][i - 1];
|
||||
let t = <Self as Poseidon>::FAST_PARTIAL_ROUND_W_HATS[r][i - 1];
|
||||
let t = Self::Extension::from_canonical_u64(t);
|
||||
let t = builder.constant_extension(t);
|
||||
d = builder.mul_add_extension(t, state[i], d);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use crate::field::extension_field::target::ExtensionTarget;
|
||||
use std::convert::TryInto;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use crate::field::extension_field::target::ExtensionTarget;
|
||||
use crate::field::extension_field::{Extendable, FieldExtension};
|
||||
use crate::field::field_types::RichField;
|
||||
use crate::hash::hash_types::{HashOut, HashOutTarget, MerkleCapTarget};
|
||||
|
||||
@ -6,7 +6,6 @@ use num::BigUint;
|
||||
use crate::field::extension_field::target::ExtensionTarget;
|
||||
use crate::field::extension_field::{Extendable, FieldExtension};
|
||||
use crate::field::field_types::Field;
|
||||
use crate::field::field_types::{Field, RichField};
|
||||
use crate::gadgets::arithmetic_u32::U32Target;
|
||||
use crate::gadgets::biguint::BigUintTarget;
|
||||
use crate::gadgets::nonnative::NonNativeTarget;
|
||||
|
||||
@ -5,7 +5,6 @@ use num::{BigUint, FromPrimitive, Zero};
|
||||
use crate::field::extension_field::target::ExtensionTarget;
|
||||
use crate::field::extension_field::{Extendable, FieldExtension};
|
||||
use crate::field::field_types::{Field, RichField};
|
||||
use crate::field::field_types::Field;
|
||||
use crate::gadgets::arithmetic_u32::U32Target;
|
||||
use crate::gadgets::biguint::BigUintTarget;
|
||||
use crate::gadgets::nonnative::NonNativeTarget;
|
||||
|
||||
@ -765,7 +765,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
|
||||
/// Various gate types can contain multiple copies in a single Gate. This helper struct lets a
|
||||
/// CircuitBuilder track such gates that are currently being "filled up."
|
||||
pub struct BatchedGates<F: RichField + Extendable<D>, const D: usize> {
|
||||
pub struct BatchedGates<F: Extendable<D>, const D: usize> {
|
||||
/// A map `(c0, c1) -> (g, i)` from constants `(c0,c1)` to an available arithmetic gate using
|
||||
/// these constants with gate index `g` and already using `i` arithmetic operations.
|
||||
pub(crate) free_arithmetic: HashMap<(F, F), (usize, usize)>,
|
||||
@ -792,7 +792,7 @@ pub struct BatchedGates<F: RichField + Extendable<D>, const D: usize> {
|
||||
pub(crate) free_constant: Option<(usize, usize)>,
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> BatchedGates<F, D> {
|
||||
impl<F: Extendable<D>, const D: usize> BatchedGates<F, D> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
free_arithmetic: HashMap::new(),
|
||||
@ -807,7 +807,7 @@ impl<F: RichField + Extendable<D>, const D: usize> BatchedGates<F, D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
/// Finds the last available arithmetic gate with the given constants or add one if there aren't any.
|
||||
/// Returns `(g,i)` such that there is an arithmetic gate with the given constants at index
|
||||
/// `g` and the gate's `i`-th operation is available.
|
||||
|
||||
@ -15,7 +15,6 @@ use crate::iop::generator::WitnessGenerator;
|
||||
use crate::iop::target::Target;
|
||||
use crate::iop::witness::PartialWitness;
|
||||
use crate::plonk::config::{GenericConfig, Hasher};
|
||||
use crate::plonk::proof::ProofWithPublicInputs;
|
||||
use crate::plonk::proof::{CompressedProofWithPublicInputs, ProofWithPublicInputs};
|
||||
use crate::plonk::prover::prove;
|
||||
use crate::plonk::verifier::verify;
|
||||
@ -108,7 +107,7 @@ impl<F: Extendable<D>, C: GenericConfig<D, F = F>, const D: usize> CircuitData<F
|
||||
|
||||
pub fn verify_compressed(
|
||||
&self,
|
||||
compressed_proof_with_pis: CompressedProofWithPublicInputs<F, D>,
|
||||
compressed_proof_with_pis: CompressedProofWithPublicInputs<F, C, D>,
|
||||
) -> Result<()> {
|
||||
compressed_proof_with_pis.verify(&self.verifier_only, &self.common)
|
||||
}
|
||||
@ -151,7 +150,7 @@ impl<F: Extendable<D>, C: GenericConfig<D, F = F>, const D: usize> VerifierCircu
|
||||
|
||||
pub fn verify_compressed(
|
||||
&self,
|
||||
compressed_proof_with_pis: CompressedProofWithPublicInputs<F, D>,
|
||||
compressed_proof_with_pis: CompressedProofWithPublicInputs<F, C, D>,
|
||||
) -> Result<()> {
|
||||
compressed_proof_with_pis.verify(&self.verifier_only, &self.common)
|
||||
}
|
||||
|
||||
@ -370,8 +370,9 @@ mod tests {
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
|
||||
let (proof, vd, cd) = dummy_proof::<F,C, D>(&config, 4_000)?;
|
||||
let (proof, _vd, cd) = recursive_proof::<F,C,C,D>(proof, vd, cd, &config, &config, None, true, true)?;
|
||||
let (proof, vd, cd) = dummy_proof::<F, C, D>(&config, 4_000)?;
|
||||
let (proof, _vd, cd) =
|
||||
recursive_proof::<F, C, C, D>(proof, vd, cd, &config, &config, None, true, true)?;
|
||||
test_serialization(&proof, &cd)?;
|
||||
|
||||
Ok(())
|
||||
@ -389,12 +390,13 @@ mod tests {
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
|
||||
// Start with a degree 2^14 proof, then shrink it to 2^13, then to 2^12.
|
||||
let (proof, vd, cd) = dummy_proof::<F,C, D>(&config, 16_000)?;
|
||||
let (proof, vd, cd) = dummy_proof::<F, C, D>(&config, 16_000)?;
|
||||
assert_eq!(cd.degree_bits, 14);
|
||||
let (proof, vd, cd) =
|
||||
recursive_proof::<F,C,C,D>(proof, vd, cd, &config, &config, Some(13), false, false)?;
|
||||
recursive_proof::<F, C, C, D>(proof, vd, cd, &config, &config, Some(13), false, false)?;
|
||||
assert_eq!(cd.degree_bits, 13);
|
||||
let (proof, _vd, cd) = recursive_proof::<F,KC,C,D>(proof, vd, cd, &config, &config, None, true, true)?;
|
||||
let (proof, _vd, cd) =
|
||||
recursive_proof::<F, KC, C, D>(proof, vd, cd, &config, &config, None, true, true)?;
|
||||
assert_eq!(cd.degree_bits, 12);
|
||||
|
||||
test_serialization(&proof, &cd)?;
|
||||
@ -416,7 +418,7 @@ mod tests {
|
||||
let standard_config = CircuitConfig::standard_recursion_config();
|
||||
|
||||
// An initial dummy proof.
|
||||
let (proof, vd, cd) = dummy_proof::<F,C, D>(&standard_config, 4_000)?;
|
||||
let (proof, vd, cd) = dummy_proof::<F, C, D>(&standard_config, 4_000)?;
|
||||
assert_eq!(cd.degree_bits, 12);
|
||||
|
||||
// A standard recursive proof.
|
||||
|
||||
@ -2,9 +2,8 @@ use std::borrow::Borrow;
|
||||
|
||||
use crate::field::extension_field::target::ExtensionTarget;
|
||||
use crate::field::extension_field::Extendable;
|
||||
use crate::field::field_types::{Field, RichField};
|
||||
use crate::gates::arithmetic_extension::ArithmeticExtensionGate;
|
||||
use crate::field::field_types::Field;
|
||||
use crate::gates::arithmetic_extension::ArithmeticExtensionGate;
|
||||
use crate::gates::reducing::ReducingGate;
|
||||
use crate::gates::reducing_extension::ReducingExtensionGate;
|
||||
use crate::iop::target::Target;
|
||||
@ -218,7 +217,7 @@ impl<const D: usize> ReducingFactorTarget<D> {
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
) -> ExtensionTarget<D>
|
||||
where
|
||||
F: RichField + Extendable<D>,
|
||||
F: Extendable<D>,
|
||||
{
|
||||
self.count += terms.len() as u64;
|
||||
terms
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user