Browse Source

Add ffi and computation for Sapling note commitment.

master
Simon 6 years ago
parent
commit
4ef2e9ae68
  1. 21
      include/librustzcash.h
  2. 76
      src/rustzcash.rs

21
include/librustzcash.h

@ -102,6 +102,27 @@ extern "C" {
/// `librustzcash_sapling_verification_ctx_init`.
void librustzcash_sapling_verification_ctx_free(void *);
/// Compute a Sapling commitment.
///
/// The `diversifier` parameter must be 11 bytes in length.
/// The `pk_d` and `r` parameters must be of length 32.
/// The result is also of length 32 and placed in `result`.
/// Returns false if the diversifier or pk_d is not valid
bool librustzcash_sapling_compute_cm(
const unsigned char *diversifier,
const unsigned char *pk_d,
const uint64_t value,
const unsigned char *r,
unsigned char *result
);
/// Generate uniform Sapling commitment randomness `r`.
/// The result is of length 32.
/// Returns false if there was an error.
bool librustzcash_sapling_generate_commitment_randomness(
unsigned char *result
);
/// Sprout JoinSplit proof generation.
void librustzcash_sprout_prove(
unsigned char *proof_out,

76
src/rustzcash.rs

@ -13,7 +13,7 @@ use pairing::{BitIterator, Field, PrimeField, PrimeFieldRepr, bls12_381::{Bls12,
use sapling_crypto::{circuit::multipack, constants::CRH_IVK_PERSONALIZATION,
jubjub::{edwards, FixedGenerators, JubjubBls12, JubjubEngine, JubjubParams,
PrimeOrder, ToUniform, Unknown, fs::FsRepr},
PrimeOrder, ToUniform, Unknown, fs::{Fs, FsRepr}},
pedersen_hash::{pedersen_hash, Personalization}, redjubjub::{self, Signature}};
use sapling_crypto::circuit::sprout::{self, TREE_DEPTH as SPROUT_TREE_DEPTH};
@ -25,7 +25,7 @@ use blake2_rfc::blake2s::Blake2s;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use rand::OsRng;
use rand::{OsRng, Rng};
use std::io::BufReader;
use libc::{c_char, c_uchar, size_t, int64_t, uint32_t, uint64_t};
@ -301,6 +301,78 @@ pub extern "system" fn librustzcash_ivk_to_pkd(
}
}
/// Return 32 byte randomness, uniform, to be used for a Sapling commitment.
#[no_mangle]
pub extern "system" fn librustzcash_sapling_generate_commitment_randomness(
result: *mut [c_uchar; 32],
) -> bool {
// create random 64 byte buffer
let mut rng = OsRng::new().expect("should be able to construct RNG");
let mut buffer = [0u8; 64];
for i in 0..buffer.len() {
buffer[i] = rng.gen();
}
// TODO: Remove this debug statement
println!("buffer of random bytes: {:?}", &buffer[..]);
// reduce to uniform value
let r = <Bls12 as JubjubEngine>::Fs::to_uniform(&buffer[..]);
let result = unsafe { &mut *result };
r.into_repr()
.write_le(&mut result[..])
.expect("result must be 32 bytes");
true
}
/// Compute Sapling note commitment.
#[no_mangle]
pub extern "system" fn librustzcash_sapling_compute_cm(
diversifier: *const [c_uchar; 11],
pk_d: *const [c_uchar; 32],
value: uint64_t,
r: *const [c_uchar; 32],
result: *mut [c_uchar; 32],
) -> bool {
let diversifier = sapling_crypto::primitives::Diversifier(unsafe { *diversifier });
let g_d = match diversifier.g_d::<Bls12>(&JUBJUB) {
Some(g_d) => g_d,
None => return false,
};
let pk_d = match edwards::Point::<Bls12, Unknown>::read(&(unsafe { &*pk_d })[..], &JUBJUB) {
Ok(p) => p,
Err(_) => return false,
};
let pk_d = match pk_d.as_prime_order(&JUBJUB) {
Some(pk_d) => pk_d,
None => return false,
};
// Deserialize randomness
let r = unsafe { *r };
let mut repr = FsRepr::default();
repr.read_le(&r[..]).expect("length is not 32 bytes");
let r = match Fs::from_repr(repr) {
Ok(p) => p,
Err(_) => return false,
};
let note = sapling_crypto::primitives::Note {
value,
g_d,
pk_d,
r,
};
let result = unsafe { &mut *result };
write_le(note.cm(&JUBJUB).into_repr(), &mut result[..]);
true
}
/// XOR two uint64_t values and return the result, used
/// as a temporary mechanism for introducing Rust into
/// Zcash.

Loading…
Cancel
Save