mirror of https://github.com/zcash/mpc.git
Evaluate A, B, C in lagrange basis over G1.
This commit is contained in:
parent
6ae611cbcb
commit
adfc73b997
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
15
src/fft.rs
15
src/fft.rs
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue