diff --git a/include/librustzcash.h b/include/librustzcash.h index 2a222a8e4..e2bf92966 100644 --- a/include/librustzcash.h +++ b/include/librustzcash.h @@ -131,7 +131,29 @@ extern "C" { unsigned char *result ); - /// Generate uniform Sapling commitment randomness `r`. + /// Compute [sk] [8] P for some 32-byte + /// point P, and 32-byte Fs. If P or sk + /// are invalid, returns false. Otherwise, + /// the result is written to the 32-byte + /// `result` buffer. + bool librustzcash_sapling_ka_agree( + const unsigned char *p, + const unsigned char *sk, + unsigned char *result + ); + + /// Compute g_d = GH(diversifier) and returns + /// false if the diversifier is invalid. + /// Computes [esk] g_d and writes the result + /// to the 32-byte `result` buffer. Returns + /// false if `esk` is not a valid scalar. + bool librustzcash_sapling_ka_derivepublic( + const unsigned char *diversifier, + const unsigned char *esk, + unsigned char *result + ); + + /// Generate uniformly random scalar in Jubjub. /// The result is of length 32. void librustzcash_sapling_generate_r( unsigned char *result diff --git a/src/equihash.rs b/src/equihash.rs index 1dcaa7bb8..0509fc256 100644 --- a/src/equihash.rs +++ b/src/equihash.rs @@ -44,7 +44,8 @@ impl Node { } fn from_children(a: Node, b: Node, trim: usize) -> Self { - let hash: Vec<_> = a.hash + let hash: Vec<_> = a + .hash .iter() .zip(b.hash.iter()) .skip(trim) @@ -66,7 +67,8 @@ impl Node { } fn from_children_ref(a: &Node, b: &Node, trim: usize) -> Self { - let hash: Vec<_> = a.hash + let hash: Vec<_> = a + .hash .iter() .zip(b.hash.iter()) .skip(trim) diff --git a/src/rustzcash.rs b/src/rustzcash.rs index 619955c6f..e4ae6eacd 100644 --- a/src/rustzcash.rs +++ b/src/rustzcash.rs @@ -9,17 +9,25 @@ extern crate sapling_crypto; #[macro_use] extern crate lazy_static; -use pairing::{BitIterator, Field, PrimeField, PrimeFieldRepr, bls12_381::{Bls12, Fr, FrRepr}}; +use pairing::{ + bls12_381::{Bls12, Fr, FrRepr}, BitIterator, Field, PrimeField, PrimeFieldRepr, +}; -use sapling_crypto::{circuit::multipack, constants::CRH_IVK_PERSONALIZATION, - jubjub::{edwards, FixedGenerators, JubjubBls12, JubjubEngine, JubjubParams, - PrimeOrder, ToUniform, Unknown, fs::{Fs, FsRepr}}, - pedersen_hash::{pedersen_hash, Personalization}, redjubjub::{self, Signature}}; +use sapling_crypto::{ + circuit::multipack, constants::CRH_IVK_PERSONALIZATION, + jubjub::{ + edwards, fs::{Fs, FsRepr}, FixedGenerators, JubjubBls12, JubjubEngine, JubjubParams, + PrimeOrder, ToUniform, Unknown, + }, + pedersen_hash::{pedersen_hash, Personalization}, redjubjub::{self, Signature}, +}; use sapling_crypto::circuit::sprout::{self, TREE_DEPTH as SPROUT_TREE_DEPTH}; -use bellman::groth16::{create_random_proof, prepare_verifying_key, verify_proof, Parameters, - PreparedVerifyingKey, Proof, VerifyingKey}; +use bellman::groth16::{ + create_random_proof, prepare_verifying_key, verify_proof, Parameters, PreparedVerifyingKey, + Proof, VerifyingKey, +}; use blake2_rfc::blake2s::Blake2s; @@ -28,7 +36,7 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use rand::{OsRng, Rng}; use std::io::BufReader; -use libc::{c_char, c_uchar, size_t, int64_t, uint32_t, uint64_t}; +use libc::{c_char, c_uchar, int64_t, size_t, uint32_t, uint64_t}; use std::ffi::CStr; use std::fs::File; use std::slice; @@ -322,7 +330,7 @@ fn test_gen_r() { let _ = Fs::from_repr(repr).unwrap(); } -/// Return 32 byte randomness, uniform, to be used for a Sapling commitment. +/// Return 32 byte random scalar, uniformly. #[no_mangle] pub extern "system" fn librustzcash_sapling_generate_r(result: *mut [c_uchar; 32]) { // create random 64 byte buffer @@ -364,11 +372,8 @@ fn priv_get_note( }; // 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, + let r = match Fs::from_repr(read_fs(&(unsafe { &*r })[..])) { + Ok(r) => r, Err(_) => return Err(()), }; @@ -447,6 +452,65 @@ pub extern "system" fn librustzcash_sapling_compute_cm( true } +#[no_mangle] +pub extern "system" fn librustzcash_sapling_ka_agree( + p: *const [c_uchar; 32], + sk: *const [c_uchar; 32], + result: *mut [c_uchar; 32], +) -> bool { + // Deserialize p + let p = match edwards::Point::::read(&(unsafe { &*p })[..], &JUBJUB) { + Ok(p) => p, + Err(_) => return false, + }; + + // Deserialize sk + let sk = match Fs::from_repr(read_fs(&(unsafe { &*sk })[..])) { + Ok(p) => p, + Err(_) => return false, + }; + + // Multiply by 8 + let p = p.mul_by_cofactor(&JUBJUB); + + // Multiply by sk + let p = p.mul(sk, &JUBJUB); + + // Produce result + let result = unsafe { &mut *result }; + p.write(&mut result[..]).expect("length is not 32 bytes"); + + true +} + +#[no_mangle] +pub extern "system" fn librustzcash_sapling_ka_derivepublic( + diversifier: *const [c_uchar; 11], + esk: *const [c_uchar; 32], + result: *mut [c_uchar; 32], +) -> bool { + let diversifier = sapling_crypto::primitives::Diversifier(unsafe { *diversifier }); + + // Compute g_d from the diversifier + let g_d = match diversifier.g_d::(&JUBJUB) { + Some(g) => g, + None => return false, + }; + + // Deserialize esk + let esk = match Fs::from_repr(read_fs(&(unsafe { &*esk })[..])) { + Ok(p) => p, + Err(_) => return false, + }; + + let p = g_d.mul(esk, &JUBJUB); + + let result = unsafe { &mut *result }; + p.write(&mut result[..]).expect("length is not 32 bytes"); + + true +} + #[no_mangle] pub extern "system" fn librustzcash_eh_isvalid( n: uint32_t, @@ -836,7 +900,8 @@ pub extern "system" fn librustzcash_sprout_prove( auth_path[i] = Some((sibling, false)); } - let mut position = auth.read_u64::() + let mut position = auth + .read_u64::() .expect("should have had index at the end"); for i in 0..SPROUT_TREE_DEPTH { diff --git a/src/tests/key_agreement.rs b/src/tests/key_agreement.rs new file mode 100644 index 000000000..01657d14b --- /dev/null +++ b/src/tests/key_agreement.rs @@ -0,0 +1,74 @@ +use pairing::bls12_381::Bls12; +use pairing::{PrimeField, PrimeFieldRepr}; +use rand::{OsRng, Rng}; +use sapling_crypto::jubjub::{edwards, JubjubBls12}; +use sapling_crypto::primitives::{Diversifier, ViewingKey}; + +use { + librustzcash_sapling_generate_r, librustzcash_sapling_ka_agree, + librustzcash_sapling_ka_derivepublic, +}; + +#[test] +fn test_key_agreement() { + let params = JubjubBls12::new(); + let mut rng = OsRng::new().unwrap(); + + // Create random viewing key + let vk = ViewingKey:: { + ak: edwards::Point::rand(&mut rng, ¶ms).mul_by_cofactor(¶ms), + nk: edwards::Point::rand(&mut rng, ¶ms).mul_by_cofactor(¶ms), + }; + + // Create a random address with the viewing key + let addr = loop { + match vk.into_payment_address(Diversifier(rng.gen()), ¶ms) { + Some(a) => break a, + None => {} + } + }; + + // Grab ivk from our viewing key in serialized form + let ivk = vk.ivk(); + let mut ivk_serialized = [0u8; 32]; + ivk.into_repr().write_le(&mut ivk_serialized[..]).unwrap(); + + // Create random esk + let mut esk = [0u8; 32]; + librustzcash_sapling_generate_r(&mut esk); + + // The sender will create a shared secret with the recipient + // by multiplying the pk_d from their address with the esk + // we randomly generated + let mut shared_secret_sender = [0u8; 32]; + + // Serialize pk_d for the call to librustzcash_sapling_ka_agree + let mut addr_pk_d = [0u8; 32]; + addr.pk_d.write(&mut addr_pk_d[..]).unwrap(); + + assert!(librustzcash_sapling_ka_agree( + &addr_pk_d, + &esk, + &mut shared_secret_sender + )); + + // Create epk for the recipient, placed in the transaction. Computed + // using the diversifier and esk. + let mut epk = [0u8; 32]; + assert!(librustzcash_sapling_ka_derivepublic( + &addr.diversifier.0, + &esk, + &mut epk + )); + + // Create sharedSecret with ephemeral key + let mut shared_secret_recipient = [0u8; 32]; + assert!(librustzcash_sapling_ka_agree( + &epk, + &ivk_serialized, + &mut shared_secret_recipient + )); + + assert!(!shared_secret_sender.iter().all(|&v| v == 0)); + assert_eq!(shared_secret_sender, shared_secret_recipient); +} diff --git a/src/tests/key_components.rs b/src/tests/key_components.rs index 8b72b109d..d63c4d480 100644 --- a/src/tests/key_components.rs +++ b/src/tests/key_components.rs @@ -1,11 +1,15 @@ -use pairing::{PrimeField, PrimeFieldRepr, bls12_381::Bls12}; -use sapling_crypto::{jubjub::{FixedGenerators, JubjubEngine, JubjubParams, fs::FsRepr}, - primitives::{Diversifier, ProofGenerationKey}}; +use pairing::{bls12_381::Bls12, PrimeField, PrimeFieldRepr}; +use sapling_crypto::{ + jubjub::{fs::FsRepr, FixedGenerators, JubjubEngine, JubjubParams}, + primitives::{Diversifier, ProofGenerationKey}, +}; use super::JUBJUB; -use {librustzcash_ask_to_ak, librustzcash_check_diversifier, librustzcash_crh_ivk, - librustzcash_ivk_to_pkd, librustzcash_nsk_to_nk}; +use { + librustzcash_ask_to_ak, librustzcash_check_diversifier, librustzcash_crh_ivk, + librustzcash_ivk_to_pkd, librustzcash_nsk_to_nk, +}; #[test] fn key_components() { @@ -64,7 +68,7 @@ fn key_components() { 0x51, 0x47, 0x92, 0x04, ], default_d: [ - 0xf1, 0x9d, 0x9b, 0x79, 0x7e, 0x39, 0xf3, 0x37, 0x44, 0x58, 0x39 + 0xf1, 0x9d, 0x9b, 0x79, 0x7e, 0x39, 0xf3, 0x37, 0x44, 0x58, 0x39, ], default_pk_d: [ 0xdb, 0x4c, 0xd2, 0xb0, 0xaa, 0xc4, 0xf7, 0xeb, 0x8c, 0xa1, 0x31, 0xf1, 0x65, 0x67, @@ -120,7 +124,7 @@ fn key_components() { 0xfc, 0x68, 0xa4, 0x06, ], default_d: [ - 0xae, 0xf1, 0x80, 0xf6, 0xe3, 0x4e, 0x35, 0x4b, 0x88, 0x8f, 0x81 + 0xae, 0xf1, 0x80, 0xf6, 0xe3, 0x4e, 0x35, 0x4b, 0x88, 0x8f, 0x81, ], default_pk_d: [ 0xa6, 0xb1, 0x3e, 0xa3, 0x36, 0xdd, 0xb7, 0xa6, 0x7b, 0xb0, 0x9a, 0x0e, 0x68, 0xe9, @@ -176,7 +180,7 @@ fn key_components() { 0x41, 0x95, 0x45, 0x05, ], default_d: [ - 0x75, 0x99, 0xf0, 0xbf, 0x9b, 0x57, 0xcd, 0x2d, 0xc2, 0x99, 0xb6 + 0x75, 0x99, 0xf0, 0xbf, 0x9b, 0x57, 0xcd, 0x2d, 0xc2, 0x99, 0xb6, ], default_pk_d: [ 0x66, 0x14, 0x17, 0x39, 0x51, 0x4b, 0x28, 0xf0, 0x5d, 0xef, 0x8a, 0x18, 0xee, 0xee, @@ -232,7 +236,7 @@ fn key_components() { 0x31, 0xc7, 0x26, 0x00, ], default_d: [ - 0x1b, 0x81, 0x61, 0x4f, 0x1d, 0xad, 0xea, 0x0f, 0x8d, 0x0a, 0x58 + 0x1b, 0x81, 0x61, 0x4f, 0x1d, 0xad, 0xea, 0x0f, 0x8d, 0x0a, 0x58, ], default_pk_d: [ 0x25, 0xeb, 0x55, 0xfc, 0xcf, 0x76, 0x1f, 0xc6, 0x4e, 0x85, 0xa5, 0x88, 0xef, 0xe6, @@ -288,7 +292,7 @@ fn key_components() { 0xb0, 0x1a, 0x1d, 0x04, ], default_d: [ - 0xfc, 0xfb, 0x68, 0xa4, 0x0d, 0x4b, 0xc6, 0xa0, 0x4b, 0x09, 0xc4 + 0xfc, 0xfb, 0x68, 0xa4, 0x0d, 0x4b, 0xc6, 0xa0, 0x4b, 0x09, 0xc4, ], default_pk_d: [ 0x8b, 0x2a, 0x33, 0x7f, 0x03, 0x62, 0x2c, 0x24, 0xff, 0x38, 0x1d, 0x4c, 0x54, 0x6f, @@ -344,7 +348,7 @@ fn key_components() { 0xa2, 0x17, 0x8e, 0x03, ], default_d: [ - 0xeb, 0x51, 0x98, 0x82, 0xad, 0x1e, 0x5c, 0xc6, 0x54, 0xcd, 0x59 + 0xeb, 0x51, 0x98, 0x82, 0xad, 0x1e, 0x5c, 0xc6, 0x54, 0xcd, 0x59, ], default_pk_d: [ 0x6b, 0x27, 0xda, 0xcc, 0xb5, 0xa8, 0x20, 0x7f, 0x53, 0x2d, 0x10, 0xca, 0x23, 0x8f, @@ -400,7 +404,7 @@ fn key_components() { 0x4f, 0x74, 0xc2, 0x05, ], default_d: [ - 0xbe, 0xbb, 0x0f, 0xb4, 0x6b, 0x8a, 0xaf, 0xf8, 0x90, 0x40, 0xf6 + 0xbe, 0xbb, 0x0f, 0xb4, 0x6b, 0x8a, 0xaf, 0xf8, 0x90, 0x40, 0xf6, ], default_pk_d: [ 0xd1, 0x1d, 0xa0, 0x1f, 0x0b, 0x43, 0xbd, 0xd5, 0x28, 0x8d, 0x32, 0x38, 0x5b, 0x87, @@ -456,7 +460,7 @@ fn key_components() { 0xb0, 0x5f, 0x84, 0x02, ], default_d: [ - 0xad, 0x6e, 0x2e, 0x18, 0x5a, 0x31, 0x00, 0xe3, 0xa6, 0xa8, 0xb3 + 0xad, 0x6e, 0x2e, 0x18, 0x5a, 0x31, 0x00, 0xe3, 0xa6, 0xa8, 0xb3, ], default_pk_d: [ 0x32, 0xcb, 0x28, 0x06, 0xb8, 0x82, 0xf1, 0x36, 0x8b, 0x0d, 0x4a, 0x89, 0x8f, 0x72, @@ -512,7 +516,7 @@ fn key_components() { 0xf1, 0x60, 0xe0, 0x01, ], default_d: [ - 0x21, 0xc9, 0x0e, 0x1c, 0x65, 0x8b, 0x3e, 0xfe, 0x86, 0xaf, 0x58 + 0x21, 0xc9, 0x0e, 0x1c, 0x65, 0x8b, 0x3e, 0xfe, 0x86, 0xaf, 0x58, ], default_pk_d: [ 0x9e, 0x64, 0x17, 0x4b, 0x4a, 0xb9, 0x81, 0x40, 0x5c, 0x32, 0x3b, 0x5e, 0x12, 0x47, @@ -568,7 +572,7 @@ fn key_components() { 0xff, 0x89, 0xed, 0x00, ], default_d: [ - 0x23, 0x3c, 0x4a, 0xb8, 0x86, 0xa5, 0x5e, 0x3b, 0xa3, 0x74, 0xc0 + 0x23, 0x3c, 0x4a, 0xb8, 0x86, 0xa5, 0x5e, 0x3b, 0xa3, 0x74, 0xc0, ], default_pk_d: [ 0xb6, 0x8e, 0x9e, 0xe0, 0xc0, 0x67, 0x8d, 0x7b, 0x30, 0x36, 0x93, 0x1c, 0x83, 0x1a, diff --git a/src/tests/mod.rs b/src/tests/mod.rs index ad5ca41fd..a8cdcb794 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -2,8 +2,9 @@ use sapling_crypto::jubjub::{FixedGenerators, JubjubParams}; use super::JUBJUB; -mod notes; +mod key_agreement; mod key_components; +mod notes; mod signatures; #[test] diff --git a/src/tests/notes.rs b/src/tests/notes.rs index c9fde9a28..6f8c0f589 100644 --- a/src/tests/notes.rs +++ b/src/tests/notes.rs @@ -60,7 +60,7 @@ fn notes() { 0x51, 0x47, 0x92, 0x04, ], default_d: [ - 0xf1, 0x9d, 0x9b, 0x79, 0x7e, 0x39, 0xf3, 0x37, 0x44, 0x58, 0x39 + 0xf1, 0x9d, 0x9b, 0x79, 0x7e, 0x39, 0xf3, 0x37, 0x44, 0x58, 0x39, ], default_pk_d: [ 0xdb, 0x4c, 0xd2, 0xb0, 0xaa, 0xc4, 0xf7, 0xeb, 0x8c, 0xa1, 0x31, 0xf1, 0x65, 0x67, @@ -122,7 +122,7 @@ fn notes() { 0xfc, 0x68, 0xa4, 0x06, ], default_d: [ - 0xae, 0xf1, 0x80, 0xf6, 0xe3, 0x4e, 0x35, 0x4b, 0x88, 0x8f, 0x81 + 0xae, 0xf1, 0x80, 0xf6, 0xe3, 0x4e, 0x35, 0x4b, 0x88, 0x8f, 0x81, ], default_pk_d: [ 0xa6, 0xb1, 0x3e, 0xa3, 0x36, 0xdd, 0xb7, 0xa6, 0x7b, 0xb0, 0x9a, 0x0e, 0x68, 0xe9, @@ -184,7 +184,7 @@ fn notes() { 0x41, 0x95, 0x45, 0x05, ], default_d: [ - 0x75, 0x99, 0xf0, 0xbf, 0x9b, 0x57, 0xcd, 0x2d, 0xc2, 0x99, 0xb6 + 0x75, 0x99, 0xf0, 0xbf, 0x9b, 0x57, 0xcd, 0x2d, 0xc2, 0x99, 0xb6, ], default_pk_d: [ 0x66, 0x14, 0x17, 0x39, 0x51, 0x4b, 0x28, 0xf0, 0x5d, 0xef, 0x8a, 0x18, 0xee, 0xee, @@ -246,7 +246,7 @@ fn notes() { 0x31, 0xc7, 0x26, 0x00, ], default_d: [ - 0x1b, 0x81, 0x61, 0x4f, 0x1d, 0xad, 0xea, 0x0f, 0x8d, 0x0a, 0x58 + 0x1b, 0x81, 0x61, 0x4f, 0x1d, 0xad, 0xea, 0x0f, 0x8d, 0x0a, 0x58, ], default_pk_d: [ 0x25, 0xeb, 0x55, 0xfc, 0xcf, 0x76, 0x1f, 0xc6, 0x4e, 0x85, 0xa5, 0x88, 0xef, 0xe6, @@ -308,7 +308,7 @@ fn notes() { 0xb0, 0x1a, 0x1d, 0x04, ], default_d: [ - 0xfc, 0xfb, 0x68, 0xa4, 0x0d, 0x4b, 0xc6, 0xa0, 0x4b, 0x09, 0xc4 + 0xfc, 0xfb, 0x68, 0xa4, 0x0d, 0x4b, 0xc6, 0xa0, 0x4b, 0x09, 0xc4, ], default_pk_d: [ 0x8b, 0x2a, 0x33, 0x7f, 0x03, 0x62, 0x2c, 0x24, 0xff, 0x38, 0x1d, 0x4c, 0x54, 0x6f, @@ -370,7 +370,7 @@ fn notes() { 0xa2, 0x17, 0x8e, 0x03, ], default_d: [ - 0xeb, 0x51, 0x98, 0x82, 0xad, 0x1e, 0x5c, 0xc6, 0x54, 0xcd, 0x59 + 0xeb, 0x51, 0x98, 0x82, 0xad, 0x1e, 0x5c, 0xc6, 0x54, 0xcd, 0x59, ], default_pk_d: [ 0x6b, 0x27, 0xda, 0xcc, 0xb5, 0xa8, 0x20, 0x7f, 0x53, 0x2d, 0x10, 0xca, 0x23, 0x8f, @@ -432,7 +432,7 @@ fn notes() { 0x4f, 0x74, 0xc2, 0x05, ], default_d: [ - 0xbe, 0xbb, 0x0f, 0xb4, 0x6b, 0x8a, 0xaf, 0xf8, 0x90, 0x40, 0xf6 + 0xbe, 0xbb, 0x0f, 0xb4, 0x6b, 0x8a, 0xaf, 0xf8, 0x90, 0x40, 0xf6, ], default_pk_d: [ 0xd1, 0x1d, 0xa0, 0x1f, 0x0b, 0x43, 0xbd, 0xd5, 0x28, 0x8d, 0x32, 0x38, 0x5b, 0x87, @@ -494,7 +494,7 @@ fn notes() { 0xb0, 0x5f, 0x84, 0x02, ], default_d: [ - 0xad, 0x6e, 0x2e, 0x18, 0x5a, 0x31, 0x00, 0xe3, 0xa6, 0xa8, 0xb3 + 0xad, 0x6e, 0x2e, 0x18, 0x5a, 0x31, 0x00, 0xe3, 0xa6, 0xa8, 0xb3, ], default_pk_d: [ 0x32, 0xcb, 0x28, 0x06, 0xb8, 0x82, 0xf1, 0x36, 0x8b, 0x0d, 0x4a, 0x89, 0x8f, 0x72, @@ -556,7 +556,7 @@ fn notes() { 0xf1, 0x60, 0xe0, 0x01, ], default_d: [ - 0x21, 0xc9, 0x0e, 0x1c, 0x65, 0x8b, 0x3e, 0xfe, 0x86, 0xaf, 0x58 + 0x21, 0xc9, 0x0e, 0x1c, 0x65, 0x8b, 0x3e, 0xfe, 0x86, 0xaf, 0x58, ], default_pk_d: [ 0x9e, 0x64, 0x17, 0x4b, 0x4a, 0xb9, 0x81, 0x40, 0x5c, 0x32, 0x3b, 0x5e, 0x12, 0x47, @@ -618,7 +618,7 @@ fn notes() { 0xff, 0x89, 0xed, 0x00, ], default_d: [ - 0x23, 0x3c, 0x4a, 0xb8, 0x86, 0xa5, 0x5e, 0x3b, 0xa3, 0x74, 0xc0 + 0x23, 0x3c, 0x4a, 0xb8, 0x86, 0xa5, 0x5e, 0x3b, 0xa3, 0x74, 0xc0, ], default_pk_d: [ 0xb6, 0x8e, 0x9e, 0xe0, 0xc0, 0x67, 0x8d, 0x7b, 0x30, 0x36, 0x93, 0x1c, 0x83, 0x1a, diff --git a/src/tests/signatures.rs b/src/tests/signatures.rs index d3e00128f..ae4ba3a56 100644 --- a/src/tests/signatures.rs +++ b/src/tests/signatures.rs @@ -1,6 +1,7 @@ -use pairing::{PrimeField, PrimeFieldRepr, bls12_381::Bls12}; -use sapling_crypto::{jubjub::{FixedGenerators, JubjubEngine}, - redjubjub::{PrivateKey, PublicKey, Signature}}; +use pairing::{bls12_381::Bls12, PrimeField, PrimeFieldRepr}; +use sapling_crypto::{ + jubjub::{FixedGenerators, JubjubEngine}, redjubjub::{PrivateKey, PublicKey, Signature}, +}; use super::JUBJUB;