Skip to content

Commit

Permalink
lightning-liquidity alpha release (#1050)
Browse files Browse the repository at this point in the history
* specify payment size with buy request

* upgrade to liquidity alpha release crate

* remove fee check when user liquidity

* fix request ids
  • Loading branch information
johncantrell97 committed Feb 26, 2024
1 parent 19e70c8 commit 13e5bf9
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 119 deletions.
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion mutiny-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ lightning-invoice = { version = "0.29.0", features = ["serde"] }
lightning-rapid-gossip-sync = { version = "0.0.121" }
lightning-background-processor = { version = "0.0.121", features = ["futures"] }
lightning-transaction-sync = { version = "0.0.121", default-features = false, features = ["esplora-async-https"] }
lightning-liquidity = { git = "https://github.com/lightningdevkit/lightning-liquidity.git", rev = "478ccf9324e2650d200ea289a0ba8905afe420b6" }
lightning-liquidity = "0.1.0-alpha"
chrono = "0.4.22"
futures-util = { version = "0.3", default-features = false }
reqwest = { version = "0.11", default-features = false, features = ["multipart", "json"] }
Expand Down
117 changes: 49 additions & 68 deletions mutiny-core/src/lsp/lsps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use lightning::util::logger::Logger;
use lightning::{log_debug, log_error, log_info};
use lightning_invoice::{Bolt11Invoice, InvoiceBuilder};
use lightning_liquidity::events::Event;
use lightning_liquidity::lsps0::msgs::RequestId;
use lightning_liquidity::lsps2::event::LSPS2ClientEvent;
use lightning_liquidity::lsps2::msgs::OpeningFeeParams;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -39,17 +40,13 @@ pub struct LspsConfig {

#[derive(Clone, Debug)]
pub(crate) struct JitChannelInfo {
pub channel_id: u128,
pub fee_params: OpeningFeeParams,
pub payment_size_msat: u64,
}

#[derive(Clone, Debug)]
pub(crate) struct GetInfoResponse {
pub opening_fee_params_menu: Vec<OpeningFeeParams>,
/// The min payment size allowed when opening the channel.
pub min_payment_size_msat: u64,
/// The max payment size allowed when opening the channel.
pub max_payment_size_msat: u64,
}

pub(crate) struct PendingPaymentInfo {
Expand All @@ -70,9 +67,9 @@ pub struct LspsClient<S: MutinyStorage> {
keys_manager: Arc<PhantomKeysManager<S>>,
network: Network,
logger: Arc<MutinyLogger>,
pending_fee_requests: Arc<Mutex<HashMap<PublicKey, PendingFeeRequestSender>>>,
pending_buy_requests: Arc<Mutex<HashMap<u128, PendingBuyRequestSender>>>,
pending_channel_info: Arc<Mutex<HashMap<u128, JitChannelInfo>>>,
pending_fee_requests: Arc<Mutex<HashMap<RequestId, PendingFeeRequestSender>>>,
pending_buy_requests: Arc<Mutex<HashMap<RequestId, PendingBuyRequestSender>>>,
pending_channel_info: Arc<Mutex<HashMap<RequestId, JitChannelInfo>>>,
pending_payments: Arc<Mutex<HashMap<PaymentHash, PendingPaymentInfo>>>,
stop: Arc<AtomicBool>,
}
Expand Down Expand Up @@ -120,8 +117,7 @@ impl<S: MutinyStorage> LspsClient<S> {
Event::LSPS2Client(LSPS2ClientEvent::OpeningParametersReady {
counterparty_node_id,
opening_fee_params_menu,
min_payment_size_msat,
max_payment_size_msat,
request_id,
}) => {
log_debug!(
self.logger,
Expand All @@ -130,14 +126,10 @@ impl<S: MutinyStorage> LspsClient<S> {

let mut pending_fee_requests = self.pending_fee_requests.lock().unwrap();

if let Some(fee_response_sender) =
pending_fee_requests.remove(&counterparty_node_id)
{
if let Some(fee_response_sender) = pending_fee_requests.remove(&request_id) {
if fee_response_sender
.send(Ok(GetInfoResponse {
opening_fee_params_menu,
min_payment_size_msat,
max_payment_size_msat,
}))
.is_err()
{
Expand All @@ -148,16 +140,15 @@ impl<S: MutinyStorage> LspsClient<S> {
Event::LSPS2Client(LSPS2ClientEvent::InvoiceParametersReady {
intercept_scid,
cltv_expiry_delta,
user_channel_id,
counterparty_node_id,
payment_size_msat,
..
request_id,
}) => {
log_debug!(self.logger, "received InvoiceGenerationReady with intercept_scid {}, cltv_expiry_delta {}, user_channel_id {}, counterparty_node_id {}, payment_size_msat {:?}", intercept_scid, cltv_expiry_delta, user_channel_id, counterparty_node_id, payment_size_msat);
log_debug!(self.logger, "received InvoiceGenerationReady with intercept_scid {}, cltv_expiry_delta {}, request_id {:?}, counterparty_node_id {}, payment_size_msat {:?}", intercept_scid, cltv_expiry_delta, request_id, counterparty_node_id, payment_size_msat);

let mut pending_buy_requests = self.pending_buy_requests.lock().unwrap();

if let Some(buy_response_sender) = pending_buy_requests.remove(&user_channel_id) {
if let Some(buy_response_sender) = pending_buy_requests.remove(&request_id) {
let invoice_expiry_delta_secs = 3600;
let (payment_hash, payment_secret) = match self
.channel_manager
Expand Down Expand Up @@ -340,34 +331,9 @@ pub fn compute_opening_fee(
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl<S: MutinyStorage> Lsp for LspsClient<S> {
async fn get_lsp_fee_msat(&self, fee_request: FeeRequest) -> Result<FeeResponse, MutinyError> {
let user_channel_id = fee_request
.user_channel_id
.ok_or(MutinyError::LspGenericError)?;

let inbound_capacity_msat: u64 = self
.channel_manager
.list_channels_with_counterparty(&self.pubkey)
.iter()
.map(|c| c.inbound_capacity_msat)
.sum();

// if there's enough capacity then the LSP won't charge an opening fee to route a normal payment
// this is only here to keep both voltage + lsps logic symmetric
if inbound_capacity_msat >= fee_request.amount_msat {
return Ok(FeeResponse {
id: None,
fee_amount_msat: 0,
});
}

let (pending_fee_request_sender, pending_fee_request_receiver) =
oneshot::channel::<Result<GetInfoResponse, MutinyError>>();

{
let mut pending_fee_requests = self.pending_fee_requests.lock().unwrap();
pending_fee_requests.insert(self.pubkey, pending_fee_request_sender);
}

log_debug!(
self.logger,
"initiating inbound flow for {}msats with token {:?}",
Expand All @@ -380,7 +346,18 @@ impl<S: MutinyStorage> Lsp for LspsClient<S> {
.lsps2_client_handler()
.expect("to be configured with lsps2 client config");

lsps2_client_handler.request_opening_params(self.pubkey, self.token.clone());
let request_id = {
let mut pending_fee_requests = self.pending_fee_requests.lock().unwrap();
let request_id =
lsps2_client_handler.request_opening_params(self.pubkey, self.token.clone());
log_debug!(
self.logger,
"requested opening params from lsp with request_id {:?}",
request_id
);
pending_fee_requests.insert(request_id.clone(), pending_fee_request_sender);
request_id
};

let get_info_response = pending_fee_request_receiver.await.map_err(|e| {
log_debug!(self.logger, "error receiving get info response: {:?}", e);
Expand All @@ -397,17 +374,17 @@ impl<S: MutinyStorage> Lsp for LspsClient<S> {
"received fee information. min_fee_msat {}, proportional fee {}, min payment {}msats, max payment {}msats",
min_fee_msat,
proportional_fee,
get_info_response.min_payment_size_msat,
get_info_response.max_payment_size_msat,
fee_params.min_payment_size_msat,
fee_params.max_payment_size_msat,
);

{
let mut pending_channel_info = self.pending_channel_info.lock().unwrap();
pending_channel_info.insert(
user_channel_id,
request_id.clone(),
JitChannelInfo {
channel_id: user_channel_id,
fee_params,
payment_size_msat: fee_request.amount_msat,
},
);
}
Expand All @@ -420,7 +397,7 @@ impl<S: MutinyStorage> Lsp for LspsClient<S> {
.ok_or(MutinyError::LspGenericError)?;

Ok(FeeResponse {
id: None,
id: request_id.0,
fee_amount_msat,
})
}
Expand All @@ -429,35 +406,39 @@ impl<S: MutinyStorage> Lsp for LspsClient<S> {
&self,
invoice_request: InvoiceRequest,
) -> Result<Bolt11Invoice, MutinyError> {
let user_channel_id = invoice_request
.user_channel_id
.ok_or(MutinyError::LspGenericError)?;

let (pending_buy_request_sender, pending_buy_request_receiver) =
oneshot::channel::<Result<Bolt11Invoice, MutinyError>>();

{
let mut pending_buy_requests = self.pending_buy_requests.lock().unwrap();
pending_buy_requests.insert(user_channel_id, pending_buy_request_sender);
}

let (channel_id, fee_params) = {
let fee_request_id = RequestId(invoice_request.fee_id);
let (fee_params, payment_size_msat) = {
let channel_info = self.pending_channel_info.lock().unwrap();
let channel_info = channel_info
.get(&user_channel_id)
.get(&fee_request_id)
.ok_or(MutinyError::LspGenericError)?;

(channel_info.channel_id, channel_info.fee_params.clone())
(
channel_info.fee_params.clone(),
channel_info.payment_size_msat,
)
};

let lsps2_client_handler = self
.liquidity_manager
.lsps2_client_handler()
.expect("to be configured with lsps2 client config");

lsps2_client_handler
.select_opening_params(self.pubkey, channel_id, None, fee_params.clone())
.map_err(|_| MutinyError::LspGenericError)?;
let (pending_buy_request_sender, pending_buy_request_receiver) =
oneshot::channel::<Result<Bolt11Invoice, MutinyError>>();

{
let mut pending_buy_requests: std::sync::MutexGuard<
'_,
HashMap<RequestId, oneshot::Sender<Result<Bolt11Invoice, MutinyError>>>,
> = self.pending_buy_requests.lock().unwrap();

let request_id = lsps2_client_handler
.select_opening_params(self.pubkey, Some(payment_size_msat), fee_params.clone())
.map_err(|_| MutinyError::LspGenericError)?;

pending_buy_requests.insert(request_id.clone(), pending_buy_request_sender);
}

let invoice = pending_buy_request_receiver
.await
Expand Down
12 changes: 4 additions & 8 deletions mutiny-core/src/lsp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,24 +86,20 @@ where
pub struct InvoiceRequest {
// Used only for VoltageFlow
pub bolt11: Option<String>,
// Used only for VoltageFlow to map to previously fetched fee
pub fee_id: Option<String>,
// Used only for LSPS to track channel creation
pub user_channel_id: Option<u128>,
// Map to previously fetched fee
pub fee_id: String,
}

#[derive(Serialize, Deserialize)]
pub struct FeeRequest {
pub pubkey: String,
pub amount_msat: u64,
// Used only for LSPS to track channel creation
pub user_channel_id: Option<u128>,
}

#[derive(Serialize, Deserialize)]
pub struct FeeResponse {
// Used only for VoltageFlow to be used in subsequent InvoiceRequest
pub id: Option<String>,
// To be used in subsequent InvoiceRequest
pub id: String,
pub fee_amount_msat: u64,
}

Expand Down
4 changes: 1 addition & 3 deletions mutiny-core/src/lsp/voltage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,6 @@ impl Lsp for LspClient {
&self,
invoice_request: InvoiceRequest,
) -> Result<Bolt11Invoice, MutinyError> {
let fee_id = invoice_request.fee_id.ok_or(MutinyError::LspGenericError)?;

let bolt11 = invoice_request
.bolt11
.ok_or(MutinyError::LspInvoiceRequired)?;
Expand All @@ -264,7 +262,7 @@ impl Lsp for LspClient {
bolt11,
host: None,
port: None,
fee_id,
fee_id: invoice_request.fee_id,
};

let request = self
Expand Down

0 comments on commit 13e5bf9

Please sign in to comment.