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
291 changes: 3 additions & 288 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ use lightning::util::config::{
use lightning::util::errors::APIError;
use lightning::util::persist::KVStoreSync;
use lightning::util::ser::{Readable, ReadableArgs, Writeable, Writer};
use lightning_liquidity::lsps2::utils::compute_opening_fee;
use lightning_types::payment::{PaymentHash, PaymentPreimage};
use rand::{thread_rng, Rng};

Expand All @@ -45,9 +44,7 @@ use crate::liquidity::LiquiditySource;
use crate::logger::{log_debug, log_error, log_info, log_trace, LdkLogger, Logger};
use crate::payment::asynchronous::om_mailbox::OnionMessageMailbox;
use crate::payment::asynchronous::static_invoice_store::StaticInvoiceStore;
use crate::payment::store::{
PaymentDetails, PaymentDetailsUpdate, PaymentDirection, PaymentKind, PaymentStatus,
};
use crate::payment::store::{PaymentDetailsUpdate, PaymentStatus};
use crate::runtime::Runtime;
use crate::types::{CustomTlvRecord, DynStore, OnionMessenger, PaymentStore, Sweeper, Wallet};
use crate::{
Expand Down Expand Up @@ -602,15 +599,8 @@ where
LdkEvent::FundingTxBroadcastSafe { .. } => {
debug_assert!(false, "We currently only support safe funding, so this event should never be emitted.");
},
LdkEvent::PaymentClaimable {
payment_hash,
purpose,
amount_msat,
claim_deadline,
onion_fields,
counterparty_skimmed_fee_msat,
..
} => {
LdkEvent::PaymentClaimable { payment_hash, .. } => {
// NOTE: Claiming of payments has been disabled.
let payment_id = PaymentId(payment_hash.0);
log_info!(
self.logger,
Expand All @@ -619,281 +609,6 @@ where
);
self.channel_manager.fail_htlc_backwards(&payment_hash);
return Ok(());
// NOTE: Claiming of payments has been disabled.
if let Some(info) = self.payment_store.get(&payment_id) {
if info.direction == PaymentDirection::Outbound {
log_info!(
self.logger,
"Refused inbound payment with ID {}: circular payments are unsupported.",
payment_id
);
self.channel_manager.fail_htlc_backwards(&payment_hash);

let update = PaymentDetailsUpdate {
status: Some(PaymentStatus::Failed),
..PaymentDetailsUpdate::new(payment_id)
};
match self.payment_store.update(&update) {
Ok(_) => return Ok(()),
Err(e) => {
log_error!(self.logger, "Failed to access payment store: {}", e);
return Err(ReplayEvent());
},
};
}

if info.status == PaymentStatus::Succeeded
|| matches!(info.kind, PaymentKind::Spontaneous { .. })
{
log_info!(
self.logger,
"Refused duplicate inbound payment from payment hash {} of {}msat",
hex_utils::to_string(&payment_hash.0),
amount_msat,
);
self.channel_manager.fail_htlc_backwards(&payment_hash);

let update = PaymentDetailsUpdate {
status: Some(PaymentStatus::Failed),
..PaymentDetailsUpdate::new(payment_id)
};
match self.payment_store.update(&update) {
Ok(_) => return Ok(()),
Err(e) => {
log_error!(self.logger, "Failed to access payment store: {}", e);
return Err(ReplayEvent());
},
};
}

let max_total_opening_fee_msat = match info.kind {
PaymentKind::Bolt11Jit { lsp_fee_limits, .. } => {
lsp_fee_limits
.max_total_opening_fee_msat
.or_else(|| {
lsp_fee_limits.max_proportional_opening_fee_ppm_msat.and_then(
|max_prop_fee| {
// If it's a variable amount payment, compute the actual fee.
compute_opening_fee(amount_msat, 0, max_prop_fee)
},
)
})
.unwrap_or(0)
},
_ => 0,
};

if counterparty_skimmed_fee_msat > max_total_opening_fee_msat {
log_info!(
self.logger,
"Refusing inbound payment with hash {} as the counterparty-withheld fee of {}msat exceeds our limit of {}msat",
hex_utils::to_string(&payment_hash.0),
counterparty_skimmed_fee_msat,
max_total_opening_fee_msat,
);
self.channel_manager.fail_htlc_backwards(&payment_hash);

let update = PaymentDetailsUpdate {
hash: Some(Some(payment_hash)),
status: Some(PaymentStatus::Failed),
..PaymentDetailsUpdate::new(payment_id)
};
match self.payment_store.update(&update) {
Ok(_) => return Ok(()),
Err(e) => {
log_error!(self.logger, "Failed to access payment store: {}", e);
return Err(ReplayEvent());
},
};
}

// If the LSP skimmed anything, update our stored payment.
if counterparty_skimmed_fee_msat > 0 {
match info.kind {
PaymentKind::Bolt11Jit { .. } => {
let update = PaymentDetailsUpdate {
counterparty_skimmed_fee_msat: Some(Some(counterparty_skimmed_fee_msat)),
..PaymentDetailsUpdate::new(payment_id)
};
match self.payment_store.update(&update) {
Ok(_) => (),
Err(e) => {
log_error!(self.logger, "Failed to access payment store: {}", e);
return Err(ReplayEvent());
},
};
}
_ => debug_assert!(false, "We only expect the counterparty to get away with withholding fees for JIT payments."),
}
}

// If this is known by the store but ChannelManager doesn't know the preimage,
// the payment has been registered via `_for_hash` variants and needs to be manually claimed via
// user interaction.
match info.kind {
PaymentKind::Bolt11 { preimage, .. }
| PaymentKind::Bolt11Jit { preimage, .. } => {
if purpose.preimage().is_none() {
debug_assert!(
preimage.is_none(),
"We would have registered the preimage if we knew"
);

let custom_records = onion_fields
.map(|cf| {
cf.custom_tlvs().into_iter().map(|tlv| tlv.into()).collect()
})
.unwrap_or_default();
let event = Event::PaymentClaimable {
payment_id,
payment_hash,
claimable_amount_msat: amount_msat,
claim_deadline,
custom_records,
};
match self.event_queue.add_event(event) {
Ok(_) => return Ok(()),
Err(e) => {
log_error!(
self.logger,
"Failed to push to event queue: {}",
e
);
return Err(ReplayEvent());
},
};
}
},
_ => {},
}
}

log_info!(
self.logger,
"Received payment from payment hash {} of {}msat",
hex_utils::to_string(&payment_hash.0),
amount_msat,
);
let payment_preimage = match purpose {
PaymentPurpose::Bolt11InvoicePayment { payment_preimage, .. } => {
payment_preimage
},
PaymentPurpose::Bolt12OfferPayment {
payment_preimage,
payment_secret,
payment_context,
..
} => {
let payer_note = payment_context.invoice_request.payer_note_truncated;
let offer_id = payment_context.offer_id;
let quantity = payment_context.invoice_request.quantity;
let kind = PaymentKind::Bolt12Offer {
hash: Some(payment_hash),
preimage: payment_preimage,
secret: Some(payment_secret),
offer_id,
payer_note,
quantity,
};

let payment = PaymentDetails::new(
payment_id,
kind,
Some(amount_msat),
None,
PaymentDirection::Inbound,
PaymentStatus::Pending,
);

match self.payment_store.insert(payment) {
Ok(false) => (),
Ok(true) => {
log_error!(
self.logger,
"Bolt12OfferPayment with ID {} was previously known",
payment_id,
);
debug_assert!(false);
},
Err(e) => {
log_error!(
self.logger,
"Failed to insert payment with ID {}: {}",
payment_id,
e
);
debug_assert!(false);
},
}
payment_preimage
},
PaymentPurpose::Bolt12RefundPayment { payment_preimage, .. } => {
payment_preimage
},
PaymentPurpose::SpontaneousPayment(preimage) => {
// Since it's spontaneous, we insert it now into our store.
let kind = PaymentKind::Spontaneous {
hash: payment_hash,
preimage: Some(preimage),
};

let payment = PaymentDetails::new(
payment_id,
kind,
Some(amount_msat),
None,
PaymentDirection::Inbound,
PaymentStatus::Pending,
);

match self.payment_store.insert(payment) {
Ok(false) => (),
Ok(true) => {
log_error!(
self.logger,
"Spontaneous payment with ID {} was previously known",
payment_id,
);
debug_assert!(false);
},
Err(e) => {
log_error!(
self.logger,
"Failed to insert payment with ID {}: {}",
payment_id,
e
);
debug_assert!(false);
},
}

Some(preimage)
},
};

if let Some(preimage) = payment_preimage {
self.channel_manager.claim_funds(preimage);
} else {
log_error!(
self.logger,
"Failed to claim payment with ID {}: preimage unknown.",
payment_id,
);
self.channel_manager.fail_htlc_backwards(&payment_hash);

let update = PaymentDetailsUpdate {
hash: Some(Some(payment_hash)),
status: Some(PaymentStatus::Failed),
..PaymentDetailsUpdate::new(payment_id)
};
match self.payment_store.update(&update) {
Ok(_) => return Ok(()),
Err(e) => {
log_error!(self.logger, "Failed to access payment store: {}", e);
return Err(ReplayEvent());
},
};
}
},
LdkEvent::PaymentClaimed {
payment_hash,
Expand Down
2 changes: 1 addition & 1 deletion src/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ use std::sync::Arc;

#[cfg(feature = "uniffi")]
use lightning::ln::msgs::SocketAddress;
use lightning::{routing::gossip::NodeId, util::ser::Writeable as _};
#[cfg(feature = "uniffi")]
use lightning::routing::gossip::RoutingFees;
#[cfg(not(feature = "uniffi"))]
use lightning::routing::gossip::{ChannelInfo, NodeInfo};
use lightning::{routing::gossip::NodeId, util::ser::Writeable as _};

use crate::types::Graph;

Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ use std::net::ToSocketAddrs;
use std::sync::{Arc, Mutex, RwLock};
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};

use crate::prober::Prober;
pub use balance::{BalanceDetails, LightningBalance, PendingSweepBalance};
use bitcoin::secp256k1::PublicKey;
#[cfg(feature = "uniffi")]
Expand Down Expand Up @@ -155,7 +156,6 @@ use types::{
pub use types::{
ChannelDetails, CustomTlvRecord, DynStore, PeerDetails, SyncAndAsyncKVStore, UserChannelId,
};
use crate::prober::Prober;

pub use {
bip39, bitcoin, lightning, lightning_invoice, lightning_liquidity, lightning_types, tokio,
Expand Down
18 changes: 10 additions & 8 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,16 @@ pub(crate) type ChainMonitor = chainmonitor::ChainMonitor<
Arc<Broadcaster>,
Arc<OnchainFeeEstimator>,
Arc<Logger>,
Arc<MonitorUpdatingPersister<
Arc<DynStore>,
Arc<Logger>,
Arc<KeysManager>,
Arc<KeysManager>,
Arc<Broadcaster>,
Arc<OnchainFeeEstimator>,
>>,
Arc<
MonitorUpdatingPersister<
Arc<DynStore>,
Arc<Logger>,
Arc<KeysManager>,
Arc<KeysManager>,
Arc<Broadcaster>,
Arc<OnchainFeeEstimator>,
>,
>,
Arc<KeysManager>,
>;

Expand Down
Loading