g1 handling
This commit is contained in:
parent
134500ffdc
commit
5d5b76bdcc
|
@ -132,7 +132,7 @@ dependencies = [
|
||||||
"bellman 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bellman 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc.git?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)",
|
"blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc.git?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)",
|
||||||
"blake2b_simd 0.4.1 (git+https://github.com/oconnor663/blake2b_simd.git)",
|
"blake2b_simd 0.4.1 (git+https://github.com/oconnor663/blake2b_simd.git)",
|
||||||
"bn 0.4.4 (git+https://github.com/paritytech/bn)",
|
"bn 0.4.4 (git+https://github.com/paritytech/bn?branch=upgrade)",
|
||||||
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pairing 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pairing 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"primitives 0.1.0",
|
"primitives 0.1.0",
|
||||||
|
@ -174,7 +174,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bn"
|
name = "bn"
|
||||||
version = "0.4.4"
|
version = "0.4.4"
|
||||||
source = "git+https://github.com/paritytech/bn#2a71dbde5ca93451c8da2135767896a64483759e"
|
source = "git+https://github.com/paritytech/bn?branch=upgrade#e9f64f518d0ae64cb4f9a8c7c544e3ff0ef82584"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2010,7 +2010,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
|
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
|
||||||
"checksum blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc.git?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)" = "<none>"
|
"checksum blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc.git?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)" = "<none>"
|
||||||
"checksum blake2b_simd 0.4.1 (git+https://github.com/oconnor663/blake2b_simd.git)" = "<none>"
|
"checksum blake2b_simd 0.4.1 (git+https://github.com/oconnor663/blake2b_simd.git)" = "<none>"
|
||||||
"checksum bn 0.4.4 (git+https://github.com/paritytech/bn)" = "<none>"
|
"checksum bn 0.4.4 (git+https://github.com/paritytech/bn?branch=upgrade)" = "<none>"
|
||||||
"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
|
"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
|
||||||
"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa"
|
"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa"
|
||||||
"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749"
|
"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749"
|
||||||
|
|
|
@ -12,7 +12,7 @@ sapling-crypto = { git = "https://github.com/zcash-hackworks/sapling-crypto.git"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
siphasher = "0.1.1"
|
siphasher = "0.1.1"
|
||||||
primitives = { path = "../primitives" }
|
primitives = { path = "../primitives" }
|
||||||
bn = { git = "https://github.com/paritytech/bn" }
|
bn = { git = "https://github.com/paritytech/bn", branch = "upgrade" }
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
rustc-hex = "2"
|
rustc-hex = "2"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
pub use bn::{Fr, G1, G2, Group};
|
pub use bn::{Fr, Fq, G1, G2, Group, arith::U256, AffineG1};
|
||||||
use bn::pairing;
|
use bn::pairing;
|
||||||
|
use std::ops::Neg;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct VerifyingKey {
|
pub struct VerifyingKey {
|
||||||
|
@ -19,6 +20,13 @@ impl ::std::fmt::Debug for VerifyingKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
InvalidFieldElement,
|
||||||
|
InvalidCurvePoint,
|
||||||
|
InvalidRawInput,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Proof {
|
pub struct Proof {
|
||||||
pub a: G1,
|
pub a: G1,
|
||||||
|
@ -31,6 +39,57 @@ pub struct Proof {
|
||||||
pub h: G1,
|
pub h: G1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref FQ: U256 = U256::from([
|
||||||
|
0x3c208c16d87cfd47,
|
||||||
|
0x97816a916871ca8d,
|
||||||
|
0xb85045b68181585d,
|
||||||
|
0x30644e72e131a029
|
||||||
|
]);
|
||||||
|
|
||||||
|
pub static ref G1_B: Fq = Fq::from_u256(3.into()).expect("3 is a valid field element and static; qed");
|
||||||
|
|
||||||
|
pub static ref FQ_MINUS3_DIV4: Fq =
|
||||||
|
Fq::from_u256(3.into()).expect("3 is a valid field element and static; qed").neg() *
|
||||||
|
Fq::from_u256(4.into()).expect("4 is a valid field element and static; qed").inverse()
|
||||||
|
.expect("4 has inverse in Fq and is static; qed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shanks’s algorithm for q ≡ 3 (mod 4)
|
||||||
|
// (FQ mod 4 = 3)
|
||||||
|
fn fq_sqrt(a: Fq) -> Option<Fq> {
|
||||||
|
let a1 = a.pow(*FQ_MINUS3_DIV4);
|
||||||
|
let a1a = a1 * a;
|
||||||
|
let a0 = a1 * (a1a);
|
||||||
|
|
||||||
|
let mut am1 = *FQ;
|
||||||
|
am1.sub(&1.into(), &*FQ);
|
||||||
|
|
||||||
|
if a0 == Fq::from_u256(am1).unwrap() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(a1a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn g1_from_compressed(data: &[u8]) -> Result<G1, Error> {
|
||||||
|
if data.len() != 33 { return Err(Error::InvalidRawInput); }
|
||||||
|
|
||||||
|
let sign = data[0];
|
||||||
|
let fq = deseerialize_fq(&data[1..])?;
|
||||||
|
let x = fq;
|
||||||
|
let y_squared = (fq * fq * fq) + *G1_B;
|
||||||
|
let mut y = fq_sqrt(y_squared).ok_or(Error::InvalidFieldElement)?;
|
||||||
|
|
||||||
|
if sign == 2 { y = y.neg(); }
|
||||||
|
|
||||||
|
AffineG1::new(x, y).map_err(|_| Error::InvalidCurvePoint).map(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deseerialize_fq(data: &[u8]) -> Result<Fq, Error> {
|
||||||
|
Ok(Fq::from_slice(data).map_err(|_| Error::InvalidRawInput)?)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn verify(vk: &VerifyingKey, primary_input: &[Fr], proof: &Proof) -> bool {
|
pub fn verify(vk: &VerifyingKey, primary_input: &[Fr], proof: &Proof) -> bool {
|
||||||
let p2 = G2::one();
|
let p2 = G2::one();
|
||||||
|
|
||||||
|
@ -48,7 +107,33 @@ pub fn verify(vk: &VerifyingKey, primary_input: &[Fr], proof: &Proof) -> bool {
|
||||||
// 3. check same coefficients were used:
|
// 3. check same coefficients were used:
|
||||||
pairing(proof.k, vk.gamma) ==
|
pairing(proof.k, vk.gamma) ==
|
||||||
pairing(acc + proof.a + proof.c, vk.gamma_beta_2) * pairing(vk.gamma_beta_1, proof.b) &&
|
pairing(acc + proof.a + proof.c, vk.gamma_beta_2) * pairing(vk.gamma_beta_1, proof.b) &&
|
||||||
|
|
||||||
// 4. check QAP divisibility
|
// 4. check QAP divisibility
|
||||||
pairing(acc + proof.a, proof.b) == pairing(proof.h, vk.z) * pairing(proof.c, p2)
|
pairing(acc + proof.a, proof.b) == pairing(proof.h, vk.z) * pairing(proof.c, p2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn hex(s: &'static str) -> Vec<u8> {
|
||||||
|
use hex::FromHex;
|
||||||
|
s.from_hex().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sqrt() {
|
||||||
|
let fq1 = Fq::from_str("5204065062716160319596273903996315000119019512886596366359652578430118331601").unwrap();
|
||||||
|
let fq2 = Fq::from_str("348579348568").unwrap();
|
||||||
|
|
||||||
|
assert_eq!(fq1, fq_sqrt(fq2).expect("348579348568 is quadratic residue"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn g1_deserialize() {
|
||||||
|
let g1 = g1_from_compressed(&hex("0230644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46")).expect("Invalid g1 decompress result");
|
||||||
|
assert_eq!(g1.x(), Fq::from_str("21888242871839275222246405745257275088696311157297823662689037894645226208582").unwrap());
|
||||||
|
assert_eq!(g1.y(), Fq::from_str("3969792565221544645472939191694882283483352126195956956354061729942568608776").unwrap());
|
||||||
|
assert_eq!(g1.z(), Fq::one());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue