mirror of https://github.com/zcash/mpc.git
Add FFT for computing the H query.
This commit is contained in:
parent
977a8e8dab
commit
4f85755795
|
@ -18,6 +18,8 @@ pub use self::g2::G2;
|
|||
extern "C" {
|
||||
fn libsnarkwrap_init();
|
||||
fn libsnarkwrap_pairing(p: *const G1, q: *const G2) -> Gt;
|
||||
fn libsnarkwrap_getqap(d: *mut libc::uint32_t, omega: *mut Fr);
|
||||
fn libsnarkwrap_test_compare_tau(i: *const G1, tau: *const Fr, d: libc::uint32_t) -> bool;
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
|
@ -34,6 +36,22 @@ pub fn initialize() {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get the QAP info for the generation routines
|
||||
pub fn getqap() -> (usize, Fr) {
|
||||
let mut d = 0;
|
||||
let mut o = Fr::zero();
|
||||
|
||||
unsafe { libsnarkwrap_getqap(&mut d, &mut o); }
|
||||
|
||||
(d as usize, o)
|
||||
}
|
||||
|
||||
/// Check that the lagrange coefficients computed by tau over
|
||||
/// G1 equal the expected vector.
|
||||
pub fn compare_tau(v: &[G1], tau: &Fr) -> bool {
|
||||
unsafe { libsnarkwrap_test_compare_tau(&v[0], tau, v.len() as u32) }
|
||||
}
|
||||
|
||||
pub trait Pairing<Other: Group> {
|
||||
fn g1<'a>(&'a self, other: &'a Other) -> &'a G1;
|
||||
fn g2<'a>(&'a self, other: &'a Other) -> &'a G2;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "algebra/curves/public_params.hpp"
|
||||
#include "relations/arithmetic_programs/qap/qap.hpp"
|
||||
#include "reductions/r1cs_to_qap/r1cs_to_qap.hpp"
|
||||
#include "relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace libsnark;
|
||||
|
@ -168,3 +169,57 @@ extern "C" curve_GT libsnarkwrap_gt_exp(const curve_GT *p, const curve_Fr *s) {
|
|||
extern "C" curve_GT libsnarkwrap_pairing(const curve_G1 *p, const curve_G2 *q) {
|
||||
return curve_pp::reduced_pairing(*p, *q);
|
||||
}
|
||||
|
||||
// QAP
|
||||
|
||||
qap_instance<curve_Fr> get_qap(
|
||||
std::shared_ptr<basic_radix2_domain<curve_Fr>> &domain
|
||||
)
|
||||
{
|
||||
// Generate a dummy circuit
|
||||
auto example = generate_r1cs_example_with_field_input<curve_Fr>(250, 4);
|
||||
|
||||
// A/B swap
|
||||
example.constraint_system.swap_AB_if_beneficial();
|
||||
|
||||
// QAP reduction
|
||||
auto qap = r1cs_to_qap_instance_map(example.constraint_system);
|
||||
|
||||
// Degree of the QAP must be a power of 2
|
||||
assert(qap.degree() == 256);
|
||||
|
||||
// Assume radix2 evaluation domain
|
||||
domain = std::static_pointer_cast<basic_radix2_domain<curve_Fr>>(qap.domain);
|
||||
|
||||
return qap;
|
||||
}
|
||||
|
||||
extern "C" void libsnarkwrap_getqap(uint32_t *d, curve_Fr *omega)
|
||||
{
|
||||
std::shared_ptr<basic_radix2_domain<curve_Fr>> domain;
|
||||
auto qap = get_qap(domain);
|
||||
|
||||
*omega = domain->omega;
|
||||
*d = qap.degree();
|
||||
}
|
||||
|
||||
extern "C" bool libsnarkwrap_test_compare_tau(
|
||||
const curve_G1 *inputs,
|
||||
const curve_Fr *tau,
|
||||
uint32_t d
|
||||
)
|
||||
{
|
||||
std::shared_ptr<basic_radix2_domain<curve_Fr>> domain;
|
||||
auto qap = get_qap(domain);
|
||||
|
||||
auto coeffs = domain->lagrange_coeffs(*tau);
|
||||
assert(coeffs.size() == d);
|
||||
assert(qap.degree() == d);
|
||||
|
||||
bool res = true;
|
||||
for (size_t i = 0; i < d; i++) {
|
||||
res &= (coeffs[i] * curve_G1::one()) == inputs[i];
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
use snark::{Group, Fr};
|
||||
|
||||
pub fn fft<G: Group>(v: &[G], omega: Fr) -> Vec<G>
|
||||
{
|
||||
if v.len() == 2 {
|
||||
vec![
|
||||
v[0] + v[1] * omega,
|
||||
v[0] + v[1]
|
||||
]
|
||||
} else {
|
||||
let d2 = v.len() / 2;
|
||||
let mut evens = Vec::with_capacity(d2);
|
||||
let mut odds = Vec::with_capacity(d2);
|
||||
|
||||
for (i, x) in v.iter().enumerate() {
|
||||
if i % 2 == 0 {
|
||||
evens.push(*x);
|
||||
} else {
|
||||
odds.push(*x);
|
||||
}
|
||||
}
|
||||
|
||||
let o2 = omega * omega;
|
||||
let evens = fft(&evens, o2);
|
||||
let odds = fft(&odds, o2);
|
||||
|
||||
let mut acc = omega;
|
||||
let mut res = Vec::with_capacity(v.len());
|
||||
for i in 0..v.len() {
|
||||
res.push(evens[i%d2] + odds[i%d2] * acc);
|
||||
acc = acc * omega;
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::fft;
|
||||
use snark::*;
|
||||
use util::*;
|
||||
|
||||
#[test]
|
||||
fn compare_to_libsnark() {
|
||||
initialize();
|
||||
|
||||
// Get the QAP degree and omega (for FFT evaluation)
|
||||
let (d, omega) = getqap();
|
||||
|
||||
// Sample a random tau
|
||||
let tau = Fr::random();
|
||||
|
||||
// Generate powers of tau in G1, from 0 to d exclusive of d
|
||||
let powers_of_tau = TauPowers::new(tau).take(d).map(|e| G1::one() * e).collect::<Vec<_>>();
|
||||
|
||||
let overd = Fr::from_str(&format!("{}", d)).inverse();
|
||||
let lc = fft(&powers_of_tau, omega) // omit tau^d
|
||||
.into_iter()
|
||||
.rev() // coefficients are in reverse
|
||||
.map(|e| e * overd) // divide by d
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Compare against libsnark
|
||||
assert!(compare_tau(&lc, &tau));
|
||||
|
||||
// Wrong tau
|
||||
assert!(!compare_tau(&lc, &Fr::random()));
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ extern crate snark;
|
|||
|
||||
mod randompowers;
|
||||
mod util;
|
||||
mod fft;
|
||||
|
||||
use snark::*;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use snark::*;
|
||||
use util::Sequences;
|
||||
use util::*;
|
||||
|
||||
struct Spair<G: Group> {
|
||||
p: G,
|
||||
|
@ -80,27 +80,6 @@ where Group1: Pairing<Group2>
|
|||
check(Sequences::new(i), a)
|
||||
}
|
||||
|
||||
struct TauPowers {
|
||||
acc: Fr,
|
||||
tau: Fr
|
||||
}
|
||||
|
||||
impl TauPowers {
|
||||
fn new(tau: Fr) -> TauPowers {
|
||||
TauPowers { acc: Fr::one(), tau: tau }
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for TauPowers {
|
||||
type Item = Fr;
|
||||
|
||||
fn next(&mut self) -> Option<Fr> {
|
||||
let tmp = self.acc;
|
||||
self.acc = tmp * self.tau;
|
||||
Some(tmp)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn randompowers_simulation() {
|
||||
initialize();
|
||||
|
|
25
src/util.rs
25
src/util.rs
|
@ -1,3 +1,5 @@
|
|||
use snark::Fr;
|
||||
|
||||
pub struct Sequences<'a, T: 'a, I: Iterator<Item=&'a T>> {
|
||||
v: I,
|
||||
last: Option<&'a T>
|
||||
|
@ -34,3 +36,26 @@ fn test_sequences() {
|
|||
let expected = vec![(&a[0], &a[1]), (&a[1], &a[2]), (&a[2], &a[3])];
|
||||
assert_eq!(b, expected);
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub struct TauPowers {
|
||||
acc: Fr,
|
||||
tau: Fr
|
||||
}
|
||||
|
||||
impl TauPowers {
|
||||
pub fn new(tau: Fr) -> TauPowers {
|
||||
TauPowers { acc: Fr::one(), tau: tau }
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for TauPowers {
|
||||
type Item = Fr;
|
||||
|
||||
fn next(&mut self) -> Option<Fr> {
|
||||
let tmp = self.acc;
|
||||
self.acc = tmp * self.tau;
|
||||
Some(tmp)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue