-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathgadget_mimc.rs
177 lines (138 loc) · 5.73 KB
/
gadget_mimc.rs
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
169
170
171
172
173
174
175
176
177
extern crate rand;
//extern crate rand_chacha;
extern crate curve25519_dalek;
extern crate merlin;
extern crate bulletproofs;
use curve25519_dalek::scalar::Scalar;
use bulletproofs::r1cs::{ConstraintSystem, R1CSError, R1CSProof, Variable, Prover, Verifier};
use bulletproofs::{BulletproofGens, PedersenGens};
use merlin::Transcript;
use bulletproofs::r1cs::LinearCombination;
use crate::r1cs_utils::{AllocatedScalar,constrain_lc_with_scalar};
pub const MIMC_ROUNDS: usize = 322;
//pub const MIMC_ROUNDS: usize = 10;
pub fn mimc(
xl: &Scalar,
xr: &Scalar,
constants: &[Scalar]
) -> Scalar
{
assert_eq!(constants.len(), MIMC_ROUNDS);
let mut xl = xl.clone();
let mut xr = xr.clone();
for i in 0..MIMC_ROUNDS {
let tmp1 = xl + constants[i];
let mut tmp2 = (tmp1 * tmp1) * tmp1;
tmp2 += xr;
xr = xl;
xl = tmp2;
}
xl
}
pub fn mimc_gadget<CS: ConstraintSystem>(
cs: &mut CS,
left: AllocatedScalar,
right: AllocatedScalar,
mimc_rounds: usize,
mimc_constants: &[Scalar],
image: &Scalar
) -> Result<(), R1CSError> {
let res_v = mimc_hash_2::<CS>(cs, left.variable.into(), right.variable.into(), mimc_rounds, mimc_constants)?;
constrain_lc_with_scalar::<CS>(cs, res_v, image);
Ok(())
}
pub fn mimc_hash_2<CS: ConstraintSystem>(cs: &mut CS,
left: LinearCombination,
right: LinearCombination,
mimc_rounds: usize,
mimc_constants: &[Scalar]) -> Result<LinearCombination, R1CSError> {
let mut left_v = left;
let mut right_v = right;
for j in 0..mimc_rounds {
// xL, xR := xR + (xL + Ci)^3, xL
//let cs = &mut cs.namespace(|| format!("mimc round {}", j));
let const_lc: LinearCombination = vec![(Variable::One(), mimc_constants[j])].iter().collect();
let left_plus_const: LinearCombination = left_v.clone() + const_lc;
let (l, _, l_sqr) = cs.multiply(left_plus_const.clone(), left_plus_const);
let (_, _, l_cube) = cs.multiply(l_sqr.into(), l.into());
let tmp = LinearCombination::from(l_cube) + right_v;
right_v = left_v;
left_v = tmp;
}
Ok(left_v)
}
#[cfg(test)]
mod tests {
use super::*;
// For benchmarking
use std::time::{Duration, Instant};
//use rand_chacha::ChaChaRng;
use rand::SeedableRng;
use super::rand::rngs::StdRng;
#[test]
fn test_mimc() {
let mut test_rng: StdRng = SeedableRng::from_seed([24u8; 32]);
// Generate the MiMC round constants
let constants = (0..MIMC_ROUNDS).map(|_| Scalar::random(&mut test_rng)).collect::<Vec<_>>();
//let constants = (0..MIMC_ROUNDS).map(|i| Scalar::one()).collect::<Vec<_>>();
let pc_gens = PedersenGens::default();
let bp_gens = BulletproofGens::new(2048, 1);
const SAMPLES: u32 = 1;
let mut total_proving = Duration::new(0, 0);
let mut total_verifying = Duration::new(0, 0);
for _ in 0..SAMPLES {
// Generate a random preimage and compute the image
let xl = Scalar::random(&mut test_rng);
let xr = Scalar::random(&mut test_rng);
let image = mimc(&xl, &xr, &constants);
let (proof, commitments) = {
let mut prover_transcript = Transcript::new(b"MiMC");
let mut prover = Prover::new(&pc_gens, &mut prover_transcript);
let (com_l, var_l) = prover.commit(xl, Scalar::random(&mut test_rng));
let (com_r, var_r) = prover.commit(xr, Scalar::random(&mut test_rng));
let left_alloc_scalar = AllocatedScalar {
variable: var_l,
assignment: Some(xl),
};
let right_alloc_scalar = AllocatedScalar {
variable: var_r,
assignment: Some(xr),
};
let start = Instant::now();
assert!(mimc_gadget(&mut prover,
left_alloc_scalar,
right_alloc_scalar,
MIMC_ROUNDS,
&constants,
&image).is_ok());
println!("For MiMC rounds {}, no of constraints is {}", &MIMC_ROUNDS, &prover.num_constraints());
let proof = prover.prove(&bp_gens).unwrap();
total_proving += start.elapsed();
(proof, (com_l, com_r))
};
let mut verifier_transcript = Transcript::new(b"MiMC");
let mut verifier = Verifier::new(&mut verifier_transcript);
let var_l = verifier.commit(commitments.0);
let var_r = verifier.commit(commitments.1);
let left_alloc_scalar = AllocatedScalar {
variable: var_l,
assignment: None,
};
let right_alloc_scalar = AllocatedScalar {
variable: var_r,
assignment: None,
};
let start = Instant::now();
assert!(mimc_gadget(&mut verifier,
left_alloc_scalar,
right_alloc_scalar,
MIMC_ROUNDS,
&constants,
&image).is_ok());
assert!(verifier.verify(&proof, &pc_gens, &bp_gens).is_ok());
total_verifying += start.elapsed();
}
println!("Total proving time for {} samples: {:?} seconds", SAMPLES, total_proving);
println!("Total verifying time for {} samples: {:?} seconds", SAMPLES, total_verifying);
}
}