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
#[macro_export]
#[doc(hidden)]
macro_rules! _define_test_circuit {
(
$name: ident,
{$($in:ident : $in_t:ty),* $(,)?},
[$($out:ident),* $(,)?],
|$executor: ident| $body: block
$(, $param_name: ident : $param_type: ty)?
) => {
::paste::paste! {
struct $name{
$(
$in: $in_t,
)*
$($param_name: $param_type),*
}
impl Default for $name {
fn default() -> Self {
Self {
$(
$in: Default::default(),
)*
$($param_name: Default::default()),*
}
}
}
impl Circuit for $name {
fn exec<B: Backend>(&self, frontend: &Frontend<B>) {
let $executor = frontend;
$(
let $in = self.$in;
)*
$(
let $param_name = self.$param_name;
)*
$(
let $out;
)*
$body
$(
$executor.output($out);
)*
}
}
}
};
}
#[doc(inline)]
pub use _define_test_circuit as define_test_circuit;
#[macro_export]
#[doc(hidden)]
macro_rules! _define_test_func {
(
$func: ident,
$num_samples: expr,
{$($in:ident : $in_t:ty),* $(,)?},
[$($out:ident),* $(,)?],
|$executor: ident| $body: block,
$ref_body: block
$(, $param_name: ident : $param_type: ty, $param_values: expr)?
) => {
::paste::paste! {
fn $func(){
use zkboo::{
circuit::Circuit,
backend::{Backend, Frontend},
executor::{exec, OwnedFlexibleWordPool},
word::{Words, WordLike},
};
use $crate::common::{rand_words::test_vec, test_func::define_test_circuit, proofs::test_proof};
type WP = OwnedFlexibleWordPool<usize>;
define_test_circuit!(TestCircuit, {$($in: $in_t,)*}, [$($out,)*], |$executor| $body $(, $param_name: $param_type)*);
let _param_values = [1usize; 1];
$(
let _param_values = $param_values;
)*
for _p in _param_values {
$(
let $param_name = _p;
)*
let mut seed = 0u64;
$(
seed += 1;
let mut [<iter_ $in>] = test_vec::<_, _, $in_t>($num_samples, seed).into_iter();
)*
for _ in 0..$num_samples {
$(
let [<_ $in>] = [<iter_ $in>].next().unwrap();
)*
// Test execution:
let circuit = TestCircuit {$($in: [<_ $in>],)* $($param_name,)*};
let outputs = exec::<_, WP>(&circuit);
// Reference execution:
$(
let $in = [<_ $in>];
)*
$(
let $out;
)*
$ref_body
let mut expected_outputs = Words::new();
$(
expected_outputs.as_vec_mut().extend(WordLike::to_word($out).to_le_words());
)*
// Ensure matching output words:
assert_eq!(outputs, expected_outputs);
// Test proof generation:
test_proof(&circuit);
}
}
}
}
};
}
#[doc(inline)]
pub use _define_test_func as define_test_func;