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" {
|
||||
fn libsnarkwrap_init();
|
||||
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_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(
|
||||
i: *const G1,
|
||||
tau: *const Fr,
|
||||
|
@ -43,6 +58,41 @@ pub fn initialize() {
|
|||
|
||||
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 {
|
||||
fn drop(&mut self) {
|
||||
unsafe { libsnarkwrap_dropcs(self.0) }
|
||||
|
@ -50,13 +100,14 @@ impl Drop for CS {
|
|||
}
|
||||
|
||||
/// 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 vars = 0;
|
||||
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
|
||||
|
|
|
@ -172,7 +172,7 @@ extern "C" curve_GT libsnarkwrap_pairing(const curve_G1 *p, const curve_G2 *q) {
|
|||
|
||||
// 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
|
||||
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
|
||||
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
|
||||
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;
|
||||
|
||||
*d = qap.degree();
|
||||
*vars = example.constraint_system.num_variables()+1;
|
||||
}
|
||||
|
||||
return new r1cs_constraint_system<curve_Fr>(example.constraint_system);
|
||||
|
@ -220,3 +226,67 @@ extern "C" bool libsnarkwrap_test_compare_tau(
|
|||
|
||||
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();
|
||||
|
||||
// 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
|
||||
let tau = Fr::random();
|
||||
|
@ -66,5 +66,18 @@ mod test {
|
|||
|
||||
// Wrong tau
|
||||
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 {
|
||||
secrets: Samples<Fr>,
|
||||
pub d: usize,
|
||||
pub num_vars: usize,
|
||||
omega: Fr,
|
||||
cs: CS
|
||||
}
|
||||
|
||||
impl Player {
|
||||
pub fn new() -> Player {
|
||||
let (d, omega, cs) = getqap();
|
||||
let (d, num_vars, omega, cs) = getqap();
|
||||
|
||||
Player {
|
||||
secrets: Samples {
|
||||
|
@ -41,6 +42,7 @@ impl Player {
|
|||
gamma: Fr::random_nonzero()
|
||||
},
|
||||
d: d,
|
||||
num_vars: num_vars,
|
||||
omega: omega,
|
||||
cs: cs
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue