mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-02-01 08:12:14 +00:00
Expose API for init/free of parameters and, to test, a merkle tree hash invocation.
This commit is contained in:
parent
7dc69c6893
commit
f1d35708bc
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -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)",
|
||||
]
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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_
|
||||
|
@ -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)),
|
||||
¶ms.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
|
||||
|
Loading…
Reference in New Issue
Block a user