Move sapling-specific primitives into the sapling module.
This commit is contained in:
parent
abbf5dfd83
commit
4086df772c
|
@ -1,6 +1,6 @@
|
|||
//! Structs for handling supported address types.
|
||||
|
||||
use zcash_primitives::{consensus, legacy::TransparentAddress, primitives::PaymentAddress};
|
||||
use zcash_primitives::{consensus, legacy::TransparentAddress, sapling::PaymentAddress};
|
||||
|
||||
use crate::encoding::{
|
||||
decode_payment_address, decode_transparent_address, encode_payment_address,
|
||||
|
|
|
@ -9,8 +9,7 @@ use zcash_primitives::{
|
|||
consensus::BlockHeight,
|
||||
memo::{Memo, MemoBytes},
|
||||
merkle_tree::{CommitmentTree, IncrementalWitness},
|
||||
primitives::{Nullifier, PaymentAddress},
|
||||
sapling::Node,
|
||||
sapling::{Node, Nullifier, PaymentAddress},
|
||||
transaction::{components::Amount, Transaction, TxId},
|
||||
zip32::ExtendedFullViewingKey,
|
||||
};
|
||||
|
@ -277,8 +276,7 @@ pub mod testing {
|
|||
consensus::BlockHeight,
|
||||
memo::Memo,
|
||||
merkle_tree::{CommitmentTree, IncrementalWitness},
|
||||
primitives::{Nullifier, PaymentAddress},
|
||||
sapling::Node,
|
||||
sapling::{Node, Nullifier, PaymentAddress},
|
||||
transaction::{components::Amount, TxId},
|
||||
zip32::ExtendedFullViewingKey,
|
||||
};
|
||||
|
|
|
@ -95,7 +95,7 @@ use zcash_primitives::{
|
|||
block::BlockHash,
|
||||
consensus::{self, BlockHeight, NetworkUpgrade},
|
||||
merkle_tree::CommitmentTree,
|
||||
primitives::Nullifier,
|
||||
sapling::Nullifier,
|
||||
zip32::ExtendedFullViewingKey,
|
||||
};
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use zcash_primitives::{
|
|||
consensus::{self, BlockHeight},
|
||||
memo::MemoBytes,
|
||||
note_encryption::{try_sapling_note_decryption, try_sapling_output_recovery},
|
||||
primitives::{Note, PaymentAddress},
|
||||
sapling::{Note, PaymentAddress},
|
||||
transaction::Transaction,
|
||||
zip32::ExtendedFullViewingKey,
|
||||
};
|
||||
|
|
|
@ -11,7 +11,7 @@ use std::convert::TryInto;
|
|||
use std::io::{self, Write};
|
||||
use zcash_primitives::{
|
||||
legacy::TransparentAddress,
|
||||
primitives::PaymentAddress,
|
||||
sapling::PaymentAddress,
|
||||
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey},
|
||||
};
|
||||
|
||||
|
@ -114,7 +114,7 @@ pub fn decode_extended_full_viewing_key(
|
|||
/// };
|
||||
/// use zcash_primitives::{
|
||||
/// constants::testnet::HRP_SAPLING_PAYMENT_ADDRESS,
|
||||
/// primitives::{Diversifier, PaymentAddress},
|
||||
/// sapling::{Diversifier, PaymentAddress},
|
||||
/// };
|
||||
///
|
||||
/// let rng = &mut XorShiftRng::from_seed([
|
||||
|
@ -302,7 +302,7 @@ mod tests {
|
|||
use rand_xorshift::XorShiftRng;
|
||||
use zcash_primitives::{
|
||||
constants,
|
||||
primitives::{Diversifier, PaymentAddress},
|
||||
sapling::{Diversifier, PaymentAddress},
|
||||
zip32::ExtendedSpendingKey,
|
||||
};
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::convert::TryInto;
|
|||
use zcash_primitives::{
|
||||
block::{BlockHash, BlockHeader},
|
||||
consensus::BlockHeight,
|
||||
primitives::Nullifier,
|
||||
sapling::Nullifier,
|
||||
};
|
||||
|
||||
pub mod compact_formats;
|
||||
|
|
|
@ -6,8 +6,7 @@ use subtle::{Choice, ConditionallySelectable};
|
|||
use zcash_primitives::{
|
||||
keys::OutgoingViewingKey,
|
||||
merkle_tree::IncrementalWitness,
|
||||
primitives::{Diversifier, Note, Nullifier, PaymentAddress, Rseed},
|
||||
sapling::Node,
|
||||
sapling::{Diversifier, Node, Note, Nullifier, PaymentAddress, Rseed},
|
||||
transaction::{components::Amount, TxId},
|
||||
};
|
||||
|
||||
|
|
|
@ -7,8 +7,7 @@ use zcash_primitives::{
|
|||
consensus::{self, BlockHeight},
|
||||
merkle_tree::{CommitmentTree, IncrementalWitness},
|
||||
note_encryption::try_sapling_compact_note_decryption,
|
||||
primitives::{Note, Nullifier, PaymentAddress, SaplingIvk},
|
||||
sapling::Node,
|
||||
sapling::{Node, Note, Nullifier, PaymentAddress, SaplingIvk},
|
||||
transaction::TxId,
|
||||
zip32::ExtendedFullViewingKey,
|
||||
};
|
||||
|
@ -307,8 +306,7 @@ mod tests {
|
|||
memo::MemoBytes,
|
||||
merkle_tree::CommitmentTree,
|
||||
note_encryption::SaplingNoteEncryption,
|
||||
primitives::{Note, Nullifier, SaplingIvk},
|
||||
sapling::util::generate_random_rseed,
|
||||
sapling::{util::generate_random_rseed, Note, Nullifier, SaplingIvk},
|
||||
transaction::components::Amount,
|
||||
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey},
|
||||
};
|
||||
|
|
|
@ -43,8 +43,7 @@ use zcash_primitives::{
|
|||
consensus::{self, BlockHeight},
|
||||
memo::Memo,
|
||||
merkle_tree::{CommitmentTree, IncrementalWitness},
|
||||
primitives::{Nullifier, PaymentAddress},
|
||||
sapling::Node,
|
||||
sapling::{Node, Nullifier, PaymentAddress},
|
||||
transaction::{components::Amount, TxId},
|
||||
zip32::ExtendedFullViewingKey,
|
||||
};
|
||||
|
@ -565,8 +564,7 @@ mod tests {
|
|||
consensus::{BlockHeight, Network, NetworkUpgrade, Parameters},
|
||||
memo::MemoBytes,
|
||||
note_encryption::SaplingNoteEncryption,
|
||||
primitives::{Note, Nullifier, PaymentAddress},
|
||||
sapling::util::generate_random_rseed,
|
||||
sapling::{util::generate_random_rseed, Note, Nullifier, PaymentAddress},
|
||||
transaction::components::Amount,
|
||||
zip32::ExtendedFullViewingKey,
|
||||
};
|
||||
|
|
|
@ -17,8 +17,7 @@ use zcash_primitives::{
|
|||
consensus::{self, BlockHeight, NetworkUpgrade},
|
||||
memo::{Memo, MemoBytes},
|
||||
merkle_tree::{CommitmentTree, IncrementalWitness},
|
||||
primitives::{Note, Nullifier, PaymentAddress},
|
||||
sapling::Node,
|
||||
sapling::{Node, Note, Nullifier, PaymentAddress},
|
||||
transaction::{components::Amount, Transaction, TxId},
|
||||
zip32::ExtendedFullViewingKey,
|
||||
};
|
||||
|
|
|
@ -8,7 +8,7 @@ use ff::PrimeField;
|
|||
use zcash_primitives::{
|
||||
consensus::BlockHeight,
|
||||
merkle_tree::IncrementalWitness,
|
||||
primitives::{Diversifier, Rseed},
|
||||
sapling::{Diversifier, Rseed},
|
||||
transaction::components::Amount,
|
||||
};
|
||||
|
||||
|
|
|
@ -471,8 +471,8 @@ mod tests {
|
|||
extensions::transparent::{self as tze, Extension, FromPayload, ToPayload},
|
||||
legacy::TransparentAddress,
|
||||
merkle_tree::{CommitmentTree, IncrementalWitness},
|
||||
primitives::Rseed,
|
||||
sapling::Node,
|
||||
sapling::Rseed,
|
||||
transaction::{
|
||||
builder::Builder,
|
||||
components::{
|
||||
|
|
|
@ -5,8 +5,9 @@ use zcash_primitives::{
|
|||
consensus::{NetworkUpgrade::Canopy, Parameters, TEST_NETWORK},
|
||||
memo::MemoBytes,
|
||||
note_encryption::{try_sapling_note_decryption, SaplingNoteEncryption},
|
||||
primitives::{Diversifier, PaymentAddress, SaplingIvk, ValueCommitment},
|
||||
sapling::util::generate_random_rseed,
|
||||
sapling::{
|
||||
util::generate_random_rseed, Diversifier, PaymentAddress, SaplingIvk, ValueCommitment,
|
||||
},
|
||||
transaction::components::{OutputDescription, GROTH_PROOF_SIZE},
|
||||
};
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
use crate::{
|
||||
constants::{PROOF_GENERATION_KEY_GENERATOR, SPENDING_KEY_GENERATOR},
|
||||
primitives::{ProofGenerationKey, ViewingKey},
|
||||
sapling::{ProofGenerationKey, ViewingKey},
|
||||
};
|
||||
use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams};
|
||||
use ff::PrimeField;
|
||||
|
@ -186,7 +186,7 @@ pub mod testing {
|
|||
use proptest::prelude::{any, prop_compose};
|
||||
|
||||
use crate::{
|
||||
primitives::PaymentAddress,
|
||||
sapling::PaymentAddress,
|
||||
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey},
|
||||
};
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ pub mod legacy;
|
|||
pub mod memo;
|
||||
pub mod merkle_tree;
|
||||
pub mod note_encryption;
|
||||
pub mod primitives;
|
||||
pub mod sapling;
|
||||
pub mod serialize;
|
||||
pub mod transaction;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use crate::{
|
||||
consensus::{self, BlockHeight, NetworkUpgrade::Canopy, ZIP212_GRACE_PERIOD},
|
||||
memo::MemoBytes,
|
||||
primitives::{Diversifier, Note, PaymentAddress, Rseed, SaplingIvk},
|
||||
sapling::{Diversifier, Note, PaymentAddress, Rseed, SaplingIvk},
|
||||
};
|
||||
use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
@ -115,7 +115,7 @@ pub fn prf_ock(
|
|||
/// keys::{OutgoingViewingKey, prf_expand},
|
||||
/// memo::MemoBytes,
|
||||
/// note_encryption::SaplingNoteEncryption,
|
||||
/// primitives::{Diversifier, PaymentAddress, Rseed, ValueCommitment},
|
||||
/// sapling::{Diversifier, PaymentAddress, Rseed, ValueCommitment},
|
||||
/// };
|
||||
///
|
||||
/// let mut rng = OsRng;
|
||||
|
@ -582,8 +582,8 @@ mod tests {
|
|||
},
|
||||
keys::OutgoingViewingKey,
|
||||
memo::MemoBytes,
|
||||
primitives::{Diversifier, PaymentAddress, Rseed, SaplingIvk, ValueCommitment},
|
||||
sapling::util::generate_random_rseed,
|
||||
sapling::{Diversifier, PaymentAddress, Rseed, SaplingIvk, ValueCommitment},
|
||||
};
|
||||
|
||||
fn random_enc_ciphertext<R: RngCore + CryptoRng>(
|
||||
|
|
|
@ -1,357 +0,0 @@
|
|||
//! Structs for core Zcash primitives.
|
||||
|
||||
use ff::PrimeField;
|
||||
use group::{Curve, Group, GroupEncoding};
|
||||
use std::array::TryFromSliceError;
|
||||
use std::convert::TryInto;
|
||||
use subtle::{Choice, ConstantTimeEq};
|
||||
|
||||
use crate::constants;
|
||||
|
||||
use crate::sapling::group_hash::group_hash;
|
||||
|
||||
use crate::sapling::pedersen_hash::{pedersen_hash, Personalization};
|
||||
|
||||
use byteorder::{LittleEndian, WriteBytesExt};
|
||||
|
||||
use crate::keys::prf_expand;
|
||||
|
||||
use blake2s_simd::Params as Blake2sParams;
|
||||
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ValueCommitment {
|
||||
pub value: u64,
|
||||
pub randomness: jubjub::Fr,
|
||||
}
|
||||
|
||||
impl ValueCommitment {
|
||||
pub fn commitment(&self) -> jubjub::SubgroupPoint {
|
||||
(constants::VALUE_COMMITMENT_VALUE_GENERATOR * jubjub::Fr::from(self.value))
|
||||
+ (constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR * self.randomness)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ProofGenerationKey {
|
||||
pub ak: jubjub::SubgroupPoint,
|
||||
pub nsk: jubjub::Fr,
|
||||
}
|
||||
|
||||
impl ProofGenerationKey {
|
||||
pub fn to_viewing_key(&self) -> ViewingKey {
|
||||
ViewingKey {
|
||||
ak: self.ak,
|
||||
nk: constants::PROOF_GENERATION_KEY_GENERATOR * self.nsk,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ViewingKey {
|
||||
pub ak: jubjub::SubgroupPoint,
|
||||
pub nk: jubjub::SubgroupPoint,
|
||||
}
|
||||
|
||||
impl ViewingKey {
|
||||
pub fn rk(&self, ar: jubjub::Fr) -> jubjub::SubgroupPoint {
|
||||
self.ak + constants::SPENDING_KEY_GENERATOR * ar
|
||||
}
|
||||
|
||||
pub fn ivk(&self) -> SaplingIvk {
|
||||
let mut h = [0; 32];
|
||||
h.copy_from_slice(
|
||||
Blake2sParams::new()
|
||||
.hash_length(32)
|
||||
.personal(constants::CRH_IVK_PERSONALIZATION)
|
||||
.to_state()
|
||||
.update(&self.ak.to_bytes())
|
||||
.update(&self.nk.to_bytes())
|
||||
.finalize()
|
||||
.as_bytes(),
|
||||
);
|
||||
|
||||
// Drop the most significant five bits, so it can be interpreted as a scalar.
|
||||
h[31] &= 0b0000_0111;
|
||||
|
||||
SaplingIvk(jubjub::Fr::from_repr(h).expect("should be a valid scalar"))
|
||||
}
|
||||
|
||||
pub fn to_payment_address(&self, diversifier: Diversifier) -> Option<PaymentAddress> {
|
||||
self.ivk().to_payment_address(diversifier)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SaplingIvk(pub jubjub::Fr);
|
||||
|
||||
impl SaplingIvk {
|
||||
pub fn to_payment_address(&self, diversifier: Diversifier) -> Option<PaymentAddress> {
|
||||
diversifier.g_d().and_then(|g_d| {
|
||||
let pk_d = g_d * self.0;
|
||||
|
||||
PaymentAddress::from_parts(diversifier, pk_d)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn to_repr(&self) -> [u8; 32] {
|
||||
self.0.to_repr()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub struct Diversifier(pub [u8; 11]);
|
||||
|
||||
impl Diversifier {
|
||||
pub fn g_d(&self) -> Option<jubjub::SubgroupPoint> {
|
||||
group_hash(&self.0, constants::KEY_DIVERSIFICATION_PERSONALIZATION)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Sapling payment address.
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// `pk_d` is guaranteed to be prime-order (i.e. in the prime-order subgroup of Jubjub,
|
||||
/// and not the identity).
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PaymentAddress {
|
||||
pk_d: jubjub::SubgroupPoint,
|
||||
diversifier: Diversifier,
|
||||
}
|
||||
|
||||
impl PartialEq for PaymentAddress {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.pk_d == other.pk_d && self.diversifier == other.diversifier
|
||||
}
|
||||
}
|
||||
|
||||
impl PaymentAddress {
|
||||
/// Constructs a PaymentAddress from a diversifier and a Jubjub point.
|
||||
///
|
||||
/// Returns None if `pk_d` is the identity.
|
||||
pub fn from_parts(diversifier: Diversifier, pk_d: jubjub::SubgroupPoint) -> Option<Self> {
|
||||
if pk_d.is_identity().into() {
|
||||
None
|
||||
} else {
|
||||
Some(PaymentAddress { pk_d, diversifier })
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs a PaymentAddress from a diversifier and a Jubjub point.
|
||||
///
|
||||
/// Only for test code, as this explicitly bypasses the invariant.
|
||||
#[cfg(test)]
|
||||
pub(crate) fn from_parts_unchecked(
|
||||
diversifier: Diversifier,
|
||||
pk_d: jubjub::SubgroupPoint,
|
||||
) -> Self {
|
||||
PaymentAddress { pk_d, diversifier }
|
||||
}
|
||||
|
||||
/// Parses a PaymentAddress from bytes.
|
||||
pub fn from_bytes(bytes: &[u8; 43]) -> Option<Self> {
|
||||
let diversifier = {
|
||||
let mut tmp = [0; 11];
|
||||
tmp.copy_from_slice(&bytes[0..11]);
|
||||
Diversifier(tmp)
|
||||
};
|
||||
// Check that the diversifier is valid
|
||||
diversifier.g_d()?;
|
||||
|
||||
let pk_d = jubjub::SubgroupPoint::from_bytes(bytes[11..43].try_into().unwrap());
|
||||
if pk_d.is_some().into() {
|
||||
PaymentAddress::from_parts(diversifier, pk_d.unwrap())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the byte encoding of this `PaymentAddress`.
|
||||
pub fn to_bytes(&self) -> [u8; 43] {
|
||||
let mut bytes = [0; 43];
|
||||
bytes[0..11].copy_from_slice(&self.diversifier.0);
|
||||
bytes[11..].copy_from_slice(&self.pk_d.to_bytes());
|
||||
bytes
|
||||
}
|
||||
|
||||
/// Returns the [`Diversifier`] for this `PaymentAddress`.
|
||||
pub fn diversifier(&self) -> &Diversifier {
|
||||
&self.diversifier
|
||||
}
|
||||
|
||||
/// Returns `pk_d` for this `PaymentAddress`.
|
||||
pub fn pk_d(&self) -> &jubjub::SubgroupPoint {
|
||||
&self.pk_d
|
||||
}
|
||||
|
||||
pub fn g_d(&self) -> Option<jubjub::SubgroupPoint> {
|
||||
self.diversifier.g_d()
|
||||
}
|
||||
|
||||
pub fn create_note(&self, value: u64, randomness: Rseed) -> Option<Note> {
|
||||
self.g_d().map(|g_d| Note {
|
||||
value,
|
||||
rseed: randomness,
|
||||
g_d,
|
||||
pk_d: self.pk_d,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Enum for note randomness before and after [ZIP 212](https://zips.z.cash/zip-0212).
|
||||
///
|
||||
/// Before ZIP 212, the note commitment trapdoor `rcm` must be a scalar value.
|
||||
/// After ZIP 212, the note randomness `rseed` is a 32-byte sequence, used to derive
|
||||
/// both the note commitment trapdoor `rcm` and the ephemeral private key `esk`.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Rseed {
|
||||
BeforeZip212(jubjub::Fr),
|
||||
AfterZip212([u8; 32]),
|
||||
}
|
||||
|
||||
/// Typesafe wrapper for nullifier values.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Nullifier(pub [u8; 32]);
|
||||
|
||||
impl Nullifier {
|
||||
pub fn from_slice(bytes: &[u8]) -> Result<Nullifier, TryFromSliceError> {
|
||||
bytes.try_into().map(Nullifier)
|
||||
}
|
||||
|
||||
pub fn to_vec(&self) -> Vec<u8> {
|
||||
self.0.to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl ConstantTimeEq for Nullifier {
|
||||
fn ct_eq(&self, other: &Self) -> Choice {
|
||||
self.0.ct_eq(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Note {
|
||||
/// The value of the note
|
||||
pub value: u64,
|
||||
/// The diversified base of the address, GH(d)
|
||||
pub g_d: jubjub::SubgroupPoint,
|
||||
/// The public key of the address, g_d^ivk
|
||||
pub pk_d: jubjub::SubgroupPoint,
|
||||
/// rseed
|
||||
pub rseed: Rseed,
|
||||
}
|
||||
|
||||
impl PartialEq for Note {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.value == other.value
|
||||
&& self.g_d == other.g_d
|
||||
&& self.pk_d == other.pk_d
|
||||
&& self.rcm() == other.rcm()
|
||||
}
|
||||
}
|
||||
|
||||
impl Note {
|
||||
pub fn uncommitted() -> bls12_381::Scalar {
|
||||
// The smallest u-coordinate that is not on the curve
|
||||
// is one.
|
||||
bls12_381::Scalar::one()
|
||||
}
|
||||
|
||||
/// Computes the note commitment, returning the full point.
|
||||
fn cm_full_point(&self) -> jubjub::SubgroupPoint {
|
||||
// Calculate the note contents, as bytes
|
||||
let mut note_contents = vec![];
|
||||
|
||||
// Writing the value in little endian
|
||||
(&mut note_contents)
|
||||
.write_u64::<LittleEndian>(self.value)
|
||||
.unwrap();
|
||||
|
||||
// Write g_d
|
||||
note_contents.extend_from_slice(&self.g_d.to_bytes());
|
||||
|
||||
// Write pk_d
|
||||
note_contents.extend_from_slice(&self.pk_d.to_bytes());
|
||||
|
||||
assert_eq!(note_contents.len(), 32 + 32 + 8);
|
||||
|
||||
// Compute the Pedersen hash of the note contents
|
||||
let hash_of_contents = pedersen_hash(
|
||||
Personalization::NoteCommitment,
|
||||
note_contents
|
||||
.into_iter()
|
||||
.flat_map(|byte| (0..8).map(move |i| ((byte >> i) & 1) == 1)),
|
||||
);
|
||||
|
||||
// Compute final commitment
|
||||
(constants::NOTE_COMMITMENT_RANDOMNESS_GENERATOR * self.rcm()) + hash_of_contents
|
||||
}
|
||||
|
||||
/// Computes the nullifier given the viewing key and
|
||||
/// note position
|
||||
pub fn nf(&self, viewing_key: &ViewingKey, position: u64) -> Nullifier {
|
||||
// Compute rho = cm + position.G
|
||||
let rho = self.cm_full_point()
|
||||
+ (constants::NULLIFIER_POSITION_GENERATOR * jubjub::Fr::from(position));
|
||||
|
||||
// Compute nf = BLAKE2s(nk | rho)
|
||||
Nullifier::from_slice(
|
||||
Blake2sParams::new()
|
||||
.hash_length(32)
|
||||
.personal(constants::PRF_NF_PERSONALIZATION)
|
||||
.to_state()
|
||||
.update(&viewing_key.nk.to_bytes())
|
||||
.update(&rho.to_bytes())
|
||||
.finalize()
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Computes the note commitment
|
||||
pub fn cmu(&self) -> bls12_381::Scalar {
|
||||
// The commitment is in the prime order subgroup, so mapping the
|
||||
// commitment to the u-coordinate is an injective encoding.
|
||||
jubjub::ExtendedPoint::from(self.cm_full_point())
|
||||
.to_affine()
|
||||
.get_u()
|
||||
}
|
||||
|
||||
pub fn rcm(&self) -> jubjub::Fr {
|
||||
match self.rseed {
|
||||
Rseed::BeforeZip212(rcm) => rcm,
|
||||
Rseed::AfterZip212(rseed) => {
|
||||
jubjub::Fr::from_bytes_wide(prf_expand(&rseed, &[0x04]).as_array())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_or_derive_esk<R: RngCore + CryptoRng>(&self, rng: &mut R) -> jubjub::Fr {
|
||||
self.generate_or_derive_esk_internal(rng)
|
||||
}
|
||||
|
||||
pub(crate) fn generate_or_derive_esk_internal<R: RngCore>(&self, rng: &mut R) -> jubjub::Fr {
|
||||
match self.derive_esk() {
|
||||
None => {
|
||||
// create random 64 byte buffer
|
||||
let mut buffer = [0u8; 64];
|
||||
rng.fill_bytes(&mut buffer);
|
||||
|
||||
// reduce to uniform value
|
||||
jubjub::Fr::from_bytes_wide(&buffer)
|
||||
}
|
||||
Some(esk) => esk,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the derived `esk` if this note was created after ZIP 212 activated.
|
||||
pub fn derive_esk(&self) -> Option<jubjub::Fr> {
|
||||
match self.rseed {
|
||||
Rseed::BeforeZip212(_) => None,
|
||||
Rseed::AfterZip212(rseed) => Some(jubjub::Fr::from_bytes_wide(
|
||||
prf_expand(&rseed, &[0x05]).as_array(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,15 +7,25 @@ pub mod redjubjub;
|
|||
pub mod util;
|
||||
|
||||
use bitvec::{order::Lsb0, view::AsBits};
|
||||
use blake2s_simd::Params as Blake2sParams;
|
||||
use byteorder::{LittleEndian, WriteBytesExt};
|
||||
use ff::PrimeField;
|
||||
use group::{Curve, GroupEncoding};
|
||||
use group::{Curve, Group, GroupEncoding};
|
||||
use lazy_static::lazy_static;
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
use std::array::TryFromSliceError;
|
||||
use std::convert::TryInto;
|
||||
use std::io::{self, Read, Write};
|
||||
use subtle::{Choice, ConstantTimeEq};
|
||||
|
||||
use crate::{constants::SPENDING_KEY_GENERATOR, merkle_tree::Hashable, primitives::Note};
|
||||
use crate::{
|
||||
constants::{self, SPENDING_KEY_GENERATOR},
|
||||
keys::prf_expand,
|
||||
merkle_tree::Hashable,
|
||||
};
|
||||
|
||||
use self::{
|
||||
group_hash::group_hash,
|
||||
pedersen_hash::{pedersen_hash, Personalization},
|
||||
redjubjub::{PrivateKey, PublicKey, Signature},
|
||||
};
|
||||
|
@ -143,3 +153,340 @@ pub(crate) fn spend_sig_internal<R: RngCore>(
|
|||
// Do the signing
|
||||
rsk.sign(&data_to_be_signed, rng, SPENDING_KEY_GENERATOR)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ValueCommitment {
|
||||
pub value: u64,
|
||||
pub randomness: jubjub::Fr,
|
||||
}
|
||||
|
||||
impl ValueCommitment {
|
||||
pub fn commitment(&self) -> jubjub::SubgroupPoint {
|
||||
(constants::VALUE_COMMITMENT_VALUE_GENERATOR * jubjub::Fr::from(self.value))
|
||||
+ (constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR * self.randomness)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ProofGenerationKey {
|
||||
pub ak: jubjub::SubgroupPoint,
|
||||
pub nsk: jubjub::Fr,
|
||||
}
|
||||
|
||||
impl ProofGenerationKey {
|
||||
pub fn to_viewing_key(&self) -> ViewingKey {
|
||||
ViewingKey {
|
||||
ak: self.ak,
|
||||
nk: constants::PROOF_GENERATION_KEY_GENERATOR * self.nsk,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ViewingKey {
|
||||
pub ak: jubjub::SubgroupPoint,
|
||||
pub nk: jubjub::SubgroupPoint,
|
||||
}
|
||||
|
||||
impl ViewingKey {
|
||||
pub fn rk(&self, ar: jubjub::Fr) -> jubjub::SubgroupPoint {
|
||||
self.ak + constants::SPENDING_KEY_GENERATOR * ar
|
||||
}
|
||||
|
||||
pub fn ivk(&self) -> SaplingIvk {
|
||||
let mut h = [0; 32];
|
||||
h.copy_from_slice(
|
||||
Blake2sParams::new()
|
||||
.hash_length(32)
|
||||
.personal(constants::CRH_IVK_PERSONALIZATION)
|
||||
.to_state()
|
||||
.update(&self.ak.to_bytes())
|
||||
.update(&self.nk.to_bytes())
|
||||
.finalize()
|
||||
.as_bytes(),
|
||||
);
|
||||
|
||||
// Drop the most significant five bits, so it can be interpreted as a scalar.
|
||||
h[31] &= 0b0000_0111;
|
||||
|
||||
SaplingIvk(jubjub::Fr::from_repr(h).expect("should be a valid scalar"))
|
||||
}
|
||||
|
||||
pub fn to_payment_address(&self, diversifier: Diversifier) -> Option<PaymentAddress> {
|
||||
self.ivk().to_payment_address(diversifier)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SaplingIvk(pub jubjub::Fr);
|
||||
|
||||
impl SaplingIvk {
|
||||
pub fn to_payment_address(&self, diversifier: Diversifier) -> Option<PaymentAddress> {
|
||||
diversifier.g_d().and_then(|g_d| {
|
||||
let pk_d = g_d * self.0;
|
||||
|
||||
PaymentAddress::from_parts(diversifier, pk_d)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn to_repr(&self) -> [u8; 32] {
|
||||
self.0.to_repr()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub struct Diversifier(pub [u8; 11]);
|
||||
|
||||
impl Diversifier {
|
||||
pub fn g_d(&self) -> Option<jubjub::SubgroupPoint> {
|
||||
group_hash(&self.0, constants::KEY_DIVERSIFICATION_PERSONALIZATION)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Sapling payment address.
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// `pk_d` is guaranteed to be prime-order (i.e. in the prime-order subgroup of Jubjub,
|
||||
/// and not the identity).
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PaymentAddress {
|
||||
pk_d: jubjub::SubgroupPoint,
|
||||
diversifier: Diversifier,
|
||||
}
|
||||
|
||||
impl PartialEq for PaymentAddress {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.pk_d == other.pk_d && self.diversifier == other.diversifier
|
||||
}
|
||||
}
|
||||
|
||||
impl PaymentAddress {
|
||||
/// Constructs a PaymentAddress from a diversifier and a Jubjub point.
|
||||
///
|
||||
/// Returns None if `pk_d` is the identity.
|
||||
pub fn from_parts(diversifier: Diversifier, pk_d: jubjub::SubgroupPoint) -> Option<Self> {
|
||||
if pk_d.is_identity().into() {
|
||||
None
|
||||
} else {
|
||||
Some(PaymentAddress { pk_d, diversifier })
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs a PaymentAddress from a diversifier and a Jubjub point.
|
||||
///
|
||||
/// Only for test code, as this explicitly bypasses the invariant.
|
||||
#[cfg(test)]
|
||||
pub(crate) fn from_parts_unchecked(
|
||||
diversifier: Diversifier,
|
||||
pk_d: jubjub::SubgroupPoint,
|
||||
) -> Self {
|
||||
PaymentAddress { pk_d, diversifier }
|
||||
}
|
||||
|
||||
/// Parses a PaymentAddress from bytes.
|
||||
pub fn from_bytes(bytes: &[u8; 43]) -> Option<Self> {
|
||||
let diversifier = {
|
||||
let mut tmp = [0; 11];
|
||||
tmp.copy_from_slice(&bytes[0..11]);
|
||||
Diversifier(tmp)
|
||||
};
|
||||
// Check that the diversifier is valid
|
||||
diversifier.g_d()?;
|
||||
|
||||
let pk_d = jubjub::SubgroupPoint::from_bytes(bytes[11..43].try_into().unwrap());
|
||||
if pk_d.is_some().into() {
|
||||
PaymentAddress::from_parts(diversifier, pk_d.unwrap())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the byte encoding of this `PaymentAddress`.
|
||||
pub fn to_bytes(&self) -> [u8; 43] {
|
||||
let mut bytes = [0; 43];
|
||||
bytes[0..11].copy_from_slice(&self.diversifier.0);
|
||||
bytes[11..].copy_from_slice(&self.pk_d.to_bytes());
|
||||
bytes
|
||||
}
|
||||
|
||||
/// Returns the [`Diversifier`] for this `PaymentAddress`.
|
||||
pub fn diversifier(&self) -> &Diversifier {
|
||||
&self.diversifier
|
||||
}
|
||||
|
||||
/// Returns `pk_d` for this `PaymentAddress`.
|
||||
pub fn pk_d(&self) -> &jubjub::SubgroupPoint {
|
||||
&self.pk_d
|
||||
}
|
||||
|
||||
pub fn g_d(&self) -> Option<jubjub::SubgroupPoint> {
|
||||
self.diversifier.g_d()
|
||||
}
|
||||
|
||||
pub fn create_note(&self, value: u64, randomness: Rseed) -> Option<Note> {
|
||||
self.g_d().map(|g_d| Note {
|
||||
value,
|
||||
rseed: randomness,
|
||||
g_d,
|
||||
pk_d: self.pk_d,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Enum for note randomness before and after [ZIP 212](https://zips.z.cash/zip-0212).
|
||||
///
|
||||
/// Before ZIP 212, the note commitment trapdoor `rcm` must be a scalar value.
|
||||
/// After ZIP 212, the note randomness `rseed` is a 32-byte sequence, used to derive
|
||||
/// both the note commitment trapdoor `rcm` and the ephemeral private key `esk`.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Rseed {
|
||||
BeforeZip212(jubjub::Fr),
|
||||
AfterZip212([u8; 32]),
|
||||
}
|
||||
|
||||
/// Typesafe wrapper for nullifier values.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Nullifier(pub [u8; 32]);
|
||||
|
||||
impl Nullifier {
|
||||
pub fn from_slice(bytes: &[u8]) -> Result<Nullifier, TryFromSliceError> {
|
||||
bytes.try_into().map(Nullifier)
|
||||
}
|
||||
|
||||
pub fn to_vec(&self) -> Vec<u8> {
|
||||
self.0.to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl ConstantTimeEq for Nullifier {
|
||||
fn ct_eq(&self, other: &Self) -> Choice {
|
||||
self.0.ct_eq(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Note {
|
||||
/// The value of the note
|
||||
pub value: u64,
|
||||
/// The diversified base of the address, GH(d)
|
||||
pub g_d: jubjub::SubgroupPoint,
|
||||
/// The public key of the address, g_d^ivk
|
||||
pub pk_d: jubjub::SubgroupPoint,
|
||||
/// rseed
|
||||
pub rseed: Rseed,
|
||||
}
|
||||
|
||||
impl PartialEq for Note {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.value == other.value
|
||||
&& self.g_d == other.g_d
|
||||
&& self.pk_d == other.pk_d
|
||||
&& self.rcm() == other.rcm()
|
||||
}
|
||||
}
|
||||
|
||||
impl Note {
|
||||
pub fn uncommitted() -> bls12_381::Scalar {
|
||||
// The smallest u-coordinate that is not on the curve
|
||||
// is one.
|
||||
bls12_381::Scalar::one()
|
||||
}
|
||||
|
||||
/// Computes the note commitment, returning the full point.
|
||||
fn cm_full_point(&self) -> jubjub::SubgroupPoint {
|
||||
// Calculate the note contents, as bytes
|
||||
let mut note_contents = vec![];
|
||||
|
||||
// Writing the value in little endian
|
||||
(&mut note_contents)
|
||||
.write_u64::<LittleEndian>(self.value)
|
||||
.unwrap();
|
||||
|
||||
// Write g_d
|
||||
note_contents.extend_from_slice(&self.g_d.to_bytes());
|
||||
|
||||
// Write pk_d
|
||||
note_contents.extend_from_slice(&self.pk_d.to_bytes());
|
||||
|
||||
assert_eq!(note_contents.len(), 32 + 32 + 8);
|
||||
|
||||
// Compute the Pedersen hash of the note contents
|
||||
let hash_of_contents = pedersen_hash(
|
||||
Personalization::NoteCommitment,
|
||||
note_contents
|
||||
.into_iter()
|
||||
.flat_map(|byte| (0..8).map(move |i| ((byte >> i) & 1) == 1)),
|
||||
);
|
||||
|
||||
// Compute final commitment
|
||||
(constants::NOTE_COMMITMENT_RANDOMNESS_GENERATOR * self.rcm()) + hash_of_contents
|
||||
}
|
||||
|
||||
/// Computes the nullifier given the viewing key and
|
||||
/// note position
|
||||
pub fn nf(&self, viewing_key: &ViewingKey, position: u64) -> Nullifier {
|
||||
// Compute rho = cm + position.G
|
||||
let rho = self.cm_full_point()
|
||||
+ (constants::NULLIFIER_POSITION_GENERATOR * jubjub::Fr::from(position));
|
||||
|
||||
// Compute nf = BLAKE2s(nk | rho)
|
||||
Nullifier::from_slice(
|
||||
Blake2sParams::new()
|
||||
.hash_length(32)
|
||||
.personal(constants::PRF_NF_PERSONALIZATION)
|
||||
.to_state()
|
||||
.update(&viewing_key.nk.to_bytes())
|
||||
.update(&rho.to_bytes())
|
||||
.finalize()
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Computes the note commitment
|
||||
pub fn cmu(&self) -> bls12_381::Scalar {
|
||||
// The commitment is in the prime order subgroup, so mapping the
|
||||
// commitment to the u-coordinate is an injective encoding.
|
||||
jubjub::ExtendedPoint::from(self.cm_full_point())
|
||||
.to_affine()
|
||||
.get_u()
|
||||
}
|
||||
|
||||
pub fn rcm(&self) -> jubjub::Fr {
|
||||
match self.rseed {
|
||||
Rseed::BeforeZip212(rcm) => rcm,
|
||||
Rseed::AfterZip212(rseed) => {
|
||||
jubjub::Fr::from_bytes_wide(prf_expand(&rseed, &[0x04]).as_array())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_or_derive_esk<R: RngCore + CryptoRng>(&self, rng: &mut R) -> jubjub::Fr {
|
||||
self.generate_or_derive_esk_internal(rng)
|
||||
}
|
||||
|
||||
pub(crate) fn generate_or_derive_esk_internal<R: RngCore>(&self, rng: &mut R) -> jubjub::Fr {
|
||||
match self.derive_esk() {
|
||||
None => {
|
||||
// create random 64 byte buffer
|
||||
let mut buffer = [0u8; 64];
|
||||
rng.fill_bytes(&mut buffer);
|
||||
|
||||
// reduce to uniform value
|
||||
jubjub::Fr::from_bytes_wide(&buffer)
|
||||
}
|
||||
Some(esk) => esk,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the derived `esk` if this note was created after ZIP 212 activated.
|
||||
pub fn derive_esk(&self) -> Option<jubjub::Fr> {
|
||||
match self.rseed {
|
||||
Rseed::BeforeZip212(_) => None,
|
||||
Rseed::AfterZip212(rseed) => Some(jubjub::Fr::from_bytes_wide(
|
||||
prf_expand(&rseed, &[0x05]).as_array(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
//! Abstractions over the proving system and parameters.
|
||||
|
||||
use crate::primitives::{Diversifier, PaymentAddress, ProofGenerationKey, Rseed};
|
||||
|
||||
use crate::{
|
||||
merkle_tree::MerklePath,
|
||||
sapling::{
|
||||
|
@ -11,6 +9,8 @@ use crate::{
|
|||
transaction::components::{Amount, GROTH_PROOF_SIZE},
|
||||
};
|
||||
|
||||
use super::{Diversifier, PaymentAddress, ProofGenerationKey, Rseed};
|
||||
|
||||
/// Interface for creating zero-knowledge proofs for shielded transactions.
|
||||
pub trait TxProver {
|
||||
/// Type for persisting any necessary context across multiple Sapling proofs.
|
||||
|
@ -69,14 +69,10 @@ pub mod mock {
|
|||
|
||||
use crate::{
|
||||
constants::SPENDING_KEY_GENERATOR,
|
||||
primitives::{Diversifier, PaymentAddress, ProofGenerationKey, Rseed, ValueCommitment},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
merkle_tree::MerklePath,
|
||||
sapling::{
|
||||
redjubjub::{PublicKey, Signature},
|
||||
Node,
|
||||
Diversifier, Node, PaymentAddress, ProofGenerationKey, Rseed, ValueCommitment,
|
||||
},
|
||||
transaction::components::{Amount, GROTH_PROOF_SIZE},
|
||||
};
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
use blake2b_simd::Params;
|
||||
|
||||
use crate::{
|
||||
consensus::{self, BlockHeight, NetworkUpgrade},
|
||||
primitives::Rseed,
|
||||
};
|
||||
|
||||
use ff::Field;
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
|
||||
use crate::consensus::{self, BlockHeight, NetworkUpgrade};
|
||||
|
||||
use super::Rseed;
|
||||
|
||||
pub fn hash_to_scalar(persona: &[u8], a: &[u8], b: &[u8]) -> jubjub::Fr {
|
||||
let mut hasher = Params::new().hash_length(64).personal(persona).to_state();
|
||||
hasher.update(a);
|
||||
|
|
|
@ -17,10 +17,9 @@ use crate::{
|
|||
memo::MemoBytes,
|
||||
merkle_tree::MerklePath,
|
||||
note_encryption::SaplingNoteEncryption,
|
||||
primitives::{Diversifier, Note, PaymentAddress},
|
||||
sapling::{
|
||||
prover::TxProver, redjubjub::PrivateKey, spend_sig_internal,
|
||||
util::generate_random_rseed_internal, Node,
|
||||
util::generate_random_rseed_internal, Diversifier, Node, Note, PaymentAddress,
|
||||
},
|
||||
transaction::{
|
||||
components::{
|
||||
|
@ -966,8 +965,7 @@ mod tests {
|
|||
consensus::{self, Parameters, H0, TEST_NETWORK},
|
||||
legacy::TransparentAddress,
|
||||
merkle_tree::{CommitmentTree, IncrementalWitness},
|
||||
primitives::Rseed,
|
||||
sapling::{prover::mock::MockTxProver, Node},
|
||||
sapling::{prover::mock::MockTxProver, Node, Rseed},
|
||||
transaction::components::{amount::Amount, amount::DEFAULT_FEE},
|
||||
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey},
|
||||
};
|
||||
|
|
|
@ -3,9 +3,9 @@ use group::GroupEncoding;
|
|||
|
||||
use std::io::{self, Read, Write};
|
||||
|
||||
use crate::{
|
||||
primitives::Nullifier,
|
||||
sapling::redjubjub::{PublicKey, Signature},
|
||||
use crate::sapling::{
|
||||
redjubjub::{PublicKey, Signature},
|
||||
Nullifier,
|
||||
};
|
||||
|
||||
use super::GROTH_PROOF_SIZE;
|
||||
|
|
|
@ -10,7 +10,7 @@ use std::ops::AddAssign;
|
|||
|
||||
use crate::{
|
||||
constants::{PROOF_GENERATION_KEY_GENERATOR, SPENDING_KEY_GENERATOR},
|
||||
primitives::{Diversifier, PaymentAddress, ViewingKey},
|
||||
sapling::{Diversifier, PaymentAddress, ViewingKey},
|
||||
};
|
||||
use std::io::{self, Read, Write};
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ use ff::Field;
|
|||
use group::Group;
|
||||
use rand_core::{RngCore, SeedableRng};
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use zcash_primitives::primitives::{Diversifier, ProofGenerationKey, ValueCommitment};
|
||||
use zcash_primitives::sapling::{Diversifier, ProofGenerationKey, ValueCommitment};
|
||||
use zcash_proofs::circuit::sapling::Spend;
|
||||
|
||||
const TREE_DEPTH: usize = 32;
|
||||
|
|
|
@ -7,7 +7,9 @@ use bellman::{Circuit, ConstraintSystem, SynthesisError};
|
|||
|
||||
use zcash_primitives::constants;
|
||||
|
||||
use zcash_primitives::primitives::{PaymentAddress, ProofGenerationKey, ValueCommitment};
|
||||
use zcash_primitives::sapling::{
|
||||
PaymentAddress, ProofGenerationKey, ValueCommitment, SAPLING_COMMITMENT_TREE_DEPTH,
|
||||
};
|
||||
|
||||
use super::ecc;
|
||||
use super::pedersen_hash;
|
||||
|
@ -22,7 +24,7 @@ use bellman::gadgets::multipack;
|
|||
use bellman::gadgets::num;
|
||||
use bellman::gadgets::Assignment;
|
||||
|
||||
pub const TREE_DEPTH: usize = zcash_primitives::sapling::SAPLING_COMMITMENT_TREE_DEPTH;
|
||||
pub const TREE_DEPTH: usize = SAPLING_COMMITMENT_TREE_DEPTH;
|
||||
|
||||
/// This is an instance of the `Spend` circuit.
|
||||
pub struct Spend {
|
||||
|
@ -516,10 +518,7 @@ fn test_input_circuit_with_bls12_381() {
|
|||
use group::Group;
|
||||
use rand_core::{RngCore, SeedableRng};
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use zcash_primitives::{
|
||||
primitives::{Diversifier, Note, ProofGenerationKey, Rseed},
|
||||
sapling::pedersen_hash,
|
||||
};
|
||||
use zcash_primitives::sapling::{pedersen_hash, Diversifier, Note, ProofGenerationKey, Rseed};
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x58, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
|
@ -659,10 +658,7 @@ fn test_input_circuit_with_bls12_381_external_test_vectors() {
|
|||
use group::Group;
|
||||
use rand_core::{RngCore, SeedableRng};
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use zcash_primitives::{
|
||||
primitives::{Diversifier, Note, ProofGenerationKey, Rseed},
|
||||
sapling::pedersen_hash,
|
||||
};
|
||||
use zcash_primitives::sapling::{pedersen_hash, Diversifier, Note, ProofGenerationKey, Rseed};
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
|
@ -836,7 +832,7 @@ fn test_output_circuit_with_bls12_381() {
|
|||
use group::Group;
|
||||
use rand_core::{RngCore, SeedableRng};
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use zcash_primitives::primitives::{Diversifier, ProofGenerationKey, Rseed};
|
||||
use zcash_primitives::sapling::{Diversifier, ProofGenerationKey, Rseed};
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x58, 0x62, 0xbe, 0x3d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
|
|
|
@ -5,11 +5,10 @@ use bls12_381::Bls12;
|
|||
use std::path::Path;
|
||||
use zcash_primitives::{
|
||||
merkle_tree::MerklePath,
|
||||
primitives::{Diversifier, PaymentAddress, ProofGenerationKey, Rseed},
|
||||
sapling::{
|
||||
prover::TxProver,
|
||||
redjubjub::{PublicKey, Signature},
|
||||
Node,
|
||||
Diversifier, Node, PaymentAddress, ProofGenerationKey, Rseed,
|
||||
},
|
||||
transaction::components::{Amount, GROTH_PROOF_SIZE},
|
||||
};
|
||||
|
|
|
@ -10,9 +10,10 @@ use std::ops::{AddAssign, Neg};
|
|||
use zcash_primitives::{
|
||||
constants::{SPENDING_KEY_GENERATOR, VALUE_COMMITMENT_RANDOMNESS_GENERATOR},
|
||||
merkle_tree::MerklePath,
|
||||
primitives::{Diversifier, Note, PaymentAddress, ProofGenerationKey, Rseed, ValueCommitment},
|
||||
sapling::redjubjub::{PrivateKey, PublicKey, Signature},
|
||||
sapling::Node,
|
||||
sapling::{
|
||||
redjubjub::{PrivateKey, PublicKey, Signature},
|
||||
Diversifier, Node, Note, PaymentAddress, ProofGenerationKey, Rseed, ValueCommitment,
|
||||
},
|
||||
transaction::components::Amount,
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue