-
Notifications
You must be signed in to change notification settings - Fork 154
/
Copy pathvitalik_test.rs
97 lines (88 loc) · 2.84 KB
/
vitalik_test.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
use lambdaworks_circom_adapter::{circom_to_lambda, read_circom_r1cs, read_circom_witness};
use lambdaworks_groth16::{common::FrElement, QuadraticArithmeticProgram};
// Converts following Circom circuit and inputs into Lambdaworks-compatible QAP and witness assignments.
//
// ```csharp
// template Test() {
// signal input x;
// signal output out;
//
// signal sym_1;
// signal y;
//
// sym_1 <== x * x;
// out <== (sym_1 * x) + (x + 5);
// }
// ```
//
// The input used is:
//
// ```js
// { "x": 3 }
// ```
#[test]
fn vitalik_w_and_qap() {
let circom_wtns = read_circom_witness("./tests/vitalik_example/witness.json")
.expect("could not read witness");
let circom_r1cs =
read_circom_r1cs("./tests/vitalik_example/test.r1cs.json").expect("could not read r1cs");
let (qap, wtns, pubs) = circom_to_lambda(circom_r1cs, circom_wtns);
// Freshly generated witness assignment "w" must be in form ["1", "~out", "x", "sym_1"]
assert_eq!(
wtns,
// 1, out, x, sym_1
["1", "23", "3", "9"]
.map(FrElement::from_hex_unchecked)
.to_vec(),
"incorrect witness"
);
assert_eq!(
pubs,
["1", "23"].map(FrElement::from_hex_unchecked).to_vec(),
"incorrect public signals"
);
// Regarding QAP, we expect 2 constraints in following form
// -sym_1 = -x * x
// x + 5 - ~out = -sym_1 * x
//
// Same ordering difference exists for variable matrices, too. Circom adapter changes the
// order of the rows in the same way it rearranges the witness ordering.
const _M1_: &str = "0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000";
const _0_: &str = "0";
const _1_: &str = "1";
#[rustfmt::skip]
let [temp_l, temp_r, temp_o] = [
// L //
[
[_0_, _0_], // 1
[_0_, _0_], // ~out
[_M1_, _0_], // x
[_0_, _M1_], // sym_1
],
// R //
[
[_0_, _0_], // 1
[_0_, _0_], // ~out
[_1_, _1_], // x
[_0_, _0_], // sym_1
],
// O //
[
[_0_, "5"], // 1
[_0_, _M1_], // ~out
[_0_, _1_], // x
[_M1_, _0_], // sym_1
],
]
.map(|matrix| matrix.map(|row| row.map(FrElement::from_hex_unchecked).to_vec()));
let expected_qap =
QuadraticArithmeticProgram::from_variable_matrices(pubs.len(), &temp_l, &temp_r, &temp_o);
assert_eq!(qap.l, expected_qap.l);
assert_eq!(qap.r, expected_qap.r);
assert_eq!(qap.o, expected_qap.o);
// check proofs
let (pk, vk) = lambdaworks_groth16::setup(&qap);
let proof = lambdaworks_groth16::Prover::prove(&wtns, &qap, &pk);
let accept = lambdaworks_groth16::verify(&vk, &proof, &pubs);
assert!(accept, "proof verification failed");
}