Add a test for unified address derivation.

This commit is contained in:
Kris Nuttycombe 2022-10-07 15:29:35 -06:00
parent 34a7abd653
commit bd8472535c
4 changed files with 100 additions and 10 deletions

View File

@ -260,7 +260,7 @@ mod tests {
#[test] #[test]
fn ua_parsing() { fn ua_parsing() {
for tv in test_vectors::UNIFIED { for tv in test_vectors::UNIFIED {
match RecipientAddress::decode(&MAIN_NETWORK, &tv.unified_addr) { match RecipientAddress::decode(&MAIN_NETWORK, tv.unified_addr) {
Some(RecipientAddress::Unified(ua)) => { Some(RecipientAddress::Unified(ua)) => {
assert_eq!( assert_eq!(
ua.transparent().is_some(), ua.transparent().is_some(),

View File

@ -591,10 +591,14 @@ mod tests {
#[cfg(feature = "transparent-inputs")] #[cfg(feature = "transparent-inputs")]
use { use {
crate::encoding::AddressCodec, crate::{address::RecipientAddress, encoding::AddressCodec},
zcash_primitives::legacy::{ zcash_address::test_vectors,
self, zcash_primitives::{
keys::{AccountPrivKey, IncomingViewingKey}, legacy::{
self,
keys::{AccountPrivKey, IncomingViewingKey},
},
zip32::DiversifierIndex,
}, },
}; };
@ -699,6 +703,50 @@ mod tests {
assert_eq!(decoded_with_t.unknown.len(), 1); assert_eq!(decoded_with_t.unknown.len(), 1);
} }
#[test]
#[cfg(feature = "transparent-inputs")]
fn ufvk_derivation() {
for tv in test_vectors::UNIFIED {
let usk = UnifiedSpendingKey::from_seed(
&MAIN_NETWORK,
&tv.root_seed,
AccountId::from(tv.account),
)
.expect("seed produced a valid unified spending key");
let d_idx = DiversifierIndex::from(tv.diversifier_index);
let ufvk = usk.to_unified_full_viewing_key();
// The test vectors contain some diversifier indices that do not generate
// valid Sapling addresses, so skip those.
if ufvk.sapling().unwrap().address(d_idx).is_none() {
continue;
}
let ua = ufvk.address(d_idx).unwrap_or_else(|| panic!("diversifier index {} should have produced a valid unified address for account {}",
tv.diversifier_index, tv.account));
match RecipientAddress::decode(&MAIN_NETWORK, tv.unified_addr) {
Some(RecipientAddress::Unified(tvua)) => {
// We always derive transparent and Sapling receivers, but not
// every value in the test vectors have these present.
if tvua.transparent().is_some() {
assert_eq!(tvua.transparent(), ua.transparent());
}
if tvua.sapling().is_some() {
assert_eq!(tvua.sapling(), ua.sapling());
}
}
_other => {
panic!(
"{} did not decode to a valid unified address",
tv.unified_addr
);
}
}
}
}
proptest! { proptest! {
#[test] #[test]
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]

View File

@ -37,6 +37,7 @@ regex = "1.4"
tempfile = "3" tempfile = "3"
zcash_proofs = { version = "0.7", path = "../zcash_proofs" } zcash_proofs = { version = "0.7", path = "../zcash_proofs" }
zcash_primitives = { version = "0.7", path = "../zcash_primitives", features = ["test-dependencies"] } zcash_primitives = { version = "0.7", path = "../zcash_primitives", features = ["test-dependencies"] }
zcash_address = { version = "0.1", path = "../components/zcash_address", features = ["test-dependencies"] }
[features] [features]
mainnet = [] mainnet = []

View File

@ -288,6 +288,8 @@ mod tests {
use std::collections::HashMap; use std::collections::HashMap;
use tempfile::NamedTempFile; use tempfile::NamedTempFile;
use zcash_address::test_vectors;
use zcash_client_backend::{ use zcash_client_backend::{
address::RecipientAddress, address::RecipientAddress,
encoding::{encode_extended_full_viewing_key, encode_payment_address}, encoding::{encode_extended_full_viewing_key, encode_payment_address},
@ -296,16 +298,19 @@ mod tests {
use zcash_primitives::{ use zcash_primitives::{
block::BlockHash, block::BlockHash,
consensus::{BlockHeight, BranchId, Parameters}, consensus::{BlockHeight, BranchId, Network, Parameters},
transaction::{TransactionData, TxVersion}, transaction::{TransactionData, TxVersion},
zip32::sapling::{DiversifiableFullViewingKey, ExtendedFullViewingKey}, zip32::{
sapling::{DiversifiableFullViewingKey, ExtendedFullViewingKey},
DiversifierIndex,
},
}; };
use crate::{ use crate::{
error::SqliteClientError, error::SqliteClientError,
tests::{self, network}, tests::{self, network},
wallet::get_address, wallet::{self, get_address},
AccountId, WalletDb, AccountId, WalletDb, WalletWrite,
}; };
use super::{init_accounts_table, init_blocks_table, init_wallet_db}; use super::{init_accounts_table, init_blocks_table, init_wallet_db};
@ -1056,7 +1061,7 @@ mod tests {
fn init_accounts_table_stores_correct_address() { fn init_accounts_table_stores_correct_address() {
let data_file = NamedTempFile::new().unwrap(); let data_file = NamedTempFile::new().unwrap();
let mut db_data = WalletDb::for_path(data_file.path(), tests::network()).unwrap(); let mut db_data = WalletDb::for_path(data_file.path(), tests::network()).unwrap();
init_wallet_db(&mut db_data, Some(Secret::new(vec![]))).unwrap(); init_wallet_db(&mut db_data, None).unwrap();
let seed = [0u8; 32]; let seed = [0u8; 32];
@ -1072,4 +1077,40 @@ mod tests {
let pa = get_address(&db_data, AccountId::from(0)).unwrap(); let pa = get_address(&db_data, AccountId::from(0)).unwrap();
assert_eq!(pa.unwrap(), expected_address); assert_eq!(pa.unwrap(), expected_address);
} }
#[test]
#[cfg(feature = "transparent-inputs")]
fn account_produces_expected_ua_sequence() {
let data_file = NamedTempFile::new().unwrap();
let mut db_data = WalletDb::for_path(data_file.path(), Network::MainNetwork).unwrap();
init_wallet_db(&mut db_data, None).unwrap();
let mut ops = db_data.get_update_ops().unwrap();
let seed = test_vectors::UNIFIED[0].root_seed;
let (account, _usk) = ops.create_account(&Secret::new(seed.to_vec())).unwrap();
assert_eq!(account, AccountId::from(0u32));
for tv in &test_vectors::UNIFIED[..3] {
if let Some(RecipientAddress::Unified(tvua)) =
RecipientAddress::decode(&Network::MainNetwork, tv.unified_addr)
{
let (ua, di) = wallet::get_current_address(&db_data, account)
.unwrap()
.expect("create_account generated the first address");
assert_eq!(DiversifierIndex::from(tv.diversifier_index), di);
assert_eq!(tvua.transparent(), ua.transparent());
assert_eq!(tvua.sapling(), ua.sapling());
assert_eq!(tv.unified_addr, ua.encode(&Network::MainNetwork));
ops.get_next_available_address(account)
.unwrap()
.expect("get_next_available_address generated an address");
} else {
panic!(
"{} did not decode to a valid unified address",
tv.unified_addr
);
}
}
}
} }