1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//! Fast cryptographic accumulator and vector commitment library, originally written by Cambrian
//! Technologies [\[GitHub\]](https://github.com/cambrian/accumulator).
//!
//! **Disclaimer**: This library is intended to be production-quality code, but it has not been
//! independently-audited for correctness or tested to a critical degree. As such, please treat this
//! library as **research-grade** for the time being.
//!
//! # Important Note
//!
//! To ensure correspondence between accumulator methods and logical set operations in your
//! application, you must ensure that **no element is accumulated twice**. In particular, deleting
//! a doubly-accumulated element will remove only one "copy" of it from the accumulator, meaning
//! that its membership can still be verified. Hence, an accumulator without this invariant can be
//! viewed as a multiset.
//!
//! # What is an accumulator?
//!
//! An accumulator is a cryptographic primitive which functions essentially as a secure
//! decentralized set. It allows parties to maintain consensus on a set of values via a
//! _succinct binding commitment_ as well as to issue _efficiently verifiable (non)membership
//! proofs_ for elements of interest, all without requiring any party to store the entire set.
//!
//! Similarly to a Merkle tree, the accumulator stores its state commitment in constant space. A
//! notable difference, however, is that its inclusion and exclusion proofs also take up constant
//! space, and can be verified in constant time. For a far more detailed discussion of accumulators
//! as implemented here, see _Batching Techniques for Accumulators with Applications to IOPs and
//! Stateless Blockchains_ (Boneh, Bünz, and Fisch 2018)
//! [\[Link\]](https://eprint.iacr.org/2018/1188.pdf).
//!
//! Throughout our code, we refer to this paper as `BBF`. We also refer to another paper, _Universal
//! Accumulators with Efficient Nonmembership Proofs_ (Li, Li, Xue 2007)
//! [\[Link\]](https://link.springer.com/content/pdf/10.1007/978-3-540-72738-5_17.pdf), abbreviated
//! henceforth as `LLX`.
//!
//! # What is a vector commitment?
//!
//! A vector commitment (VC) is a closely-related primitive, distinguished from an accumulator in
//! that it provides a _position-binding_ commitment to state. That is, a VC allows parties to
//! prove or disprove that a certain element exists at a certain position.
//!
//! (Think VC : Vector :: Accumulator : Set.)
//!
//! Our vector commitment implementation is a work-in-progress (WIP), and should be treated with
//! even more skepticism than our accumulators.
//!
//! # Usage
//! ```
//! // A very basic example.
//! use accumulator::Accumulator;
//! use accumulator::group::Rsa2048;
//!
//! let acc = Accumulator::<Rsa2048, &'static str>::empty();
//!
//! // Accumulate "dog" and "cat". The `add_with_proof` method returns the new accumulator state
//! // and a proof that you accumulated "dog" and "cat".
//! let (acc, proof) = acc.add_with_proof(&["dog", "cat"]);
//!
//! // A network participant who sees (acc, proof, and ["dog", "cat"]) can verify that the update
//! // was formed correctly ...
//! assert!(acc.verify_membership_batch(&["dog", "cat"], &proof));
//!
//! // ... and trying to verify something that has not been accumulated will fail.
//! assert!(!acc.verify_membership(&"cow", &proof));
//! ```
//!
//! Typical users of this library will access public-facing routines on `accumulator` and
//! `vector_commitment`. However, we also export internal modules for useful traits, types (such as
//! the `Rsa2048` group), and specialized procedures. **Use internal components at your own risk**.
//!
//! You can find a more interesting application of our library
//! [here](https://github.com/cambrian/accumulator-demo), where we create a proof-of-concept for
//! stateless Bitcoin nodes!
//!
//! # Groups
//!
//! Accumulator and vector commitment operations take place over algebraic groups with certain
//! cryptographic properties. We provide implementations for two suitable groups:
//! (1) an RSA group with the [RSA-2048 modulus](https://en.wikipedia.org/wiki/RSA_numbers#RSA-2048)
//! and (2) an ideal class group with a fixed discriminant generated by OpenSSL.
//!
//! The RSA group is fast but relies on the security of the RSA-2048 modulus and needs trusted
//! setup if using a different modulus. The class group is slower but eliminates the need for a
//! trusted setup. For more on class groups, please visit this
//! [thorough explainer](https://www.michaelstraka.com/posts/classgroups/) by contributor Michael
//! Straka.
//!
//! # Performance
//!
//! Most accumulator or vector commitment functions will bottleneck in hashing to large primes. To
//! alleviate this, we created a zero-allocation `U256` type that uses the low-level `mpn_`
//! functions in [GMP](https://gmplib.org). Our `hash_to_prime` uses this type internally.
//!
//! Class groups are currently not performant for any meaningful use case. A pull request is in the
//! works to drastically improve their performance using techniques learned from the
//! [Chia VDF competition](https://github.com/Chia-Network/vdf-competition).
#![allow(clippy::unknown_clippy_lints)]
#![allow(clippy::many_single_char_names)]
#![allow(clippy::empty_enum)]
#![warn(missing_docs)]

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate arrayref;

mod accumulator;
pub use crate::accumulator::*;
mod vector_commitment;
pub use vector_commitment::*;

pub mod group;
pub mod hash;
pub mod proof;
#[allow(missing_docs)]
pub mod uint;
pub mod util;