Skip to content

Commit ad4a3a8

Browse files
authored
Merge pull request #937 from tnull/2026-06-fix-770-payment-store-followups
Bump BDK, address pending payment store follow ups
2 parents c66676c + c82c2e5 commit ad4a3a8

8 files changed

Lines changed: 261 additions & 162 deletions

File tree

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ lightning-liquidity = { git = "https://github.com/lightningdevkit/rust-lightning
5454
lightning-macros = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "3dfcc4cca1866c5e5d4d4eaf3b82e09584e2ce5c" }
5555
lightning-dns-resolver = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "3dfcc4cca1866c5e5d4d4eaf3b82e09584e2ce5c" }
5656

57-
bdk_chain = { version = "0.23.0", default-features = false, features = ["std"] }
58-
bdk_esplora = { version = "0.22.0", default-features = false, features = ["async-https-rustls", "tokio"]}
57+
bdk_chain = { version = "0.23.3", default-features = false, features = ["std"] }
58+
bdk_esplora = { version = "0.22.2", default-features = false, features = ["async-https-rustls", "tokio"]}
5959
bdk_electrum = { version = "0.24.0", default-features = false, features = ["use-rustls-ring"]}
60-
bdk_wallet = { version = "2.3.0", default-features = false, features = ["std", "keys-bip39"]}
60+
bdk_wallet = { version = "3.1.0", default-features = false, features = ["std", "keys-bip39"]}
6161

6262
bitreq = { version = "0.3", default-features = false, features = ["async-https", "json-using-serde"] }
6363
rustls = { version = "0.23", default-features = false }

