forked from arcalinea/bellman-examples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmultiply.rs
133 lines (107 loc) · 3.22 KB
/
multiply.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
#![allow(unused_imports)]
#![allow(unused_variables)]
extern crate bellman;
extern crate pairing;
extern crate rand;
// For randomness (during paramgen and proof generation)
use self::rand::{thread_rng};
// Bring in some tools for using pairing-friendly curves
use self::pairing::{
Engine,
Field,
PrimeField
};
// We're going to use the BLS12-381 pairing-friendly elliptic curve.
use self::pairing::bls12_381::{
Bls12,
Fr,
};
// We'll use these interfaces to construct our circuit.
use self::bellman::{
Circuit,
ConstraintSystem,
SynthesisError
};
// We're going to use the Groth16 proving system.
use self::bellman::groth16::{
Proof,
generate_random_parameters,
prepare_verifying_key,
create_random_proof,
verify_proof,
};
// demo circuit
// proving that I know a such that a * 3 = 21
pub struct MultiplyDemo<E: Engine> {
pub a: Option<E::Fr>,
pub b: Option<E::Fr>,
pub c: Option<E::Fr>
}
// create a demo circuit by using the `Circuit` trait which
/// is used during paramgen and proving in order to
/// synthesize the constraint system.
impl <E: Engine> Circuit<E> for MultiplyDemo<E> {
fn synthesize<CS: ConstraintSystem<E>>(
self,
cs: &mut CS
) -> Result<(), SynthesisError>
{
// Allocate the first value (private)
let a = cs.alloc(|| "a", || {
self.a.ok_or(SynthesisError::AssignmentMissing)
})?;
// Allocate the second value (private)
let b = cs.alloc(|| "b", || {
self.b.ok_or(SynthesisError::AssignmentMissing)
})?;
// Allocate the third value (public)
// allocating a public input uses alloc_input
let c = cs.alloc_input(|| "c", || {
self.c.ok_or(SynthesisError::AssignmentMissing)
})?;
// a * b = c?
cs.enforce(
|| "mult",
|lc| lc + a,
|lc| lc + b,
|lc| lc + c
);
Ok(())
}
}
#[test]
fn test_multiply(){
// This may not be cryptographically safe, use
// `OsRng` (for example) in production software.
let rng = &mut thread_rng();
println!("Creating parameters...");
// Create parameters for our circuit
let params = {
let c = MultiplyDemo::<Bls12> {
a: None,
// make option values as None for these variables, for paramgen
// don't want to bake these nums into parameters
b: None,
c: None
};
generate_random_parameters(c, rng).unwrap()
};
// Prepare the verification key (for proof verification)
let pvk = prepare_verifying_key(¶ms.vk);
println!("Creating proofs...");
let public_input = Fr::from_str("21");
// Create an instance of circuit
let c = MultiplyDemo::<Bls12> {
a: Fr::from_str("7"),
// when creating instance here, pass in Some of actual variables you're using
b: Fr::from_str("3"),
c: public_input
};
// Create a groth16 proof with our parameters.
let proof = create_random_proof(c, ¶ms, rng).unwrap();
assert!(verify_proof(
&pvk,
&proof,
&[public_input.unwrap()]
).unwrap());
}