diff --git a/crates/bdk/src/wallet/coin_selection.rs b/crates/bdk/src/wallet/coin_selection.rs index 373dbdc3..e7927cab 100644 --- a/crates/bdk/src/wallet/coin_selection.rs +++ b/crates/bdk/src/wallet/coin_selection.rs @@ -722,9 +722,13 @@ mod test { fn get_test_utxos() -> Vec { vec![ - utxo(100_000, 0, ConfirmationTime::Unconfirmed), - utxo(FEE_AMOUNT - 40, 1, ConfirmationTime::Unconfirmed), - utxo(200_000, 2, ConfirmationTime::Unconfirmed), + utxo(100_000, 0, ConfirmationTime::Unconfirmed { last_seen: 0 }), + utxo( + FEE_AMOUNT - 40, + 1, + ConfirmationTime::Unconfirmed { last_seen: 0 }, + ), + utxo(200_000, 2, ConfirmationTime::Unconfirmed { last_seen: 0 }), ] } @@ -780,7 +784,7 @@ mod test { time: rng.next_u64(), } } else { - ConfirmationTime::Unconfirmed + ConfirmationTime::Unconfirmed { last_seen: 0 } }, }), }); @@ -803,7 +807,7 @@ mod test { keychain: KeychainKind::External, is_spent: false, derivation_index: 42, - confirmation_time: ConfirmationTime::Unconfirmed, + confirmation_time: ConfirmationTime::Unconfirmed { last_seen: 0 }, }), }; vec![utxo; utxos_number] @@ -1091,7 +1095,11 @@ mod test { let required = vec![utxos[0].clone()]; let mut optional = utxos[1..].to_vec(); - optional.push(utxo(500_000, 3, ConfirmationTime::Unconfirmed)); + optional.push(utxo( + 500_000, + 3, + ConfirmationTime::Unconfirmed { last_seen: 0 }, + )); // Defensive assertions, for sanity and in case someone changes the test utxos vector. let amount: u64 = required.iter().map(|u| u.utxo.txout().value).sum(); diff --git a/crates/bdk/src/wallet/export.rs b/crates/bdk/src/wallet/export.rs index 36b75ea2..fe87fedd 100644 --- a/crates/bdk/src/wallet/export.rs +++ b/crates/bdk/src/wallet/export.rs @@ -247,7 +247,6 @@ mod test { height: 5000, time: 0, }, - None, ) .unwrap(); wallet diff --git a/crates/bdk/src/wallet/mod.rs b/crates/bdk/src/wallet/mod.rs index 2d2a70f9..5fabc6d1 100644 --- a/crates/bdk/src/wallet/mod.rs +++ b/crates/bdk/src/wallet/mod.rs @@ -504,9 +504,7 @@ impl Wallet { { let changeset = self.chain.insert_block(block_id)?; let changed = !changeset.is_empty(); - if changed { - self.persist.stage(changeset.into()); - } + self.persist.stage(changeset.into()); Ok(changed) } @@ -528,24 +526,13 @@ impl Wallet { &mut self, tx: Transaction, position: ConfirmationTime, - seen_at: Option, ) -> Result where D: PersistBackend, { let tip = self.chain.tip(); - if let ConfirmationTime::Confirmed { height, .. } = position { - let tip_height = tip.map(|b| b.height); - if Some(height) > tip_height { - return Err(InsertTxError::ConfirmationHeightCannotBeGreaterThanTip { - tip_height, - tx_height: height, - }); - } - } - - let anchor = match position { + let (anchor, last_seen) = match position { ConfirmationTime::Confirmed { height, time } => { let tip_height = tip.map(|b| b.height); if Some(height) > tip_height { @@ -554,20 +541,21 @@ impl Wallet { tx_height: height, }); } - Some(ConfirmationTimeAnchor { - anchor_block: tip.expect("already checked if tip_height > height"), - confirmation_height: height, - confirmation_time: time, - }) + ( + Some(ConfirmationTimeAnchor { + anchor_block: tip.expect("already checked if tip_height > height"), + confirmation_height: height, + confirmation_time: time, + }), + None, + ) } - ConfirmationTime::Unconfirmed => None, + ConfirmationTime::Unconfirmed { last_seen } => (None, Some(last_seen)), }; - let changeset: ChangeSet = self.indexed_graph.insert_tx(&tx, anchor, seen_at).into(); + let changeset: ChangeSet = self.indexed_graph.insert_tx(&tx, anchor, last_seen).into(); let changed = !changeset.is_empty(); - if changed { - self.persist.stage(changeset); - } + self.persist.stage(changeset); Ok(changed) } @@ -1032,7 +1020,7 @@ impl Wallet { let transaction_details = TransactionDetails { transaction: None, txid, - confirmation_time: ConfirmationTime::Unconfirmed, + confirmation_time: ConfirmationTime::Unconfirmed { last_seen: 0 }, received, sent, fee: Some(fee_amount), @@ -1541,7 +1529,7 @@ impl Wallet { spendable &= (current_height.saturating_sub(height)) >= COINBASE_MATURITY; } - ConfirmationTime::Unconfirmed => spendable = false, + ConfirmationTime::Unconfirmed { .. } => spendable = false, } } } @@ -1771,9 +1759,7 @@ impl Wallet { changeset.append(self.indexed_graph.apply_update(update.graph).into()); let changed = !changeset.is_empty(); - if changed { - self.persist.stage(changeset); - } + self.persist.stage(changeset); Ok(changed) } @@ -1797,16 +1783,18 @@ impl Wallet { self.persist.staged() } - /// Get a reference to the inner [`TxGraph`](bdk_chain::tx_graph::TxGraph). - pub fn as_graph(&self) -> &TxGraph { + /// Get a reference to the inner [`TxGraph`]. + pub fn tx_graph(&self) -> &TxGraph { self.indexed_graph.graph() } - pub fn as_index(&self) -> &KeychainTxOutIndex { + /// Get a reference to the inner [`KeychainTxOutIndex`]. + pub fn spk_index(&self) -> &KeychainTxOutIndex { &self.indexed_graph.index } - pub fn as_chain(&self) -> &LocalChain { + /// Get a reference to the inner [`LocalChain`]. + pub fn local_chain(&self) -> &LocalChain { &self.chain } } @@ -1949,7 +1937,7 @@ macro_rules! doctest_wallet { let _ = wallet.insert_tx(tx.clone(), ConfirmationTime::Confirmed { height: 500, time: 50_000 - }, None); + }); wallet }} diff --git a/crates/bdk/src/wallet/tx_builder.rs b/crates/bdk/src/wallet/tx_builder.rs index 5d106260..165f01f2 100644 --- a/crates/bdk/src/wallet/tx_builder.rs +++ b/crates/bdk/src/wallet/tx_builder.rs @@ -884,7 +884,7 @@ mod test { txout: Default::default(), keychain: KeychainKind::External, is_spent: false, - confirmation_time: ConfirmationTime::Unconfirmed, + confirmation_time: ConfirmationTime::Unconfirmed { last_seen: 0 }, derivation_index: 0, }, LocalUtxo { diff --git a/crates/bdk/tests/common.rs b/crates/bdk/tests/common.rs index cbf74f24..de946703 100644 --- a/crates/bdk/tests/common.rs +++ b/crates/bdk/tests/common.rs @@ -35,7 +35,6 @@ pub fn get_funded_wallet_with_change( height: 1_000, time: 100, }, - None, ) .unwrap(); diff --git a/crates/bdk/tests/wallet.rs b/crates/bdk/tests/wallet.rs index 6291df1d..c5bf8e16 100644 --- a/crates/bdk/tests/wallet.rs +++ b/crates/bdk/tests/wallet.rs @@ -42,9 +42,8 @@ fn receive_output(wallet: &mut Wallet, value: u64, height: TxHeight) -> OutPoint height, time: 42_000, }, - TxHeight::Unconfirmed => ConfirmationTime::Unconfirmed, + TxHeight::Unconfirmed => ConfirmationTime::Unconfirmed { last_seen: 0 }, }, - None, ) .unwrap(); @@ -812,7 +811,10 @@ fn test_create_tx_add_utxo() { lock_time: PackedLockTime(0), }; wallet - .insert_tx(small_output_tx.clone(), ConfirmationTime::Unconfirmed, None) + .insert_tx( + small_output_tx.clone(), + ConfirmationTime::Unconfirmed { last_seen: 0 }, + ) .unwrap(); let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap(); @@ -849,7 +851,10 @@ fn test_create_tx_manually_selected_insufficient() { }; wallet - .insert_tx(small_output_tx.clone(), ConfirmationTime::Unconfirmed, None) + .insert_tx( + small_output_tx.clone(), + ConfirmationTime::Unconfirmed { last_seen: 0 }, + ) .unwrap(); let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap(); @@ -891,7 +896,7 @@ fn test_create_tx_policy_path_no_csv() { }], }; wallet - .insert_tx(tx, ConfirmationTime::Unconfirmed, None) + .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); let external_policy = wallet.policies(KeychainKind::External).unwrap().unwrap(); @@ -1218,7 +1223,7 @@ fn test_bump_fee_irreplaceable_tx() { let tx = psbt.extract_tx(); let txid = tx.txid(); wallet - .insert_tx(tx, ConfirmationTime::Unconfirmed, None) + .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); wallet.build_fee_bump(txid).unwrap().finish().unwrap(); } @@ -1242,7 +1247,6 @@ fn test_bump_fee_confirmed_tx() { height: 42, time: 42_000, }, - None, ) .unwrap(); @@ -1264,7 +1268,7 @@ fn test_bump_fee_low_fee_rate() { let txid = tx.txid(); wallet - .insert_tx(tx, ConfirmationTime::Unconfirmed, None) + .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); let mut builder = wallet.build_fee_bump(txid).unwrap(); @@ -1287,7 +1291,7 @@ fn test_bump_fee_low_abs() { let txid = tx.txid(); wallet - .insert_tx(tx, ConfirmationTime::Unconfirmed, None) + .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); let mut builder = wallet.build_fee_bump(txid).unwrap(); @@ -1309,7 +1313,7 @@ fn test_bump_fee_zero_abs() { let tx = psbt.extract_tx(); let txid = tx.txid(); wallet - .insert_tx(tx, ConfirmationTime::Unconfirmed, None) + .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); let mut builder = wallet.build_fee_bump(txid).unwrap(); @@ -1329,7 +1333,7 @@ fn test_bump_fee_reduce_change() { let tx = psbt.extract_tx(); let txid = tx.txid(); wallet - .insert_tx(tx, ConfirmationTime::Unconfirmed, None) + .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); let mut builder = wallet.build_fee_bump(txid).unwrap(); @@ -1416,7 +1420,7 @@ fn test_bump_fee_reduce_single_recipient() { let tx = psbt.extract_tx(); let txid = tx.txid(); wallet - .insert_tx(tx, ConfirmationTime::Unconfirmed, None) + .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); let mut builder = wallet.build_fee_bump(txid).unwrap(); @@ -1449,7 +1453,7 @@ fn test_bump_fee_absolute_reduce_single_recipient() { let tx = psbt.extract_tx(); let txid = tx.txid(); wallet - .insert_tx(tx, ConfirmationTime::Unconfirmed, None) + .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); let mut builder = wallet.build_fee_bump(txid).unwrap(); @@ -1489,7 +1493,6 @@ fn test_bump_fee_drain_wallet() { height: wallet.latest_checkpoint().unwrap().height, time: 42_000, }, - None, ) .unwrap(); let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap(); @@ -1508,7 +1511,7 @@ fn test_bump_fee_drain_wallet() { let tx = psbt.extract_tx(); let txid = tx.txid(); wallet - .insert_tx(tx, ConfirmationTime::Unconfirmed, None) + .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); assert_eq!(original_details.sent, 25_000); @@ -1553,7 +1556,6 @@ fn test_bump_fee_remove_output_manually_selected_only() { .observed_as .cloned() .into(), - None, ) .unwrap(); let outpoint = OutPoint { @@ -1572,7 +1574,7 @@ fn test_bump_fee_remove_output_manually_selected_only() { let tx = psbt.extract_tx(); let txid = tx.txid(); wallet - .insert_tx(tx, ConfirmationTime::Unconfirmed, None) + .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); assert_eq!(original_details.sent, 25_000); @@ -1602,7 +1604,7 @@ fn test_bump_fee_add_input() { .observed_as .cloned() .into(); - wallet.insert_tx(init_tx, pos, None).unwrap(); + wallet.insert_tx(init_tx, pos).unwrap(); let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap(); let mut builder = wallet.build_tx().coin_selection(LargestFirstCoinSelection); @@ -1613,7 +1615,7 @@ fn test_bump_fee_add_input() { let tx = psbt.extract_tx(); let txid = tx.txid(); wallet - .insert_tx(tx, ConfirmationTime::Unconfirmed, None) + .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); let mut builder = wallet.build_fee_bump(txid).unwrap(); @@ -1659,7 +1661,7 @@ fn test_bump_fee_absolute_add_input() { let tx = psbt.extract_tx(); let txid = tx.txid(); wallet - .insert_tx(tx, ConfirmationTime::Unconfirmed, None) + .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); let mut builder = wallet.build_fee_bump(txid).unwrap(); @@ -1711,7 +1713,7 @@ fn test_bump_fee_no_change_add_input_and_change() { let tx = psbt.extract_tx(); let txid = tx.txid(); wallet - .insert_tx(tx, ConfirmationTime::Unconfirmed, None) + .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); // now bump the fees without using `allow_shrinking`. the wallet should add an @@ -1769,7 +1771,7 @@ fn test_bump_fee_add_input_change_dust() { assert_eq!(tx.output.len(), 2); let txid = tx.txid(); wallet - .insert_tx(tx, ConfirmationTime::Unconfirmed, None) + .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); let mut builder = wallet.build_fee_bump(txid).unwrap(); @@ -1830,7 +1832,7 @@ fn test_bump_fee_force_add_input() { txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature } wallet - .insert_tx(tx.clone(), ConfirmationTime::Unconfirmed, None) + .insert_tx(tx.clone(), ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); // 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()` @@ -1885,7 +1887,7 @@ fn test_bump_fee_absolute_force_add_input() { txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature } wallet - .insert_tx(tx.clone(), ConfirmationTime::Unconfirmed, None) + .insert_tx(tx.clone(), ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); // the new fee_rate is low enough that just reducing the change would be fine, but we force @@ -1946,7 +1948,7 @@ fn test_bump_fee_unconfirmed_inputs_only() { txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature } wallet - .insert_tx(tx, ConfirmationTime::Unconfirmed, None) + .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); let mut builder = wallet.build_fee_bump(txid).unwrap(); builder.fee_rate(FeeRate::from_sat_per_vb(25.0)); @@ -1977,7 +1979,7 @@ fn test_bump_fee_unconfirmed_input() { txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature } wallet - .insert_tx(tx, ConfirmationTime::Unconfirmed, None) + .insert_tx(tx, ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); let mut builder = wallet.build_fee_bump(txid).unwrap(); @@ -3072,7 +3074,6 @@ fn test_spend_coinbase() { height: confirmation_height, time: 30_000, }, - None, ) .unwrap(); diff --git a/crates/chain/src/chain_data.rs b/crates/chain/src/chain_data.rs index 9baa643e..022e1299 100644 --- a/crates/chain/src/chain_data.rs +++ b/crates/chain/src/chain_data.rs @@ -99,14 +99,14 @@ impl TxHeight { )] pub enum ConfirmationTime { Confirmed { height: u32, time: u64 }, - Unconfirmed, + Unconfirmed { last_seen: u64 }, } impl sparse_chain::ChainPosition for ConfirmationTime { fn height(&self) -> TxHeight { match self { ConfirmationTime::Confirmed { height, .. } => TxHeight::Confirmed(*height), - ConfirmationTime::Unconfirmed => TxHeight::Unconfirmed, + ConfirmationTime::Unconfirmed { .. } => TxHeight::Unconfirmed, } } @@ -116,7 +116,7 @@ impl sparse_chain::ChainPosition for ConfirmationTime { height, time: u64::MAX, }, - TxHeight::Unconfirmed => Self::Unconfirmed, + TxHeight::Unconfirmed => Self::Unconfirmed { last_seen: 0 }, } } @@ -126,7 +126,7 @@ impl sparse_chain::ChainPosition for ConfirmationTime { height, time: u64::MIN, }, - TxHeight::Unconfirmed => Self::Unconfirmed, + TxHeight::Unconfirmed => Self::Unconfirmed { last_seen: 0 }, } } } @@ -144,7 +144,7 @@ impl From> for ConfirmationTime { height: a.confirmation_height, time: a.confirmation_time, }, - ObservedAs::Unconfirmed(_) => Self::Unconfirmed, + ObservedAs::Unconfirmed(_) => Self::Unconfirmed { last_seen: 0 }, } } } diff --git a/crates/chain/tests/test_keychain_tracker.rs b/crates/chain/tests/test_keychain_tracker.rs index bd8c6e03..fe725ea4 100644 --- a/crates/chain/tests/test_keychain_tracker.rs +++ b/crates/chain/tests/test_keychain_tracker.rs @@ -33,7 +33,7 @@ fn test_insert_tx() { let _ = tracker.txout_index.reveal_to_target(&(), 5); let changeset = tracker - .insert_tx_preview(tx.clone(), ConfirmationTime::Unconfirmed) + .insert_tx_preview(tx.clone(), ConfirmationTime::Unconfirmed { last_seen: 0 }) .unwrap(); tracker.apply_changeset(changeset); assert_eq!( @@ -41,7 +41,7 @@ fn test_insert_tx() { .chain_graph() .transactions_in_chain() .collect::>(), - vec![(&ConfirmationTime::Unconfirmed, &tx,)] + vec![(&ConfirmationTime::Unconfirmed { last_seen: 0 }, &tx,)] ); assert_eq!( diff --git a/crates/electrum/src/lib.rs b/crates/electrum/src/lib.rs index bddbd8f2..6d352ca1 100644 --- a/crates/electrum/src/lib.rs +++ b/crates/electrum/src/lib.rs @@ -296,7 +296,7 @@ impl ElectrumUpdate { height, time: height_to_time[&height], }, - TxHeight::Unconfirmed => ConfirmationTime::Unconfirmed, + TxHeight::Unconfirmed => ConfirmationTime::Unconfirmed { last_seen: 0 }, }; let _ = new_update.insert_tx(txid, conf_time).expect("must insert"); } diff --git a/crates/esplora/src/lib.rs b/crates/esplora/src/lib.rs index 8398fcb3..a6af0fad 100644 --- a/crates/esplora/src/lib.rs +++ b/crates/esplora/src/lib.rs @@ -22,6 +22,6 @@ pub(crate) fn map_confirmation_time( (Some(time), Some(height)) if height <= height_at_start => { ConfirmationTime::Confirmed { height, time } } - _ => ConfirmationTime::Unconfirmed, + _ => ConfirmationTime::Unconfirmed { last_seen: 0 }, } }