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}