zcash_client_backend: Fix `UnifiedFullViewingKey` Sapling item type
Per ZIP 316, the Sapling FVK Encoding only includes `(ak, nk, ovk, dk)` which is a subset of the Sapling `ExtendedFullViewingKey`. We therefore need to use `DiversifiableFullViewingKey` inside `UnifiedFullViewingKey` in order to make it parseable from the UFVK string encoding. `zcash_client_sqlite::wallet::get_extended_full_viewing_keys` has been removed as a consequence of this change: we can no longer reconstruct the correct `ExtendedFullViewingKey` from the `UnifiedFullViewingKey`.
This commit is contained in:
parent
d8b860207d
commit
76d015ed11
|
@ -84,7 +84,6 @@ use zcash_primitives::{
|
|||
consensus::{self, BlockHeight, NetworkUpgrade},
|
||||
merkle_tree::CommitmentTree,
|
||||
sapling::Nullifier,
|
||||
zip32::{AccountId, ExtendedFullViewingKey},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
|
@ -214,7 +213,7 @@ where
|
|||
let ufvks = data.get_unified_full_viewing_keys()?;
|
||||
// TODO: Change `scan_block` to also scan Orchard.
|
||||
// https://github.com/zcash/librustzcash/issues/403
|
||||
let extfvks: Vec<(&AccountId, &ExtendedFullViewingKey)> = ufvks
|
||||
let dfvks: Vec<_> = ufvks
|
||||
.iter()
|
||||
.map(|(account, ufvk)| (account, ufvk.sapling().expect("TODO Add Orchard support")))
|
||||
.collect();
|
||||
|
@ -249,7 +248,7 @@ where
|
|||
scan_block(
|
||||
params,
|
||||
block,
|
||||
&extfvks,
|
||||
&dfvks,
|
||||
&nullifiers,
|
||||
&mut tree,
|
||||
&mut witness_refs[..],
|
||||
|
|
|
@ -46,9 +46,9 @@ pub fn decrypt_transaction<P: consensus::Parameters>(
|
|||
|
||||
if let Some(bundle) = tx.sapling_bundle() {
|
||||
for (account, ufvk) in ufvks.iter() {
|
||||
let extfvk = ufvk.sapling().expect("TODO: Add Orchard support");
|
||||
let ivk = extfvk.fvk.vk.ivk();
|
||||
let ovk = extfvk.fvk.ovk;
|
||||
let dfvk = ufvk.sapling().expect("TODO: Add Orchard support");
|
||||
let ivk = dfvk.fvk().vk.ivk();
|
||||
let ovk = dfvk.fvk().ovk;
|
||||
|
||||
for (index, output) in bundle.shielded_outputs.iter().enumerate() {
|
||||
let ((note, to, memo), outgoing) =
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
//! Helper functions for managing light client key material.
|
||||
use zcash_primitives::{
|
||||
consensus,
|
||||
sapling::keys as sapling_keys,
|
||||
zip32::{AccountId, DiversifierIndex},
|
||||
};
|
||||
|
||||
use crate::address::UnifiedAddress;
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
|
@ -109,7 +109,7 @@ impl UnifiedSpendingKey {
|
|||
UnifiedFullViewingKey {
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
transparent: Some(self.transparent.to_account_pubkey()),
|
||||
sapling: Some(sapling::ExtendedFullViewingKey::from(&self.sapling)),
|
||||
sapling: Some(sapling::ExtendedFullViewingKey::from(&self.sapling).into()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,9 +138,7 @@ impl UnifiedSpendingKey {
|
|||
pub struct UnifiedFullViewingKey {
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
transparent: Option<legacy::AccountPubKey>,
|
||||
// TODO: This type is invalid for a UFVK; create a `sapling::DiversifiableFullViewingKey`
|
||||
// to replace it.
|
||||
sapling: Option<sapling::ExtendedFullViewingKey>,
|
||||
sapling: Option<sapling_keys::DiversifiableFullViewingKey>,
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
|
@ -148,7 +146,7 @@ impl UnifiedFullViewingKey {
|
|||
/// Construct a new unified full viewing key, if the required components are present.
|
||||
pub fn new(
|
||||
#[cfg(feature = "transparent-inputs")] transparent: Option<legacy::AccountPubKey>,
|
||||
sapling: Option<sapling::ExtendedFullViewingKey>,
|
||||
sapling: Option<sapling_keys::DiversifiableFullViewingKey>,
|
||||
) -> Option<UnifiedFullViewingKey> {
|
||||
if sapling.is_none() {
|
||||
None
|
||||
|
@ -185,7 +183,12 @@ impl UnifiedFullViewingKey {
|
|||
};
|
||||
|
||||
let sapling = if flag & 2 != 0 {
|
||||
Some(sapling::ExtendedFullViewingKey::read(data).ok()?)
|
||||
if data.len() != 128 {
|
||||
return None;
|
||||
}
|
||||
Some(sapling_keys::DiversifiableFullViewingKey::from_bytes(
|
||||
data.try_into().unwrap(),
|
||||
)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -212,7 +215,7 @@ impl UnifiedFullViewingKey {
|
|||
};
|
||||
|
||||
if let Some(sapling) = self.sapling.as_ref() {
|
||||
sapling.write(&mut ufvk).unwrap();
|
||||
ufvk.extend_from_slice(&sapling.to_bytes());
|
||||
}
|
||||
|
||||
format!("DONOTUSEUFVK{}", hex::encode(&ufvk))
|
||||
|
@ -225,9 +228,8 @@ impl UnifiedFullViewingKey {
|
|||
self.transparent.as_ref()
|
||||
}
|
||||
|
||||
/// Returns the Sapling extended full viewing key component of this
|
||||
/// unified key.
|
||||
pub fn sapling(&self) -> Option<&sapling::ExtendedFullViewingKey> {
|
||||
/// Returns the Sapling diversifiable full viewing key component of this unified key.
|
||||
pub fn sapling(&self) -> Option<&sapling_keys::DiversifiableFullViewingKey> {
|
||||
self.sapling.as_ref()
|
||||
}
|
||||
|
||||
|
@ -348,7 +350,7 @@ mod tests {
|
|||
|
||||
let sapling = {
|
||||
let extsk = sapling::spending_key(&[0; 32], 0, account);
|
||||
Some(ExtendedFullViewingKey::from(&extsk))
|
||||
Some(ExtendedFullViewingKey::from(&extsk).into())
|
||||
};
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
|
@ -368,6 +370,9 @@ mod tests {
|
|||
decoded.transparent.map(|t| t.serialize()),
|
||||
ufvk.transparent.map(|t| t.serialize()),
|
||||
);
|
||||
assert_eq!(decoded.sapling, ufvk.sapling);
|
||||
assert_eq!(
|
||||
decoded.sapling.map(|s| s.to_bytes()),
|
||||
ufvk.sapling.map(|s| s.to_bytes()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ use zcash_primitives::{
|
|||
consensus::{self, BlockHeight},
|
||||
merkle_tree::{CommitmentTree, IncrementalWitness},
|
||||
sapling::{
|
||||
keys::DiversifiableFullViewingKey,
|
||||
note_encryption::{try_sapling_compact_note_decryption, SaplingDomain},
|
||||
Node, Note, Nullifier, PaymentAddress, SaplingIvk,
|
||||
},
|
||||
|
@ -127,6 +128,26 @@ pub trait ScanningKey {
|
|||
fn nf(&self, note: &Note, witness: &IncrementalWitness<Node>) -> Self::Nf;
|
||||
}
|
||||
|
||||
impl ScanningKey for DiversifiableFullViewingKey {
|
||||
type Nf = Nullifier;
|
||||
|
||||
fn try_decryption<
|
||||
P: consensus::Parameters,
|
||||
Output: ShieldedOutput<SaplingDomain<P>, COMPACT_NOTE_SIZE>,
|
||||
>(
|
||||
&self,
|
||||
params: &P,
|
||||
height: BlockHeight,
|
||||
output: &Output,
|
||||
) -> Option<(Note, PaymentAddress)> {
|
||||
try_sapling_compact_note_decryption(params, height, &self.fvk().vk.ivk(), output)
|
||||
}
|
||||
|
||||
fn nf(&self, note: &Note, witness: &IncrementalWitness<Node>) -> Self::Nf {
|
||||
note.nf(&self.fvk().vk, witness.position() as u64)
|
||||
}
|
||||
}
|
||||
|
||||
/// The [`ScanningKey`] implementation for [`ExtendedFullViewingKey`]s.
|
||||
/// Nullifiers may be derived when scanning with these keys.
|
||||
///
|
||||
|
|
|
@ -49,6 +49,12 @@ and this library adheres to Rust's notion of
|
|||
constructed, rather than only in the case that a transaction has
|
||||
been decrypted after being retrieved from the network.
|
||||
|
||||
### Removed
|
||||
- `zcash_client_sqlite::wallet`:
|
||||
- `get_extended_full_viewing_keys` (use
|
||||
`zcash_client_backend::data_api::WalletRead::get_unified_full_viewing_keys`
|
||||
instead).
|
||||
|
||||
### Deprecated
|
||||
- A number of public API methods that are used internally to support the
|
||||
`zcash_client_backend::data_api::{WalletRead, WalletWrite}` interfaces have
|
||||
|
|
|
@ -101,7 +101,7 @@ mod tests {
|
|||
init_wallet_db(&db_data).unwrap();
|
||||
|
||||
// Add an account to the wallet
|
||||
let (extfvk, _taddr) = init_test_accounts_table(&db_data);
|
||||
let (dfvk, _taddr) = init_test_accounts_table(&db_data);
|
||||
|
||||
// Empty chain should be valid
|
||||
validate_chain(
|
||||
|
@ -115,7 +115,7 @@ mod tests {
|
|||
let (cb, _) = fake_compact_block(
|
||||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
extfvk.clone(),
|
||||
&dfvk,
|
||||
Amount::from_u64(5).unwrap(),
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -144,7 +144,7 @@ mod tests {
|
|||
let (cb2, _) = fake_compact_block(
|
||||
sapling_activation_height() + 1,
|
||||
cb.hash(),
|
||||
extfvk,
|
||||
&dfvk,
|
||||
Amount::from_u64(7).unwrap(),
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb2);
|
||||
|
@ -180,19 +180,19 @@ mod tests {
|
|||
init_wallet_db(&db_data).unwrap();
|
||||
|
||||
// Add an account to the wallet
|
||||
let (extfvk, _taddr) = init_test_accounts_table(&db_data);
|
||||
let (dfvk, _taddr) = init_test_accounts_table(&db_data);
|
||||
|
||||
// Create some fake CompactBlocks
|
||||
let (cb, _) = fake_compact_block(
|
||||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
extfvk.clone(),
|
||||
&dfvk,
|
||||
Amount::from_u64(5).unwrap(),
|
||||
);
|
||||
let (cb2, _) = fake_compact_block(
|
||||
sapling_activation_height() + 1,
|
||||
cb.hash(),
|
||||
extfvk.clone(),
|
||||
&dfvk,
|
||||
Amount::from_u64(7).unwrap(),
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -214,13 +214,13 @@ mod tests {
|
|||
let (cb3, _) = fake_compact_block(
|
||||
sapling_activation_height() + 2,
|
||||
BlockHash([1; 32]),
|
||||
extfvk.clone(),
|
||||
&dfvk,
|
||||
Amount::from_u64(8).unwrap(),
|
||||
);
|
||||
let (cb4, _) = fake_compact_block(
|
||||
sapling_activation_height() + 3,
|
||||
cb3.hash(),
|
||||
extfvk,
|
||||
&dfvk,
|
||||
Amount::from_u64(3).unwrap(),
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb3);
|
||||
|
@ -250,19 +250,19 @@ mod tests {
|
|||
init_wallet_db(&db_data).unwrap();
|
||||
|
||||
// Add an account to the wallet
|
||||
let (extfvk, _taddr) = init_test_accounts_table(&db_data);
|
||||
let (dfvk, _taddr) = init_test_accounts_table(&db_data);
|
||||
|
||||
// Create some fake CompactBlocks
|
||||
let (cb, _) = fake_compact_block(
|
||||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
extfvk.clone(),
|
||||
&dfvk,
|
||||
Amount::from_u64(5).unwrap(),
|
||||
);
|
||||
let (cb2, _) = fake_compact_block(
|
||||
sapling_activation_height() + 1,
|
||||
cb.hash(),
|
||||
extfvk.clone(),
|
||||
&dfvk,
|
||||
Amount::from_u64(7).unwrap(),
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -284,13 +284,13 @@ mod tests {
|
|||
let (cb3, _) = fake_compact_block(
|
||||
sapling_activation_height() + 2,
|
||||
cb2.hash(),
|
||||
extfvk.clone(),
|
||||
&dfvk,
|
||||
Amount::from_u64(8).unwrap(),
|
||||
);
|
||||
let (cb4, _) = fake_compact_block(
|
||||
sapling_activation_height() + 3,
|
||||
BlockHash([1; 32]),
|
||||
extfvk,
|
||||
&dfvk,
|
||||
Amount::from_u64(3).unwrap(),
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb3);
|
||||
|
@ -320,7 +320,7 @@ mod tests {
|
|||
init_wallet_db(&db_data).unwrap();
|
||||
|
||||
// Add an account to the wallet
|
||||
let (extfvk, _taddr) = init_test_accounts_table(&db_data);
|
||||
let (dfvk, _taddr) = init_test_accounts_table(&db_data);
|
||||
|
||||
// Account balance should be zero
|
||||
assert_eq!(
|
||||
|
@ -334,12 +334,12 @@ mod tests {
|
|||
let (cb, _) = fake_compact_block(
|
||||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
extfvk.clone(),
|
||||
&dfvk,
|
||||
value,
|
||||
);
|
||||
|
||||
let (cb2, _) =
|
||||
fake_compact_block(sapling_activation_height() + 1, cb.hash(), extfvk, value2);
|
||||
fake_compact_block(sapling_activation_height() + 1, cb.hash(), &dfvk, value2);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
insert_into_cache(&db_cache, &cb2);
|
||||
|
||||
|
@ -389,14 +389,14 @@ mod tests {
|
|||
init_wallet_db(&db_data).unwrap();
|
||||
|
||||
// Add an account to the wallet
|
||||
let (extfvk, _taddr) = init_test_accounts_table(&db_data);
|
||||
let (dfvk, _taddr) = init_test_accounts_table(&db_data);
|
||||
|
||||
// Create a block with height SAPLING_ACTIVATION_HEIGHT
|
||||
let value = Amount::from_u64(50000).unwrap();
|
||||
let (cb1, _) = fake_compact_block(
|
||||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
extfvk.clone(),
|
||||
&dfvk,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb1);
|
||||
|
@ -405,14 +405,10 @@ mod tests {
|
|||
assert_eq!(get_balance(&db_data, AccountId::from(0)).unwrap(), value);
|
||||
|
||||
// We cannot scan a block of height SAPLING_ACTIVATION_HEIGHT + 2 next
|
||||
let (cb2, _) = fake_compact_block(
|
||||
sapling_activation_height() + 1,
|
||||
cb1.hash(),
|
||||
extfvk.clone(),
|
||||
value,
|
||||
);
|
||||
let (cb2, _) =
|
||||
fake_compact_block(sapling_activation_height() + 1, cb1.hash(), &dfvk, value);
|
||||
let (cb3, _) =
|
||||
fake_compact_block(sapling_activation_height() + 2, cb2.hash(), extfvk, value);
|
||||
fake_compact_block(sapling_activation_height() + 2, cb2.hash(), &dfvk, value);
|
||||
insert_into_cache(&db_cache, &cb3);
|
||||
match scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None) {
|
||||
Err(SqliteClientError::BackendError(e)) => {
|
||||
|
@ -448,7 +444,7 @@ mod tests {
|
|||
init_wallet_db(&db_data).unwrap();
|
||||
|
||||
// Add an account to the wallet
|
||||
let (extfvk, _taddr) = init_test_accounts_table(&db_data);
|
||||
let (dfvk, _taddr) = init_test_accounts_table(&db_data);
|
||||
|
||||
// Account balance should be zero
|
||||
assert_eq!(
|
||||
|
@ -461,7 +457,7 @@ mod tests {
|
|||
let (cb, _) = fake_compact_block(
|
||||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
extfvk.clone(),
|
||||
&dfvk,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -476,7 +472,7 @@ mod tests {
|
|||
// Create a second fake CompactBlock sending more value to the address
|
||||
let value2 = Amount::from_u64(7).unwrap();
|
||||
let (cb2, _) =
|
||||
fake_compact_block(sapling_activation_height() + 1, cb.hash(), extfvk, value2);
|
||||
fake_compact_block(sapling_activation_height() + 1, cb.hash(), &dfvk, value2);
|
||||
insert_into_cache(&db_cache, &cb2);
|
||||
|
||||
// Scan the cache again
|
||||
|
@ -500,7 +496,7 @@ mod tests {
|
|||
init_wallet_db(&db_data).unwrap();
|
||||
|
||||
// Add an account to the wallet
|
||||
let (extfvk, _taddr) = init_test_accounts_table(&db_data);
|
||||
let (dfvk, _taddr) = init_test_accounts_table(&db_data);
|
||||
|
||||
// Account balance should be zero
|
||||
assert_eq!(
|
||||
|
@ -513,7 +509,7 @@ mod tests {
|
|||
let (cb, nf) = fake_compact_block(
|
||||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
extfvk.clone(),
|
||||
&dfvk,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -535,7 +531,7 @@ mod tests {
|
|||
sapling_activation_height() + 1,
|
||||
cb.hash(),
|
||||
(nf, value),
|
||||
extfvk,
|
||||
&dfvk,
|
||||
to2,
|
||||
value2,
|
||||
),
|
||||
|
|
|
@ -745,8 +745,8 @@ mod tests {
|
|||
legacy::TransparentAddress,
|
||||
memo::MemoBytes,
|
||||
sapling::{
|
||||
note_encryption::sapling_note_encryption, util::generate_random_rseed, Note, Nullifier,
|
||||
PaymentAddress,
|
||||
keys::DiversifiableFullViewingKey, note_encryption::sapling_note_encryption,
|
||||
util::generate_random_rseed, Note, Nullifier, PaymentAddress,
|
||||
},
|
||||
transaction::components::Amount,
|
||||
zip32::ExtendedFullViewingKey,
|
||||
|
@ -783,11 +783,11 @@ mod tests {
|
|||
#[cfg(test)]
|
||||
pub(crate) fn init_test_accounts_table(
|
||||
db_data: &WalletDb<Network>,
|
||||
) -> (ExtendedFullViewingKey, Option<TransparentAddress>) {
|
||||
) -> (DiversifiableFullViewingKey, Option<TransparentAddress>) {
|
||||
let seed = [0u8; 32];
|
||||
let account = AccountId::from(0);
|
||||
let extsk = sapling::spending_key(&seed, network().coin_type(), account);
|
||||
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||
let dfvk = DiversifiableFullViewingKey::from(ExtendedFullViewingKey::from(&extsk));
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
let (tkey, taddr) = {
|
||||
|
@ -804,13 +804,13 @@ mod tests {
|
|||
let ufvk = UnifiedFullViewingKey::new(
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
tkey,
|
||||
Some(extfvk.clone()),
|
||||
Some(dfvk.clone()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
init_accounts_table(db_data, &[ufvk]).unwrap();
|
||||
|
||||
(extfvk, taddr)
|
||||
(dfvk, taddr)
|
||||
}
|
||||
|
||||
/// Create a fake CompactBlock at the given height, containing a single output paying
|
||||
|
@ -818,10 +818,10 @@ mod tests {
|
|||
pub(crate) fn fake_compact_block(
|
||||
height: BlockHeight,
|
||||
prev_hash: BlockHash,
|
||||
extfvk: ExtendedFullViewingKey,
|
||||
dfvk: &DiversifiableFullViewingKey,
|
||||
value: Amount,
|
||||
) -> (CompactBlock, Nullifier) {
|
||||
let to = extfvk.default_address().1;
|
||||
let to = dfvk.default_address().1;
|
||||
|
||||
// Create a fake Note for the account
|
||||
let mut rng = OsRng;
|
||||
|
@ -833,7 +833,7 @@ mod tests {
|
|||
rseed,
|
||||
};
|
||||
let encryptor = sapling_note_encryption::<_, Network>(
|
||||
Some(extfvk.fvk.ovk),
|
||||
Some(dfvk.fvk().ovk),
|
||||
note.clone(),
|
||||
to,
|
||||
MemoBytes::empty(),
|
||||
|
@ -859,7 +859,7 @@ mod tests {
|
|||
rng.fill_bytes(&mut cb.hash);
|
||||
cb.prevHash.extend_from_slice(&prev_hash.0);
|
||||
cb.vtx.push(ctx);
|
||||
(cb, note.nf(&extfvk.fvk.vk, 0))
|
||||
(cb, note.nf(&dfvk.fvk().vk, 0))
|
||||
}
|
||||
|
||||
/// Create a fake CompactBlock at the given height, spending a single note from the
|
||||
|
@ -868,7 +868,7 @@ mod tests {
|
|||
height: BlockHeight,
|
||||
prev_hash: BlockHash,
|
||||
(nf, in_value): (Nullifier, Amount),
|
||||
extfvk: ExtendedFullViewingKey,
|
||||
dfvk: &DiversifiableFullViewingKey,
|
||||
to: PaymentAddress,
|
||||
value: Amount,
|
||||
) -> CompactBlock {
|
||||
|
@ -893,7 +893,7 @@ mod tests {
|
|||
rseed,
|
||||
};
|
||||
let encryptor = sapling_note_encryption::<_, Network>(
|
||||
Some(extfvk.fvk.ovk),
|
||||
Some(dfvk.fvk().ovk),
|
||||
note.clone(),
|
||||
to,
|
||||
MemoBytes::empty(),
|
||||
|
@ -912,7 +912,7 @@ mod tests {
|
|||
|
||||
// Create a fake Note for the change
|
||||
ctx.outputs.push({
|
||||
let change_addr = extfvk.default_address().1;
|
||||
let change_addr = dfvk.default_address().1;
|
||||
let rseed = generate_random_rseed(&network(), height, &mut rng);
|
||||
let note = Note {
|
||||
g_d: change_addr.diversifier().g_d().unwrap(),
|
||||
|
@ -921,7 +921,7 @@ mod tests {
|
|||
rseed,
|
||||
};
|
||||
let encryptor = sapling_note_encryption::<_, Network>(
|
||||
Some(extfvk.fvk.ovk),
|
||||
Some(dfvk.fvk().ovk),
|
||||
note.clone(),
|
||||
change_addr,
|
||||
MemoBytes::empty(),
|
||||
|
|
|
@ -17,7 +17,7 @@ use zcash_primitives::{
|
|||
consensus::{self, BlockHeight, BranchId, NetworkUpgrade, Parameters},
|
||||
memo::{Memo, MemoBytes},
|
||||
merkle_tree::{CommitmentTree, IncrementalWitness},
|
||||
sapling::{Node, Note, Nullifier, PaymentAddress},
|
||||
sapling::{keys::DiversifiableFullViewingKey, Node, Note, Nullifier, PaymentAddress},
|
||||
transaction::{components::Amount, Transaction, TxId},
|
||||
zip32::{AccountId, ExtendedFullViewingKey},
|
||||
};
|
||||
|
@ -172,28 +172,6 @@ pub fn get_address<P: consensus::Parameters>(
|
|||
})
|
||||
}
|
||||
|
||||
/// Returns the [`ExtendedFullViewingKey`]s for the wallet.
|
||||
///
|
||||
/// [`ExtendedFullViewingKey`]: zcash_primitives::zip32::ExtendedFullViewingKey
|
||||
#[deprecated(
|
||||
note = "This function will be removed in a future release. Use zcash_client_backend::data_api::WalletRead::get_unified_full_viewing_keys instead."
|
||||
)]
|
||||
pub fn get_extended_full_viewing_keys<P: consensus::Parameters>(
|
||||
wdb: &WalletDb<P>,
|
||||
) -> Result<HashMap<AccountId, ExtendedFullViewingKey>, SqliteClientError> {
|
||||
get_unified_full_viewing_keys(wdb).map(|ufvks| {
|
||||
ufvks
|
||||
.into_iter()
|
||||
.map(|(account, ufvk)| {
|
||||
(
|
||||
account,
|
||||
ufvk.sapling().cloned().expect("TODO: Add Orchard support"),
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the [`UnifiedFullViewingKey`]s for the wallet.
|
||||
pub(crate) fn get_unified_full_viewing_keys<P: consensus::Parameters>(
|
||||
wdb: &WalletDb<P>,
|
||||
|
@ -248,7 +226,10 @@ pub fn is_valid_account_extfvk<P: consensus::Parameters>(
|
|||
.map_err(SqliteClientError::from)
|
||||
.and_then(|row| {
|
||||
if let Some(ufvk) = row {
|
||||
ufvk.map(|ufvk| ufvk.sapling() == Some(extfvk))
|
||||
ufvk.map(|ufvk| {
|
||||
ufvk.sapling().map(|dfvk| dfvk.to_bytes())
|
||||
== Some(DiversifiableFullViewingKey::from(extfvk.clone()).to_bytes())
|
||||
})
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
|
|
|
@ -179,8 +179,8 @@ pub fn init_wallet_db<P>(wdb: &WalletDb<P>) -> Result<(), rusqlite::Error> {
|
|||
/// let seed = [0u8; 32]; // insecure; replace with a strong random seed
|
||||
/// let account = AccountId::from(0);
|
||||
/// let extsk = sapling::spending_key(&seed, Network::TestNetwork.coin_type(), account);
|
||||
/// let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||
/// let ufvk = UnifiedFullViewingKey::new(None, Some(extfvk)).unwrap();
|
||||
/// let dfvk = ExtendedFullViewingKey::from(&extsk).into();
|
||||
/// let ufvk = UnifiedFullViewingKey::new(None, Some(dfvk)).unwrap();
|
||||
/// init_accounts_table(&db_data, &[ufvk]).unwrap();
|
||||
/// # }
|
||||
/// ```
|
||||
|
@ -293,6 +293,7 @@ mod tests {
|
|||
use zcash_primitives::{
|
||||
block::BlockHash,
|
||||
consensus::{BlockHeight, Parameters},
|
||||
sapling::keys::DiversifiableFullViewingKey,
|
||||
zip32::ExtendedFullViewingKey,
|
||||
};
|
||||
|
||||
|
@ -319,7 +320,7 @@ mod tests {
|
|||
|
||||
// First call with data should initialise the accounts table
|
||||
let extsk = sapling::spending_key(&seed, network().coin_type(), account);
|
||||
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||
let dfvk = DiversifiableFullViewingKey::from(ExtendedFullViewingKey::from(&extsk));
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
let ufvk = UnifiedFullViewingKey::new(
|
||||
|
@ -328,12 +329,12 @@ mod tests {
|
|||
.unwrap()
|
||||
.to_account_pubkey(),
|
||||
),
|
||||
Some(extfvk),
|
||||
Some(dfvk),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
#[cfg(not(feature = "transparent-inputs"))]
|
||||
let ufvk = UnifiedFullViewingKey::new(Some(extfvk)).unwrap();
|
||||
let ufvk = UnifiedFullViewingKey::new(Some(dfvk), None).unwrap();
|
||||
|
||||
init_accounts_table(&db_data, &[ufvk.clone()]).unwrap();
|
||||
|
||||
|
|
|
@ -165,7 +165,10 @@ mod tests {
|
|||
block::BlockHash,
|
||||
consensus::{BlockHeight, BranchId, Parameters},
|
||||
legacy::TransparentAddress,
|
||||
sapling::{note_encryption::try_sapling_output_recovery, prover::TxProver},
|
||||
sapling::{
|
||||
keys::DiversifiableFullViewingKey, note_encryption::try_sapling_output_recovery,
|
||||
prover::TxProver,
|
||||
},
|
||||
transaction::{components::Amount, Transaction},
|
||||
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey},
|
||||
};
|
||||
|
@ -207,8 +210,8 @@ mod tests {
|
|||
// Add two accounts to the wallet
|
||||
let extsk0 = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId::from(0));
|
||||
let extsk1 = sapling::spending_key(&[1u8; 32], network().coin_type(), AccountId::from(1));
|
||||
let extfvk0 = ExtendedFullViewingKey::from(&extsk0);
|
||||
let extfvk1 = ExtendedFullViewingKey::from(&extsk1);
|
||||
let dfvk0 = DiversifiableFullViewingKey::from(ExtendedFullViewingKey::from(&extsk0));
|
||||
let dfvk1 = DiversifiableFullViewingKey::from(ExtendedFullViewingKey::from(&extsk1));
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
let ufvks = {
|
||||
|
@ -219,14 +222,14 @@ mod tests {
|
|||
transparent::AccountPrivKey::from_seed(&network(), &[1u8; 32], AccountId::from(1))
|
||||
.unwrap();
|
||||
[
|
||||
UnifiedFullViewingKey::new(Some(tsk0.to_account_pubkey()), Some(extfvk0)).unwrap(),
|
||||
UnifiedFullViewingKey::new(Some(tsk1.to_account_pubkey()), Some(extfvk1)).unwrap(),
|
||||
UnifiedFullViewingKey::new(Some(tsk0.to_account_pubkey()), Some(dfvk0)).unwrap(),
|
||||
UnifiedFullViewingKey::new(Some(tsk1.to_account_pubkey()), Some(dfvk1)).unwrap(),
|
||||
]
|
||||
};
|
||||
#[cfg(not(feature = "transparent-inputs"))]
|
||||
let ufvks = [
|
||||
UnifiedFullViewingKey::new(Some(extfvk0)).unwrap(),
|
||||
UnifiedFullViewingKey::new(Some(extfvk1)).unwrap(),
|
||||
UnifiedFullViewingKey::new(Some(dfvk0), None).unwrap(),
|
||||
UnifiedFullViewingKey::new(Some(dfvk1), None).unwrap(),
|
||||
];
|
||||
|
||||
init_accounts_table(&db_data, &ufvks).unwrap();
|
||||
|
@ -275,12 +278,12 @@ mod tests {
|
|||
|
||||
// Add an account to the wallet
|
||||
let extsk = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId::from(0));
|
||||
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||
let dfvk = DiversifiableFullViewingKey::from(ExtendedFullViewingKey::from(&extsk));
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
let ufvk = UnifiedFullViewingKey::new(None, Some(extfvk)).unwrap();
|
||||
let ufvk = UnifiedFullViewingKey::new(None, Some(dfvk)).unwrap();
|
||||
#[cfg(not(feature = "transparent-inputs"))]
|
||||
let ufvk = UnifiedFullViewingKey::new(Some(extfvk)).unwrap();
|
||||
let ufvk = UnifiedFullViewingKey::new(Some(dfvk)).unwrap();
|
||||
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
||||
let to = extsk.default_address().1.into();
|
||||
|
||||
|
@ -319,11 +322,11 @@ mod tests {
|
|||
|
||||
// Add an account to the wallet
|
||||
let extsk = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId::from(0));
|
||||
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||
let dfvk = DiversifiableFullViewingKey::from(ExtendedFullViewingKey::from(&extsk));
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
let ufvk = UnifiedFullViewingKey::new(None, Some(extfvk)).unwrap();
|
||||
let ufvk = UnifiedFullViewingKey::new(None, Some(dfvk)).unwrap();
|
||||
#[cfg(not(feature = "transparent-inputs"))]
|
||||
let ufvk = UnifiedFullViewingKey::new(Some(extfvk)).unwrap();
|
||||
let ufvk = UnifiedFullViewingKey::new(Some(dfvk)).unwrap();
|
||||
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
||||
let to = extsk.default_address().1.into();
|
||||
|
||||
|
@ -367,11 +370,11 @@ mod tests {
|
|||
|
||||
// Add an account to the wallet
|
||||
let extsk = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId::from(0));
|
||||
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||
let dfvk = DiversifiableFullViewingKey::from(ExtendedFullViewingKey::from(&extsk));
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
let ufvk = UnifiedFullViewingKey::new(None, Some(extfvk.clone())).unwrap();
|
||||
let ufvk = UnifiedFullViewingKey::new(None, Some(dfvk.clone())).unwrap();
|
||||
#[cfg(not(feature = "transparent-inputs"))]
|
||||
let ufvk = UnifiedFullViewingKey::new(Some(extfvk.clone())).unwrap();
|
||||
let ufvk = UnifiedFullViewingKey::new(Some(dfvk.clone())).unwrap();
|
||||
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
||||
|
||||
// Add funds to the wallet in a single note
|
||||
|
@ -379,7 +382,7 @@ mod tests {
|
|||
let (cb, _) = fake_compact_block(
|
||||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
extfvk.clone(),
|
||||
&dfvk,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -398,12 +401,7 @@ mod tests {
|
|||
);
|
||||
|
||||
// Add more funds to the wallet in a second note
|
||||
let (cb, _) = fake_compact_block(
|
||||
sapling_activation_height() + 1,
|
||||
cb.hash(),
|
||||
extfvk.clone(),
|
||||
value,
|
||||
);
|
||||
let (cb, _) = fake_compact_block(sapling_activation_height() + 1, cb.hash(), &dfvk, value);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
||||
|
||||
|
@ -446,12 +444,8 @@ mod tests {
|
|||
// Mine blocks SAPLING_ACTIVATION_HEIGHT + 2 to 9 until just before the second
|
||||
// note is verified
|
||||
for i in 2..10 {
|
||||
let (cb, _) = fake_compact_block(
|
||||
sapling_activation_height() + i,
|
||||
cb.hash(),
|
||||
extfvk.clone(),
|
||||
value,
|
||||
);
|
||||
let (cb, _) =
|
||||
fake_compact_block(sapling_activation_height() + i, cb.hash(), &dfvk, value);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
}
|
||||
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
||||
|
@ -477,8 +471,7 @@ mod tests {
|
|||
}
|
||||
|
||||
// Mine block 11 so that the second note becomes verified
|
||||
let (cb, _) =
|
||||
fake_compact_block(sapling_activation_height() + 10, cb.hash(), extfvk, value);
|
||||
let (cb, _) = fake_compact_block(sapling_activation_height() + 10, cb.hash(), &dfvk, value);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
||||
|
||||
|
@ -510,11 +503,11 @@ mod tests {
|
|||
|
||||
// Add an account to the wallet
|
||||
let extsk = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId::from(0));
|
||||
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||
let dfvk = DiversifiableFullViewingKey::from(ExtendedFullViewingKey::from(&extsk));
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
let ufvk = UnifiedFullViewingKey::new(None, Some(extfvk.clone())).unwrap();
|
||||
let ufvk = UnifiedFullViewingKey::new(None, Some(dfvk.clone())).unwrap();
|
||||
#[cfg(not(feature = "transparent-inputs"))]
|
||||
let ufvk = UnifiedFullViewingKey::new(Some(extfvk.clone())).unwrap();
|
||||
let ufvk = UnifiedFullViewingKey::new(Some(dfvk.clone())).unwrap();
|
||||
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
||||
|
||||
// Add funds to the wallet in a single note
|
||||
|
@ -522,7 +515,7 @@ mod tests {
|
|||
let (cb, _) = fake_compact_block(
|
||||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
extfvk,
|
||||
&dfvk,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -573,7 +566,7 @@ mod tests {
|
|||
let (cb, _) = fake_compact_block(
|
||||
sapling_activation_height() + i,
|
||||
cb.hash(),
|
||||
ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[i as u8])),
|
||||
&ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[i as u8])).into(),
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -604,7 +597,7 @@ mod tests {
|
|||
let (cb, _) = fake_compact_block(
|
||||
sapling_activation_height() + 22,
|
||||
cb.hash(),
|
||||
ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[22])),
|
||||
&ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[22])).into(),
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -639,11 +632,11 @@ mod tests {
|
|||
|
||||
// Add an account to the wallet
|
||||
let extsk = sapling::spending_key(&[0u8; 32], network.coin_type(), AccountId::from(0));
|
||||
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||
let dfvk = DiversifiableFullViewingKey::from(ExtendedFullViewingKey::from(&extsk));
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
let ufvk = UnifiedFullViewingKey::new(None, Some(extfvk.clone())).unwrap();
|
||||
let ufvk = UnifiedFullViewingKey::new(None, Some(dfvk.clone())).unwrap();
|
||||
#[cfg(not(feature = "transparent-inputs"))]
|
||||
let ufvk = UnifiedFullViewingKey::new(Some(extfvk.clone())).unwrap();
|
||||
let ufvk = UnifiedFullViewingKey::new(Some(dfvk.clone())).unwrap();
|
||||
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
||||
|
||||
// Add funds to the wallet in a single note
|
||||
|
@ -651,7 +644,7 @@ mod tests {
|
|||
let (cb, _) = fake_compact_block(
|
||||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
extfvk.clone(),
|
||||
&dfvk,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -708,7 +701,7 @@ mod tests {
|
|||
try_sapling_output_recovery(
|
||||
&network,
|
||||
sapling_activation_height(),
|
||||
&extfvk.fvk.ovk,
|
||||
&dfvk.fvk().ovk,
|
||||
output,
|
||||
)
|
||||
};
|
||||
|
@ -725,7 +718,7 @@ mod tests {
|
|||
let (cb, _) = fake_compact_block(
|
||||
sapling_activation_height() + i,
|
||||
cb.hash(),
|
||||
ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[i as u8])),
|
||||
&ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[i as u8])).into(),
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -749,11 +742,11 @@ mod tests {
|
|||
|
||||
// Add an account to the wallet
|
||||
let extsk = sapling::spending_key(&[0u8; 32], network().coin_type(), AccountId::from(0));
|
||||
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||
let dfvk = DiversifiableFullViewingKey::from(ExtendedFullViewingKey::from(&extsk));
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
let ufvk = UnifiedFullViewingKey::new(None, Some(extfvk.clone())).unwrap();
|
||||
let ufvk = UnifiedFullViewingKey::new(None, Some(dfvk.clone())).unwrap();
|
||||
#[cfg(not(feature = "transparent-inputs"))]
|
||||
let ufvk = UnifiedFullViewingKey::new(Some(extfvk.clone())).unwrap();
|
||||
let ufvk = UnifiedFullViewingKey::new(Some(dfvk.clone())).unwrap();
|
||||
init_accounts_table(&db_data, &[ufvk]).unwrap();
|
||||
|
||||
// Add funds to the wallet in a single note
|
||||
|
@ -761,7 +754,7 @@ mod tests {
|
|||
let (cb, _) = fake_compact_block(
|
||||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
extfvk,
|
||||
&dfvk,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
|
|
@ -276,6 +276,13 @@ impl DiversifiableFullViewingKey {
|
|||
zip32::sapling_find_address(&self.fvk, &self.dk, j)
|
||||
}
|
||||
|
||||
/// Returns the payment address corresponding to the smallest valid diversifier index,
|
||||
/// along with that index.
|
||||
// TODO: See if this is only used in tests.
|
||||
pub fn default_address(&self) -> (zip32::DiversifierIndex, PaymentAddress) {
|
||||
zip32::sapling_default_address(&self.fvk, &self.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
|
||||
|
|
Loading…
Reference in New Issue