Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lightning-liquidity alpha release #1050

Merged
merged 4 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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