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