Add test for fee calculation in add_transaction_views migration.

This commit is contained in:
Kris Nuttycombe 2022-09-02 17:26:59 -06:00
parent b327bf7073
commit 7934e834d3
3 changed files with 126 additions and 25 deletions

View File

@ -14,19 +14,17 @@ use zcash_primitives::{
use super::super::{WalletMigration2, WalletMigrationError};
pub(super) struct Migration<P> {
pub(super) params: P,
pub(crate) fn migration_id() -> Uuid {
Uuid::parse_str("282fad2e-8372-4ca0-8bed-71821320909f").unwrap()
}
impl<P> Migration<P> {
fn id() -> Uuid {
Uuid::parse_str("282fad2e-8372-4ca0-8bed-71821320909f").unwrap()
}
pub(crate) struct Migration<P> {
pub(super) params: P,
}
impl<P> schemer::Migration for Migration<P> {
fn id(&self) -> Uuid {
Migration::<P>::id()
migration_id()
}
fn dependencies(&self) -> HashSet<Uuid> {
@ -97,7 +95,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
SUM(
CASE
WHEN sent_notes.memo IS NULL THEN 0
WHEN SUBSTR(sent_notes.memo, 0, 2) = X'F6' THEN 0
WHEN sent_notes.memo = X'F600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' THEN 0
ELSE 1
END
) AS memo_count,
@ -118,7 +116,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
SUM(
CASE
WHEN received_notes.memo IS NULL THEN 0
WHEN SUBSTR(received_notes.memo, 0, 2) = X'F6' THEN 0
WHEN received_notes.memo = X'F600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' THEN 0
ELSE 1
END
) AS memo_count,
@ -154,7 +152,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
received_notes.is_change AS is_change,
CASE
WHEN received_notes.memo IS NULL THEN 0
WHEN SUBSTR(received_notes.memo, 0, 2) = X'F6' THEN 0
WHEN received_notes.memo = X'F600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' THEN 0
ELSE 1
END AS memo_present
FROM transactions
@ -171,7 +169,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
false AS is_change,
CASE
WHEN sent_notes.memo IS NULL THEN 0
WHEN SUBSTR(sent_notes.memo, 0, 2) = X'F6' THEN 0
WHEN sent_notes.memo = X'F600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' THEN 0
ELSE 1
END AS memo_present
FROM transactions
@ -192,15 +190,29 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
#[cfg(test)]
mod tests {
use rusqlite::{self, NO_PARAMS};
use tempfile::NamedTempFile;
use crate::{
tests::{self},
wallet::init::init_wallet_db,
WalletDb,
#[cfg(feature = "transparent-inputs")]
use {
crate::wallet::init::{init_wallet_db_internal, WalletMigration2},
rusqlite::params,
zcash_client_backend::{encoding::AddressCodec, keys::UnifiedSpendingKey},
zcash_primitives::{
consensus::{BlockHeight, BranchId, Network},
legacy::{keys::IncomingViewingKey, Script},
transaction::{
components::{
transparent::{self, Authorized, OutPoint},
Amount, TxIn, TxOut,
},
TransactionData, TxVersion,
},
zip32::AccountId,
},
};
use crate::{tests, wallet::init::init_wallet_db, WalletDb};
#[test]
fn transaction_views() {
let data_file = NamedTempFile::new().unwrap();
@ -217,7 +229,7 @@ mod tests {
INSERT INTO sent_notes (tx, output_pool, output_index, from_account, address, value, memo)
VALUES (0, 2, 1, 0, '', 3, X'61');
INSERT INTO sent_notes (tx, output_pool, output_index, from_account, address, value, memo)
VALUES (0, 2, 2, 0, '', 0, X'f600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000');
VALUES (0, 2, 2, 0, '', 0, X'F600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000');
INSERT INTO received_notes (tx, output_index, account, diversifier, value, rcm, nf, is_change, memo)
VALUES (0, 0, 0, '', 5, '', 'a', false, X'62');
@ -276,4 +288,91 @@ mod tests {
}
assert_eq!(row_count, 1);
}
#[test]
#[cfg(feature = "transparent-inputs")]
fn migrate_from_wm2() {
let data_file = NamedTempFile::new().unwrap();
let mut db_data = WalletDb::for_path(data_file.path(), tests::network()).unwrap();
init_wallet_db_internal(&mut db_data, None, Some(WalletMigration2::<Network>::id()))
.unwrap();
// create a UTXO to spend
let tx = TransactionData::from_parts(
TxVersion::Sapling,
BranchId::Canopy,
0,
BlockHeight::from(3),
Some(transparent::Bundle {
vin: vec![TxIn {
prevout: OutPoint::new([1u8; 32], 1),
script_sig: Script(vec![]),
sequence: 0,
}],
vout: vec![TxOut {
value: Amount::from_i64(1100000000).unwrap(),
script_pubkey: Script(vec![]),
}],
authorization: Authorized,
}),
None,
None,
None,
)
.freeze()
.unwrap();
let mut tx_bytes = vec![];
tx.write(&mut tx_bytes).unwrap();
let usk =
UnifiedSpendingKey::from_seed(&tests::network(), &[0u8; 32][..], AccountId::from(0))
.unwrap();
let ufvk = usk.to_unified_full_viewing_key();
let (ua, _) = ufvk.default_address();
let taddr = ufvk
.transparent()
.and_then(|k| {
k.derive_external_ivk()
.ok()
.map(|k| k.derive_address(0).unwrap())
})
.map(|a| a.encode(&tests::network()));
db_data.conn.execute(
"INSERT INTO accounts (account, ufvk, address, transparent_address) VALUES (0, ?, ?, ?)",
params![ufvk.encode(&tests::network()), ua.encode(&tests::network()), &taddr]
).unwrap();
db_data
.conn
.execute_batch(
"INSERT INTO blocks (height, hash, time, sapling_tree) VALUES (0, 0, 0, '');",
)
.unwrap();
db_data.conn.execute(
"INSERT INTO utxos (address, prevout_txid, prevout_idx, script, value_zat, height)
VALUES (?, X'0101010101010101010101010101010101010101010101010101010101010101', 1, X'', 1400000000, 1)",
&[taddr]
).unwrap();
db_data
.conn
.execute(
"INSERT INTO transactions (block, id_tx, txid, raw) VALUES (0, 0, '', ?)",
params![tx_bytes],
)
.unwrap();
init_wallet_db(&mut db_data, None).unwrap();
let fee = db_data
.conn
.query_row(
"SELECT fee FROM transactions WHERE id_tx = 0",
NO_PARAMS,
|row| Ok(Amount::from_i64(row.get(0)?).unwrap()),
)
.unwrap();
assert_eq!(fee, Amount::from_i64(300000000).unwrap());
}
}

View File

@ -28,7 +28,11 @@ and this library adheres to Rust's notion of
- `Builder::new_with_rng_and_fee`
- `zcash_primitives::transaction::TransactionData::fee_paid`
- `zcash_primitives::transaction::components::amount::BalanceError`
- `zcash_primitives::transaction::components::sprout::Bundle::value_balance`
- Added in `zcash_primitives::transaction::components::sprout`
- `Bundle::value_balance`
- `JSDescription::net_value`
- Added in `zcash_primitives::transaction::components::transparent`
- `Bundle::value_balance`
### Changed
- `zcash_primitives::sapling::ViewingKey` now stores `nk` as a

View File

@ -396,15 +396,13 @@ impl<A: Authorization> TransactionData<A> {
self.tze_bundle.as_ref()
}
/// Returns the total fees paid by the transaction, given a function that can
/// be used to retrieve the output values of previous transactions' outputs
/// that are being spent in this transaction.
pub fn fee_paid<E, F: FnMut(&OutPoint) -> Result<Amount, E>>(
&self,
get_prevout: F,
) -> Result<Amount, E>
/// Returns the total fees paid by the transaction, given a function that can be used to
/// retrieve the value of previous transactions' transparent outputs that are being spent in
/// this transaction.
pub fn fee_paid<E, F>(&self, get_prevout: F) -> Result<Amount, E>
where
E: From<BalanceError>,
F: FnMut(&OutPoint) -> Result<Amount, E>,
{
let value_balances = [
self.transparent_bundle