fix(wallet)!: Rework Wallet::insert_tx to no longer insert anchors
since we'd be lacking context that should normally occur during sync with a chain source. The logic for inserting a graph anchor from a `ConfirmationTime` is moved to the wallet common test module in order to simulate receiving new txs and confirming them.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
#![allow(unused)]
|
||||
|
||||
use bdk_chain::indexed_tx_graph::Indexer;
|
||||
use bdk_chain::{BlockId, ConfirmationTime};
|
||||
use bdk_chain::{BlockId, ConfirmationTime, ConfirmationTimeHeightAnchor};
|
||||
use bdk_wallet::{KeychainKind, LocalOutput, Wallet};
|
||||
use bitcoin::hashes::Hash;
|
||||
use bitcoin::{
|
||||
@@ -77,24 +77,26 @@ pub fn get_funded_wallet_with_change(descriptor: &str, change: &str) -> (Wallet,
|
||||
hash: BlockHash::all_zeros(),
|
||||
})
|
||||
.unwrap();
|
||||
wallet
|
||||
.insert_tx(
|
||||
tx0,
|
||||
ConfirmationTime::Confirmed {
|
||||
height: 1_000,
|
||||
time: 100,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
wallet
|
||||
.insert_tx(
|
||||
tx1.clone(),
|
||||
ConfirmationTime::Confirmed {
|
||||
height: 2_000,
|
||||
time: 200,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
wallet.insert_tx(tx0.clone());
|
||||
insert_anchor_from_conf(
|
||||
&mut wallet,
|
||||
tx0.compute_txid(),
|
||||
ConfirmationTime::Confirmed {
|
||||
height: 1_000,
|
||||
time: 100,
|
||||
},
|
||||
);
|
||||
|
||||
wallet.insert_tx(tx1.clone());
|
||||
insert_anchor_from_conf(
|
||||
&mut wallet,
|
||||
tx1.compute_txid(),
|
||||
ConfirmationTime::Confirmed {
|
||||
height: 2_000,
|
||||
time: 200,
|
||||
},
|
||||
);
|
||||
|
||||
(wallet, tx1.compute_txid())
|
||||
}
|
||||
@@ -192,3 +194,24 @@ pub fn feerate_unchecked(sat_vb: f64) -> FeeRate {
|
||||
let sat_kwu = (sat_vb * 250.0).ceil() as u64;
|
||||
FeeRate::from_sat_per_kwu(sat_kwu)
|
||||
}
|
||||
|
||||
/// Simulates confirming a tx with `txid` at the specified `position` by inserting an anchor
|
||||
/// at the lowest height in local chain that is greater or equal to `position`'s height,
|
||||
/// assuming the confirmation time matches `ConfirmationTime::Confirmed`.
|
||||
pub fn insert_anchor_from_conf(wallet: &mut Wallet, txid: Txid, position: ConfirmationTime) {
|
||||
if let ConfirmationTime::Confirmed { height, time } = position {
|
||||
// anchor tx to checkpoint with lowest height that is >= position's height
|
||||
let anchor = wallet
|
||||
.local_chain()
|
||||
.range(height..)
|
||||
.last()
|
||||
.map(|anchor_cp| ConfirmationTimeHeightAnchor {
|
||||
anchor_block: anchor_cp.block_id(),
|
||||
confirmation_height: height,
|
||||
confirmation_time: time,
|
||||
})
|
||||
.expect("confirmation height cannot be greater than tip");
|
||||
|
||||
wallet.insert_anchor(txid, anchor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,12 +42,19 @@ fn receive_output(wallet: &mut Wallet, value: u64, height: ConfirmationTime) ->
|
||||
}],
|
||||
};
|
||||
|
||||
wallet.insert_tx(tx.clone(), height).unwrap();
|
||||
let txid = tx.compute_txid();
|
||||
wallet.insert_tx(tx);
|
||||
|
||||
OutPoint {
|
||||
txid: tx.compute_txid(),
|
||||
vout: 0,
|
||||
match height {
|
||||
ConfirmationTime::Confirmed { .. } => {
|
||||
insert_anchor_from_conf(wallet, txid, height);
|
||||
}
|
||||
ConfirmationTime::Unconfirmed { last_seen } => {
|
||||
wallet.insert_seen_at(txid, last_seen);
|
||||
}
|
||||
}
|
||||
|
||||
OutPoint { txid, vout: 0 }
|
||||
}
|
||||
|
||||
fn receive_output_in_latest_block(wallet: &mut Wallet, value: u64) -> OutPoint {
|
||||
@@ -1180,12 +1187,7 @@ fn test_create_tx_add_utxo() {
|
||||
version: transaction::Version::non_standard(0),
|
||||
lock_time: absolute::LockTime::ZERO,
|
||||
};
|
||||
wallet
|
||||
.insert_tx(
|
||||
small_output_tx.clone(),
|
||||
ConfirmationTime::Unconfirmed { last_seen: 0 },
|
||||
)
|
||||
.unwrap();
|
||||
wallet.insert_tx(small_output_tx.clone());
|
||||
|
||||
let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX")
|
||||
.unwrap()
|
||||
@@ -1230,12 +1232,7 @@ fn test_create_tx_manually_selected_insufficient() {
|
||||
lock_time: absolute::LockTime::ZERO,
|
||||
};
|
||||
|
||||
wallet
|
||||
.insert_tx(
|
||||
small_output_tx.clone(),
|
||||
ConfirmationTime::Unconfirmed { last_seen: 0 },
|
||||
)
|
||||
.unwrap();
|
||||
wallet.insert_tx(small_output_tx.clone());
|
||||
|
||||
let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX")
|
||||
.unwrap()
|
||||
@@ -1281,9 +1278,7 @@ fn test_create_tx_policy_path_no_csv() {
|
||||
value: Amount::from_sat(50_000),
|
||||
}],
|
||||
};
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
wallet.insert_tx(tx);
|
||||
|
||||
let external_policy = wallet.policies(KeychainKind::External).unwrap().unwrap();
|
||||
let root_id = external_policy.id;
|
||||
@@ -1674,9 +1669,7 @@ fn test_bump_fee_irreplaceable_tx() {
|
||||
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
wallet.insert_tx(tx);
|
||||
wallet.build_fee_bump(txid).unwrap().finish().unwrap();
|
||||
}
|
||||
|
||||
@@ -1692,15 +1685,15 @@ fn test_bump_fee_confirmed_tx() {
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let txid = tx.compute_txid();
|
||||
|
||||
wallet
|
||||
.insert_tx(
|
||||
tx,
|
||||
ConfirmationTime::Confirmed {
|
||||
height: 42,
|
||||
time: 42_000,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
wallet.insert_tx(tx);
|
||||
insert_anchor_from_conf(
|
||||
&mut wallet,
|
||||
txid,
|
||||
ConfirmationTime::Confirmed {
|
||||
height: 42,
|
||||
time: 42_000,
|
||||
},
|
||||
);
|
||||
|
||||
wallet.build_fee_bump(txid).unwrap().finish().unwrap();
|
||||
}
|
||||
@@ -1719,9 +1712,7 @@ fn test_bump_fee_low_fee_rate() {
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let txid = tx.compute_txid();
|
||||
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
wallet.insert_tx(tx);
|
||||
|
||||
let mut builder = wallet.build_fee_bump(txid).unwrap();
|
||||
builder.fee_rate(FeeRate::BROADCAST_MIN);
|
||||
@@ -1752,9 +1743,7 @@ fn test_bump_fee_low_abs() {
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let txid = tx.compute_txid();
|
||||
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
wallet.insert_tx(tx);
|
||||
|
||||
let mut builder = wallet.build_fee_bump(txid).unwrap();
|
||||
builder.fee_absolute(Amount::from_sat(10));
|
||||
@@ -1774,9 +1763,7 @@ fn test_bump_fee_zero_abs() {
|
||||
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
wallet.insert_tx(tx);
|
||||
|
||||
let mut builder = wallet.build_fee_bump(txid).unwrap();
|
||||
builder.fee_absolute(Amount::ZERO);
|
||||
@@ -1800,9 +1787,7 @@ fn test_bump_fee_reduce_change() {
|
||||
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
wallet.insert_tx(tx);
|
||||
|
||||
let feerate = FeeRate::from_sat_per_kwu(625); // 2.5 sat/vb
|
||||
let mut builder = wallet.build_fee_bump(txid).unwrap();
|
||||
@@ -1898,9 +1883,7 @@ fn test_bump_fee_reduce_single_recipient() {
|
||||
let original_sent_received = wallet.sent_and_received(&tx);
|
||||
let original_fee = check_fee!(wallet, psbt);
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
wallet.insert_tx(tx);
|
||||
|
||||
let feerate = FeeRate::from_sat_per_kwu(625); // 2.5 sat/vb
|
||||
let mut builder = wallet.build_fee_bump(txid).unwrap();
|
||||
@@ -1946,9 +1929,7 @@ fn test_bump_fee_absolute_reduce_single_recipient() {
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let original_sent_received = wallet.sent_and_received(&tx);
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
wallet.insert_tx(tx);
|
||||
|
||||
let mut builder = wallet.build_fee_bump(txid).unwrap();
|
||||
builder
|
||||
@@ -1991,15 +1972,18 @@ fn test_bump_fee_drain_wallet() {
|
||||
value: Amount::from_sat(25_000),
|
||||
}],
|
||||
};
|
||||
wallet
|
||||
.insert_tx(
|
||||
tx.clone(),
|
||||
ConfirmationTime::Confirmed {
|
||||
height: wallet.latest_checkpoint().height(),
|
||||
time: 42_000,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let txid = tx.compute_txid();
|
||||
let tip = wallet.latest_checkpoint().height();
|
||||
wallet.insert_tx(tx.clone());
|
||||
insert_anchor_from_conf(
|
||||
&mut wallet,
|
||||
txid,
|
||||
ConfirmationTime::Confirmed {
|
||||
height: tip,
|
||||
time: 42_000,
|
||||
},
|
||||
);
|
||||
|
||||
let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX")
|
||||
.unwrap()
|
||||
.assume_checked();
|
||||
@@ -2019,9 +2003,7 @@ fn test_bump_fee_drain_wallet() {
|
||||
let original_sent_received = wallet.sent_and_received(&tx);
|
||||
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
wallet.insert_tx(tx);
|
||||
assert_eq!(original_sent_received.0, Amount::from_sat(25_000));
|
||||
|
||||
// for the new feerate, it should be enough to reduce the output, but since we specify
|
||||
@@ -2056,18 +2038,17 @@ fn test_bump_fee_remove_output_manually_selected_only() {
|
||||
value: Amount::from_sat(25_000),
|
||||
}],
|
||||
};
|
||||
wallet
|
||||
.insert_tx(
|
||||
init_tx.clone(),
|
||||
wallet
|
||||
.transactions()
|
||||
.last()
|
||||
.unwrap()
|
||||
.chain_position
|
||||
.cloned()
|
||||
.into(),
|
||||
)
|
||||
.unwrap();
|
||||
let position: ConfirmationTime = wallet
|
||||
.transactions()
|
||||
.last()
|
||||
.unwrap()
|
||||
.chain_position
|
||||
.cloned()
|
||||
.into();
|
||||
|
||||
wallet.insert_tx(init_tx.clone());
|
||||
insert_anchor_from_conf(&mut wallet, init_tx.compute_txid(), position);
|
||||
|
||||
let outpoint = OutPoint {
|
||||
txid: init_tx.compute_txid(),
|
||||
vout: 0,
|
||||
@@ -2086,9 +2067,7 @@ fn test_bump_fee_remove_output_manually_selected_only() {
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let original_sent_received = wallet.sent_and_received(&tx);
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
wallet.insert_tx(tx);
|
||||
assert_eq!(original_sent_received.0, Amount::from_sat(25_000));
|
||||
|
||||
let mut builder = wallet.build_fee_bump(txid).unwrap();
|
||||
@@ -2112,14 +2091,16 @@ fn test_bump_fee_add_input() {
|
||||
value: Amount::from_sat(25_000),
|
||||
}],
|
||||
};
|
||||
let pos = wallet
|
||||
let txid = init_tx.compute_txid();
|
||||
let pos: ConfirmationTime = wallet
|
||||
.transactions()
|
||||
.last()
|
||||
.unwrap()
|
||||
.chain_position
|
||||
.cloned()
|
||||
.into();
|
||||
wallet.insert_tx(init_tx, pos).unwrap();
|
||||
wallet.insert_tx(init_tx);
|
||||
insert_anchor_from_conf(&mut wallet, txid, pos);
|
||||
|
||||
let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX")
|
||||
.unwrap()
|
||||
@@ -2132,9 +2113,7 @@ fn test_bump_fee_add_input() {
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let original_details = wallet.sent_and_received(&tx);
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
wallet.insert_tx(tx);
|
||||
|
||||
let mut builder = wallet.build_fee_bump(txid).unwrap();
|
||||
builder.fee_rate(FeeRate::from_sat_per_vb_unchecked(50));
|
||||
@@ -2189,9 +2168,7 @@ fn test_bump_fee_absolute_add_input() {
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let original_sent_received = wallet.sent_and_received(&tx);
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
wallet.insert_tx(tx);
|
||||
|
||||
let mut builder = wallet.build_fee_bump(txid).unwrap();
|
||||
builder.fee_absolute(Amount::from_sat(6_000));
|
||||
@@ -2255,9 +2232,7 @@ fn test_bump_fee_no_change_add_input_and_change() {
|
||||
|
||||
let tx = psbt.extract_tx().expect("failed to extract tx");
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
wallet.insert_tx(tx);
|
||||
|
||||
// Now bump the fees, the wallet should add an extra input and a change output, and leave
|
||||
// the original output untouched.
|
||||
@@ -2325,9 +2300,7 @@ fn test_bump_fee_add_input_change_dust() {
|
||||
assert_eq!(tx.input.len(), 1);
|
||||
assert_eq!(tx.output.len(), 2);
|
||||
let txid = tx.compute_txid();
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
wallet.insert_tx(tx);
|
||||
|
||||
let mut builder = wallet.build_fee_bump(txid).unwrap();
|
||||
// We set a fee high enough that during rbf we are forced to add
|
||||
@@ -2396,9 +2369,7 @@ fn test_bump_fee_force_add_input() {
|
||||
for txin in &mut tx.input {
|
||||
txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
|
||||
}
|
||||
wallet
|
||||
.insert_tx(tx.clone(), ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
wallet.insert_tx(tx.clone());
|
||||
// the new fee_rate is low enough that just reducing the change would be fine, but we force
|
||||
// the addition of an extra input with `add_utxo()`
|
||||
let mut builder = wallet.build_fee_bump(txid).unwrap();
|
||||
@@ -2463,9 +2434,7 @@ fn test_bump_fee_absolute_force_add_input() {
|
||||
for txin in &mut tx.input {
|
||||
txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
|
||||
}
|
||||
wallet
|
||||
.insert_tx(tx.clone(), ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
wallet.insert_tx(tx.clone());
|
||||
|
||||
// the new fee_rate is low enough that just reducing the change would be fine, but we force
|
||||
// the addition of an extra input with `add_utxo()`
|
||||
@@ -2542,9 +2511,7 @@ fn test_bump_fee_unconfirmed_inputs_only() {
|
||||
for txin in &mut tx.input {
|
||||
txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
|
||||
}
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
wallet.insert_tx(tx);
|
||||
let mut builder = wallet.build_fee_bump(txid).unwrap();
|
||||
builder.fee_rate(FeeRate::from_sat_per_vb_unchecked(25));
|
||||
builder.finish().unwrap();
|
||||
@@ -2575,9 +2542,7 @@ fn test_bump_fee_unconfirmed_input() {
|
||||
for txin in &mut tx.input {
|
||||
txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
|
||||
}
|
||||
wallet
|
||||
.insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 })
|
||||
.unwrap();
|
||||
wallet.insert_tx(tx);
|
||||
|
||||
let mut builder = wallet.build_fee_bump(txid).unwrap();
|
||||
builder
|
||||
@@ -3774,15 +3739,16 @@ fn test_spend_coinbase() {
|
||||
value: Amount::from_sat(25_000),
|
||||
}],
|
||||
};
|
||||
wallet
|
||||
.insert_tx(
|
||||
coinbase_tx,
|
||||
ConfirmationTime::Confirmed {
|
||||
height: confirmation_height,
|
||||
time: 30_000,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let txid = coinbase_tx.compute_txid();
|
||||
wallet.insert_tx(coinbase_tx);
|
||||
insert_anchor_from_conf(
|
||||
&mut wallet,
|
||||
txid,
|
||||
ConfirmationTime::Confirmed {
|
||||
height: confirmation_height,
|
||||
time: 30_000,
|
||||
},
|
||||
);
|
||||
|
||||
let not_yet_mature_time = confirmation_height + COINBASE_MATURITY - 1;
|
||||
let maturity_time = confirmation_height + COINBASE_MATURITY;
|
||||
|
||||
Reference in New Issue
Block a user