src/event.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1648,7 +1648,7 @@ where
16481648
})
16491649
.collect(),
16501650
};
1651-
if let Err(e) = self.wallet.cancel_tx(&tx) {
1651+
if let Err(e) = self.wallet.cancel_tx(tx) {
16521652
log_error!(self.logger, "Failed reclaiming unused addresses: {}", e);
16531653
return Err(ReplayEvent());
16541654
}

src/io/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ pub(crate) const PEER_INFO_PERSISTENCE_KEY: &str = "peers";
2929
pub(crate) const PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE: &str = "payments";
3030
pub(crate) const PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE: &str = "";
3131

32+
/// The pending payment information will be persisted under this prefix.
33+
pub(crate) const PENDING_PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE: &str = "pending_payments";
34+
pub(crate) const PENDING_PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE: &str = "";
35+
3236
/// The node metrics will be persisted under this key.
3337
pub(crate) const NODE_METRICS_PRIMARY_NAMESPACE: &str = "";
3438
pub(crate) const NODE_METRICS_SECONDARY_NAMESPACE: &str = "";
@@ -80,7 +84,3 @@ pub(crate) const BDK_WALLET_INDEXER_KEY: &str = "indexer";
8084
///
8185
/// [`StaticInvoice`]: lightning::offers::static_invoice::StaticInvoice
8286
pub(crate) const STATIC_INVOICE_STORE_PRIMARY_NAMESPACE: &str = "static_invoices";
83-
84-
/// The pending payment information will be persisted under this prefix.
85-
pub(crate) const PENDING_PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE: &str = "pending_payments";
86-
pub(crate) const PENDING_PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE: &str = "";

src/payment/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub use bolt11::Bolt11Payment;
2020
pub(crate) use bolt11::PaymentMetadata;
2121
pub use bolt12::Bolt12Payment;
2222
pub use onchain::OnchainPayment;
23-
pub use pending_payment_store::PendingPaymentDetails;
23+
pub(crate) use pending_payment_store::PendingPaymentDetails;
2424
pub use spontaneous::SpontaneousPayment;
2525
pub use store::{
2626
ConfirmationStatus, LSPS2Parameters, PaymentDetails, PaymentDirection, PaymentKind,

src/payment/onchain.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,18 @@ impl OnchainPayment {
134134
/// The new transaction will have the same outputs as the original but with a
135135
/// higher fee, resulting in faster confirmation potential.
136136
///
137+
/// This will respect any on-chain reserve we need to keep, i.e., won't allow to cut into
138+
/// [`BalanceDetails::total_anchor_channels_reserve_sats`].
139+
///
137140
/// Returns the [`Txid`] of the new replacement transaction if successful.
141+
///
142+
/// [`BalanceDetails::total_anchor_channels_reserve_sats`]: crate::BalanceDetails::total_anchor_channels_reserve_sats
138143
pub fn bump_fee_rbf(
139144
&self, payment_id: PaymentId, fee_rate: Option<FeeRate>,
140145
) -> Result<Txid, Error> {
146+
let cur_anchor_reserve_sats =
147+
crate::total_anchor_channels_reserve_sats(&self.channel_manager, &self.config);
141148
let fee_rate_opt = maybe_map_fee_rate_opt!(fee_rate);
142-
self.wallet.bump_fee_rbf(payment_id, fee_rate_opt)
149+
self.wallet.bump_fee_rbf(payment_id, fee_rate_opt, cur_anchor_reserve_sats)
143150
}
144151
}

src/payment/pending_payment_store.rs

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use lightning::ln::channelmanager::PaymentId;
1111

1212
use crate::data_store::{StorableObject, StorableObjectUpdate};
1313
use crate::payment::store::PaymentDetailsUpdate;
14-
use crate::payment::PaymentDetails;
14+
use crate::payment::{PaymentDetails, PaymentKind};
1515

1616
/// Represents a pending payment
1717
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -26,11 +26,6 @@ impl PendingPaymentDetails {
2626
pub(crate) fn new(details: PaymentDetails, conflicting_txids: Vec<Txid>) -> Self {
2727
Self { details, conflicting_txids }
2828
}
29-
30-
/// Convert to finalized payment for the main payment store
31-
pub fn into_payment_details(self) -> PaymentDetails {
32-
self.details
33-
}
3429
}
3530

3631
impl_writeable_tlv_based!(PendingPaymentDetails, {
@@ -68,6 +63,12 @@ impl StorableObject for PendingPaymentDetails {
6863
}
6964
}
7065

66+
if let PaymentKind::Onchain { txid, .. } = &self.details.kind {
67+
let conflicts_len = self.conflicting_txids.len();
68+
self.conflicting_txids.retain(|conflicting_txid| conflicting_txid != txid);
69+
updated |= self.conflicting_txids.len() != conflicts_len;
70+
}
71+
7172
updated
7273
}
7374

@@ -92,3 +93,50 @@ impl From<&PendingPaymentDetails> for PendingPaymentDetailsUpdate {
9293
Self { id: value.id(), payment_update: Some(value.details.to_update()), conflicting_txids }
9394
}
9495
}
96+
97+
#[cfg(test)]
98+
mod tests {
99+
use bitcoin::hashes::Hash;
100+
101+
use super::*;
102+
use crate::payment::{ConfirmationStatus, PaymentDirection, PaymentKind, PaymentStatus};
103+
104+
fn test_txid(byte: u8) -> Txid {
105+
Txid::from_byte_array([byte; 32])
106+
}
107+
108+
fn pending_onchain_payment(payment_id: PaymentId, txid: Txid) -> PaymentDetails {
109+
PaymentDetails::new(
110+
payment_id,
111+
PaymentKind::Onchain { txid, status: ConfirmationStatus::Unconfirmed },
112+
Some(1_000),
113+
Some(100),
114+
PaymentDirection::Outbound,
115+
PaymentStatus::Pending,
116+
)
117+
}
118+
119+
#[test]
120+
fn pending_onchain_conflicts_exclude_current_txid_after_txid_rotation() {
121+
let original_txid = test_txid(1);
122+
let replacement_txid = test_txid(2);
123+
let payment_id = PaymentId(original_txid.to_byte_array());
124+
125+
let mut pending_payment = PendingPaymentDetails::new(
126+
pending_onchain_payment(payment_id, replacement_txid),
127+
vec![original_txid],
128+
);
129+
let update = PendingPaymentDetails::new(
130+
pending_onchain_payment(payment_id, original_txid),
131+
Vec::new(),
132+
)
133+
.to_update();
134+
135+
assert!(pending_payment.update(update));
136+
assert_eq!(
137+
pending_payment.conflicting_txids,
138+
Vec::<Txid>::new(),
139+
"current txid must not remain in its own conflict list"
140+
);
141+
}
142+
}

0 commit comments

Comments
 (0)