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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
//! Implementation of Stake-based Threshold Multisignatures
//! Top-level API for Mithril Stake-based Threshold Multisignature scheme.
//! See figure 6 of [the paper](https://eprint.iacr.org/2021/916) for most of the
//! protocol.
//!
//! What follows is a simple example showing the usage of STM.
//!
//! ```rust
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! use blake2::{Blake2b, digest::consts::U32};
//! use rand_chacha::ChaCha20Rng;
//! use rand_core::{RngCore, SeedableRng};
//! use rayon::prelude::*; // We use par_iter to speed things up
//!
//! use mithril_stm::{
//! AggregateSignatureType, AggregationError, Clerk, Initializer, KeyRegistration, Parameters,
//! Signer, SingleSignature, MithrilMembershipDigest,
//! };
//!
//! let nparties = 4; // Use a small number of parties for this example
//! type D = MithrilMembershipDigest; // Setting the hash function for convenience
//!
//! let mut rng = ChaCha20Rng::from_seed([0u8; 32]); // create and initialize rng
//! let mut msg = [0u8; 16]; // setting an arbitrary message
//! rng.fill_bytes(&mut msg);
//!
//! // In the following, we will have 4 parties try to sign `msg`, then aggregate and
//! // verify those signatures.
//!
//! //////////////////////////
//! // initialization phase //
//! //////////////////////////
//!
//! // Set low parameters for testing
//! // XXX: not for production
//! let params = Parameters {
//! m: 100, // Security parameter XXX: not for production
//! k: 2, // Quorum parameter XXX: not for production
//! phi_f: 0.2, // Lottery parameter XXX: not for production
//! };
//!
//! // Generate some arbitrary stake for each party
//! // Stake is an integer.
//! // Total stake of all parties is total stake in the system.
//! let stakes = (0..nparties)
//! .into_iter()
//! .map(|_| 1 + (rng.next_u64() % 9999))
//! .collect::<Vec<_>>();
//!
//! // Create a new key registry from the parties and their stake
//! let mut key_reg = KeyRegistration::init();
//!
//! // For each party, crate a Initializer.
//! // This struct can create keys for the party.
//! let mut ps: Vec<Initializer> = Vec::with_capacity(nparties);
//! for stake in stakes {
//! // Create keys for this party
//! let p = Initializer::new(params, stake, &mut rng);
//! // Register keys with the KeyRegistration service
//! key_reg
//! .register(p.stake, p.get_verification_key_proof_of_possession())
//! .unwrap();
//! ps.push(p);
//! }
//!
//! // Close the key registration.
//! let closed_reg = key_reg.close();
//!
//! // Finalize the Initializer and turn it into a Signer, which can execute the
//! // rest of the protocol.
//! let ps = ps
//! .into_par_iter()
//! .map(|p| p.create_signer(closed_reg.clone()).unwrap())
//! .collect::<Vec<Signer<D>>>();
//!
//! /////////////////////
//! // operation phase //
//! /////////////////////
//!
//! // Next, each party tries to sign the message for each index available.
//! // We collect the successful signatures into a vec.
//! let sigs = ps
//! .par_iter()
//! .filter_map(|p| {
//! return p.sign(&msg);
//! })
//! .collect::<Vec<SingleSignature>>();
//!
//! // Clerk can aggregate and verify signatures.
//! let clerk = Clerk::new_clerk_from_signer(&ps[0]);
//!
//! // Aggregate and verify the signatures
//! let msig = clerk.aggregate_signatures_with_type(&sigs, &msg, AggregateSignatureType::Concatenation);
//! match msig {
//! Ok(aggr) => {
//! println!("Aggregate ok");
//! assert!(aggr
//! .verify(&msg, &clerk.compute_aggregate_verification_key(), ¶ms)
//! .is_ok());
//! }
//! Err(error) => assert!(
//! matches!(
//! error.downcast_ref::<AggregationError>(),
//! Some(AggregationError::NotEnoughSignatures { .. })
//! ),
//! "Unexpected error: {error}"
//! ),
//! }
//! # Ok(())
//! # }
//! ```
pub use *;
pub use BlsSignatureError;
pub use ;
pub use ;
use U64;
use ;
use ;
use Debug;
/// The quantity of stake held by a party, represented as a `u64`.
pub type Stake = u64;
/// Quorum index for signatures.
/// An aggregate signature (`StmMultiSig`) must have at least `k` unique indices.
pub type Index = u64;
/// Mithril-stm error type
pub type StmError = Error;
/// Mithril-stm result type
pub type StmResult<T> = Result;
/// Trait defining the different hash types for different proof systems.
/// Default Mithril Membership Digest
/// Default implementation of MembershipDigest for Mithril
/// TODO: `SnarkHash` will be changed with Poseidon. For now, we use `Blake2b<U64>` (`U64` is set
/// for having something different than the `ConcatenationHash`) as a placeholder.