clacc/lib.rs
1//! This is a Rust implementanion of a CL universal accumulator as described
2//! in [Efficient oblivious transfer with membership verification][1].
3//!
4//! An accumulation is a fixed size digest that, along with the witness of an
5//! element's addition, can be used to prove an element is a member of a set.
6//! The drawback to this solution is that any state changes to the
7//! accumulation invalidate the witneses of the other elements in the set,
8//! requiring computational resources to update them.
9//!
10//! The benefit of CL accumulators is that they support efficient untrusted
11//! witness updates. The resource intensive task of updating witnesses can be
12//! outsourced to an untrusted party without sacrificing the integrity of the
13//! accumulator.
14//!
15//! This project is focused on a use case where a central authority is both
16//! memory- and processing-constrained. The authority controls the private key
17//! and is able to add and delete elements while untrusted workers are able to
18//! recalculate witnesses provided they have access to the previous witnesses,
19//! the current state of the accumulator, and its public key.
20//!
21//! # Backends
22//! This crate is built with a modular integer type backend. Integer types must
23//! implement the [`BigInt`] trait.
24//!
25//! # Optional Features
26//! - `bigint` (default): Enable this feature to support
27//! [`::num_bigint::BigInt`] as an integer type. [`::num_bigint`] is
28//! a pure Rust big integer library.
29//! - `gmp`: Enable this feature to support [`::gmp::mpz::Mpz`] as an
30//! integer type. [`::gmp`] is not a pure Rust library, but it is
31//! currently more performant than [`::num_bigint`].
32//!
33//! [1]: https://journals.sagepub.com/doi/pdf/10.1177/1550147719875645
34#![cfg_attr(docsrs, feature(doc_cfg))]
35
36use std::sync::{Arc, Mutex};
37
38#[cfg(feature = "gmp")]
39pub mod gmp;
40
41#[cfg(feature = "bigint")]
42pub mod bigint;
43
44/// The accumulator base.
45const BASE: i64 = 65537;
46
47/// A trait describing an arbitrary precision integer.
48pub trait BigInt:
49 Clone
50 + Sized
51 + Send
52 + Sync
53 + Eq
54 + PartialOrd
55 + std::ops::Neg
56 + for<'a> std::ops::Add<&'a Self, Output = Self>
57 + for<'a> std::ops::Sub<&'a Self, Output = Self>
58 + for<'a> std::ops::Mul<&'a Self, Output = Self>
59 + for<'a> std::ops::Div<&'a Self, Output = Self>
60 + for<'a> std::ops::Rem<&'a Self, Output = Self>
61{
62 /// Constructs a [`BigInt`] from an i64.
63 fn from_i64(v: i64) -> Self;
64
65 /// Constructs a [`BigInt`] from a slice of bytes, with the most
66 /// significant byte first.
67 fn from_bytes_be(bytes: &[u8]) -> Self;
68
69 /// Constructs a byte vector of the [`BigInt`] with the most significant
70 /// byte first.
71 fn to_bytes_be(&self) -> Vec<u8>;
72
73 /// Returns (g, a, b) where `g` is the greatest common divisor of `self`
74 /// and `y` satisfying `g = a * self + b * y`.
75 fn gcdext<'a>(&self, y: &'a Self) -> (Self, Self, Self);
76
77 /// Returns `self^e (mod m)`.
78 fn powm<'a>(&self, e: &'a Self, m: &Self) -> Self;
79
80 /// Returns the size of `self` in bits.
81 fn size_in_bits(&self) -> usize;
82}
83
84/// An accumulator.
85///
86/// Elements may be added and deleted from the acculumator without increasing
87/// the size of its internal parameters. That is, the bit depth in the
88/// accumulation `z` will never exceed the bit depth in the modulus `n`.
89#[derive(Clone)]
90pub struct Accumulator<T: BigInt> {
91
92 /// Modulus.
93 n: T,
94
95 /// Private exponent.
96 d: Option<T>,
97
98 /// The current accumulation value.
99 z: T,
100}
101
102impl<T: BigInt> Accumulator<T> {
103
104 /// Initialize an accumulator from private key parameters `n` the modulus
105 /// and `d` ϕ(n). All accumulators are able to add elements and verify
106 /// witnesses. An accumulator constructed from a private key is able to
107 /// delete elements and prove elements after their addition.
108 ///
109 /// ```
110 /// use clacc::Accumulator;
111 /// use num_bigint::BigInt;
112 /// let n = vec![0x0c, 0xa1];
113 /// let d = vec![0x0c, 0x30];
114 /// let acc = Accumulator::<BigInt>::with_private_key(
115 /// &<BigInt as clacc::BigInt>::from_bytes_be(n.as_slice()),
116 /// &<BigInt as clacc::BigInt>::from_bytes_be(d.as_slice()),
117 /// );
118 /// ```
119 pub fn with_private_key(
120 n: &T,
121 d: &T,
122 ) -> Self {
123 Accumulator {
124 n: n.clone(),
125 d: Some(d.clone()),
126 z: T::from_i64(BASE),
127 }
128 }
129
130 /// Initialize an accumulator from a public key. An accumulator constructed
131 /// from a public key is only able to add elements and verify witnesses.
132 ///
133 /// ```
134 /// use clacc::Accumulator;
135 /// use num_bigint::BigInt;
136 /// let n = vec![0x0c, 0xa1];
137 /// let acc = Accumulator::<BigInt>::with_public_key(
138 /// &<BigInt as clacc::BigInt>::from_bytes_be(n.as_slice()),
139 /// );
140 /// ```
141 pub fn with_public_key(
142 n: &T,
143 ) -> Self {
144 Accumulator {
145 n: n.clone(),
146 d: None,
147 z: T::from_i64(BASE),
148 }
149 }
150
151 /// Get an accumulator's public key.
152 pub fn get_public_key(
153 &self,
154 ) -> T {
155 self.n.clone()
156 }
157
158 /// Add an element to the accumulator. The element `x` must be a prime.
159 /// The returned value is a witness to the element's addition.
160 ///
161 /// ```
162 /// use clacc::Accumulator;
163 /// use num_bigint::BigInt;
164 /// let n = vec![0x0c, 0xa1];
165 /// let mut acc = Accumulator::<BigInt>::with_public_key(
166 /// &<BigInt as clacc::BigInt>::from_bytes_be(n.as_slice()),
167 /// );
168 /// let x = <BigInt as clacc::BigInt>::from_i64(3);
169 /// let w = acc.add(&x);
170 /// assert!(acc.verify(&x, &w).is_ok());
171 /// ```
172 ///
173 /// This works with accumulators constructed from a public key or a
174 /// private key.
175 ///
176 /// ```
177 /// use clacc::Accumulator;
178 /// use num_bigint::BigInt;
179 /// let n = vec![0x0c, 0xa1];
180 /// let d = vec![0x0c, 0x30];
181 /// let mut acc = Accumulator::<BigInt>::with_private_key(
182 /// &<BigInt as clacc::BigInt>::from_bytes_be(n.as_slice()),
183 /// &<BigInt as clacc::BigInt>::from_bytes_be(d.as_slice()),
184 /// );
185 /// let x = <BigInt as clacc::BigInt>::from_i64(3);
186 /// let w = acc.add(&x);
187 /// assert!(acc.verify(&x, &w).is_ok());
188 /// ```
189 pub fn add(
190 &mut self,
191 x: &T,
192 ) -> T {
193 let w = self.z.clone();
194 self.z = self.z.powm(&x, &self.n);
195 w
196 }
197
198 /// Delete an element from an accumulator. The element `x` must be a prime.
199 /// The returned value is the accumulation less the element.
200 ///
201 /// ```
202 /// use clacc::Accumulator;
203 /// use num_bigint::BigInt;
204 /// let n = vec![0x0c, 0xa1];
205 /// let d = vec![0x0c, 0x30];
206 /// let mut acc = Accumulator::<BigInt>::with_private_key(
207 /// &<BigInt as clacc::BigInt>::from_bytes_be(n.as_slice()),
208 /// &<BigInt as clacc::BigInt>::from_bytes_be(d.as_slice()),
209 /// );
210 /// let x = <BigInt as clacc::BigInt>::from_i64(7);
211 /// let w = acc.add(&x);
212 /// assert!(acc.del(&x).is_ok());
213 /// assert!(acc.verify(&x, &w).is_err());
214 /// ```
215 ///
216 /// This will only succeed with an accumulator constructed from a private
217 /// key.
218 ///
219 /// ```
220 /// use clacc::Accumulator;
221 /// use num_bigint::BigInt;
222 /// let n = vec![0x0c, 0xa1];
223 /// let mut acc = Accumulator::<BigInt>::with_public_key(
224 /// &<BigInt as clacc::BigInt>::from_bytes_be(n.as_slice())
225 /// );
226 /// let x = <BigInt as clacc::BigInt>::from_i64(3);
227 /// acc.add(&x);
228 /// assert!(acc.del(&x).is_err());
229 /// ```
230 pub fn del(
231 &mut self,
232 x: &T,
233 ) -> Result<T, MissingPrivateKeyError> {
234 let d = match self.d.as_ref() {
235 Some(d) => d,
236 None => return Err(MissingPrivateKeyError {}),
237 };
238 let x_i = x.powm(&T::from_i64(-1), &d);
239 self.z = self.z.powm(&x_i, &self.n);
240 Ok(self.z.clone())
241 }
242
243 /// Generate a witness to an element's addition to the accumulation.
244 /// The element `x` must be a prime.
245 ///
246 /// ```
247 /// use clacc::Accumulator;
248 /// use num_bigint::BigInt;
249 /// let n = vec![0x0c, 0xa1];
250 /// let d = vec![0x0c, 0x30];
251 /// let mut acc = Accumulator::<BigInt>::with_private_key(
252 /// &<BigInt as clacc::BigInt>::from_bytes_be(n.as_slice()),
253 /// &<BigInt as clacc::BigInt>::from_bytes_be(d.as_slice()),
254 /// );
255 /// let x = <BigInt as clacc::BigInt>::from_i64(7);
256 /// acc.add(&x);
257 /// let u = acc.prove(&x).unwrap();
258 /// assert!(acc.verify(&x, &u).is_ok());
259 /// ```
260 ///
261 /// This will only succeed with an accumulator constructed from a private
262 /// key.
263 ///
264 /// ```
265 /// use clacc::Accumulator;
266 /// use num_bigint::BigInt;
267 /// let n = vec![0x0c, 0xa1];
268 /// let mut acc = Accumulator::<BigInt>::with_public_key(
269 /// &<BigInt as clacc::BigInt>::from_bytes_be(n.as_slice()),
270 /// );
271 /// let x = <BigInt as clacc::BigInt>::from_i64(7);
272 /// acc.add(&x);
273 /// assert!(acc.prove(&x).is_err());
274 /// ```
275 pub fn prove(
276 &self,
277 x: &T,
278 ) -> Result<T, MissingPrivateKeyError> {
279 let d = match self.d.as_ref() {
280 Some(d) => d,
281 None => return Err(MissingPrivateKeyError {}),
282 };
283 let x_i = x.powm(&T::from_i64(-1), &d);
284 Ok(self.z.powm(&x_i, &self.n))
285 }
286
287 /// Verify an element is a member of the accumulator. The element `x` must
288 /// be a prime.
289 ///
290 /// ```
291 /// use clacc::Accumulator;
292 /// use num_bigint::BigInt;
293 /// let n = vec![0x0c, 0xa1];
294 /// let mut acc = Accumulator::<BigInt>::with_public_key(
295 /// &<BigInt as clacc::BigInt>::from_bytes_be(n.as_slice()),
296 /// );
297 /// let x = <BigInt as clacc::BigInt>::from_i64(3);
298 /// let u = acc.add(&x);
299 /// assert!(acc.verify(&x, &u).is_ok());
300 /// ```
301 ///
302 /// This works with accumulators constructed from a public key or a
303 /// private key.
304 ///
305 /// ```
306 /// use clacc::Accumulator;
307 /// use num_bigint::BigInt;
308 /// let n = vec![0x0c, 0xa1];
309 /// let d = vec![0x0c, 0x30];
310 /// let mut acc = Accumulator::<BigInt>::with_private_key(
311 /// &<BigInt as clacc::BigInt>::from_bytes_be(n.as_slice()),
312 /// &<BigInt as clacc::BigInt>::from_bytes_be(d.as_slice()),
313 /// );
314 /// let x = <BigInt as clacc::BigInt>::from_i64(3);
315 /// let w = acc.add(&x);
316 /// assert!(acc.verify(&x, &w).is_ok());
317 /// ```
318 pub fn verify(
319 &self,
320 x: &T,
321 w: &T,
322 ) -> Result<(), ElementNotFoundError> {
323 let w_x = w.powm(x, &self.n);
324 if self.z != w_x {
325 Err(ElementNotFoundError {})
326 } else {
327 Ok(())
328 }
329 }
330
331 /// Return the accumulation value as a [`BigInt`].
332 ///
333 /// ```
334 /// use clacc::Accumulator;
335 /// use num_bigint::BigInt;
336 /// let n = vec![0x0c, 0xa1];
337 /// let mut acc = Accumulator::<BigInt>::with_public_key(
338 /// &<BigInt as clacc::BigInt>::from_bytes_be(n.as_slice()),
339 /// );
340 /// let x = <BigInt as clacc::BigInt>::from_i64(3);
341 /// let y = <BigInt as clacc::BigInt>::from_i64(5);
342 /// // Add an element.
343 /// acc.add(&x);
344 /// // Save the current accumulation. This value is effectively
345 /// // a witness for the next element added.
346 /// let w = acc.get_value().clone();
347 /// // Add another element.
348 /// acc.add(&y);
349 /// // Verify that `w` is a witness for `y`.
350 /// assert!(acc.verify(&y, &w).is_ok());
351 /// ```
352 pub fn get_value(
353 &self,
354 ) -> T {
355 self.z.clone()
356 }
357
358 /// Set the accumulation value from a [`BigInt`].
359 ///
360 /// ```
361 /// use clacc::Accumulator;
362 /// use num_bigint::BigInt;
363 /// let n = vec![0x0c, 0xa1];
364 /// let d = vec![0x0c, 0x30];
365 /// let mut acc_prv = Accumulator::<BigInt>::with_private_key(
366 /// &<BigInt as clacc::BigInt>::from_bytes_be(n.as_slice()),
367 /// &<BigInt as clacc::BigInt>::from_bytes_be(d.as_slice()),
368 /// );
369 /// let mut acc_pub = Accumulator::<BigInt>::with_public_key(
370 /// &<BigInt as clacc::BigInt>::from_bytes_be(n.as_slice()),
371 /// );
372 /// let x = <BigInt as clacc::BigInt>::from_i64(3);
373 /// let w = acc_prv.add(&x);
374 /// acc_pub.set_value(&acc_prv.get_value());
375 /// assert!(acc_prv.verify(&x, &w).is_ok());
376 /// ```
377 pub fn set_value(
378 &mut self,
379 z: &T,
380 ) {
381 self.z = z.clone();
382 }
383
384}
385
386/// A sum of updates to be applied to witnesses.
387#[derive(Default)]
388#[derive(Clone)]
389pub struct Update<T: BigInt> {
390 n: T,
391 z: T,
392 pi_a: T,
393 pi_d: T,
394}
395
396impl<'u, T: 'u + BigInt> Update<T> {
397
398 /// Create a new batched update.
399 pub fn new(
400 acc: &Accumulator<T>,
401 ) -> Self {
402 Update {
403 n: acc.get_public_key(),
404 z: acc.get_value(),
405 pi_a: T::from_i64(1),
406 pi_d: T::from_i64(1),
407 }
408 }
409
410 /// Create a new batched update from products.
411 pub fn from_products(
412 acc: &Accumulator<T>,
413 pi_a: &T,
414 pi_d: &T,
415 ) -> Self {
416 Update {
417 n: acc.get_public_key(),
418 z: acc.get_value(),
419 pi_a: pi_a.clone(),
420 pi_d: pi_d.clone(),
421 }
422 }
423
424 /// Absorb an element that must be added to a witness.
425 pub fn add(
426 &mut self,
427 x: &T,
428 ) {
429 self.pi_a = self.pi_a.clone() * x;
430 }
431
432 /// Absorb an element that must be deleted from a witness.
433 pub fn del(
434 &mut self,
435 x: &T,
436 ) {
437 self.pi_d = self.pi_d.clone() * x;
438 }
439
440 /// Return the update's product of additions.
441 pub fn get_add(
442 &self,
443 ) -> T {
444 self.pi_a.clone()
445 }
446
447 /// Return the update's product of deletions.
448 pub fn get_del(
449 &self,
450 ) -> T {
451 self.pi_d.clone()
452 }
453
454 /// Update a witness. The update will include all additions and deletions
455 /// previously absorbed into this update struct.
456 ///
457 /// ```
458 /// use clacc::{
459 /// Accumulator,
460 /// Update,
461 /// };
462 /// use num_bigint::BigInt;
463 /// // In this example, the update will include a deletion, so the
464 /// // accumulator must be created with a private key.
465 /// let n = vec![0x0c, 0xa1];
466 /// let d = vec![0x0c, 0x30];
467 /// let mut acc = Accumulator::<BigInt>::with_private_key(
468 /// &<BigInt as clacc::BigInt>::from_bytes_be(n.as_slice()),
469 /// &<BigInt as clacc::BigInt>::from_bytes_be(d.as_slice()),
470 /// );
471 /// // Create the static elements.
472 /// let xs = <BigInt as clacc::BigInt>::from_i64(5);
473 /// // Create the deletion.
474 /// let xd = <BigInt as clacc::BigInt>::from_i64(7);
475 /// // Create the addition.
476 /// let xa = <BigInt as clacc::BigInt>::from_i64(11);
477 /// // Add the deletion element.
478 /// acc.add(&xd);
479 /// // Add the static element to the accumulator.
480 /// let mut wxs = acc.add(&xs);
481 /// // Delete the deletion element from the accumulator.
482 /// acc.prove(&xd).unwrap();
483 /// acc.del(&xd).unwrap();
484 /// // Add the addition element to the accumulator.
485 /// acc.add(&xa);
486 /// // Create an update object and absorb the addition and deletion.
487 /// let mut u = Update::new(&acc);
488 /// u.del(&xd);
489 /// u.add(&xa);
490 /// // Update the static element's witness.
491 /// wxs = u.update_witness(&xs, &wxs);
492 /// assert!(acc.verify(&xs, &wxs).is_ok());
493 /// ```
494 pub fn update_witness(
495 &self,
496 x: &T,
497 w: &T,
498 ) -> T {
499 let (_, a, b) = self.pi_d.gcdext(&x);
500 (w.powm(&(a * &self.pi_a), &self.n)
501 * &self.z.powm(&b, &self.n))
502 % &self.n
503 }
504
505 /// Thread-safe method that updates multiple witnesses.
506 ///
507 /// It is assumed that the additional elements have been absorbed by the
508 /// update and that their witnesses are the accumulator's value before any
509 /// of the additions or deletions absorbed by this update were applied.
510 /// Updating the witnesses for each of these additional elements is thus
511 /// achieved by simply removing its respective element from the update and
512 /// applying the result to its witness.
513 ///
514 /// This method operates on atomic references to iterators over collections
515 /// of element-witness pairs. An invocation will run until the referenced
516 /// iterators have reached the end of their collections. To update
517 /// witnesses concurrently, simply invoke this method from multiple threads
518 /// using references to the same iterators.
519 ///
520 /// ```
521 /// use clacc::{
522 /// Accumulator,
523 /// BigInt as BigIntTrait,
524 /// Update,
525 /// };
526 /// use crossbeam::thread;
527 /// use num_cpus;
528 /// use num_bigint::{BigInt, ToBigInt};
529 /// use num_prime::nt_funcs::next_prime;
530 /// use rand::RngCore;
531 /// use std::sync::{Arc, Mutex};
532 /// // Create elements.
533 /// const BUCKET_SIZE: usize = 20;
534 /// const DELETIONS_COUNT: usize = 2;
535 /// const ADDITIONS_COUNT: usize = 10;
536 /// const STATICELS_COUNT: usize = BUCKET_SIZE - DELETIONS_COUNT;
537 /// let mut deletions: Vec<(BigInt, BigInt)> = vec![
538 /// Default::default(); DELETIONS_COUNT
539 /// ];
540 /// let mut additions: Vec<(BigInt, BigInt)> = vec![
541 /// Default::default(); ADDITIONS_COUNT
542 /// ];
543 /// let mut staticels: Vec<(BigInt, BigInt)> = vec![
544 /// Default::default(); STATICELS_COUNT
545 /// ];
546 /// let mut rng = rand::thread_rng();
547 /// let mut bytes = vec![0; 8];
548 /// for deletion in deletions.iter_mut() {
549 /// rng.fill_bytes(&mut bytes);
550 /// let x = <BigInt as clacc::BigInt>::from_bytes_be(bytes.as_slice());
551 /// deletion.0 = next_prime(
552 /// &x.to_biguint().unwrap(),
553 /// None,
554 /// ).unwrap().to_bigint().unwrap();
555 /// }
556 /// for addition in additions.iter_mut() {
557 /// rng.fill_bytes(&mut bytes);
558 /// let x = <BigInt as clacc::BigInt>::from_bytes_be(bytes.as_slice());
559 /// addition.0 = next_prime(
560 /// &x.to_biguint().unwrap(),
561 /// None,
562 /// ).unwrap().to_bigint().unwrap();
563 /// }
564 /// for staticel in staticels.iter_mut() {
565 /// rng.fill_bytes(&mut bytes);
566 /// let x = <BigInt as clacc::BigInt>::from_bytes_be(bytes.as_slice());
567 /// staticel.0 = next_prime(
568 /// &x.to_biguint().unwrap(),
569 /// None,
570 /// ).unwrap().to_bigint().unwrap();
571 /// }
572 /// // Create accumulator with private key.
573 /// let n = vec![0x0c, 0xa1];
574 /// let d = vec![0x0c, 0x30];
575 /// let mut acc = Accumulator::<BigInt>::with_private_key(
576 /// &<BigInt as clacc::BigInt>::from_bytes_be(n.as_slice()),
577 /// &<BigInt as clacc::BigInt>::from_bytes_be(d.as_slice()),
578 /// );
579 /// // Accumulate elements.
580 /// for (x, _) in deletions.iter() {
581 /// acc.add(&x);
582 /// }
583 /// for (x, _) in staticels.iter() {
584 /// acc.add(&x);
585 /// }
586 /// // Generate witnesses for static elements.
587 /// for (x, w) in staticels.iter_mut() {
588 /// *w = acc.prove(&x).unwrap()
589 /// }
590 /// // Save accumulation at current state.
591 /// let prev = acc.clone();
592 /// // Accumulate deletions.
593 /// for (x, w) in deletions.iter_mut() {
594 /// *w = acc.prove(&x).unwrap();
595 /// acc.del(&x).unwrap();
596 /// }
597 /// // Accumulate additions.
598 /// for (x, w) in additions.iter_mut() {
599 /// acc.add(&x);
600 /// // Use the saved accumulation as the witness value.
601 /// *w = prev.get_value();
602 /// }
603 /// // Batch updates.
604 /// let mut update = Update::new(&acc);
605 /// for (x, _) in deletions.iter() {
606 /// update.del(&x);
607 /// }
608 /// for (x, _) in additions.iter() {
609 /// update.add(&x);
610 /// }
611 /// // Update all witnesses concurrently.
612 /// let additions_iter = Arc::new(Mutex::new(additions.iter_mut()));
613 /// let staticels_iter = Arc::new(Mutex::new(staticels.iter_mut()));
614 /// thread::scope(|scope| {
615 /// for _ in 0..num_cpus::get() {
616 /// let u = update.clone();
617 /// let add = additions_iter.clone();
618 /// let sta = staticels_iter.clone();
619 /// scope.spawn(move |_| u.update_witnesses(add, sta));
620 /// }
621 /// }).unwrap();
622 /// // Verify all updated witnesses.
623 /// for (x, w) in additions.iter() {
624 /// assert!(acc.verify(&x, &w).is_ok());
625 /// }
626 /// for (x, w) in staticels.iter() {
627 /// assert!(acc.verify(&x, &w).is_ok());
628 /// }
629 /// ```
630 pub fn update_witnesses<
631 IA: Iterator<Item = &'u mut (T, T)> + Send,
632 IS: Iterator<Item = &'u mut (T, T)> + Send,
633 >(
634 &self,
635 additions: Arc<Mutex<IA>>,
636 staticels: Arc<Mutex<IS>>,
637 ) {
638 loop {
639 let update;
640 let (x, w, u) = {
641 match staticels.lock().unwrap().next() {
642 Some((x, w)) => (x, w, self),
643 None => {
644 match additions.lock().unwrap().next() {
645 Some((x, w)) => {
646 update = Update {
647 n: self.n.clone(),
648 z: self.z.clone(),
649 pi_a: self.pi_a.clone() / x,
650 pi_d: self.pi_d.clone(),
651 };
652 (x, w, &update)
653 }
654 None => break,
655 }
656 }
657 }
658 };
659 *w = u.update_witness(&x, &w);
660 }
661 }
662}
663
664#[derive(Debug)]
665pub struct MissingPrivateKeyError;
666
667impl std::fmt::Display for MissingPrivateKeyError {
668 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
669 write!(f, "Missing private key")
670 }
671}
672
673#[derive(Debug)]
674pub struct ElementNotFoundError;
675
676impl std::fmt::Display for ElementNotFoundError {
677 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
678 write!(f, "Element not found")
679 }
680}