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)",
|
||||
"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)",
|
||||
"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)",
|
||||
"pairing 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"primitives 0.1.0",
|
||||
|
@ -174,7 +174,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "bn"
|
||||
version = "0.4.4"
|
||||
source = "git+https://github.com/paritytech/bn#2a71dbde5ca93451c8da2135767896a64483759e"
|
||||
source = "git+https://github.com/paritytech/bn?branch=upgrade#e9f64f518d0ae64cb4f9a8c7c544e3ff0ef82584"
|
||||
dependencies = [
|
||||
"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)",
|
||||
|
@ -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 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 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 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"
|
||||
|
|
|
@ -12,7 +12,7 @@ sapling-crypto = { git = "https://github.com/zcash-hackworks/sapling-crypto.git"
|
|||
serde_json = "1.0"
|
||||
siphasher = "0.1.1"
|
||||
primitives = { path = "../primitives" }
|
||||
bn = { git = "https://github.com/paritytech/bn" }
|
||||
bn = { git = "https://github.com/paritytech/bn", branch = "upgrade" }
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
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 std::ops::Neg;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct VerifyingKey {
|
||||
|
@ -19,6 +20,13 @@ impl ::std::fmt::Debug for VerifyingKey {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
InvalidFieldElement,
|
||||
InvalidCurvePoint,
|
||||
InvalidRawInput,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Proof {
|
||||
pub a: G1,
|
||||
|
@ -31,6 +39,57 @@ pub struct Proof {
|
|||
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 {
|
||||
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:
|
||||
pairing(proof.k, vk.gamma) ==
|
||||
pairing(acc + proof.a + proof.c, vk.gamma_beta_2) * pairing(vk.gamma_beta_1, proof.b) &&
|
||||
|
||||
// 4. check QAP divisibility
|
||||
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