-
Notifications
You must be signed in to change notification settings - Fork 94
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move spontaneous payments API to
SpontaneousPaymentsHandler
- Loading branch information
Showing
6 changed files
with
173 additions
and
123 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
//! Handlers for different types of payments. | ||
mod bolt11; | ||
mod spontaneous; | ||
|
||
pub use bolt11::Bolt11PaymentsHandler; | ||
pub use spontaneous::SpontaneousPaymentsHandler; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
//! Holds a payment handler allowing to send spontaneous ("keysend") payments. | ||
//! | ||
//! [`BOLT11`]: https://github.com/lightning/bolts/blob/master/11-payment-encoding.md | ||
use crate::config::{Config, LDK_PAYMENT_RETRY_TIMEOUT}; | ||
use crate::error::Error; | ||
use crate::logger::{log_error, log_info, FilesystemLogger, Logger}; | ||
use crate::payment_store::{PaymentDetails, PaymentDirection, PaymentStatus, PaymentStore}; | ||
use crate::types::{ChannelManager, KeysManager}; | ||
|
||
use lightning::ln::channelmanager::{PaymentId, RecipientOnionFields, Retry, RetryableSendFailure}; | ||
use lightning::ln::{PaymentHash, PaymentPreimage}; | ||
use lightning::routing::router::{PaymentParameters, RouteParameters}; | ||
use lightning::sign::EntropySource; | ||
|
||
use bitcoin::secp256k1::PublicKey; | ||
|
||
use std::sync::{Arc, RwLock}; | ||
|
||
/// A payment handler allowing to send spontaneous ("keysend") payments. | ||
/// | ||
/// Should be retrieved by calling [`Node::spontaneous_payment`]. | ||
/// | ||
/// [`Node::spontaneous_payment`]: crate::Node::spontaneous_payment | ||
pub struct SpontaneousPaymentsHandler { | ||
runtime: Arc<RwLock<Option<tokio::runtime::Runtime>>>, | ||
channel_manager: Arc<ChannelManager>, | ||
keys_manager: Arc<KeysManager>, | ||
payment_store: Arc<PaymentStore<Arc<FilesystemLogger>>>, | ||
config: Arc<Config>, | ||
logger: Arc<FilesystemLogger>, | ||
} | ||
|
||
impl SpontaneousPaymentsHandler { | ||
pub(crate) fn new( | ||
runtime: Arc<RwLock<Option<tokio::runtime::Runtime>>>, | ||
channel_manager: Arc<ChannelManager>, keys_manager: Arc<KeysManager>, | ||
payment_store: Arc<PaymentStore<Arc<FilesystemLogger>>>, config: Arc<Config>, | ||
logger: Arc<FilesystemLogger>, | ||
) -> Self { | ||
Self { runtime, channel_manager, keys_manager, payment_store, config, logger } | ||
} | ||
|
||
/// Send a spontaneous, aka. "keysend", payment | ||
pub fn send(&self, amount_msat: u64, node_id: PublicKey) -> Result<PaymentHash, Error> { | ||
let rt_lock = self.runtime.read().unwrap(); | ||
if rt_lock.is_none() { | ||
return Err(Error::NotRunning); | ||
} | ||
|
||
let payment_preimage = PaymentPreimage(self.keys_manager.get_secure_random_bytes()); | ||
let payment_hash = PaymentHash::from(payment_preimage); | ||
|
||
if let Some(payment) = self.payment_store.get(&payment_hash) { | ||
if payment.status == PaymentStatus::Pending | ||
|| payment.status == PaymentStatus::Succeeded | ||
{ | ||
log_error!(self.logger, "Payment error: must not send duplicate payments."); | ||
return Err(Error::DuplicatePayment); | ||
} | ||
} | ||
|
||
let route_params = RouteParameters::from_payment_params_and_value( | ||
PaymentParameters::from_node_id(node_id, self.config.default_cltv_expiry_delta), | ||
amount_msat, | ||
); | ||
let recipient_fields = RecipientOnionFields::spontaneous_empty(); | ||
|
||
match self.channel_manager.send_spontaneous_payment_with_retry( | ||
Some(payment_preimage), | ||
recipient_fields, | ||
PaymentId(payment_hash.0), | ||
route_params, | ||
Retry::Timeout(LDK_PAYMENT_RETRY_TIMEOUT), | ||
) { | ||
Ok(_payment_id) => { | ||
log_info!(self.logger, "Initiated sending {}msat to {}.", amount_msat, node_id); | ||
|
||
let payment = PaymentDetails { | ||
hash: payment_hash, | ||
preimage: Some(payment_preimage), | ||
secret: None, | ||
status: PaymentStatus::Pending, | ||
direction: PaymentDirection::Outbound, | ||
amount_msat: Some(amount_msat), | ||
lsp_fee_limits: None, | ||
}; | ||
self.payment_store.insert(payment)?; | ||
|
||
Ok(payment_hash) | ||
}, | ||
Err(e) => { | ||
log_error!(self.logger, "Failed to send payment: {:?}", e); | ||
|
||
match e { | ||
RetryableSendFailure::DuplicatePayment => Err(Error::DuplicatePayment), | ||
_ => { | ||
let payment = PaymentDetails { | ||
hash: payment_hash, | ||
preimage: Some(payment_preimage), | ||
secret: None, | ||
status: PaymentStatus::Failed, | ||
direction: PaymentDirection::Outbound, | ||
amount_msat: Some(amount_msat), | ||
lsp_fee_limits: None, | ||
}; | ||
|
||
self.payment_store.insert(payment)?; | ||
Err(Error::PaymentSendingFailed) | ||
}, | ||
} | ||
}, | ||
} | ||
} | ||
|
||
/// Sends payment probes over all paths of a route that would be used to pay the given | ||
/// amount to the given `node_id`. | ||
/// | ||
/// See [`Bolt11PaymentsHandler::send_probes`] for more information. | ||
/// | ||
/// [`Bolt11PaymentsHandler::send_probes`]: crate::payment::Bolt11PaymentsHandler | ||
pub fn send_probes(&self, amount_msat: u64, node_id: PublicKey) -> Result<(), Error> { | ||
let rt_lock = self.runtime.read().unwrap(); | ||
if rt_lock.is_none() { | ||
return Err(Error::NotRunning); | ||
} | ||
|
||
let liquidity_limit_multiplier = Some(self.config.probing_liquidity_limit_multiplier); | ||
let cltv_expiry_delta = self.config.default_cltv_expiry_delta; | ||
|
||
self.channel_manager | ||
.send_spontaneous_preflight_probes( | ||
node_id, | ||
amount_msat, | ||
cltv_expiry_delta, | ||
liquidity_limit_multiplier, | ||
) | ||
.map_err(|e| { | ||
log_error!(self.logger, "Failed to send payment probes: {:?}", e); | ||
Error::ProbeSendingFailed | ||
})?; | ||
|
||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters