2018-04-17 14:22:35 -06:00
|
|
|
extern crate bellman;
|
2017-03-17 11:07:23 -06:00
|
|
|
extern crate libc;
|
2018-04-11 21:51:30 -06:00
|
|
|
extern crate pairing;
|
2018-04-17 14:22:35 -06:00
|
|
|
extern crate sapling_crypto;
|
2018-04-09 18:28:42 -06:00
|
|
|
|
2018-04-12 18:38:25 -06:00
|
|
|
#[macro_use]
|
|
|
|
extern crate lazy_static;
|
|
|
|
|
2018-04-17 14:22:35 -06:00
|
|
|
use pairing::{BitIterator, PrimeField, PrimeFieldRepr, bls12_381::{Bls12, Fr, FrRepr}};
|
2018-04-11 21:51:30 -06:00
|
|
|
|
2018-05-07 18:06:53 -06:00
|
|
|
use sapling_crypto::{jubjub::JubjubBls12, pedersen_hash::{pedersen_hash, Personalization}, util::swap_bits_u64};
|
2018-04-17 14:16:14 -06:00
|
|
|
|
2018-04-17 14:22:35 -06:00
|
|
|
use bellman::groth16::{prepare_verifying_key, Parameters, PreparedVerifyingKey, VerifyingKey};
|
|
|
|
|
|
|
|
use libc::{c_char, c_uchar, size_t, uint64_t};
|
2018-04-17 14:16:14 -06:00
|
|
|
use std::ffi::CStr;
|
|
|
|
use std::fs::File;
|
2018-04-11 21:51:30 -06:00
|
|
|
|
2018-04-12 18:38:25 -06:00
|
|
|
lazy_static! {
|
2018-04-17 14:22:35 -06:00
|
|
|
static ref JUBJUB: JubjubBls12 = { JubjubBls12::new() };
|
2018-04-11 21:51:30 -06:00
|
|
|
}
|
|
|
|
|
2018-04-17 14:16:14 -06:00
|
|
|
static mut SAPLING_SPEND_VK: Option<PreparedVerifyingKey<Bls12>> = None;
|
|
|
|
static mut SAPLING_OUTPUT_VK: Option<PreparedVerifyingKey<Bls12>> = None;
|
|
|
|
static mut SPROUT_GROTH16_VK: Option<PreparedVerifyingKey<Bls12>> = None;
|
|
|
|
|
|
|
|
static mut SAPLING_SPEND_PARAMS: Option<Parameters<Bls12>> = None;
|
|
|
|
static mut SAPLING_OUTPUT_PARAMS: Option<Parameters<Bls12>> = None;
|
|
|
|
static mut SPROUT_GROTH16_PARAMS_PATH: Option<String> = None;
|
|
|
|
|
2018-05-07 18:06:53 -06:00
|
|
|
/// Writes an FrRepr to [u8] of length 32
|
|
|
|
fn write_le(mut f: FrRepr, to: &mut [u8]) {
|
|
|
|
assert_eq!(to.len(), 32);
|
|
|
|
|
|
|
|
f.as_mut().reverse();
|
|
|
|
for b in f.as_mut() {
|
|
|
|
*b = swap_bits_u64(*b);
|
|
|
|
}
|
|
|
|
|
|
|
|
f.write_be(to).expect("length is 32 bytes");
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Reads an FrRepr from a [u8] of length 32.
|
|
|
|
/// This will panic (abort) if length provided is
|
|
|
|
/// not correct.
|
|
|
|
fn read_le(from: &[u8]) -> FrRepr
|
|
|
|
{
|
|
|
|
assert_eq!(from.len(), 32);
|
|
|
|
|
|
|
|
let mut f = FrRepr::default();
|
|
|
|
f.read_be(from).expect("length is 32 bytes");
|
|
|
|
|
|
|
|
f.as_mut().reverse();
|
|
|
|
for b in f.as_mut() {
|
|
|
|
*b = swap_bits_u64(*b);
|
|
|
|
}
|
|
|
|
|
|
|
|
f
|
|
|
|
}
|
|
|
|
|
2018-04-17 14:16:14 -06:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "system" fn librustzcash_init_zksnark_params(
|
|
|
|
spend_path: *const c_char,
|
|
|
|
output_path: *const c_char,
|
2018-04-17 14:22:35 -06:00
|
|
|
sprout_path: *const c_char,
|
|
|
|
) {
|
2018-04-21 17:46:08 -06:00
|
|
|
// Initialize jubjub parameters here
|
|
|
|
lazy_static::initialize(&JUBJUB);
|
|
|
|
|
2018-04-17 14:16:14 -06:00
|
|
|
// These should be valid CStr's, but the decoding may fail on Windows
|
|
|
|
// so we may need to use OSStr or something.
|
2018-04-17 14:22:35 -06:00
|
|
|
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();
|
2018-04-17 14:16:14 -06:00
|
|
|
|
|
|
|
// Load from each of the paths
|
|
|
|
let mut spend_fs = File::open(spend_path).expect("couldn't load Sapling spend parameters file");
|
2018-04-17 14:22:35 -06:00
|
|
|
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");
|
2018-04-17 14:16:14 -06:00
|
|
|
|
|
|
|
// Deserialize params
|
2018-04-17 14:22:35 -06:00
|
|
|
let spend_params = Parameters::<Bls12>::read(&mut spend_fs, false)
|
|
|
|
.expect("couldn't deserialize Sapling spend parameters file");
|
|
|
|
let output_params = Parameters::<Bls12>::read(&mut output_fs, false)
|
|
|
|
.expect("couldn't deserialize Sapling spend parameters file");
|
|
|
|
let sprout_vk = VerifyingKey::<Bls12>::read(&mut sprout_fs)
|
|
|
|
.expect("couldn't deserialize Sprout Groth16 verifying key");
|
2018-04-17 14:16:14 -06:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-11 21:51:30 -06:00
|
|
|
#[no_mangle]
|
2018-04-17 14:22:35 -06:00
|
|
|
pub extern "system" fn librustzcash_tree_uncommitted(result: *mut [c_uchar; 32]) {
|
2018-04-12 18:38:25 -06:00
|
|
|
let tmp = sapling_crypto::primitives::Note::<Bls12>::uncommitted().into_repr();
|
2018-04-11 21:51:30 -06:00
|
|
|
|
2018-04-12 18:38:25 -06:00
|
|
|
// Should be okay, caller is responsible for ensuring the pointer
|
|
|
|
// is a valid pointer to 32 bytes that can be mutated.
|
|
|
|
let result = unsafe { &mut *result };
|
|
|
|
|
2018-05-07 18:06:53 -06:00
|
|
|
write_le(tmp, &mut result[..]);
|
2018-04-11 21:51:30 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "system" fn librustzcash_merkle_hash(
|
|
|
|
depth: size_t,
|
|
|
|
a: *const [c_uchar; 32],
|
|
|
|
b: *const [c_uchar; 32],
|
|
|
|
result: *mut [c_uchar; 32],
|
2018-04-17 14:22:35 -06:00
|
|
|
) {
|
2018-04-11 21:51:30 -06:00
|
|
|
// Should be okay, because caller is responsible for ensuring
|
|
|
|
// the pointer is a valid pointer to 32 bytes, and that is the
|
|
|
|
// size of the representation
|
2018-05-07 18:06:53 -06:00
|
|
|
let a_repr = read_le(unsafe { &(&*a)[..] });
|
2018-04-11 21:51:30 -06:00
|
|
|
|
|
|
|
// Should be okay, because caller is responsible for ensuring
|
|
|
|
// the pointer is a valid pointer to 32 bytes, and that is the
|
|
|
|
// size of the representation
|
2018-05-07 18:06:53 -06:00
|
|
|
let b_repr = read_le(unsafe { &(&*b)[..] });
|
2018-04-11 21:51:30 -06:00
|
|
|
|
|
|
|
let mut lhs = [false; 256];
|
|
|
|
let mut rhs = [false; 256];
|
|
|
|
|
|
|
|
for (a, b) in lhs.iter_mut().rev().zip(BitIterator::new(a_repr)) {
|
|
|
|
*a = b;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (a, b) in rhs.iter_mut().rev().zip(BitIterator::new(b_repr)) {
|
|
|
|
*a = b;
|
|
|
|
}
|
2018-04-17 14:22:35 -06:00
|
|
|
|
2018-04-11 21:51:30 -06:00
|
|
|
let tmp = pedersen_hash::<Bls12, _>(
|
|
|
|
Personalization::MerkleTree(depth),
|
2018-04-17 14:22:35 -06:00
|
|
|
lhs.iter()
|
|
|
|
.map(|&x| x)
|
2018-04-11 21:51:30 -06:00
|
|
|
.take(Fr::NUM_BITS as usize)
|
|
|
|
.chain(rhs.iter().map(|&x| x).take(Fr::NUM_BITS as usize)),
|
2018-04-17 14:22:35 -06:00
|
|
|
&JUBJUB,
|
|
|
|
).into_xy()
|
|
|
|
.0
|
|
|
|
.into_repr();
|
2018-04-11 21:51:30 -06:00
|
|
|
|
|
|
|
// Should be okay, caller is responsible for ensuring the pointer
|
2018-04-12 15:01:48 -06:00
|
|
|
// is a valid pointer to 32 bytes that can be mutated.
|
2018-04-11 21:51:30 -06:00
|
|
|
let result = unsafe { &mut *result };
|
|
|
|
|
2018-05-07 18:06:53 -06:00
|
|
|
write_le(tmp, &mut result[..]);
|
2018-04-11 21:51:30 -06:00
|
|
|
}
|
2017-03-17 11:07:23 -06:00
|
|
|
|
|
|
|
/// XOR two uint64_t values and return the result, used
|
|
|
|
/// as a temporary mechanism for introducing Rust into
|
|
|
|
/// Zcash.
|
|
|
|
#[no_mangle]
|
2018-04-17 14:22:35 -06:00
|
|
|
pub extern "system" fn librustzcash_xor(a: uint64_t, b: uint64_t) -> uint64_t {
|
2017-03-17 11:07:23 -06:00
|
|
|
a ^ b
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_xor() {
|
2018-04-17 14:22:35 -06:00
|
|
|
assert_eq!(
|
|
|
|
librustzcash_xor(0x0f0f0f0f0f0f0f0f, 0x1111111111111111),
|
|
|
|
0x1e1e1e1e1e1e1e1e
|
|
|
|
);
|
2017-03-17 11:07:23 -06:00
|
|
|
}
|