From be4c19d82e4003cf4f4443239424d8590b7f96fc Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Thu, 8 Dec 2022 11:52:11 -0700 Subject: [PATCH 1/2] Fix transparent balance error when the wallet is empty. Fixes #724 --- zcash_client_sqlite/src/wallet.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/zcash_client_sqlite/src/wallet.rs b/zcash_client_sqlite/src/wallet.rs index fa6044f89..eb6f6f3d6 100644 --- a/zcash_client_sqlite/src/wallet.rs +++ b/zcash_client_sqlite/src/wallet.rs @@ -1026,7 +1026,8 @@ pub(crate) fn get_transparent_balances( ON tx.id_tx = u.spent_in_tx WHERE u.received_by_account = ? AND u.height <= ? - AND tx.block IS NULL", + AND tx.block IS NULL + GROUP BY u.address", )?; let mut res = HashMap::new(); @@ -1371,6 +1372,11 @@ mod tests { let uaddr = db_data.get_current_address(account_id).unwrap().unwrap(); let taddr = uaddr.transparent().unwrap(); + let bal_absent = db_data + .get_transparent_balances(account_id, BlockHeight::from_u32(12345)) + .unwrap(); + assert!(bal_absent.is_empty()); + let utxo = WalletTransparentOutput::from_parts( OutPoint::new([1u8; 32], 1), TxOut { @@ -1421,6 +1427,11 @@ mod tests { } )); + assert_matches!( + db_data.get_transparent_balances(account_id, BlockHeight::from_u32(34567)), + Ok(h) if h.get(taddr) == Amount::from_u64(100000).ok().as_ref() + ); + // Artificially delete the address from the addresses table so that // we can ensure the update fails if the join doesn't work. db_data From fff6983512ea949f45f746b9dca805c4653df79d Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Thu, 8 Dec 2022 12:06:32 -0700 Subject: [PATCH 2/2] Replace a number of uses of `assert!(matches!(...))` with `assert_matches!(...)` The remaining uses of `assert!(matches!(...))` are all in cases where for some reason the `assert_matches` macro interferes with correct type inference. --- zcash_client_sqlite/src/wallet.rs | 14 +++++++------- zcash_client_sqlite/src/wallet/init.rs | 4 ++-- zcash_client_sqlite/src/wallet/transact.rs | 4 ++-- zcash_primitives/Cargo.toml | 1 + zcash_primitives/src/zip32.rs | 3 ++- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/zcash_client_sqlite/src/wallet.rs b/zcash_client_sqlite/src/wallet.rs index eb6f6f3d6..1ce2aa87f 100644 --- a/zcash_client_sqlite/src/wallet.rs +++ b/zcash_client_sqlite/src/wallet.rs @@ -1388,7 +1388,7 @@ mod tests { .unwrap(); let res0 = super::put_received_transparent_utxo(&mut ops, &utxo); - assert!(matches!(res0, Ok(_))); + assert_matches!(res0, Ok(_)); // Change the mined height of the UTXO and upsert; we should get back // the same utxoid @@ -1402,9 +1402,9 @@ mod tests { ) .unwrap(); let res1 = super::put_received_transparent_utxo(&mut ops, &utxo2); - assert!(matches!(res1, Ok(id) if id == res0.unwrap())); + assert_matches!(res1, Ok(id) if id == res0.unwrap()); - assert!(matches!( + assert_matches!( super::get_unspent_transparent_outputs( &db_data, taddr, @@ -1412,9 +1412,9 @@ mod tests { &[] ), Ok(utxos) if utxos.is_empty() - )); + ); - assert!(matches!( + assert_matches!( super::get_unspent_transparent_outputs( &db_data, taddr, @@ -1425,7 +1425,7 @@ mod tests { utxos.len() == 1 && utxos.iter().any(|rutxo| rutxo.height() == utxo2.height()) } - )); + ); assert_matches!( db_data.get_transparent_balances(account_id, BlockHeight::from_u32(34567)), @@ -1443,6 +1443,6 @@ mod tests { .unwrap(); let res2 = super::put_received_transparent_utxo(&mut ops, &utxo2); - assert!(matches!(res2, Err(_))); + assert_matches!(res2, Err(_)); } } diff --git a/zcash_client_sqlite/src/wallet/init.rs b/zcash_client_sqlite/src/wallet/init.rs index 125488e7f..c6a8e529e 100644 --- a/zcash_client_sqlite/src/wallet/init.rs +++ b/zcash_client_sqlite/src/wallet/init.rs @@ -1070,10 +1070,10 @@ mod tests { }; // should fail if we have a gap - assert!(matches!( + assert_matches!( init_accounts_table(&db_data, &ufvks(&[0, 2])), Err(SqliteClientError::AccountIdDiscontinuity) - )); + ); // should succeed if there are no gaps assert!(init_accounts_table(&db_data, &ufvks(&[0, 1, 2])).is_ok()); diff --git a/zcash_client_sqlite/src/wallet/transact.rs b/zcash_client_sqlite/src/wallet/transact.rs index 23e87c5de..a28268d24 100644 --- a/zcash_client_sqlite/src/wallet/transact.rs +++ b/zcash_client_sqlite/src/wallet/transact.rs @@ -769,7 +769,7 @@ mod tests { ); let to = TransparentAddress::PublicKey([7; 20]).into(); - assert!(matches!( + assert_matches!( create_spend_to_address( &mut db_write, &tests::network(), @@ -782,7 +782,7 @@ mod tests { 10, ), Ok(_) - )); + ); } #[test] diff --git a/zcash_primitives/Cargo.toml b/zcash_primitives/Cargo.toml index e045a20ee..41f7ae208 100644 --- a/zcash_primitives/Cargo.toml +++ b/zcash_primitives/Cargo.toml @@ -88,6 +88,7 @@ features = ["pre-zip-212"] chacha20poly1305 = "0.10" criterion = "0.3" proptest = "1.0.0" +assert_matches = "1.3.0" rand_xorshift = "0.3" orchard = { version = "0.3", features = ["test-dependencies"] } diff --git a/zcash_primitives/src/zip32.rs b/zcash_primitives/src/zip32.rs index c763177e2..d2778523e 100644 --- a/zcash_primitives/src/zip32.rs +++ b/zcash_primitives/src/zip32.rs @@ -158,6 +158,7 @@ memuse::impl_no_dynamic_usage!(Scope); #[cfg(test)] mod tests { use super::DiversifierIndex; + use assert_matches::assert_matches; #[test] fn diversifier_index_to_u32() { @@ -174,6 +175,6 @@ mod tests { let too_big = DiversifierIndex([ 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]); - assert!(matches!(u32::try_from(too_big), Err(_))); + assert_matches!(u32::try_from(too_big), Err(_)); } }