w3f_ring_proof/piop/
params.rs

1use ark_ec::twisted_edwards::{Affine, TECurveConfig};
2use ark_ec::{AdditiveGroup, AffineRepr, CurveGroup};
3use ark_ff::{BigInteger, PrimeField};
4use ark_std::{vec, vec::Vec};
5
6use w3f_plonk_common::domain::Domain;
7use w3f_plonk_common::gadgets::ec::AffineColumn;
8
9use crate::piop::FixedColumns;
10
11/// Plonk Interactive Oracle Proofs (PIOP) parameters.
12#[derive(Clone)]
13pub struct PiopParams<F: PrimeField, Curve: TECurveConfig<BaseField = F>> {
14    /// Domain over which the piop is represented.
15    pub(crate) domain: Domain<F>,
16    /// Number of bits used to represent a jubjub scalar.
17    pub(crate) scalar_bitlen: usize,
18    /// Length of the part of the column representing the public keys (including the padding).
19    pub keyset_part_size: usize,
20    /// Blinding base point.
21    pub(crate) h: Affine<Curve>,
22    /// Summation base point.
23    pub(crate) seed: Affine<Curve>,
24    /// The point used to pad the list of public keys.
25    pub(crate) padding: Affine<Curve>,
26}
27
28impl<F: PrimeField, Curve: TECurveConfig<BaseField = F>> PiopParams<F, Curve> {
29    /// Initialize PIOP parameters.
30    ///
31    /// - `domain`: polynomials evaluation domain.
32    /// - `h`: Blinding base point.
33    /// - `seed`: Accumulation base point
34    /// - `padding`: The point used to pad the list of public keys.
35    ///
36    /// All points should be of an unknown discrete log.
37    pub fn setup(
38        domain: Domain<F>,
39        h: Affine<Curve>,
40        seed: Affine<Curve>,
41        padding: Affine<Curve>,
42    ) -> Self {
43        let scalar_bitlen = Curve::ScalarField::MODULUS_BIT_SIZE as usize;
44        // 1 accounts for the last cells of the points and bits columns that remain unconstrained
45        let keyset_part_size = domain.capacity - scalar_bitlen - 1;
46        Self {
47            domain,
48            scalar_bitlen,
49            keyset_part_size,
50            h,
51            seed,
52            padding,
53        }
54    }
55
56    pub fn fixed_columns(&self, keys: &[Affine<Curve>]) -> FixedColumns<F, Affine<Curve>> {
57        let ring_selector = self.keyset_part_selector();
58        let ring_selector = self.domain.public_column(ring_selector);
59        let points = self.points_column(&keys);
60        FixedColumns {
61            points,
62            ring_selector,
63        }
64    }
65
66    pub fn points_column(&self, keys: &[Affine<Curve>]) -> AffineColumn<F, Affine<Curve>> {
67        assert!(keys.len() <= self.keyset_part_size);
68        let padding_len = self.keyset_part_size - keys.len();
69        let padding = vec![self.padding; padding_len];
70        let points = [keys, &padding, &self.power_of_2_multiples_of_h()].concat();
71        assert_eq!(points.len(), self.domain.capacity - 1);
72        AffineColumn::public_column(points, &self.domain)
73    }
74
75    pub fn power_of_2_multiples_of_h(&self) -> Vec<Affine<Curve>> {
76        let mut h = self.h.into_group();
77        let mut multiples = Vec::with_capacity(self.scalar_bitlen);
78        multiples.push(h);
79        for _ in 1..self.scalar_bitlen {
80            h.double_in_place();
81            multiples.push(h);
82        }
83        CurveGroup::normalize_batch(&multiples)
84    }
85
86    pub fn scalar_part(&self, e: Curve::ScalarField) -> Vec<bool> {
87        let bits_with_trailing_zeroes = e.into_bigint().to_bits_le();
88        let significant_bits = &bits_with_trailing_zeroes[..self.scalar_bitlen];
89        significant_bits.to_vec()
90    }
91
92    pub fn keyset_part_selector(&self) -> Vec<F> {
93        [
94            vec![F::one(); self.keyset_part_size],
95            vec![F::zero(); self.scalar_bitlen],
96        ]
97        .concat()
98    }
99}
100
101#[cfg(test)]
102mod tests {
103    use ark_ed_on_bls12_381_bandersnatch::{BandersnatchConfig, EdwardsAffine, Fq, Fr};
104    use ark_std::ops::Mul;
105    use ark_std::{test_rng, UniformRand};
106
107    use w3f_plonk_common::domain::Domain;
108    use w3f_plonk_common::test_helpers::cond_sum;
109
110    use crate::piop::params::PiopParams;
111
112    #[test]
113    fn test_powers_of_h() {
114        let rng = &mut test_rng();
115        let h = EdwardsAffine::rand(rng);
116        let seed = EdwardsAffine::rand(rng);
117        let padding = EdwardsAffine::rand(rng);
118        let domain = Domain::new(1024, false);
119
120        let params = PiopParams::<Fq, BandersnatchConfig>::setup(domain, h, seed, padding);
121        let t = Fr::rand(rng);
122        let t_bits = params.scalar_part(t);
123        let th = cond_sum(&t_bits, &params.power_of_2_multiples_of_h());
124        assert_eq!(th, params.h.mul(t));
125    }
126}