forked from privacy-scaling-explorations/halo2curves
-
Notifications
You must be signed in to change notification settings - Fork 10
/
zal.rs
116 lines (98 loc) · 3.48 KB
/
zal.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
//! This module provides "ZK Acceleration Layer" traits
//! to abstract away the execution engine for performance-critical primitives.
//!
//! The ZAL Engine is voluntarily left unconstrained
//! so that accelerator libraries are not prematurely limited.
//!
//! Terminology
//! -----------
//!
//! We use the name Backend+Engine for concrete implementations of ZalEngine.
//! For exaple H2cEngine for pure Halo2curves implementation.
//!
//! Alternative names considered were Executor or Driver however
//! - executor is already used in Rust (and the name is long)
//! - driver will be confusing as we work quite low-level with GPUs and FPGAs.
//!
//! Unfortunately Engine is used in bn256 for pairings.
//! Fortunately ZalEngine is only used in the prover
//! while "pairing engine" is only used in the verifier
//!
//! Initialization design space
//! ---------------------------
//!
//! It is recommended that ZAL backends provide:
//! - an initialization function:
//! - either "fn new() -> ZalEngine" for simple libraries
//! - or a builder pattern for complex initializations
//! - a shutdown function.
//!
//! The ZalEngine can be a stub type
//! and the shutdown function might be unnecessary
//! if the ZalEngine uses a global threadpool like Rayon.
//!
//! Backends might want to add as an option:
//! - The number of threads (CPU)
//! - The device(s) to run on (multi-sockets machines, multi-GPUs machines, ...)
//! - The curve (JIT-compiled backend)
use crate::msm::best_multiexp;
use pasta_curves::arithmetic::CurveAffine;
// The ZK Accel Layer API
// ---------------------------------------------------
pub trait ZalEngine{}
pub trait MsmAccel<C: CurveAffine>: ZalEngine {
fn msm(&self, coeffs: &[C::Scalar], base: &[C]) -> C:: Curve;
}
// ZAL using Halo2curves as a backend
// ---------------------------------------------------
pub struct H2cEngine;
impl H2cEngine {
pub fn new() -> Self {
Self{}
}
}
impl ZalEngine for H2cEngine{}
impl<C: CurveAffine> MsmAccel<C> for H2cEngine {
fn msm(&self, coeffs: &[C::Scalar], bases: &[C]) -> C:: Curve {
best_multiexp(coeffs, bases)
}
}
// Testing
// ---------------------------------------------------
#[cfg(test)]
mod test {
use crate::bn256::G1Affine;
use ark_std::{end_timer, start_timer};
use ff::Field;
use group::{Curve, Group};
use pasta_curves::arithmetic::CurveAffine;
use rand_core::OsRng;
use super::{H2cEngine, MsmAccel};
fn run_msm_zal<C: CurveAffine>(min_k: usize, max_k: usize) {
let points = (0..1 << max_k)
.map(|_| C::Curve::random(OsRng))
.collect::<Vec<_>>();
let mut affine_points = vec![C::identity(); 1 << max_k];
C::Curve::batch_normalize(&points[..], &mut affine_points[..]);
let points = affine_points;
let scalars = (0..1 << max_k)
.map(|_| C::Scalar::random(OsRng))
.collect::<Vec<_>>();
for k in min_k..=max_k {
let points = &points[..1 << k];
let scalars = &scalars[..1 << k];
let t0 = start_timer!(|| format!("freestanding msm k={}", k));
let e0 = super::best_multiexp(scalars, points);
end_timer!(t0);
let engine = H2cEngine::new();
let t1 = start_timer!(|| format!("H2cEngine msm k={}", k));
let e1 = engine.msm(scalars, points);
end_timer!(t1);
assert_eq!(e0, e1);
}
}
#[test]
fn test_msm_zal() {
run_msm_zal::<G1Affine>(3, 14);
}
}