fullcodec_plonk/plonkup/
multiset.rs1use crate::error::Error;
8use crate::fft::{EvaluationDomain, Polynomial};
9use core::ops::{Add, Mul};
10use dusk_bls12_381::BlsScalar;
11use dusk_bytes::{DeserializableSlice, Serializable};
12use sp_std::vec;
13use sp_std::vec::Vec;
14
15#[derive(Clone, Eq, PartialEq, Debug)]
19pub struct MultiSet(pub Vec<BlsScalar>);
20
21impl Default for MultiSet {
22 fn default() -> Self {
23 MultiSet::new()
24 }
25}
26
27impl From<&[BlsScalar]> for MultiSet {
28 fn from(slice: &[BlsScalar]) -> MultiSet {
29 MultiSet(slice.to_vec())
30 }
31}
32
33impl MultiSet {
34 pub fn new() -> MultiSet {
36 MultiSet(vec![])
37 }
38
39 pub fn from_slice(bytes: &[u8]) -> Result<MultiSet, Error> {
41 let elements = bytes
42 .chunks(BlsScalar::SIZE)
43 .map(|chunk| BlsScalar::from_slice(chunk))
44 .collect::<Result<Vec<BlsScalar>, dusk_bytes::Error>>()?;
45
46 Ok(MultiSet(elements))
47 }
48
49 pub fn to_var_bytes(&self) -> Vec<u8> {
52 self.0
53 .iter()
54 .map(|item| item.to_bytes().to_vec())
55 .flatten()
56 .collect()
57 }
58
59 pub fn pad(&mut self, n: u32) {
63 assert!(n.is_power_of_two());
64 let diff = n - self.len() as u32;
65 self.0.extend(vec![self.0[0]; diff as usize]);
66 }
67
68 pub fn push(&mut self, value: BlsScalar) {
70 self.0.push(value)
71 }
72
73 pub fn last(&self) -> Option<&BlsScalar> {
76 self.0.last()
77 }
78
79 pub fn len(&self) -> usize {
81 self.0.len()
82 }
83
84 pub fn is_empty(&self) -> bool {
86 self.0.is_empty()
87 }
88
89 pub fn position(&self, element: &BlsScalar) -> Option<usize> {
92 self.0.iter().position(|&x| x == *element)
93 }
94
95 pub fn sorted_concat(&self, f: &MultiSet) -> Result<MultiSet, Error> {
103 let mut s = self.clone();
104 s.0.reserve(f.0.len());
105 for element in f.0.iter() {
106 let index = s.position(element).ok_or(Error::ElementNotIndexed)?;
107 s.0.insert(index, *element);
108 }
109
110 Ok(s)
111 }
112
113 pub fn contains_all(&self, other: &MultiSet) -> bool {
117 other.0.iter().all(|item| self.contains(item))
118 }
119
120 pub fn contains(&self, entry: &BlsScalar) -> bool {
122 self.0.contains(entry)
123 }
124
125 pub fn halve(&self) -> (MultiSet, MultiSet) {
131 let length = self.0.len();
132
133 let first_half = MultiSet::from(&self.0[0..=length / 2]);
134 let second_half = MultiSet::from(&self.0[length / 2..]);
135
136 (first_half, second_half)
137 }
138
139 pub fn halve_alternating(&self) -> (MultiSet, MultiSet) {
143 let mut evens = vec![];
144 let mut odds = vec![];
145 for i in 0..self.len() {
146 if i % 2 == 0 {
147 evens.push(self.0[i]);
148 } else {
149 odds.push(self.0[i]);
150 }
151 }
152
153 (MultiSet(evens), MultiSet(odds))
154 }
155
156 pub(crate) fn to_polynomial(
160 &self,
161 domain: &EvaluationDomain,
162 ) -> Polynomial {
163 Polynomial::from_coefficients_vec(domain.ifft(&self.0))
164 }
165
166 pub fn compress_three_arity(
172 multisets: [&MultiSet; 3],
173 alpha: BlsScalar,
174 ) -> MultiSet {
175 MultiSet(
176 multisets[0]
177 .0
178 .iter()
179 .zip(multisets[1].0.iter())
180 .zip(multisets[2].0.iter())
181 .map(|((a, b), c)| a + b * alpha + c * alpha.square())
182 .collect::<Vec<BlsScalar>>(),
183 )
184 }
185
186 pub fn compress_four_arity(
192 multisets: [&MultiSet; 4],
193 alpha: BlsScalar,
194 ) -> MultiSet {
195 MultiSet(
196 multisets[0]
197 .0
198 .iter()
199 .zip(multisets[1].0.iter())
200 .zip(multisets[2].0.iter())
201 .zip(multisets[3].0.iter())
202 .map(|(((a, b), c), d)| {
203 a + b * alpha
204 + c * alpha.square()
205 + d * alpha.pow(&[3u64, 0u64, 0u64, 0u64])
206 })
207 .collect::<Vec<BlsScalar>>(),
208 )
209 }
210}
211
212impl Add for MultiSet {
213 type Output = MultiSet;
214
215 fn add(self, other: MultiSet) -> Self::Output {
216 let result = self
217 .0
218 .into_iter()
219 .zip(other.0.iter())
220 .map(|(x, y)| x + y)
221 .collect();
222
223 MultiSet(result)
224 }
225}
226
227impl Mul for MultiSet {
228 type Output = MultiSet;
229
230 fn mul(self, other: MultiSet) -> Self::Output {
231 let result = self
232 .0
233 .into_iter()
234 .zip(other.0.iter())
235 .map(|(x, y)| x * y)
236 .collect();
237
238 MultiSet(result)
239 }
240}
241
242#[cfg(test)]
243mod test {
244 use super::*;
245 use crate::fft::EvaluationDomain;
246 use crate::plonkup::WitnessTable;
247
248 #[test]
249 fn test_halve() {
250 let mut s = MultiSet::new();
251 s.push(BlsScalar::from(0));
252 s.push(BlsScalar::from(1));
253 s.push(BlsScalar::from(2));
254 s.push(BlsScalar::from(3));
255 s.push(BlsScalar::from(4));
256 s.push(BlsScalar::from(5));
257 s.push(BlsScalar::from(6));
258
259 let (h_1, h_2) = s.halve();
260 assert_eq!(h_1.len(), 4);
261 assert_eq!(h_2.len(), 4);
262
263 let left_half = MultiSet(vec![
264 BlsScalar::from(0),
265 BlsScalar::from(1),
266 BlsScalar::from(2),
267 BlsScalar::from(3),
268 ]);
269
270 assert_eq!(left_half, h_1);
271
272 let right_half = MultiSet(vec![
273 BlsScalar::from(3),
274 BlsScalar::from(4),
275 BlsScalar::from(5),
276 BlsScalar::from(6),
277 ]);
278
279 assert_eq!(right_half, h_2);
280
281 assert_eq!(h_1.0.last().unwrap(), &h_2.0[0])
284 }
285
286 #[test]
287 fn test_to_polynomial() {
288 let mut s = MultiSet::new();
289 s.push(BlsScalar::from(1));
290 s.push(BlsScalar::from(2));
291 s.push(BlsScalar::from(3));
292 s.push(BlsScalar::from(4));
293 s.push(BlsScalar::from(5));
294 s.push(BlsScalar::from(6));
295 s.push(BlsScalar::from(7));
296
297 let domain = EvaluationDomain::new(s.len() + 1).unwrap();
298 let s_poly = s.to_polynomial(&domain);
299
300 assert_eq!(s_poly.degree(), 7)
301 }
302 #[test]
303 fn test_is_subset() {
304 let mut t = MultiSet::new();
305 t.push(BlsScalar::from(1));
306 t.push(BlsScalar::from(2));
307 t.push(BlsScalar::from(3));
308 t.push(BlsScalar::from(4));
309 t.push(BlsScalar::from(5));
310 t.push(BlsScalar::from(6));
311 t.push(BlsScalar::from(7));
312 let mut f = MultiSet::new();
313 f.push(BlsScalar::from(1));
314 f.push(BlsScalar::from(2));
315 let mut n = MultiSet::new();
316 n.push(BlsScalar::from(8));
317
318 assert!(t.contains_all(&f));
319 assert!(!t.contains_all(&n));
320 }
321
322 #[test]
323 fn test_full_compression_into_s() {
324 let mut t = MultiSet::new();
325
326 t.push(BlsScalar::zero());
327 t.push(BlsScalar::one());
328 t.push(BlsScalar::from(2));
329 t.push(BlsScalar::from(3));
330 t.push(BlsScalar::from(4));
331 t.push(BlsScalar::from(5));
332 t.push(BlsScalar::from(6));
333 t.push(BlsScalar::from(7));
334
335 let mut f = MultiSet::new();
336 f.push(BlsScalar::from(3));
337 f.push(BlsScalar::from(6));
338 f.push(BlsScalar::from(0));
339 f.push(BlsScalar::from(5));
340 f.push(BlsScalar::from(4));
341 f.push(BlsScalar::from(3));
342 f.push(BlsScalar::from(2));
343 f.push(BlsScalar::from(0));
344 f.push(BlsScalar::from(0));
345 f.push(BlsScalar::from(1));
346 f.push(BlsScalar::from(2));
347
348 assert!(t.contains_all(&f));
349
350 assert!(t.contains(&BlsScalar::from(2)));
351
352 let s = t.sorted_concat(&f);
353
354 let concatenated_set = MultiSet(vec![
357 BlsScalar::zero(),
358 BlsScalar::zero(),
359 BlsScalar::zero(),
360 BlsScalar::zero(),
361 BlsScalar::one(),
362 BlsScalar::one(),
363 BlsScalar::from(2),
364 BlsScalar::from(2),
365 BlsScalar::from(2),
366 BlsScalar::from(3),
367 BlsScalar::from(3),
368 BlsScalar::from(3),
369 BlsScalar::from(4),
370 BlsScalar::from(4),
371 BlsScalar::from(5),
372 BlsScalar::from(5),
373 BlsScalar::from(6),
374 BlsScalar::from(6),
375 BlsScalar::from(7),
376 ]);
377
378 assert_eq!(s.unwrap(), concatenated_set);
379 }
380
381 #[test]
382 fn multiset_compression_input() {
383 let alpha = BlsScalar::from(2);
386 let alpha_squared = alpha * alpha;
387
388 let mut table = WitnessTable::default();
389
390 table.from_wire_values(
394 BlsScalar::from(1),
395 BlsScalar::from(2),
396 BlsScalar::from(3),
397 BlsScalar::from(4),
398 );
399
400 let compressed_element = MultiSet::compress_three_arity(
402 [&table.f_1, &table.f_2, &table.f_3],
403 alpha,
404 );
405
406 let actual_element = BlsScalar::from(1)
407 + (BlsScalar::from(2) * alpha)
408 + (BlsScalar::from(3) * alpha_squared);
409
410 let mut actual_set = MultiSet::new();
411
412 actual_set.push(actual_element);
413
414 assert_eq!(actual_set, compressed_element);
415 }
416}