halo2_axiom/poly/ipa/
multiopen.rs
1use super::*;
7use crate::{poly::query::Query, transcript::ChallengeScalar};
8use ff::Field;
9use std::collections::{BTreeMap, BTreeSet};
10
11mod prover;
12mod verifier;
13
14pub use prover::ProverIPA;
15pub use verifier::VerifierIPA;
16
17#[derive(Clone, Copy, Debug)]
18struct X1 {}
19type ChallengeX1<F> = ChallengeScalar<F, X1>;
21
22#[derive(Clone, Copy, Debug)]
23struct X2 {}
24type ChallengeX2<F> = ChallengeScalar<F, X2>;
26
27#[derive(Clone, Copy, Debug)]
28struct X3 {}
29type ChallengeX3<F> = ChallengeScalar<F, X3>;
31
32#[derive(Clone, Copy, Debug)]
33struct X4 {}
34type ChallengeX4<F> = ChallengeScalar<F, X4>;
37
38#[derive(Debug)]
39struct CommitmentData<F, T: PartialEq> {
40 pub(crate) commitment: T,
41 pub(crate) set_index: usize,
42 pub(crate) point_indices: Vec<usize>,
43 pub(crate) evals: Vec<F>,
44}
45
46impl<F, T: PartialEq> CommitmentData<F, T> {
47 fn new(commitment: T) -> Self {
48 CommitmentData {
49 commitment,
50 set_index: 0,
51 point_indices: vec![],
52 evals: vec![],
53 }
54 }
55}
56
57type IntermediateSets<F, Q> = (
58 Vec<CommitmentData<<Q as Query<F>>::Eval, <Q as Query<F>>::Commitment>>,
59 Vec<Vec<F>>,
60);
61
62fn construct_intermediate_sets<F: Field + Ord, I, Q: Query<F>>(queries: I) -> IntermediateSets<F, Q>
63where
64 I: IntoIterator<Item = Q> + Clone,
65{
66 let mut commitment_map: Vec<CommitmentData<Q::Eval, Q::Commitment>> = vec![];
69
70 let mut point_index_map = BTreeMap::new();
73
74 for query in queries.clone() {
77 let num_points = point_index_map.len();
78 let point_idx = point_index_map
79 .entry(query.get_point())
80 .or_insert(num_points);
81
82 if let Some(pos) = commitment_map
83 .iter()
84 .position(|comm| comm.commitment == query.get_commitment())
85 {
86 commitment_map[pos].point_indices.push(*point_idx);
87 } else {
88 let mut tmp = CommitmentData::new(query.get_commitment());
89 tmp.point_indices.push(*point_idx);
90 commitment_map.push(tmp);
91 }
92 }
93
94 let mut inverse_point_index_map = BTreeMap::new();
96 for (&point, &point_index) in point_index_map.iter() {
97 inverse_point_index_map.insert(point_index, point);
98 }
99
100 let mut point_idx_sets = BTreeMap::new();
102 let mut commitment_set_map = Vec::new();
104
105 for commitment_data in commitment_map.iter() {
106 let mut point_index_set = BTreeSet::new();
107 for &point_index in commitment_data.point_indices.iter() {
109 point_index_set.insert(point_index);
110 }
111
112 commitment_set_map.push((commitment_data.commitment, point_index_set.clone()));
114
115 let num_sets = point_idx_sets.len();
116 point_idx_sets.entry(point_index_set).or_insert(num_sets);
117 }
118
119 for commitment_data in commitment_map.iter_mut() {
121 let len = commitment_data.point_indices.len();
122 commitment_data.evals = vec![Q::Eval::default(); len];
123 }
124
125 for query in queries {
127 let point_index = point_index_map.get(&query.get_point()).unwrap();
129
130 let mut point_index_set = BTreeSet::new();
132 for (commitment, point_idx_set) in commitment_set_map.iter() {
133 if query.get_commitment() == *commitment {
134 point_index_set = point_idx_set.clone();
135 }
136 }
137 assert!(!point_index_set.is_empty());
138
139 let set_index = point_idx_sets.get(&point_index_set).unwrap();
141 for commitment_data in commitment_map.iter_mut() {
142 if query.get_commitment() == commitment_data.commitment {
143 commitment_data.set_index = *set_index;
144 }
145 }
146 let point_index_set: Vec<usize> = point_index_set.iter().cloned().collect();
147
148 let point_index_in_set = point_index_set
150 .iter()
151 .position(|i| i == point_index)
152 .unwrap();
153
154 for commitment_data in commitment_map.iter_mut() {
155 if query.get_commitment() == commitment_data.commitment {
156 commitment_data.evals[point_index_in_set] = query.get_eval();
158 }
159 }
160 }
161
162 let mut point_sets: Vec<Vec<F>> = vec![Vec::new(); point_idx_sets.len()];
164 for (point_idx_set, &set_idx) in point_idx_sets.iter() {
165 for &point_idx in point_idx_set.iter() {
166 let point = inverse_point_index_map.get(&point_idx).unwrap();
167 point_sets[set_idx].push(*point);
168 }
169 }
170
171 (commitment_map, point_sets)
172}