Evaluate A, B, C in lagrange basis over G1.

This commit is contained in:
Sean Bowe 2016-08-06 01:24:58 -06:00
parent 6ae611cbcb
commit adfc73b997
No known key found for this signature in database
GPG Key ID: 95684257D8F8B031
4 changed files with 143 additions and 7 deletions

View File

@ -18,8 +18,23 @@ pub use self::g2::G2;
extern "C" { extern "C" {
fn libsnarkwrap_init(); fn libsnarkwrap_init();
fn libsnarkwrap_pairing(p: *const G1, q: *const G2) -> Gt; fn libsnarkwrap_pairing(p: *const G1, q: *const G2) -> Gt;
fn libsnarkwrap_getcs(d: *mut libc::uint32_t, omega: *mut Fr) -> *mut libc::c_void; fn libsnarkwrap_getcs(d: *mut libc::uint32_t, vars: *mut libc::uint32_t, omega: *mut Fr) -> *mut libc::c_void;
fn libsnarkwrap_dropcs(cs: *mut libc::c_void); fn libsnarkwrap_dropcs(cs: *mut libc::c_void);
fn libsnarkwrap_eval(
cs: *const libc::c_void,
lc: *const G1,
d: libc::uint32_t,
vars: libc::uint32_t,
At: *mut G1,
Bt: *mut G1,
Ct: *mut G1);
fn libsnarkwrap_test_eval(
cs: *const libc::c_void,
tau: *const Fr,
vars: libc::uint32_t,
At: *const G1,
Bt: *const G1,
Ct: *const G1) -> bool;
fn libsnarkwrap_test_compare_tau( fn libsnarkwrap_test_compare_tau(
i: *const G1, i: *const G1,
tau: *const Fr, tau: *const Fr,
@ -43,6 +58,41 @@ pub fn initialize() {
pub struct CS(*mut libc::c_void); pub struct CS(*mut libc::c_void);
impl CS {
pub fn test_eval(&self, tau: &Fr, At: &[G1], Bt: &[G1], Ct: &[G1]) -> bool {
assert_eq!(At.len(), Bt.len());
assert_eq!(Bt.len(), Ct.len());
unsafe {
libsnarkwrap_test_eval(self.0,
tau,
At.len() as u32,
&At[0],
&Bt[0],
&Ct[0])
}
}
pub fn eval(&self,
Lt: &[G1],
At: &mut [G1],
Bt: &mut [G1],
Ct: &mut [G1]) {
assert_eq!(At.len(), Bt.len());
assert_eq!(Bt.len(), Ct.len());
unsafe {
libsnarkwrap_eval(self.0,
&Lt[0],
Lt.len() as u32,
At.len() as u32,
&mut At[0],
&mut Bt[0],
&mut Ct[0]);
}
}
}
impl Drop for CS { impl Drop for CS {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { libsnarkwrap_dropcs(self.0) } unsafe { libsnarkwrap_dropcs(self.0) }
@ -50,13 +100,14 @@ impl Drop for CS {
} }
/// Get the QAP info for the generation routines /// Get the QAP info for the generation routines
pub fn getqap() -> (usize, Fr, CS) { pub fn getqap() -> (usize, usize, Fr, CS) {
let mut d = 0; let mut d = 0;
let mut vars = 0;
let mut o = Fr::zero(); let mut o = Fr::zero();
let cs = unsafe { libsnarkwrap_getcs(&mut d, &mut o) }; let cs = unsafe { libsnarkwrap_getcs(&mut d, &mut vars, &mut o) };
(d as usize, o, CS(cs)) (d as usize, vars as usize, o, CS(cs))
} }
/// Check that the lagrange coefficients computed by tau over /// Check that the lagrange coefficients computed by tau over

View File

@ -172,7 +172,7 @@ extern "C" curve_GT libsnarkwrap_pairing(const curve_G1 *p, const curve_G2 *q) {
// QAP // QAP
extern "C" void* libsnarkwrap_getcs(uint32_t *d, curve_Fr *omega) extern "C" void* libsnarkwrap_getcs(uint32_t *d, uint32_t *vars, curve_Fr *omega)
{ {
// Generate a dummy circuit // Generate a dummy circuit
auto example = generate_r1cs_example_with_field_input<curve_Fr>(250, 4); auto example = generate_r1cs_example_with_field_input<curve_Fr>(250, 4);
@ -184,6 +184,11 @@ extern "C" void* libsnarkwrap_getcs(uint32_t *d, curve_Fr *omega)
// QAP reduction // QAP reduction
auto qap = r1cs_to_qap_instance_map(example.constraint_system); auto qap = r1cs_to_qap_instance_map(example.constraint_system);
// Sanity checks
assert(qap.A_in_Lagrange_basis.size() == example.constraint_system.num_variables()+1);
assert(qap.B_in_Lagrange_basis.size() == example.constraint_system.num_variables()+1);
assert(qap.C_in_Lagrange_basis.size() == example.constraint_system.num_variables()+1);
// Degree of the QAP must be a power of 2 // Degree of the QAP must be a power of 2
assert(qap.degree() == 256); assert(qap.degree() == 256);
@ -191,6 +196,7 @@ extern "C" void* libsnarkwrap_getcs(uint32_t *d, curve_Fr *omega)
*omega = std::static_pointer_cast<basic_radix2_domain<curve_Fr>>(qap.domain)->omega; *omega = std::static_pointer_cast<basic_radix2_domain<curve_Fr>>(qap.domain)->omega;
*d = qap.degree(); *d = qap.degree();
*vars = example.constraint_system.num_variables()+1;
} }
return new r1cs_constraint_system<curve_Fr>(example.constraint_system); return new r1cs_constraint_system<curve_Fr>(example.constraint_system);
@ -220,3 +226,67 @@ extern "C" bool libsnarkwrap_test_compare_tau(
return res; return res;
} }
extern "C" void libsnarkwrap_eval(
const r1cs_constraint_system<curve_Fr> *cs,
const curve_G1 *lc,
uint32_t d,
uint32_t vars,
curve_G1 *At,
curve_G1 *Bt,
curve_G1 *Ct
)
{
auto qap = r1cs_to_qap_instance_map(*cs);
assert(qap.degree() == d);
assert(qap.A_in_Lagrange_basis.size() == vars);
assert(qap.B_in_Lagrange_basis.size() == vars);
assert(qap.C_in_Lagrange_basis.size() == vars);
for (size_t i = 0; i < vars; i++) {
for (auto const &it : qap.A_in_Lagrange_basis[i]) {
assert(it.first < d);
At[i] = At[i] + it.second * lc[it.first];
}
for (auto const &it : qap.B_in_Lagrange_basis[i]) {
assert(it.first < d);
Bt[i] = Bt[i] + it.second * lc[it.first];
}
for (auto const &it : qap.C_in_Lagrange_basis[i]) {
assert(it.first < d);
Ct[i] = Ct[i] + it.second * lc[it.first];
}
}
}
extern "C" bool libsnarkwrap_test_eval(
const r1cs_constraint_system<curve_Fr> *cs,
const curve_Fr *tau,
uint32_t vars,
const curve_G1 *At,
const curve_G1 *Bt,
const curve_G1 *Ct
) {
auto qap = r1cs_to_qap_instance_map_with_evaluation(*cs, *tau);
assert(qap.At.size() == vars);
assert(qap.Bt.size() == vars);
assert(qap.Ct.size() == vars);
bool res = true;
for (size_t i = 0; i < vars; i++) {
res &= (qap.At[i] * curve_G1::one()) == At[i];
}
for (size_t i = 0; i < vars; i++) {
res &= (qap.Bt[i] * curve_G1::one()) == Bt[i];
}
for (size_t i = 0; i < vars; i++) {
res &= (qap.Ct[i] * curve_G1::one()) == Ct[i];
}
return res;
}

View File

@ -46,7 +46,7 @@ mod test {
initialize(); initialize();
// Get the QAP degree and omega (for FFT evaluation) // Get the QAP degree and omega (for FFT evaluation)
let (d, omega, cs) = getqap(); let (d, num_vars, omega, cs) = getqap();
// Sample a random tau // Sample a random tau
let tau = Fr::random(); let tau = Fr::random();
@ -66,5 +66,18 @@ mod test {
// Wrong tau // Wrong tau
assert!(!compare_tau(&lc, &Fr::random(), &cs)); assert!(!compare_tau(&lc, &Fr::random(), &cs));
// Evaluate At, Bt, Ct in G1
let mut At = (0..num_vars).map(|_| G1::zero()).collect::<Vec<_>>();
let mut Bt = (0..num_vars).map(|_| G1::zero()).collect::<Vec<_>>();
let mut Ct = (0..num_vars).map(|_| G1::zero()).collect::<Vec<_>>();
cs.eval(&lc, &mut At, &mut Bt, &mut Ct);
// Compare evaluation with libsnark
assert!(cs.test_eval(&tau, &At, &Bt, &Ct));
// Wrong tau
assert!(!cs.test_eval(&Fr::random(), &At, &Bt, &Ct));
} }
} }

View File

@ -21,13 +21,14 @@ pub struct Samples<T> {
pub struct Player { pub struct Player {
secrets: Samples<Fr>, secrets: Samples<Fr>,
pub d: usize, pub d: usize,
pub num_vars: usize,
omega: Fr, omega: Fr,
cs: CS cs: CS
} }
impl Player { impl Player {
pub fn new() -> Player { pub fn new() -> Player {
let (d, omega, cs) = getqap(); let (d, num_vars, omega, cs) = getqap();
Player { Player {
secrets: Samples { secrets: Samples {
@ -41,6 +42,7 @@ impl Player {
gamma: Fr::random_nonzero() gamma: Fr::random_nonzero()
}, },
d: d, d: d,
num_vars: num_vars,
omega: omega, omega: omega,
cs: cs cs: cs
} }