Add test for fee calculation in add_transaction_views migration.
This commit is contained in:
parent
b327bf7073
commit
7934e834d3
|
@ -14,19 +14,17 @@ use zcash_primitives::{
|
||||||
|
|
||||||
use super::super::{WalletMigration2, WalletMigrationError};
|
use super::super::{WalletMigration2, WalletMigrationError};
|
||||||
|
|
||||||
pub(super) struct Migration<P> {
|
pub(crate) fn migration_id() -> Uuid {
|
||||||
pub(super) params: P,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P> Migration<P> {
|
|
||||||
fn id() -> Uuid {
|
|
||||||
Uuid::parse_str("282fad2e-8372-4ca0-8bed-71821320909f").unwrap()
|
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> {
|
impl<P> schemer::Migration for Migration<P> {
|
||||||
fn id(&self) -> Uuid {
|
fn id(&self) -> Uuid {
|
||||||
Migration::<P>::id()
|
migration_id()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dependencies(&self) -> HashSet<Uuid> {
|
fn dependencies(&self) -> HashSet<Uuid> {
|
||||||
|
@ -97,7 +95,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
|
||||||
SUM(
|
SUM(
|
||||||
CASE
|
CASE
|
||||||
WHEN sent_notes.memo IS NULL THEN 0
|
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
|
ELSE 1
|
||||||
END
|
END
|
||||||
) AS memo_count,
|
) AS memo_count,
|
||||||
|
@ -118,7 +116,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
|
||||||
SUM(
|
SUM(
|
||||||
CASE
|
CASE
|
||||||
WHEN received_notes.memo IS NULL THEN 0
|
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
|
ELSE 1
|
||||||
END
|
END
|
||||||
) AS memo_count,
|
) AS memo_count,
|
||||||
|
@ -154,7 +152,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
|
||||||
received_notes.is_change AS is_change,
|
received_notes.is_change AS is_change,
|
||||||
CASE
|
CASE
|
||||||
WHEN received_notes.memo IS NULL THEN 0
|
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
|
ELSE 1
|
||||||
END AS memo_present
|
END AS memo_present
|
||||||
FROM transactions
|
FROM transactions
|
||||||
|
@ -171,7 +169,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
|
||||||
false AS is_change,
|
false AS is_change,
|
||||||
CASE
|
CASE
|
||||||
WHEN sent_notes.memo IS NULL THEN 0
|
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
|
ELSE 1
|
||||||
END AS memo_present
|
END AS memo_present
|
||||||
FROM transactions
|
FROM transactions
|
||||||
|
@ -192,15 +190,29 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use rusqlite::{self, NO_PARAMS};
|
use rusqlite::{self, NO_PARAMS};
|
||||||
|
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
|
|
||||||
use crate::{
|
#[cfg(feature = "transparent-inputs")]
|
||||||
tests::{self},
|
use {
|
||||||
wallet::init::init_wallet_db,
|
crate::wallet::init::{init_wallet_db_internal, WalletMigration2},
|
||||||
WalletDb,
|
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]
|
#[test]
|
||||||
fn transaction_views() {
|
fn transaction_views() {
|
||||||
let data_file = NamedTempFile::new().unwrap();
|
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)
|
INSERT INTO sent_notes (tx, output_pool, output_index, from_account, address, value, memo)
|
||||||
VALUES (0, 2, 1, 0, '', 3, X'61');
|
VALUES (0, 2, 1, 0, '', 3, X'61');
|
||||||
INSERT INTO sent_notes (tx, output_pool, output_index, from_account, address, value, memo)
|
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)
|
INSERT INTO received_notes (tx, output_index, account, diversifier, value, rcm, nf, is_change, memo)
|
||||||
VALUES (0, 0, 0, '', 5, '', 'a', false, X'62');
|
VALUES (0, 0, 0, '', 5, '', 'a', false, X'62');
|
||||||
|
@ -276,4 +288,91 @@ mod tests {
|
||||||
}
|
}
|
||||||
assert_eq!(row_count, 1);
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,11 @@ and this library adheres to Rust's notion of
|
||||||
- `Builder::new_with_rng_and_fee`
|
- `Builder::new_with_rng_and_fee`
|
||||||
- `zcash_primitives::transaction::TransactionData::fee_paid`
|
- `zcash_primitives::transaction::TransactionData::fee_paid`
|
||||||
- `zcash_primitives::transaction::components::amount::BalanceError`
|
- `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
|
### Changed
|
||||||
- `zcash_primitives::sapling::ViewingKey` now stores `nk` as a
|
- `zcash_primitives::sapling::ViewingKey` now stores `nk` as a
|
||||||
|
|
|
@ -396,15 +396,13 @@ impl<A: Authorization> TransactionData<A> {
|
||||||
self.tze_bundle.as_ref()
|
self.tze_bundle.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the total fees paid by the transaction, given a function that can
|
/// Returns the total fees paid by the transaction, given a function that can be used to
|
||||||
/// be used to retrieve the output values of previous transactions' outputs
|
/// retrieve the value of previous transactions' transparent outputs that are being spent in
|
||||||
/// that are being spent in this transaction.
|
/// this transaction.
|
||||||
pub fn fee_paid<E, F: FnMut(&OutPoint) -> Result<Amount, E>>(
|
pub fn fee_paid<E, F>(&self, get_prevout: F) -> Result<Amount, E>
|
||||||
&self,
|
|
||||||
get_prevout: F,
|
|
||||||
) -> Result<Amount, E>
|
|
||||||
where
|
where
|
||||||
E: From<BalanceError>,
|
E: From<BalanceError>,
|
||||||
|
F: FnMut(&OutPoint) -> Result<Amount, E>,
|
||||||
{
|
{
|
||||||
let value_balances = [
|
let value_balances = [
|
||||||
self.transparent_bundle
|
self.transparent_bundle
|
||||||
|
|
Loading…
Reference in New Issue