Merge pull request #663 from nuttycom/sapling_key_cleanup

Fix Sapling key organization.
This commit is contained in:
Kris Nuttycombe 2022-10-05 14:35:16 -06:00 committed by GitHub
commit e9406201d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 1922 additions and 1863 deletions

View File

@ -85,7 +85,8 @@ use zcash_primitives::{
block::BlockHash, block::BlockHash,
consensus::{self, BlockHeight, NetworkUpgrade}, consensus::{self, BlockHeight, NetworkUpgrade},
merkle_tree::CommitmentTree, merkle_tree::CommitmentTree,
sapling::{keys::Scope, note_encryption::PreparedIncomingViewingKey, Nullifier}, sapling::{note_encryption::PreparedIncomingViewingKey, Nullifier},
zip32::Scope,
}; };
use crate::{ use crate::{

View File

@ -15,7 +15,8 @@ use zcash_primitives::{
use { use {
zcash_address::unified::Typecode, zcash_address::unified::Typecode,
zcash_primitives::{ zcash_primitives::{
keys::OutgoingViewingKey, legacy::keys as transparent, legacy::keys::IncomingViewingKey, legacy::keys::{self as transparent, IncomingViewingKey},
sapling::keys::OutgoingViewingKey,
}, },
}; };

View File

@ -25,11 +25,10 @@ use {
}; };
pub mod sapling { pub mod sapling {
use zcash_primitives::zip32::{AccountId, ChildIndex}; pub use zcash_primitives::zip32::sapling::{
pub use zcash_primitives::{ DiversifiableFullViewingKey, ExtendedFullViewingKey, ExtendedSpendingKey,
sapling::keys::DiversifiableFullViewingKey,
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey},
}; };
use zcash_primitives::zip32::{AccountId, ChildIndex};
/// Derives the ZIP 32 [`ExtendedSpendingKey`] for a given coin type and account from the /// Derives the ZIP 32 [`ExtendedSpendingKey`] for a given coin type and account from the
/// given seed. /// given seed.

View File

@ -11,12 +11,14 @@ use zcash_primitives::{
merkle_tree::{CommitmentTree, IncrementalWitness}, merkle_tree::{CommitmentTree, IncrementalWitness},
sapling::{ sapling::{
self, self,
keys::{DiversifiableFullViewingKey, Scope},
note_encryption::{PreparedIncomingViewingKey, SaplingDomain}, note_encryption::{PreparedIncomingViewingKey, SaplingDomain},
Node, Note, Nullifier, NullifierDerivingKey, SaplingIvk, Node, Note, Nullifier, NullifierDerivingKey, SaplingIvk,
}, },
transaction::components::sapling::CompactOutputDescription, transaction::components::sapling::CompactOutputDescription,
zip32::{AccountId, ExtendedFullViewingKey}, zip32::{
sapling::{DiversifiableFullViewingKey, ExtendedFullViewingKey},
AccountId, Scope,
},
}; };
use crate::{ use crate::{

View File

@ -645,7 +645,7 @@ pub mod testing {
use proptest::strategy::Strategy; use proptest::strategy::Strategy;
use zcash_primitives::{ use zcash_primitives::{
consensus::TEST_NETWORK, legacy::testing::arb_transparent_addr, consensus::TEST_NETWORK, legacy::testing::arb_transparent_addr,
sapling::keys::testing::arb_shielded_addr, sapling::testing::arb_payment_address,
transaction::components::amount::testing::arb_nonnegative_amount, transaction::components::amount::testing::arb_nonnegative_amount,
}; };
@ -655,7 +655,7 @@ pub mod testing {
prop_compose! { prop_compose! {
fn arb_unified_addr()( fn arb_unified_addr()(
sapling in arb_shielded_addr(), sapling in arb_payment_address(),
transparent in option::of(arb_transparent_addr()), transparent in option::of(arb_transparent_addr()),
) -> UnifiedAddress { ) -> UnifiedAddress {
UnifiedAddress::from_receivers(None, Some(sapling), transparent).unwrap() UnifiedAddress::from_receivers(None, Some(sapling), transparent).unwrap()
@ -664,7 +664,7 @@ pub mod testing {
pub fn arb_addr() -> impl Strategy<Value = RecipientAddress> { pub fn arb_addr() -> impl Strategy<Value = RecipientAddress> {
prop_oneof![ prop_oneof![
arb_shielded_addr().prop_map(RecipientAddress::Shielded), arb_payment_address().prop_map(RecipientAddress::Shielded),
arb_transparent_addr().prop_map(RecipientAddress::Transparent), arb_transparent_addr().prop_map(RecipientAddress::Transparent),
arb_unified_addr().prop_map(RecipientAddress::Unified), arb_unified_addr().prop_map(RecipientAddress::Unified),
] ]

View File

@ -902,11 +902,11 @@ mod tests {
legacy::TransparentAddress, legacy::TransparentAddress,
memo::MemoBytes, memo::MemoBytes,
sapling::{ sapling::{
keys::DiversifiableFullViewingKey, note_encryption::sapling_note_encryption, note_encryption::sapling_note_encryption, util::generate_random_rseed, Note, Nullifier,
util::generate_random_rseed, Note, Nullifier, PaymentAddress, PaymentAddress,
}, },
transaction::components::Amount, transaction::components::Amount,
zip32::ExtendedFullViewingKey, zip32::sapling::{DiversifiableFullViewingKey, ExtendedFullViewingKey},
}; };
use zcash_client_backend::{ use zcash_client_backend::{

View File

@ -20,9 +20,12 @@ use zcash_primitives::{
consensus::{self, BlockHeight, BranchId, NetworkUpgrade, Parameters}, consensus::{self, BlockHeight, BranchId, NetworkUpgrade, Parameters},
memo::{Memo, MemoBytes}, memo::{Memo, MemoBytes},
merkle_tree::{CommitmentTree, IncrementalWitness}, merkle_tree::{CommitmentTree, IncrementalWitness},
sapling::{keys::DiversifiableFullViewingKey, Node, Note, Nullifier, PaymentAddress}, sapling::{Node, Note, Nullifier, PaymentAddress},
transaction::{components::Amount, Transaction, TxId}, transaction::{components::Amount, Transaction, TxId},
zip32::{AccountId, DiversifierIndex, ExtendedFullViewingKey}, zip32::{
sapling::{DiversifiableFullViewingKey, ExtendedFullViewingKey},
AccountId, DiversifierIndex,
},
}; };
use zcash_client_backend::{ use zcash_client_backend::{

View File

@ -297,9 +297,8 @@ mod tests {
use zcash_primitives::{ use zcash_primitives::{
block::BlockHash, block::BlockHash,
consensus::{BlockHeight, BranchId, Parameters}, consensus::{BlockHeight, BranchId, Parameters},
sapling::keys::DiversifiableFullViewingKey,
transaction::{TransactionData, TxVersion}, transaction::{TransactionData, TxVersion},
zip32::ExtendedFullViewingKey, zip32::sapling::{DiversifiableFullViewingKey, ExtendedFullViewingKey},
}; };
use crate::{ use crate::{

View File

@ -166,12 +166,11 @@ mod tests {
block::BlockHash, block::BlockHash,
consensus::{BlockHeight, BranchId, Parameters}, consensus::{BlockHeight, BranchId, Parameters},
legacy::TransparentAddress, legacy::TransparentAddress,
sapling::{ sapling::{note_encryption::try_sapling_output_recovery, prover::TxProver},
keys::DiversifiableFullViewingKey, note_encryption::try_sapling_output_recovery,
prover::TxProver,
},
transaction::{components::Amount, Transaction}, transaction::{components::Amount, Transaction},
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}, zip32::sapling::{
DiversifiableFullViewingKey, ExtendedFullViewingKey, ExtendedSpendingKey,
},
}; };
#[cfg(feature = "transparent-inputs")] #[cfg(feature = "transparent-inputs")]

View File

@ -13,7 +13,6 @@ and this library adheres to Rust's notion of
- `zcash_primitives::sapling::NullifierDerivingKey` - `zcash_primitives::sapling::NullifierDerivingKey`
- Added in `zcash_primitives::sapling::keys` - Added in `zcash_primitives::sapling::keys`
- `DecodingError` - `DecodingError`
- `DiversifiableFullViewingKey`
- `Scope` - `Scope`
- `ExpandedSpendingKey::from_bytes` - `ExpandedSpendingKey::from_bytes`
- `ExtendedSpendingKey::{from_bytes, to_bytes}` - `ExtendedSpendingKey::{from_bytes, to_bytes}`
@ -22,10 +21,14 @@ and this library adheres to Rust's notion of
- `PreparedEphemeralPublicKey` - `PreparedEphemeralPublicKey`
- Added in `zcash_primitives::zip32` - Added in `zcash_primitives::zip32`
- `ChainCode::as_bytes` - `ChainCode::as_bytes`
- `DiversifierKey::{from_bytes, as_bytes}`
- `DiversifierIndex::{as_bytes}` - `DiversifierIndex::{as_bytes}`
- `ExtendedSpendingKey::{from_bytes, to_bytes}`
- Implementations of `From<u32>` and `From<u64>` for `DiversifierIndex` - Implementations of `From<u32>` and `From<u64>` for `DiversifierIndex`
- `zcash_primitives::zip32::sapling` has been added and now contains
all of the Sapling zip32 key types that were previously located in
`zcash_primitives::zip32` directly. The base `zip32` module reexports
the moved types for backwards compatibility.
- `DiversifierKey::{from_bytes, as_bytes}`
- `ExtendedSpendingKey::{from_bytes, to_bytes}`
- `zcash_primitives::transaction::Builder` constructors: - `zcash_primitives::transaction::Builder` constructors:
- `Builder::new_with_fee` - `Builder::new_with_fee`
- `Builder::new_with_rng_and_fee` - `Builder::new_with_rng_and_fee`

View File

@ -1,5 +1,7 @@
use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams}; use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams};
pub use crate::sapling::keys::OutgoingViewingKey;
pub const PRF_EXPAND_PERSONALIZATION: &[u8; 16] = b"Zcash_ExpandSeed"; pub const PRF_EXPAND_PERSONALIZATION: &[u8; 16] = b"Zcash_ExpandSeed";
/// PRF^expand(sk, t) := BLAKE2b-512("Zcash_ExpandSeed", sk || t) /// PRF^expand(sk, t) := BLAKE2b-512("Zcash_ExpandSeed", sk || t)
@ -18,7 +20,3 @@ pub fn prf_expand_vec(sk: &[u8], ts: &[&[u8]]) -> Blake2bHash {
} }
h.finalize() h.finalize()
} }
/// An outgoing viewing key
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct OutgoingViewingKey(pub [u8; 32]);

View File

@ -524,11 +524,12 @@ pub mod testing {
use proptest::prelude::*; use proptest::prelude::*;
use std::cmp::min; use std::cmp::min;
use crate::{ use crate::transaction::components::amount::MAX_MONEY;
transaction::components::amount::MAX_MONEY, zip32::testing::arb_extended_spending_key,
};
use super::{Node, Note, NoteValue, PaymentAddress, Rseed}; use super::{
keys::testing::arb_full_viewing_key, Diversifier, Node, Note, NoteValue, PaymentAddress,
Rseed, SaplingIvk,
};
prop_compose! { prop_compose! {
pub fn arb_note_value()(value in 0u64..=MAX_MONEY as u64) -> NoteValue { pub fn arb_note_value()(value in 0u64..=MAX_MONEY as u64) -> NoteValue {
@ -545,8 +546,19 @@ pub mod testing {
} }
} }
prop_compose! {
pub fn arb_incoming_viewing_key()(fvk in arb_full_viewing_key()) -> SaplingIvk {
fvk.vk.ivk()
}
}
pub fn arb_payment_address() -> impl Strategy<Value = PaymentAddress> { pub fn arb_payment_address() -> impl Strategy<Value = PaymentAddress> {
arb_extended_spending_key().prop_map(|sk| sk.default_address().1) arb_incoming_viewing_key().prop_flat_map(|ivk: SaplingIvk| {
any::<[u8; 11]>().prop_filter_map(
"Sampled diversifier must generate a valid Sapling payment address.",
move |d| ivk.to_payment_address(Diversifier(d)),
)
})
} }
prop_compose! { prop_compose! {

View File

@ -8,15 +8,13 @@ use std::io::{self, Read, Write};
use crate::{ use crate::{
constants::{PROOF_GENERATION_KEY_GENERATOR, SPENDING_KEY_GENERATOR}, constants::{PROOF_GENERATION_KEY_GENERATOR, SPENDING_KEY_GENERATOR},
keys::{prf_expand, OutgoingViewingKey}, keys::prf_expand,
zip32,
}; };
use ff::PrimeField; use ff::PrimeField;
use group::{Group, GroupEncoding}; use group::{Group, GroupEncoding};
use memuse::DynamicUsage;
use subtle::CtOption; use subtle::CtOption;
use super::{NullifierDerivingKey, PaymentAddress, ProofGenerationKey, SaplingIvk, ViewingKey}; use super::{NullifierDerivingKey, ProofGenerationKey, ViewingKey};
/// Errors that can occur in the decoding of Sapling spending keys. /// Errors that can occur in the decoding of Sapling spending keys.
pub enum DecodingError { pub enum DecodingError {
@ -28,6 +26,10 @@ pub enum DecodingError {
InvalidNsk, InvalidNsk,
} }
/// An outgoing viewing key
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct OutgoingViewingKey(pub [u8; 32]);
/// A Sapling expanded spending key /// A Sapling expanded spending key
#[derive(Clone)] #[derive(Clone)]
pub struct ExpandedSpendingKey { pub struct ExpandedSpendingKey {
@ -36,13 +38,6 @@ pub struct ExpandedSpendingKey {
pub ovk: OutgoingViewingKey, pub ovk: OutgoingViewingKey,
} }
/// A Sapling key that provides the capability to view incoming and outgoing transactions.
#[derive(Debug)]
pub struct FullViewingKey {
pub vk: ViewingKey,
pub ovk: OutgoingViewingKey,
}
impl ExpandedSpendingKey { impl ExpandedSpendingKey {
pub fn from_spending_key(sk: &[u8]) -> Self { pub fn from_spending_key(sk: &[u8]) -> Self {
let ask = jubjub::Fr::from_bytes_wide(prf_expand(sk, &[0x00]).as_array()); let ask = jubjub::Fr::from_bytes_wide(prf_expand(sk, &[0x00]).as_array());
@ -110,6 +105,13 @@ impl ExpandedSpendingKey {
} }
} }
/// A Sapling key that provides the capability to view incoming and outgoing transactions.
#[derive(Debug)]
pub struct FullViewingKey {
pub vk: ViewingKey,
pub ovk: OutgoingViewingKey,
}
impl Clone for FullViewingKey { impl Clone for FullViewingKey {
fn clone(&self) -> Self { fn clone(&self) -> Self {
FullViewingKey { FullViewingKey {
@ -184,199 +186,29 @@ impl FullViewingKey {
} }
} }
/// The scope of a viewing key or address.
///
/// A "scope" narrows the visibility or usage to a level below "full".
///
/// Consistent usage of `Scope` enables the user to provide consistent views over a wallet
/// to other people. For example, a user can give an external [`SaplingIvk`] to a merchant
/// terminal, enabling it to only detect "real" transactions from customers and not
/// internal transactions from the wallet.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Scope {
/// A scope used for wallet-external operations, namely deriving addresses to give to
/// other users in order to receive funds.
External,
/// A scope used for wallet-internal operations, such as creating change notes,
/// auto-shielding, and note management.
Internal,
}
memuse::impl_no_dynamic_usage!(Scope);
/// A Sapling key that provides the capability to view incoming and outgoing transactions.
///
/// This key is useful anywhere you need to maintain accurate balance, but do not want the
/// ability to spend funds (such as a view-only wallet).
///
/// It comprises the subset of the ZIP 32 extended full viewing key that is used for the
/// Sapling item in a [ZIP 316 Unified Full Viewing Key][zip-0316-ufvk].
///
/// [zip-0316-ufvk]: https://zips.z.cash/zip-0316#encoding-of-unified-full-incoming-viewing-keys
#[derive(Clone, Debug)]
pub struct DiversifiableFullViewingKey {
fvk: FullViewingKey,
dk: zip32::DiversifierKey,
}
impl From<zip32::ExtendedFullViewingKey> for DiversifiableFullViewingKey {
fn from(extfvk: zip32::ExtendedFullViewingKey) -> Self {
Self {
fvk: extfvk.fvk,
dk: extfvk.dk,
}
}
}
impl DiversifiableFullViewingKey {
/// Parses a `DiversifiableFullViewingKey` from its raw byte encoding.
///
/// Returns `None` if the bytes do not contain a valid encoding of a diversifiable
/// Sapling full viewing key.
pub fn from_bytes(bytes: &[u8; 128]) -> Option<Self> {
FullViewingKey::read(&bytes[..96]).ok().map(|fvk| Self {
fvk,
dk: zip32::DiversifierKey::from_bytes(bytes[96..].try_into().unwrap()),
})
}
/// Returns the raw encoding of this `DiversifiableFullViewingKey`.
pub fn to_bytes(&self) -> [u8; 128] {
let mut bytes = [0; 128];
self.fvk
.write(&mut bytes[..96])
.expect("slice should be the correct length");
bytes[96..].copy_from_slice(&self.dk.as_bytes()[..]);
bytes
}
/// Derives the internal `DiversifiableFullViewingKey` corresponding to `self` (which
/// is assumed here to be an external DFVK).
fn derive_internal(&self) -> Self {
let (fvk, dk) = zip32::sapling_derive_internal_fvk(&self.fvk, &self.dk);
Self { fvk, dk }
}
/// Exposes the external [`FullViewingKey`] component of this diversifiable full viewing key.
pub fn fvk(&self) -> &FullViewingKey {
&self.fvk
}
/// Derives a nullifier-deriving key for the provided scope.
///
/// This API is provided so that nullifiers for change notes can be correctly computed.
pub fn to_nk(&self, scope: Scope) -> NullifierDerivingKey {
match scope {
Scope::External => self.fvk.vk.nk,
Scope::Internal => self.derive_internal().fvk.vk.nk,
}
}
/// Derives an incoming viewing key corresponding to this full viewing key.
pub fn to_ivk(&self, scope: Scope) -> SaplingIvk {
match scope {
Scope::External => self.fvk.vk.ivk(),
Scope::Internal => self.derive_internal().fvk.vk.ivk(),
}
}
/// Derives an outgoing viewing key corresponding to this full viewing key.
pub fn to_ovk(&self, scope: Scope) -> OutgoingViewingKey {
match scope {
Scope::External => self.fvk.ovk,
Scope::Internal => self.derive_internal().fvk.ovk,
}
}
/// Attempts to produce a valid payment address for the given diversifier index.
///
/// Returns `None` if the diversifier index does not produce a valid diversifier for
/// this `DiversifiableFullViewingKey`.
pub fn address(&self, j: zip32::DiversifierIndex) -> Option<PaymentAddress> {
zip32::sapling_address(&self.fvk, &self.dk, j)
}
/// Finds the next valid payment address starting from the given diversifier index.
///
/// This searches the diversifier space starting at `j` and incrementing, to find an
/// index which will produce a valid diversifier (a 50% probability for each index).
///
/// Returns the index at which the valid diversifier was found along with the payment
/// address constructed using that diversifier, or `None` if the maximum index was
/// reached and no valid diversifier was found.
pub fn find_address(
&self,
j: zip32::DiversifierIndex,
) -> Option<(zip32::DiversifierIndex, PaymentAddress)> {
zip32::sapling_find_address(&self.fvk, &self.dk, j)
}
/// Returns the payment address corresponding to the smallest valid diversifier index,
/// along with that index.
pub fn default_address(&self) -> (zip32::DiversifierIndex, PaymentAddress) {
zip32::sapling_default_address(&self.fvk, &self.dk)
}
/// Returns the internal address corresponding to the smallest valid diversifier index,
/// along with that index.
///
/// This address **MUST NOT** be encoded and exposed to end users. User interfaces
/// should instead mark these notes as "change notes" or "internal wallet operations".
pub fn change_address(&self) -> (zip32::DiversifierIndex, PaymentAddress) {
let internal_dfvk = self.derive_internal();
zip32::sapling_default_address(&internal_dfvk.fvk, &internal_dfvk.dk)
}
/// Attempts to decrypt the given address's diversifier with this full viewing key.
///
/// This method extracts the diversifier from the given address and decrypts it as a
/// diversifier index, then verifies that this diversifier index produces the same
/// address. Decryption is attempted using both the internal and external parts of the
/// full viewing key.
///
/// Returns the decrypted diversifier index and its scope, or `None` if the address
/// was not generated from this key.
pub fn decrypt_diversifier(
&self,
addr: &PaymentAddress,
) -> Option<(zip32::DiversifierIndex, Scope)> {
let j_external = self.dk.diversifier_index(addr.diversifier());
if self.address(j_external).as_ref() == Some(addr) {
return Some((j_external, Scope::External));
}
let j_internal = self
.derive_internal()
.dk
.diversifier_index(addr.diversifier());
if self.address(j_internal).as_ref() == Some(addr) {
return Some((j_internal, Scope::Internal));
}
None
}
}
#[cfg(any(test, feature = "test-dependencies"))] #[cfg(any(test, feature = "test-dependencies"))]
pub mod testing { pub mod testing {
use proptest::collection::vec; use proptest::collection::vec;
use proptest::prelude::{any, prop_compose}; use proptest::prelude::*;
use std::fmt::{self, Debug, Formatter};
use crate::{ use super::{ExpandedSpendingKey, FullViewingKey};
sapling::PaymentAddress,
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey},
};
prop_compose! { impl Debug for ExpandedSpendingKey {
pub fn arb_extended_spending_key()(v in vec(any::<u8>(), 32..252)) -> ExtendedSpendingKey { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
ExtendedSpendingKey::master(&v) write!(f, "Spending keys cannot be Debug-formatted.")
} }
} }
prop_compose! { prop_compose! {
pub fn arb_shielded_addr()(extsk in arb_extended_spending_key()) -> PaymentAddress { pub fn arb_expanded_spending_key()(v in vec(any::<u8>(), 32..252)) -> ExpandedSpendingKey {
let extfvk = ExtendedFullViewingKey::from(&extsk); ExpandedSpendingKey::from_spending_key(&v)
extfvk.default_address().1 }
}
prop_compose! {
pub fn arb_full_viewing_key()(sk in arb_expanded_spending_key()) -> FullViewingKey {
FullViewingKey::from_expanded_spending_key(&sk)
} }
} }
} }
@ -385,8 +217,8 @@ pub mod testing {
mod tests { mod tests {
use group::{Group, GroupEncoding}; use group::{Group, GroupEncoding};
use super::{DiversifiableFullViewingKey, FullViewingKey}; use super::FullViewingKey;
use crate::{constants::SPENDING_KEY_GENERATOR, zip32}; use crate::constants::SPENDING_KEY_GENERATOR;
#[test] #[test]
fn ak_must_be_prime_order() { fn ak_must_be_prime_order() {
@ -410,24 +242,4 @@ mod tests {
// nk is allowed to be the identity. // nk is allowed to be the identity.
assert!(FullViewingKey::read(&buf[..]).is_ok()); assert!(FullViewingKey::read(&buf[..]).is_ok());
} }
#[test]
fn dfvk_round_trip() {
let dfvk = {
let extsk = zip32::ExtendedSpendingKey::master(&[]);
let extfvk = zip32::ExtendedFullViewingKey::from(&extsk);
DiversifiableFullViewingKey::from(extfvk)
};
// Check value -> bytes -> parsed round trip.
let dfvk_bytes = dfvk.to_bytes();
let dfvk_parsed = DiversifiableFullViewingKey::from_bytes(&dfvk_bytes).unwrap();
assert_eq!(dfvk_parsed.fvk.vk.ak, dfvk.fvk.vk.ak);
assert_eq!(dfvk_parsed.fvk.vk.nk, dfvk.fvk.vk.nk);
assert_eq!(dfvk_parsed.fvk.ovk, dfvk.fvk.ovk);
assert_eq!(dfvk_parsed.dk, dfvk.dk);
// Check bytes -> parsed -> bytes round trip.
assert_eq!(dfvk_parsed.to_bytes(), dfvk_bytes);
}
} }

View File

@ -19,9 +19,8 @@ use zcash_note_encryption::{
use crate::{ use crate::{
consensus::{self, BlockHeight, NetworkUpgrade::Canopy, ZIP212_GRACE_PERIOD}, consensus::{self, BlockHeight, NetworkUpgrade::Canopy, ZIP212_GRACE_PERIOD},
keys::OutgoingViewingKey,
memo::MemoBytes, memo::MemoBytes,
sapling::{Diversifier, Note, PaymentAddress, Rseed, SaplingIvk}, sapling::{keys::OutgoingViewingKey, Diversifier, Note, PaymentAddress, Rseed, SaplingIvk},
transaction::components::{ transaction::components::{
amount::Amount, amount::Amount,
sapling::{self, OutputDescription}, sapling::{self, OutputDescription},

View File

@ -568,7 +568,7 @@ pub mod testing {
amount::MAX_MONEY, amount::MAX_MONEY,
sapling::{Authorized, Bundle}, sapling::{Authorized, Bundle},
}, },
zip32::testing::arb_extended_spending_key, zip32::sapling::testing::arb_extended_spending_key,
}; };
use super::SaplingBuilder; use super::SaplingBuilder;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff