From 4f9953f18ff51dcdf3736d15fa4581c089f96ca1 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Tue, 17 Apr 2018 14:16:14 -0600 Subject: [PATCH 1/2] Support loading zk-SNARK parameters --- Cargo.lock | 1 + Cargo.toml | 1 + include/librustzcash.h | 8 ++++++ src/rustzcash.rs | 63 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 63b1c3e..b1409e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -114,6 +114,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "librustzcash" version = "0.1.0" dependencies = [ + "bellman 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 45e1ff0..18c28e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ crate-type = ["staticlib"] libc = "0.2" pairing = "0.14.1" lazy_static = "1" +bellman = "0.1" [dependencies.sapling-crypto] git = "https://github.com/zcash-hackworks/sapling-crypto" diff --git a/include/librustzcash.h b/include/librustzcash.h index df937e5..d5a596c 100644 --- a/include/librustzcash.h +++ b/include/librustzcash.h @@ -6,6 +6,14 @@ extern "C" { uint64_t librustzcash_xor(uint64_t a, uint64_t b); + /// Loads the zk-SNARK parameters into memory and saves + /// paths as necessary. Only called once. + void librustzcash_init_zksnark_params( + const char* spend_path, + const char* output_path, + const char* sprout_path + ); + /// Writes the "uncommitted" note value for empty leaves /// of the merkle tree. `result` must be a valid pointer /// to 32 bytes which will be written. diff --git a/src/rustzcash.rs b/src/rustzcash.rs index ea358cc..8c69c50 100644 --- a/src/rustzcash.rs +++ b/src/rustzcash.rs @@ -1,6 +1,7 @@ extern crate libc; extern crate sapling_crypto; extern crate pairing; +extern crate bellman; #[macro_use] extern crate lazy_static; @@ -24,7 +25,18 @@ use sapling_crypto::{ } }; -use libc::{uint64_t, size_t, c_uchar}; +use bellman::{ + groth16::{ + Parameters, + PreparedVerifyingKey, + VerifyingKey, + prepare_verifying_key + } +}; + +use libc::{uint64_t, size_t, c_uchar, c_char}; +use std::ffi::CStr; +use std::fs::File; lazy_static! { static ref JUBJUB: JubjubBls12 = { @@ -32,6 +44,55 @@ lazy_static! { }; } +static mut SAPLING_SPEND_VK: Option> = None; +static mut SAPLING_OUTPUT_VK: Option> = None; +static mut SPROUT_GROTH16_VK: Option> = None; + +static mut SAPLING_SPEND_PARAMS: Option> = None; +static mut SAPLING_OUTPUT_PARAMS: Option> = None; +static mut SPROUT_GROTH16_PARAMS_PATH: Option = None; + +#[no_mangle] +pub extern "system" fn librustzcash_init_zksnark_params( + spend_path: *const c_char, + output_path: *const c_char, + sprout_path: *const c_char +) +{ + // These should be valid CStr's, but the decoding may fail on Windows + // so we may need to use OSStr or something. + let spend_path = unsafe { CStr::from_ptr(spend_path) }.to_str().expect("parameter path encoding error").to_string(); + let output_path = unsafe { CStr::from_ptr(output_path) }.to_str().expect("parameter path encoding error").to_string(); + let sprout_path = unsafe { CStr::from_ptr(sprout_path) }.to_str().expect("parameter path encoding error").to_string(); + + // Load from each of the paths + let mut spend_fs = File::open(spend_path).expect("couldn't load Sapling spend parameters file"); + let mut output_fs = File::open(output_path).expect("couldn't load Sapling output parameters file"); + let mut sprout_fs = File::open(&sprout_path).expect("couldn't load Sprout groth16 parameters file"); + + // Deserialize params + let spend_params = Parameters::::read(&mut spend_fs, false).expect("couldn't deserialize Sapling spend parameters file"); + let output_params = Parameters::::read(&mut output_fs, false).expect("couldn't deserialize Sapling spend parameters file"); + let sprout_vk = VerifyingKey::::read(&mut sprout_fs).expect("couldn't deserialize Sprout Groth16 verifying key"); + + // Prepare verifying keys + let spend_vk = prepare_verifying_key(&spend_params.vk); + let output_vk = prepare_verifying_key(&output_params.vk); + let sprout_vk = prepare_verifying_key(&sprout_vk); + + // Caller is responsible for calling this function once, so + // these global mutations are safe. + unsafe { + SAPLING_SPEND_PARAMS = Some(spend_params); + SAPLING_OUTPUT_PARAMS = Some(output_params); + SPROUT_GROTH16_PARAMS_PATH = Some(sprout_path); + + SAPLING_SPEND_VK = Some(spend_vk); + SAPLING_OUTPUT_VK = Some(output_vk); + SPROUT_GROTH16_VK = Some(sprout_vk); + } +} + #[no_mangle] pub extern "system" fn librustzcash_tree_uncommitted( result: *mut [c_uchar; 32] From 170397b5a5ebfa2f6823bb631ca7b248f17823ac Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Tue, 17 Apr 2018 14:22:35 -0600 Subject: [PATCH 2/2] Apply rustfmt --- src/rustzcash.rs | 102 +++++++++++++++++++++-------------------------- 1 file changed, 46 insertions(+), 56 deletions(-) diff --git a/src/rustzcash.rs b/src/rustzcash.rs index 8c69c50..649a021 100644 --- a/src/rustzcash.rs +++ b/src/rustzcash.rs @@ -1,47 +1,23 @@ -extern crate libc; -extern crate sapling_crypto; -extern crate pairing; extern crate bellman; +extern crate libc; +extern crate pairing; +extern crate sapling_crypto; #[macro_use] extern crate lazy_static; -use pairing::{ - BitIterator, - PrimeFieldRepr, - PrimeField, - bls12_381::{ - Bls12, - Fr, - FrRepr - } -}; +use pairing::{BitIterator, PrimeField, PrimeFieldRepr, bls12_381::{Bls12, Fr, FrRepr}}; -use sapling_crypto::{ - jubjub::JubjubBls12, - pedersen_hash::{ - pedersen_hash, - Personalization - } -}; +use sapling_crypto::{jubjub::JubjubBls12, pedersen_hash::{pedersen_hash, Personalization}}; -use bellman::{ - groth16::{ - Parameters, - PreparedVerifyingKey, - VerifyingKey, - prepare_verifying_key - } -}; +use bellman::groth16::{prepare_verifying_key, Parameters, PreparedVerifyingKey, VerifyingKey}; -use libc::{uint64_t, size_t, c_uchar, c_char}; +use libc::{c_char, c_uchar, size_t, uint64_t}; use std::ffi::CStr; use std::fs::File; lazy_static! { - static ref JUBJUB: JubjubBls12 = { - JubjubBls12::new() - }; + static ref JUBJUB: JubjubBls12 = { JubjubBls12::new() }; } static mut SAPLING_SPEND_VK: Option> = None; @@ -56,24 +32,37 @@ static mut SPROUT_GROTH16_PARAMS_PATH: Option = None; pub extern "system" fn librustzcash_init_zksnark_params( spend_path: *const c_char, output_path: *const c_char, - sprout_path: *const c_char -) -{ + sprout_path: *const c_char, +) { // These should be valid CStr's, but the decoding may fail on Windows // so we may need to use OSStr or something. - let spend_path = unsafe { CStr::from_ptr(spend_path) }.to_str().expect("parameter path encoding error").to_string(); - let output_path = unsafe { CStr::from_ptr(output_path) }.to_str().expect("parameter path encoding error").to_string(); - let sprout_path = unsafe { CStr::from_ptr(sprout_path) }.to_str().expect("parameter path encoding error").to_string(); + let spend_path = unsafe { CStr::from_ptr(spend_path) } + .to_str() + .expect("parameter path encoding error") + .to_string(); + let output_path = unsafe { CStr::from_ptr(output_path) } + .to_str() + .expect("parameter path encoding error") + .to_string(); + let sprout_path = unsafe { CStr::from_ptr(sprout_path) } + .to_str() + .expect("parameter path encoding error") + .to_string(); // Load from each of the paths let mut spend_fs = File::open(spend_path).expect("couldn't load Sapling spend parameters file"); - let mut output_fs = File::open(output_path).expect("couldn't load Sapling output parameters file"); - let mut sprout_fs = File::open(&sprout_path).expect("couldn't load Sprout groth16 parameters file"); + let mut output_fs = + File::open(output_path).expect("couldn't load Sapling output parameters file"); + let mut sprout_fs = + File::open(&sprout_path).expect("couldn't load Sprout groth16 parameters file"); // Deserialize params - let spend_params = Parameters::::read(&mut spend_fs, false).expect("couldn't deserialize Sapling spend parameters file"); - let output_params = Parameters::::read(&mut output_fs, false).expect("couldn't deserialize Sapling spend parameters file"); - let sprout_vk = VerifyingKey::::read(&mut sprout_fs).expect("couldn't deserialize Sprout Groth16 verifying key"); + let spend_params = Parameters::::read(&mut spend_fs, false) + .expect("couldn't deserialize Sapling spend parameters file"); + let output_params = Parameters::::read(&mut output_fs, false) + .expect("couldn't deserialize Sapling spend parameters file"); + let sprout_vk = VerifyingKey::::read(&mut sprout_fs) + .expect("couldn't deserialize Sprout Groth16 verifying key"); // Prepare verifying keys let spend_vk = prepare_verifying_key(&spend_params.vk); @@ -94,10 +83,7 @@ pub extern "system" fn librustzcash_init_zksnark_params( } #[no_mangle] -pub extern "system" fn librustzcash_tree_uncommitted( - result: *mut [c_uchar; 32] -) -{ +pub extern "system" fn librustzcash_tree_uncommitted(result: *mut [c_uchar; 32]) { let tmp = sapling_crypto::primitives::Note::::uncommitted().into_repr(); // Should be okay, caller is responsible for ensuring the pointer @@ -113,8 +99,7 @@ pub extern "system" fn librustzcash_merkle_hash( a: *const [c_uchar; 32], b: *const [c_uchar; 32], result: *mut [c_uchar; 32], -) -{ +) { let mut a_repr = FrRepr::default(); let mut b_repr = FrRepr::default(); @@ -138,14 +123,17 @@ pub extern "system" fn librustzcash_merkle_hash( for (a, b) in rhs.iter_mut().rev().zip(BitIterator::new(b_repr)) { *a = b; } - + let tmp = pedersen_hash::( Personalization::MerkleTree(depth), - lhs.iter().map(|&x| x) + lhs.iter() + .map(|&x| x) .take(Fr::NUM_BITS as usize) .chain(rhs.iter().map(|&x| x).take(Fr::NUM_BITS as usize)), - &JUBJUB - ).into_xy().0.into_repr(); + &JUBJUB, + ).into_xy() + .0 + .into_repr(); // Should be okay, caller is responsible for ensuring the pointer // is a valid pointer to 32 bytes that can be mutated. @@ -158,12 +146,14 @@ pub extern "system" fn librustzcash_merkle_hash( /// as a temporary mechanism for introducing Rust into /// Zcash. #[no_mangle] -pub extern "system" fn librustzcash_xor(a: uint64_t, b: uint64_t) -> uint64_t -{ +pub extern "system" fn librustzcash_xor(a: uint64_t, b: uint64_t) -> uint64_t { a ^ b } #[test] fn test_xor() { - assert_eq!(librustzcash_xor(0x0f0f0f0f0f0f0f0f, 0x1111111111111111), 0x1e1e1e1e1e1e1e1e); + assert_eq!( + librustzcash_xor(0x0f0f0f0f0f0f0f0f, 0x1111111111111111), + 0x1e1e1e1e1e1e1e1e + ); }