Skip to content

Commit

Permalink
Merge pull request #1528 from get10101/feat/jit-channel-fee-lsp-flow
Browse files Browse the repository at this point in the history
feat: Charge channel opening fee through lsp flow
  • Loading branch information
holzeis authored Nov 3, 2023
2 parents 118f472 + f71d546 commit ce33f34
Show file tree
Hide file tree
Showing 43 changed files with 389 additions and 564 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Allow to drain on-chain wallet by sending amount `0`.
- Load persisted `rust-dlc` `ChainMonitor` on restart.
- Upgrade `rust-lightning` to version 0.0.116.
- Charge channel opening fee through the lsp flow

## [1.4.4] - 2023-10-28

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-- This file should undo anything in `up.sql`
ALTER TABLE channels DROP COLUMN "fee_sats";

ALTER TABLE
channels
ADD
COLUMN open_channel_fee_payment_hash TEXT REFERENCES payments(payment_hash);
CREATE INDEX IF NOT EXISTS channels_funding_txid ON channels(funding_txid);
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-- Your SQL goes here
ALTER TABLE channels ADD COLUMN "fee_sats" BIGINT DEFAULT null;

ALTER TABLE
channels DROP COLUMN open_channel_fee_payment_hash;
DROP INDEX IF EXISTS channels_funding_txid;
22 changes: 4 additions & 18 deletions coordinator/src/db/channels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::schema;
use crate::schema::channels;
use crate::schema::sql_types::ChannelStateType;
use anyhow::ensure;
use anyhow::Context;
use anyhow::Result;
use bitcoin::hashes::hex::ToHex;
use bitcoin::secp256k1::PublicKey;
Expand All @@ -23,7 +22,6 @@ use diesel::QueryableByName;
use diesel::RunQueryDsl;
use dlc_manager::ChannelId;
use hex::FromHex;
use lightning::ln::PaymentHash;
use ln_dlc_node::channel::UserChannelId;
use std::any::TypeId;
use std::str::FromStr;
Expand Down Expand Up @@ -61,8 +59,8 @@ pub(crate) struct Channel {
pub counterparty_pubkey: String,
pub created_at: OffsetDateTime,
pub updated_at: OffsetDateTime,
pub open_channel_fee_payment_hash: Option<String>,
pub liquidity_option_id: Option<i32>,
pub fee_sats: Option<i64>,
}

pub(crate) fn get(user_channel_id: &str, conn: &mut PgConnection) -> QueryResult<Option<Channel>> {
Expand Down Expand Up @@ -93,20 +91,6 @@ pub(crate) fn get_all_non_pending_channels(conn: &mut PgConnection) -> QueryResu
.load(conn)
}

pub(crate) fn update_payment_hash(
payment_hash: PaymentHash,
funding_txid: String,
conn: &mut PgConnection,
) -> Result<()> {
let mut channel: Channel = channels::table
.filter(channels::funding_txid.eq(funding_txid.clone()))
.first(conn)
.with_context(|| format!("No channel found for funding txid {funding_txid}"))?;

channel.open_channel_fee_payment_hash = Some(payment_hash.0.to_hex());
upsert(channel, conn)
}

pub fn get_by_channel_id(
channel_id: String,
conn: &mut PgConnection,
Expand Down Expand Up @@ -145,7 +129,7 @@ impl From<ln_dlc_node::channel::Channel> for Channel {
counterparty_pubkey: value.counterparty.to_string(),
created_at: value.created_at,
updated_at: value.updated_at,
open_channel_fee_payment_hash: None,
fee_sats: value.fee_sats.map(|fee| fee as i64),
}
}
}
Expand Down Expand Up @@ -187,6 +171,8 @@ impl From<Channel> for ln_dlc_node::channel::Channel {
.expect("valid public key"),
created_at: value.created_at,
updated_at: value.updated_at,
fee_sats: value.fee_sats.map(|fee| fee as u64),
open_channel_payment_hash: None,
}
}
}
Expand Down
1 change: 1 addition & 0 deletions coordinator/src/db/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ impl TryFrom<Payment> for (lightning::ln::PaymentHash, ln_dlc_node::PaymentInfo)
timestamp: value.payment_timestamp,
description: value.description,
invoice: value.invoice,
funding_txid: None,
},
))
}
Expand Down
1 change: 0 additions & 1 deletion coordinator/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ use trade::cfd::calculate_short_liquidation_price;
use trade::Direction;
use uuid::Uuid;

