Add last_seen to the the ConfirmationTime::Unconfirmed variant

This allows us to skip adding an extra input to `Wallet::insert_tx`.

Also remove redundant logic.
This commit is contained in:
志宇 2023-05-11 22:56:26 +08:00
parent aba88130d9
commit 7261669c09
No known key found for this signature in database
GPG Key ID: F6345C9837C2BDE8
10 changed files with 75 additions and 80 deletions

View File

@ -722,9 +722,13 @@ mod test {
fn get_test_utxos() -> Vec<WeightedUtxo> {
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();

View File

@ -247,7 +247,6 @@ mod test {
height: 5000,
time: 0,
},
None,
)
.unwrap();
wallet

View File

@ -504,9 +504,7 @@ impl<D> Wallet<D> {
{
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<D> Wallet<D> {
&mut self,
tx: Transaction,
position: ConfirmationTime,
seen_at: Option<u64>,
) -> Result<bool, InsertTxError>
where
D: PersistBackend<ChangeSet>,
{
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<D> Wallet<D> {
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<D> Wallet<D> {
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<D> Wallet<D> {
spendable &=
(current_height.saturating_sub(height)) >= COINBASE_MATURITY;
}
ConfirmationTime::Unconfirmed => spendable = false,
ConfirmationTime::Unconfirmed { .. } => spendable = false,
}
}
}
@ -1771,9 +1759,7 @@ impl<D> Wallet<D> {
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<D> Wallet<D> {
self.persist.staged()
}
/// Get a reference to the inner [`TxGraph`](bdk_chain::tx_graph::TxGraph).
pub fn as_graph(&self) -> &TxGraph<ConfirmationTimeAnchor> {
/// Get a reference to the inner [`TxGraph`].
pub fn tx_graph(&self) -> &TxGraph<ConfirmationTimeAnchor> {
self.indexed_graph.graph()
}
pub fn as_index(&self) -> &KeychainTxOutIndex<KeychainKind> {
/// Get a reference to the inner [`KeychainTxOutIndex`].
pub fn spk_index(&self) -> &KeychainTxOutIndex<KeychainKind> {
&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
}}

View File

@ -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 {

View File

@ -35,7 +35,6 @@ pub fn get_funded_wallet_with_change(
height: 1_000,
time: 100,
},
None,
)
.unwrap();

View File

@ -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();

View File

@ -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<ObservedAs<ConfirmationTimeAnchor>> for ConfirmationTime {
height: a.confirmation_height,
time: a.confirmation_time,
},
ObservedAs::Unconfirmed(_) => Self::Unconfirmed,
ObservedAs::Unconfirmed(_) => Self::Unconfirmed { last_seen: 0 },
}
}
}

View File

@ -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<_>>(),
vec![(&ConfirmationTime::Unconfirmed, &tx,)]
vec![(&ConfirmationTime::Unconfirmed { last_seen: 0 }, &tx,)]
);
assert_eq!(

View File

@ -296,7 +296,7 @@ impl<K: Ord + Clone + Debug> ElectrumUpdate<K, TxHeight> {
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");
}

View File

@ -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 },
}
}