w3f_pcs/aggregation/
single.rs1use ark_ec::{AffineRepr, CurveGroup};
2use ark_ff::{PrimeField, Zero};
3use ark_poly::Polynomial;
4use ark_std::vec::Vec;
5
6use crate::pcs::{Commitment, PCS};
7use crate::utils::ec::small_multiexp_affine;
8use crate::Poly;
9
10#[derive(Clone, Debug)]
14pub struct Claim<F: PrimeField, C: Commitment<F>> {
15 pub c: C,
16 pub x: F,
17 pub y: F,
18}
19
20impl<F: PrimeField, C: Commitment<F>> Claim<F, C> {
21 pub fn new<CS>(ck: &CS::CK, poly: &Poly<F>, at: F) -> Claim<F, C>
22 where
23 CS: PCS<F, C = C>,
24 {
25 Claim {
26 c: CS::commit(ck, poly).unwrap(),
27 x: at,
28 y: poly.evaluate(&at),
29 }
30 }
31}
32
33pub fn aggregate_claims<F: PrimeField, CS: PCS<F>>(
42 claims: &[Claim<F, CS::C>],
43 rs: &[F],
44) -> Claim<F, CS::C> {
45 assert_eq!(claims.len(), rs.len());
46
47 let mut iter_over_xs = claims.iter().map(|cl| cl.x);
48 let same_x = iter_over_xs.next().expect("claims is empty");
49 assert!(
50 iter_over_xs.all(|x| x == same_x),
51 "multiple evaluation points"
52 );
53
54 let (rcs, rys): (Vec<CS::C>, Vec<F>) = claims
60 .iter()
61 .zip(rs.iter())
62 .map(|(cl, &r)| (cl.c.mul(r), r * cl.y))
63 .unzip();
64
65 Claim {
66 c: rcs.into_iter().sum(),
67 x: same_x,
68 y: rys.iter().sum(),
69 }
70}
71
72pub fn aggregate_claims_multiexp<F, C>(cs: Vec<C>, ys: Vec<F>, rs: &[F]) -> (C, F)
73where
74 F: PrimeField,
75 C: AffineRepr<ScalarField = F>,
76{
77 assert_eq!(cs.len(), rs.len());
78 assert_eq!(ys.len(), rs.len());
79
80 let agg_c = small_multiexp_affine(rs, &cs);
81 let agg_y = ys.into_iter().zip(rs.iter()).map(|(y, r)| y * r).sum();
82
83 (agg_c.into_affine(), agg_y)
84}
85
86pub fn aggregate_polys<F: PrimeField>(polys: &[Poly<F>], rs: &[F]) -> Poly<F> {
88 assert_eq!(polys.len(), rs.len());
89 polys
90 .iter()
91 .zip(rs.iter())
92 .map(|(p, &r)| p * r)
93 .fold(Poly::zero(), |acc, p| acc + p)
94}
95
96#[cfg(test)]
97mod tests {
98 use ark_poly::DenseUVPolynomial;
99 use ark_std::test_rng;
100
101 use crate::pcs::IdentityCommitment;
102 use crate::pcs::PcsParams;
103 use crate::tests::{TestField, TestKzg};
104
105 use super::*;
106
107 fn _test_aggregation<F: PrimeField, CS: PCS<F>>() {
108 let rng = &mut test_rng();
109 let d = 15;
110 let t = 4;
111 let params = CS::setup(d, rng);
112 let ck = params.ck();
113
114 assert!(aggregate_polys::<F>(&[], &[]).is_zero());
115
116 let rs = (0..t).map(|_| F::rand(rng)).collect::<Vec<_>>();
118
119 let polys = (0..t).map(|_| Poly::<F>::rand(d, rng)).collect::<Vec<_>>();
120 let agg_poly = aggregate_polys(&polys, &rs);
121
122 let same_x = F::rand(rng);
123 let claims_at_same_x = polys
124 .iter()
125 .map(|p| Claim::new::<CS>(&ck, p, same_x))
126 .collect::<Vec<_>>();
127 let agg_claim = aggregate_claims::<F, CS>(&claims_at_same_x, &rs);
128
129 assert_eq!(CS::commit(&ck, &agg_poly).unwrap(), agg_claim.c);
130 assert_eq!(same_x, agg_claim.x);
131 assert_eq!(agg_poly.evaluate(&same_x), agg_claim.y);
132 }
133
134 #[test]
135 fn test_aggregation() {
136 _test_aggregation::<TestField, IdentityCommitment>();
137 _test_aggregation::<TestField, TestKzg>();
138 }
139}