pub mod channel_opening_fee;
pub mod closed_positions;
pub mod connection;
pub mod expired_positions;
Expand Down
66 changes: 0 additions & 66 deletions coordinator/src/node/channel_opening_fee.rs

This file was deleted.

8 changes: 8 additions & 0 deletions coordinator/src/node/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::db::payments;
use anyhow::anyhow;
use anyhow::Result;
use bitcoin::secp256k1::PublicKey;
use bitcoin::Txid;
use diesel::r2d2::ConnectionManager;
use diesel::r2d2::Pool;
use diesel::PgConnection;
Expand Down Expand Up @@ -48,6 +49,7 @@ impl node::Storage for NodeStorage {
htlc_status: HTLCStatus,
preimage: Option<PaymentPreimage>,
secret: Option<PaymentSecret>,
_: Option<Txid>,
) -> Result<()> {
let mut conn = self.pool.get()?;

Expand Down Expand Up @@ -77,6 +79,7 @@ impl node::Storage for NodeStorage {
timestamp: OffsetDateTime::now_utc(),
description: "".to_string(),
invoice: None,
funding_txid: None,
},
),
&mut conn,
Expand Down Expand Up @@ -161,6 +164,11 @@ impl node::Storage for NodeStorage {
Ok(channel)
}

fn get_channel_by_payment_hash(&self, _payment_hash: String) -> Result<Option<Channel>> {
// the payment hash is not stored on the coordinator side.
unimplemented!()
}

// Transaction

fn upsert_transaction(&self, transaction: Transaction) -> Result<()> {
Expand Down
23 changes: 6 additions & 17 deletions coordinator/src/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ use orderbook_commons::Message;
use orderbook_commons::RouteHintHop;
use prometheus::Encoder;
use prometheus::TextEncoder;
use rust_decimal::prelude::ToPrimitive;
use rust_decimal::Decimal;
use serde::Deserialize;
use serde::Serialize;
use std::str::FromStr;
Expand Down Expand Up @@ -123,10 +125,6 @@ pub fn router(
.route("/api/newaddress", get(get_unused_address))
.route("/api/node", get(get_node_info))
.route("/api/invoice", get(get_invoice))
.route(
"/api/invoice/open_channel_fee",
get(get_open_channel_fee_invoice),
)
.route("/api/orderbook/orders", get(get_orders).post(post_order))
.route(
"/api/orderbook/orders/:order_id",
Expand Down Expand Up @@ -247,6 +245,10 @@ pub async fn prepare_onboarding_payment(
trade_up_to_sats: liquidity_option.trade_up_to_sats,
max_deposit_sats: liquidity_option.max_deposit_sats,
coordinator_leverage: liquidity_option.coordinator_leverage,
fee_sats: liquidity_option
.get_fee(Decimal::from(amount_sats))
.to_u64()
.expect("to fit into u64"),
})
}
})
Expand Down Expand Up @@ -299,19 +301,6 @@ pub async fn get_invoice(
Ok(invoice.to_string())
}

pub async fn get_open_channel_fee_invoice(
Query(params): Query<OpenChannelFeeInvoiceParams>,
State(state): State<Arc<AppState>>,
) -> Result<String, AppError> {
let invoice = state
.node
.channel_opening_fee_invoice(params.amount, params.channel_funding_txid, params.expiry)
.await
.map_err(|e| AppError::InternalServerError(format!("Failed to create invoice: {e:#}")))?;

Ok(invoice.to_string())
}

