Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ lightning-liquidity = { git = "https://github.com/lightningdevkit/rust-lightning
lightning-macros = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "3dfcc4cca1866c5e5d4d4eaf3b82e09584e2ce5c" }
lightning-dns-resolver = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "3dfcc4cca1866c5e5d4d4eaf3b82e09584e2ce5c" }

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

bitreq = { version = "0.3", default-features = false, features = ["async-https", "json-using-serde"] }
rustls = { version = "0.23", default-features = false }
Expand Down
2 changes: 1 addition & 1 deletion src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1648,7 +1648,7 @@ where
})
.collect(),
};
if let Err(e) = self.wallet.cancel_tx(&tx) {
if let Err(e) = self.wallet.cancel_tx(tx) {
log_error!(self.logger, "Failed reclaiming unused addresses: {}", e);
return Err(ReplayEvent());
}
Expand Down
8 changes: 4 additions & 4 deletions src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ pub(crate) const PEER_INFO_PERSISTENCE_KEY: &str = "peers";
pub(crate) const PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE: &str = "payments";
pub(crate) const PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE: &str = "";

/// The pending payment information will be persisted under this prefix.
pub(crate) const PENDING_PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE: &str = "pending_payments";
pub(crate) const PENDING_PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE: &str = "";

/// The node metrics will be persisted under this key.
pub(crate) const NODE_METRICS_PRIMARY_NAMESPACE: &str = "";
pub(crate) const NODE_METRICS_SECONDARY_NAMESPACE: &str = "";
Expand Down Expand Up @@ -80,7 +84,3 @@ pub(crate) const BDK_WALLET_INDEXER_KEY: &str = "indexer";
///
/// [`StaticInvoice`]: lightning::offers::static_invoice::StaticInvoice
pub(crate) const STATIC_INVOICE_STORE_PRIMARY_NAMESPACE: &str = "static_invoices";

/// The pending payment information will be persisted under this prefix.
pub(crate) const PENDING_PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE: &str = "pending_payments";
pub(crate) const PENDING_PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE: &str = "";
2 changes: 1 addition & 1 deletion src/payment/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub use bolt11::Bolt11Payment;
pub(crate) use bolt11::PaymentMetadata;
pub use bolt12::Bolt12Payment;
pub use onchain::OnchainPayment;
pub use pending_payment_store::PendingPaymentDetails;
pub(crate) use pending_payment_store::PendingPaymentDetails;
pub use spontaneous::SpontaneousPayment;
pub use store::{
ConfirmationStatus, LSPS2Parameters, PaymentDetails, PaymentDirection, PaymentKind,
Expand Down
9 changes: 8 additions & 1 deletion src/payment/onchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,18 @@ impl OnchainPayment {
/// The new transaction will have the same outputs as the original but with a
/// higher fee, resulting in faster confirmation potential.
///
/// This will respect any on-chain reserve we need to keep, i.e., won't allow to cut into
/// [`BalanceDetails::total_anchor_channels_reserve_sats`].
///
/// Returns the [`Txid`] of the new replacement transaction if successful.
///
/// [`BalanceDetails::total_anchor_channels_reserve_sats`]: crate::BalanceDetails::total_anchor_channels_reserve_sats
pub fn bump_fee_rbf(
&self, payment_id: PaymentId, fee_rate: Option<FeeRate>,
) -> Result<Txid, Error> {
let cur_anchor_reserve_sats =
crate::total_anchor_channels_reserve_sats(&self.channel_manager, &self.config);
let fee_rate_opt = maybe_map_fee_rate_opt!(fee_rate);
self.wallet.bump_fee_rbf(payment_id, fee_rate_opt)
self.wallet.bump_fee_rbf(payment_id, fee_rate_opt, cur_anchor_reserve_sats)
}
}
60 changes: 54 additions & 6 deletions src/payment/pending_payment_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use lightning::ln::channelmanager::PaymentId;

use crate::data_store::{StorableObject, StorableObjectUpdate};
use crate::payment::store::PaymentDetailsUpdate;
use crate::payment::PaymentDetails;
use crate::payment::{PaymentDetails, PaymentKind};

/// Represents a pending payment
#[derive(Clone, Debug, PartialEq, Eq)]
Expand All @@ -26,11 +26,6 @@ impl PendingPaymentDetails {
pub(crate) fn new(details: PaymentDetails, conflicting_txids: Vec<Txid>) -> Self {
Self { details, conflicting_txids }
}

/// Convert to finalized payment for the main payment store
pub fn into_payment_details(self) -> PaymentDetails {
self.details
}
}

impl_writeable_tlv_based!(PendingPaymentDetails, {
Expand Down Expand Up @@ -68,6 +63,12 @@ impl StorableObject for PendingPaymentDetails {
}
}

if let PaymentKind::Onchain { txid, .. } = &self.details.kind {
let conflicts_len = self.conflicting_txids.len();
self.conflicting_txids.retain(|conflicting_txid| conflicting_txid != txid);
updated |= self.conflicting_txids.len() != conflicts_len;
}

updated
}

Expand All @@ -92,3 +93,50 @@ impl From<&PendingPaymentDetails> for PendingPaymentDetailsUpdate {
Self { id: value.id(), payment_update: Some(value.details.to_update()), conflicting_txids }
}
}

#[cfg(test)]
mod tests {
use bitcoin::hashes::Hash;

use super::*;
use crate::payment::{ConfirmationStatus, PaymentDirection, PaymentKind, PaymentStatus};

fn test_txid(byte: u8) -> Txid {
Txid::from_byte_array([byte; 32])
}

fn pending_onchain_payment(payment_id: PaymentId, txid: Txid) -> PaymentDetails {
PaymentDetails::new(
payment_id,
PaymentKind::Onchain { txid, status: ConfirmationStatus::Unconfirmed },
Some(1_000),
Some(100),
PaymentDirection::Outbound,
PaymentStatus::Pending,
)
}

#[test]
fn pending_onchain_conflicts_exclude_current_txid_after_txid_rotation() {
let original_txid = test_txid(1);
let replacement_txid = test_txid(2);
let payment_id = PaymentId(original_txid.to_byte_array());

let mut pending_payment = PendingPaymentDetails::new(
pending_onchain_payment(payment_id, replacement_txid),
vec![original_txid],
);
let update = PendingPaymentDetails::new(
pending_onchain_payment(payment_id, original_txid),
Vec::new(),
)
.to_update();

assert!(pending_payment.update(update));
assert_eq!(
pending_payment.conflicting_txids,
Vec::<Txid>::new(),
"current txid must not remain in its own conflict list"
);
}
}
Loading
Loading