diff --git a/include/librustzcash.h b/include/librustzcash.h index 9033dc2..6aa388a 100644 --- a/include/librustzcash.h +++ b/include/librustzcash.h @@ -6,6 +6,8 @@ extern "C" { uint64_t librustzcash_xor(uint64_t a, uint64_t b); + void librustzcash_to_scalar(const unsigned char *input, unsigned char *result); + /// Loads the zk-SNARK parameters into memory and saves /// paths as necessary. Only called once. void librustzcash_init_zksnark_params( diff --git a/src/rustzcash.rs b/src/rustzcash.rs index 35c63d3..74fc115 100644 --- a/src/rustzcash.rs +++ b/src/rustzcash.rs @@ -12,8 +12,8 @@ extern crate lazy_static; use pairing::{BitIterator, Field, PrimeField, PrimeFieldRepr, bls12_381::{Bls12, Fr, FrRepr}}; use sapling_crypto::{circuit::multipack, - jubjub::{edwards, FixedGenerators, JubjubBls12, JubjubParams, Unknown, - fs::FsRepr}, + jubjub::{edwards, FixedGenerators, JubjubBls12, JubjubEngine, JubjubParams, + ToUniform, Unknown, fs::FsRepr}, pedersen_hash::{pedersen_hash, Personalization}, redjubjub::{self, Signature}}; use sapling_crypto::circuit::sprout::{self, TREE_DEPTH as SPROUT_TREE_DEPTH}; @@ -185,6 +185,23 @@ pub extern "system" fn librustzcash_merkle_hash( write_le(tmp, &mut result[..]); } +#[no_mangle] // ToScalar +pub extern "system" fn librustzcash_to_scalar( + input: *const [c_uchar; 64], + result: *mut [c_uchar; 32], +) { + // 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 + let scalar = ::Fs::to_uniform(unsafe { &(&*input)[..] }).into_repr(); + + let result = unsafe { &mut *result }; + + scalar + .write_le(&mut result[..]) + .expect("length is 32 bytes"); +} + /// XOR two uint64_t values and return the result, used /// as a temporary mechanism for introducing Rust into /// Zcash.