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`.
|
/// `librustzcash_sapling_verification_ctx_init`.
|
||||||
void librustzcash_sapling_verification_ctx_free(void *);
|
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.
|
/// Compute a Sapling commitment.
|
||||||
///
|
///
|
||||||
/// The `diversifier` parameter must be 11 bytes in length.
|
/// 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::fs::File;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
|
use sapling_crypto::primitives::ViewingKey;
|
||||||
|
|
||||||
pub mod equihash;
|
pub mod equihash;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[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");
|
.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.
|
/// Compute Sapling note commitment.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "system" fn librustzcash_sapling_compute_cm(
|
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],
|
r: *const [c_uchar; 32],
|
||||||
result: *mut [c_uchar; 32],
|
result: *mut [c_uchar; 32],
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let diversifier = sapling_crypto::primitives::Diversifier(unsafe { *diversifier });
|
let note = match priv_get_note(diversifier, pk_d, value, r) {
|
||||||
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,
|
Ok(p) => p,
|
||||||
Err(_) => return false,
|
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 };
|
let result = unsafe { &mut *result };
|
||||||
write_le(note.cm(&JUBJUB).into_repr(), &mut result[..]);
|
write_le(note.cm(&JUBJUB).into_repr(), &mut result[..]);
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ use sapling_crypto::jubjub::{FixedGenerators, JubjubParams};
|
|||||||
|
|
||||||
use super::JUBJUB;
|
use super::JUBJUB;
|
||||||
|
|
||||||
mod commitments;
|
mod notes;
|
||||||
mod key_components;
|
mod key_components;
|
||||||
mod signatures;
|
mod signatures;
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use librustzcash_sapling_compute_cm;
|
use librustzcash_sapling_compute_cm;
|
||||||
|
use librustzcash_sapling_compute_nf;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn commitments() {
|
fn notes() {
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
struct TestVector {
|
struct TestVector {
|
||||||
sk: [u8; 32],
|
sk: [u8; 32],
|
||||||
@ -655,5 +656,18 @@ fn commitments() {
|
|||||||
&mut result
|
&mut result
|
||||||
));
|
));
|
||||||
assert_eq!(&result, &tv.note_cm);
|
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