Test spending of change notes.
This commit is contained in:
parent
18e61346cc
commit
cd29022233
|
@ -236,7 +236,7 @@ mod tests {
|
|||
error::SqliteClientError,
|
||||
tests::{
|
||||
self, fake_compact_block, fake_compact_block_spending, init_test_accounts_table,
|
||||
insert_into_cache, sapling_activation_height,
|
||||
insert_into_cache, sapling_activation_height, AddressType,
|
||||
},
|
||||
wallet::{get_balance, init::init_wallet_db, rewind_to_height},
|
||||
AccountId, BlockDb, NoteId, WalletDb,
|
||||
|
@ -268,6 +268,7 @@ mod tests {
|
|||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
Amount::from_u64(5).unwrap(),
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -297,6 +298,7 @@ mod tests {
|
|||
sapling_activation_height() + 1,
|
||||
cb.hash(),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
Amount::from_u64(7).unwrap(),
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb2);
|
||||
|
@ -339,12 +341,14 @@ mod tests {
|
|||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
Amount::from_u64(5).unwrap(),
|
||||
);
|
||||
let (cb2, _) = fake_compact_block(
|
||||
sapling_activation_height() + 1,
|
||||
cb.hash(),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
Amount::from_u64(7).unwrap(),
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -367,12 +371,14 @@ mod tests {
|
|||
sapling_activation_height() + 2,
|
||||
BlockHash([1; 32]),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
Amount::from_u64(8).unwrap(),
|
||||
);
|
||||
let (cb4, _) = fake_compact_block(
|
||||
sapling_activation_height() + 3,
|
||||
cb3.hash(),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
Amount::from_u64(3).unwrap(),
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb3);
|
||||
|
@ -409,12 +415,14 @@ mod tests {
|
|||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
Amount::from_u64(5).unwrap(),
|
||||
);
|
||||
let (cb2, _) = fake_compact_block(
|
||||
sapling_activation_height() + 1,
|
||||
cb.hash(),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
Amount::from_u64(7).unwrap(),
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -437,12 +445,14 @@ mod tests {
|
|||
sapling_activation_height() + 2,
|
||||
cb2.hash(),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
Amount::from_u64(8).unwrap(),
|
||||
);
|
||||
let (cb4, _) = fake_compact_block(
|
||||
sapling_activation_height() + 3,
|
||||
BlockHash([1; 32]),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
Amount::from_u64(3).unwrap(),
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb3);
|
||||
|
@ -487,11 +497,17 @@ mod tests {
|
|||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
value,
|
||||
);
|
||||
|
||||
let (cb2, _) =
|
||||
fake_compact_block(sapling_activation_height() + 1, cb.hash(), &dfvk, value2);
|
||||
let (cb2, _) = fake_compact_block(
|
||||
sapling_activation_height() + 1,
|
||||
cb.hash(),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
value2,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
insert_into_cache(&db_cache, &cb2);
|
||||
|
||||
|
@ -549,6 +565,7 @@ mod tests {
|
|||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb1);
|
||||
|
@ -557,10 +574,20 @@ 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(), &dfvk, value);
|
||||
let (cb3, _) =
|
||||
fake_compact_block(sapling_activation_height() + 2, cb2.hash(), &dfvk, value);
|
||||
let (cb2, _) = fake_compact_block(
|
||||
sapling_activation_height() + 1,
|
||||
cb1.hash(),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
value,
|
||||
);
|
||||
let (cb3, _) = fake_compact_block(
|
||||
sapling_activation_height() + 2,
|
||||
cb2.hash(),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb3);
|
||||
match scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None) {
|
||||
Err(SqliteClientError::BackendError(e)) => {
|
||||
|
@ -610,6 +637,7 @@ mod tests {
|
|||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -623,8 +651,13 @@ 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(), &dfvk, value2);
|
||||
let (cb2, _) = fake_compact_block(
|
||||
sapling_activation_height() + 1,
|
||||
cb.hash(),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
value2,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb2);
|
||||
|
||||
// Scan the cache again
|
||||
|
@ -662,6 +695,7 @@ mod tests {
|
|||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
|
|
@ -933,7 +933,7 @@ mod tests {
|
|||
PaymentAddress,
|
||||
},
|
||||
transaction::components::Amount,
|
||||
zip32::sapling::DiversifiableFullViewingKey,
|
||||
zip32::{sapling::DiversifiableFullViewingKey, DiversifierIndex},
|
||||
};
|
||||
|
||||
use zcash_client_backend::{
|
||||
|
@ -1018,15 +1018,27 @@ mod tests {
|
|||
(ufvk, taddr)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) enum AddressType {
|
||||
DefaultExternal,
|
||||
DiversifiedExternal(DiversifierIndex),
|
||||
Internal,
|
||||
}
|
||||
|
||||
/// Create a fake CompactBlock at the given height, containing a single output paying
|
||||
/// the given address. Returns the CompactBlock and the nullifier for the new note.
|
||||
/// an address. Returns the CompactBlock and the nullifier for the new note.
|
||||
pub(crate) fn fake_compact_block(
|
||||
height: BlockHeight,
|
||||
prev_hash: BlockHash,
|
||||
dfvk: &DiversifiableFullViewingKey,
|
||||
req: AddressType,
|
||||
value: Amount,
|
||||
) -> (CompactBlock, Nullifier) {
|
||||
let to = dfvk.default_address().1;
|
||||
let to = match req {
|
||||
AddressType::DefaultExternal => dfvk.default_address().1,
|
||||
AddressType::DiversifiedExternal(idx) => dfvk.find_address(idx).unwrap().1,
|
||||
AddressType::Internal => dfvk.change_address().1,
|
||||
};
|
||||
|
||||
// Create a fake Note for the account
|
||||
let mut rng = OsRng;
|
||||
|
@ -1262,6 +1274,7 @@ mod tests {
|
|||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
|
|
@ -181,7 +181,10 @@ mod tests {
|
|||
|
||||
use crate::{
|
||||
chain::init::init_cache_database,
|
||||
tests::{self, fake_compact_block, insert_into_cache, network, sapling_activation_height},
|
||||
tests::{
|
||||
self, fake_compact_block, insert_into_cache, network, sapling_activation_height,
|
||||
AddressType,
|
||||
},
|
||||
wallet::{
|
||||
get_balance, get_balance_at,
|
||||
init::{init_blocks_table, init_wallet_db},
|
||||
|
@ -341,6 +344,7 @@ mod tests {
|
|||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -356,7 +360,13 @@ mod tests {
|
|||
);
|
||||
|
||||
// Add more funds to the wallet in a second note
|
||||
let (cb, _) = fake_compact_block(sapling_activation_height() + 1, cb.hash(), &dfvk, value);
|
||||
let (cb, _) = fake_compact_block(
|
||||
sapling_activation_height() + 1,
|
||||
cb.hash(),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
||||
|
||||
|
@ -399,8 +409,13 @@ 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(), &dfvk, value);
|
||||
let (cb, _) = fake_compact_block(
|
||||
sapling_activation_height() + i,
|
||||
cb.hash(),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
}
|
||||
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
||||
|
@ -429,7 +444,13 @@ mod tests {
|
|||
));
|
||||
|
||||
// Mine block 11 so that the second note becomes verified
|
||||
let (cb, _) = fake_compact_block(sapling_activation_height() + 10, cb.hash(), &dfvk, value);
|
||||
let (cb, _) = fake_compact_block(
|
||||
sapling_activation_height() + 10,
|
||||
cb.hash(),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
||||
|
||||
|
@ -472,6 +493,7 @@ mod tests {
|
|||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -526,6 +548,7 @@ mod tests {
|
|||
sapling_activation_height() + i,
|
||||
cb.hash(),
|
||||
&ExtendedSpendingKey::master(&[i as u8]).to_diversifiable_full_viewing_key(),
|
||||
AddressType::DefaultExternal,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -559,6 +582,7 @@ mod tests {
|
|||
sapling_activation_height() + 22,
|
||||
cb.hash(),
|
||||
&ExtendedSpendingKey::master(&[22]).to_diversifiable_full_viewing_key(),
|
||||
AddressType::DefaultExternal,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -602,6 +626,7 @@ mod tests {
|
|||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -675,6 +700,7 @@ mod tests {
|
|||
sapling_activation_height() + i,
|
||||
cb.hash(),
|
||||
&ExtendedSpendingKey::master(&[i as u8]).to_diversifiable_full_viewing_key(),
|
||||
AddressType::DefaultExternal,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
@ -708,6 +734,61 @@ mod tests {
|
|||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
&dfvk,
|
||||
AddressType::DefaultExternal,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
let mut db_write = db_data.get_update_ops().unwrap();
|
||||
scan_cached_blocks(&tests::network(), &db_cache, &mut db_write, None).unwrap();
|
||||
|
||||
// Verified balance matches total balance
|
||||
let (_, anchor_height) = db_data.get_target_and_anchor_heights(10).unwrap().unwrap();
|
||||
assert_eq!(get_balance(&db_data, AccountId::from(0)).unwrap(), value);
|
||||
assert_eq!(
|
||||
get_balance_at(&db_data, AccountId::from(0), anchor_height).unwrap(),
|
||||
value
|
||||
);
|
||||
|
||||
let to = TransparentAddress::PublicKey([7; 20]).into();
|
||||
assert!(matches!(
|
||||
create_spend_to_address(
|
||||
&mut db_write,
|
||||
&tests::network(),
|
||||
test_prover(),
|
||||
&usk,
|
||||
&to,
|
||||
Amount::from_u64(50000).unwrap(),
|
||||
None,
|
||||
OvkPolicy::Sender,
|
||||
10,
|
||||
),
|
||||
Ok(_)
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_to_address_spends_a_change_note() {
|
||||
let cache_file = NamedTempFile::new().unwrap();
|
||||
let db_cache = BlockDb(Connection::open(cache_file.path()).unwrap());
|
||||
init_cache_database(&db_cache).unwrap();
|
||||
|
||||
let data_file = NamedTempFile::new().unwrap();
|
||||
let mut db_data = WalletDb::for_path(data_file.path(), tests::network()).unwrap();
|
||||
init_wallet_db(&mut db_data, None).unwrap();
|
||||
|
||||
// Add an account to the wallet
|
||||
let mut ops = db_data.get_update_ops().unwrap();
|
||||
let seed = Secret::new([0u8; 32].to_vec());
|
||||
let (_, usk) = ops.create_account(&seed).unwrap();
|
||||
let dfvk = usk.sapling().to_diversifiable_full_viewing_key();
|
||||
|
||||
// Add funds to the wallet in a single note
|
||||
let value = Amount::from_u64(51000).unwrap();
|
||||
let (cb, _) = fake_compact_block(
|
||||
sapling_activation_height(),
|
||||
BlockHash([0; 32]),
|
||||
&dfvk,
|
||||
AddressType::Internal,
|
||||
value,
|
||||
);
|
||||
insert_into_cache(&db_cache, &cb);
|
||||
|
|
Loading…
Reference in New Issue