// TODO: We might want to have our own ContractInput type here so we can potentially map fields if
// the library changes?
#[instrument(skip_all, err(Debug))]
Expand Down
2 changes: 1 addition & 1 deletion coordinator/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ diesel::table! {
counterparty_pubkey -> Text,
created_at -> Timestamptz,
updated_at -> Timestamptz,
open_channel_fee_payment_hash -> Nullable<Text>,
liquidity_option_id -> Nullable<Int4>,
fee_sats -> Nullable<Int8>,
}
}

Expand Down
11 changes: 7 additions & 4 deletions crates/ln-dlc-node/src/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ use std::str::FromStr;
use time::OffsetDateTime;
use uuid::Uuid;

/// The prefix used in the description field of an JIT channel opening invoice to be paid by the
/// client.
pub const JIT_FEE_INVOICE_DESCRIPTION_PREFIX: &str = "jit-channel-fee-";

/// We introduce a shadow copy of the Lightning channel as LDK deletes channels from its
/// [`ChannelManager`] as soon as they are closed.
///
Expand Down Expand Up @@ -46,6 +42,8 @@ pub struct Channel {
pub counterparty: PublicKey,
pub created_at: OffsetDateTime,
pub updated_at: OffsetDateTime,
pub fee_sats: Option<u64>,
pub open_channel_payment_hash: Option<String>,
}

impl Channel {
Expand All @@ -66,13 +64,16 @@ impl Channel {
channel_id: None,
funding_txid: None,
liquidity_option_id: None,
fee_sats: None,
open_channel_payment_hash: None,
}
}

pub fn new_jit_channel(
user_channel_id: UserChannelId,
counterparty: PublicKey,
liquidity_option_id: i32,
fee: u64,
) -> Self {
Channel {
user_channel_id,
Expand All @@ -85,6 +86,8 @@ impl Channel {
channel_id: None,
funding_txid: None,
liquidity_option_id: Some(liquidity_option_id),
fee_sats: Some(fee),
open_channel_payment_hash: None,
}
}

Expand Down
3 changes: 3 additions & 0 deletions crates/ln-dlc-node/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ pub fn app_config() -> UserConfig {
},
channel_config: ChannelConfig {
cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA,
// Allows the coordinator to charge us a channel-opening fee after intercepting the
// app's funding HTLC.
accept_underpaying_htlcs: true,
..Default::default()
},
// we want to accept 0-conf channels from the coordinator
Expand Down
5 changes: 5 additions & 0 deletions crates/ln-dlc-node/src/ldk_node_wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@ pub mod tests {
_htlc_status: crate::HTLCStatus,
_preimage: Option<lightning::ln::PaymentPreimage>,
_secret: Option<lightning::ln::PaymentSecret>,
_funding_txid: Option<Txid>,
) -> Result<()> {
unimplemented!();
}
Expand Down Expand Up @@ -551,6 +552,10 @@ pub mod tests {
unimplemented!();
}

fn get_channel_by_payment_hash(&self, _payment_hash: String) -> Result<Option<Channel>> {
unimplemented!();
}

fn upsert_transaction(&self, _transaction: crate::transaction::Transaction) -> Result<()> {
unimplemented!();
}
Expand Down
5 changes: 5 additions & 0 deletions crates/ln-dlc-node/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::ln::TracingLogger;
use crate::node::SubChannelManager;
use bitcoin::hashes::hex::ToHex;
use bitcoin::Txid;
use dlc_custom_signer::CustomKeysManager;
use dlc_custom_signer::CustomSigner;
use dlc_messages::message_handler::MessageHandler as DlcMessageHandler;
Expand Down Expand Up @@ -106,6 +107,9 @@ pub struct PaymentInfo {
pub timestamp: OffsetDateTime,
pub description: String,
pub invoice: Option<String>,
/// If the payment was used to open an inbound channel, this tx id refers the funding
/// transaction for opening the channel.
pub funding_txid: Option<Txid>,
}

#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -151,6 +155,7 @@ impl From<Bolt11Invoice> for PaymentInfo {
Bolt11InvoiceDescription::Hash(hash) => hash.0.to_hex(),
},
invoice: Some(value.to_string()),
funding_txid: None,
}
}
}
Loading

0 comments on commit ce33f34

Please sign in to comment.