Expose API for init/free of parameters and, to test, a merkle tree hash invocation.

This commit is contained in:
Sean Bowe 2018-04-11 21:51:30 -06:00
parent 7dc69c6893
commit f1d35708bc
No known key found for this signature in database
GPG Key ID: 95684257D8F8B031
4 changed files with 130 additions and 1 deletions

1
Cargo.lock generated
View File

@ -110,6 +110,7 @@ name = "librustzcash"
version = "0.1.0"
dependencies = [
"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)",
"sapling-crypto 0.0.1 (git+https://github.com/zcash-hackworks/sapling-crypto?rev=e554b473dd10885d232f42237c13282f5b6fee43)",
]

View File

@ -10,6 +10,7 @@ crate-type = ["staticlib"]
[dependencies]
libc = "0.2"
pairing = "0.14.1"
[dependencies.sapling-crypto]
git = "https://github.com/zcash-hackworks/sapling-crypto"

View File

@ -3,8 +3,42 @@
#include <stdint.h>
struct librustzcash_params {
};
extern "C" {
uint64_t librustzcash_xor(uint64_t a, uint64_t b);
/// Initializes some parameters for sapling-crypto,
/// returning a pointer to the parameters. You should
/// free this when you're done with
/// `librustzcash_init_params()`.
librustzcash_params* librustzcash_init_params();
/// Frees some parameters that were previously returned
/// from `librustzcash_init_params()`. Only call this
/// once.
void librustzcash_free_params(librustzcash_params* params);
/// Computes a merkle tree hash for a given depth.
/// The `depth` parameter should not be larger than
/// 62.
///
/// Params must be a valid pointer that was returned
/// from `librustzcash_init_params()`.
///
/// `a` and `b` each must be of length 32, and must each
/// be scalars of BLS12-381.
///
/// The result of the merkle tree hash is placed in
/// `result`, which must also be of length 32.
void librustzcash_merkle_hash(
const librustzcash_params* params,
size_t depth,
const unsigned char *a,
const unsigned char *b,
unsigned char *result
);
}
#endif // LIBRUSTZCASH_INCLUDE_H_

View File

@ -1,7 +1,100 @@
extern crate libc;
extern crate sapling_crypto;
extern crate pairing;
use libc::uint64_t;
use pairing::{
BitIterator,
PrimeFieldRepr,
PrimeField,
bls12_381::{
Bls12,
Fr,
FrRepr
}
};
use sapling_crypto::{
jubjub::JubjubBls12,
pedersen_hash::{
pedersen_hash,
Personalization
}
};
use libc::{uint64_t, size_t, c_uchar};
pub struct SaplingParams {
pub jubjub_params: JubjubBls12
}
#[no_mangle]
pub extern "system" fn librustzcash_init_params() -> *mut SaplingParams {
Box::into_raw(Box::new(SaplingParams{
jubjub_params: JubjubBls12::new()
}))
}
#[no_mangle]
pub extern "system" fn librustzcash_free_params(
params: *mut SaplingParams
)
{
let tmp = unsafe { Box::from_raw(params) };
drop(tmp);
}
#[no_mangle]
pub extern "system" fn librustzcash_merkle_hash(
params: *const SaplingParams,
depth: size_t,
a: *const [c_uchar; 32],
b: *const [c_uchar; 32],
result: *mut [c_uchar; 32],
)
{
// Should be okay, because caller is responsible for ensuring
// params points to valid parameters.
let params = unsafe { &*params };
let mut a_repr = FrRepr::default();
let mut b_repr = FrRepr::default();
// 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
a_repr.read_be(unsafe { &(&*a)[..] }).unwrap();
// 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
b_repr.read_be(unsafe { &(&*b)[..] }).unwrap();
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;
}
let tmp = pedersen_hash::<Bls12, _>(
Personalization::MerkleTree(depth),
lhs.iter().map(|&x| x)
.take(Fr::NUM_BITS as usize)
.chain(rhs.iter().map(|&x| x).take(Fr::NUM_BITS as usize)),
&params.jubjub_params
).into_xy().0.into_repr();
// Should be okay, caller is responsible for ensuring the pointer
// is valid.
let result = unsafe { &mut *result };
tmp.write_be(&mut result[..]).unwrap();
}
/// XOR two uint64_t values and return the result, used
/// as a temporary mechanism for introducing Rust into