mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-02-07 06:44:11 +00:00
Merge pull request #19 from bitcartel/add_note_nullifier_computation
Add interface and computation of Sapling note nullifier
This commit is contained in:
commit
0af1ce8bf1
@ -100,6 +100,23 @@ extern "C" {
|
||||
/// `librustzcash_sapling_verification_ctx_init`.
|
||||
void librustzcash_sapling_verification_ctx_free(void *);
|
||||
|
||||
/// Compute a Sapling nullifier.
|
||||
///
|
||||
/// The `diversifier` parameter must be 11 bytes in length.
|
||||
/// The `pk_d`, `r`, `ak` and `nk` 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_nf(
|
||||
const unsigned char *diversifier,
|
||||
const unsigned char *pk_d,
|
||||
const uint64_t value,
|
||||
const unsigned char *r,
|
||||
const unsigned char *ak,
|
||||
const unsigned char *nk,
|
||||
const uint64_t position,
|
||||
unsigned char *result
|
||||
);
|
||||
|
||||
/// Compute a Sapling commitment.
|
||||
///
|
||||
/// The `diversifier` parameter must be 11 bytes in length.
|
||||
|
118
src/rustzcash.rs
118
src/rustzcash.rs
@ -33,6 +33,8 @@ use std::ffi::CStr;
|
||||
use std::fs::File;
|
||||
use std::slice;
|
||||
|
||||
use sapling_crypto::primitives::ViewingKey;
|
||||
|
||||
pub mod equihash;
|
||||
|
||||
#[cfg(test)]
|
||||
@ -338,6 +340,93 @@ pub extern "system" fn librustzcash_sapling_generate_r(result: *mut [c_uchar; 32
|
||||
.expect("result must be 32 bytes");
|
||||
}
|
||||
|
||||
// Private utility function to get Note from C parameters
|
||||
fn priv_get_note(
|
||||
diversifier: *const [c_uchar; 11],
|
||||
pk_d: *const [c_uchar; 32],
|
||||
value: uint64_t,
|
||||
r: *const [c_uchar; 32],
|
||||
) -> Result<sapling_crypto::primitives::Note<Bls12>, ()> {
|
||||
let diversifier = sapling_crypto::primitives::Diversifier(unsafe { *diversifier });
|
||||
let g_d = match diversifier.g_d::<Bls12>(&JUBJUB) {
|
||||
Some(g_d) => g_d,
|
||||
None => return Err(()),
|
||||
};
|
||||
|
||||
let pk_d = match edwards::Point::<Bls12, Unknown>::read(&(unsafe { &*pk_d })[..], &JUBJUB) {
|
||||
Ok(p) => p,
|
||||
Err(_) => return Err(()),
|
||||
};
|
||||
|
||||
let pk_d = match pk_d.as_prime_order(&JUBJUB) {
|
||||
Some(pk_d) => pk_d,
|
||||
None => return Err(()),
|
||||
};
|
||||
|
||||
// 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 Err(()),
|
||||
};
|
||||
|
||||
let note = sapling_crypto::primitives::Note {
|
||||
value,
|
||||
g_d,
|
||||
pk_d,
|
||||
r,
|
||||
};
|
||||
|
||||
Ok(note)
|
||||
}
|
||||
|
||||
/// Compute Sapling note nullifier.
|
||||
#[no_mangle]
|
||||
pub extern "system" fn librustzcash_sapling_compute_nf(
|
||||
diversifier: *const [c_uchar; 11],
|
||||
pk_d: *const [c_uchar; 32],
|
||||
value: uint64_t,
|
||||
r: *const [c_uchar; 32],
|
||||
ak: *const [c_uchar; 32],
|
||||
nk: *const [c_uchar; 32],
|
||||
position: uint64_t,
|
||||
result: *mut [c_uchar; 32],
|
||||
) -> bool {
|
||||
let note = match priv_get_note(diversifier, pk_d, value, r) {
|
||||
Ok(p) => p,
|
||||
Err(_) => return false,
|
||||
};
|
||||
|
||||
let ak = match edwards::Point::<Bls12, Unknown>::read(&(unsafe { &*ak })[..], &JUBJUB) {
|
||||
Ok(p) => p,
|
||||
Err(_) => return false,
|
||||
};
|
||||
|
||||
let ak = match ak.as_prime_order(&JUBJUB) {
|
||||
Some(ak) => ak,
|
||||
None => return false,
|
||||
};
|
||||
|
||||
let nk = match edwards::Point::<Bls12, Unknown>::read(&(unsafe { &*nk })[..], &JUBJUB) {
|
||||
Ok(p) => p,
|
||||
Err(_) => return false,
|
||||
};
|
||||
|
||||
let nk = match nk.as_prime_order(&JUBJUB) {
|
||||
Some(nk) => nk,
|
||||
None => return false,
|
||||
};
|
||||
|
||||
let vk = ViewingKey { ak, nk };
|
||||
let nf = note.nf(&vk, position, &JUBJUB);
|
||||
let result = unsafe { &mut *result };
|
||||
result.copy_from_slice(&nf);
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
/// Compute Sapling note commitment.
|
||||
#[no_mangle]
|
||||
pub extern "system" fn librustzcash_sapling_compute_cm(
|
||||
@ -347,38 +436,11 @@ pub extern "system" fn librustzcash_sapling_compute_cm(
|
||||
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) {
|
||||
let note = match priv_get_note(diversifier, pk_d, value, r) {
|
||||
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[..]);
|
||||
|
||||
|
@ -2,7 +2,7 @@ use sapling_crypto::jubjub::{FixedGenerators, JubjubParams};
|
||||
|
||||
use super::JUBJUB;
|
||||
|
||||
mod commitments;
|
||||
mod notes;
|
||||
mod key_components;
|
||||
mod signatures;
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
use librustzcash_sapling_compute_cm;
|
||||
use librustzcash_sapling_compute_nf;
|
||||
|
||||
#[test]
|
||||
fn commitments() {
|
||||
fn notes() {
|
||||
#![allow(dead_code)]
|
||||
struct TestVector {
|
||||
sk: [u8; 32],
|
||||
@ -655,5 +656,18 @@ fn commitments() {
|
||||
&mut result
|
||||
));
|
||||
assert_eq!(&result, &tv.note_cm);
|
||||
|
||||
// Compute nullifier and compare with test vector
|
||||
assert!(librustzcash_sapling_compute_nf(
|
||||
&tv.default_d,
|
||||
&tv.default_pk_d,
|
||||
tv.note_v,
|
||||
&tv.note_r,
|
||||
&tv.ak,
|
||||
&tv.nk,
|
||||
tv.note_pos,
|
||||
&mut result
|
||||
));
|
||||
assert_eq!(&result, &tv.note_nf);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user