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

feat: Charge channel opening fee through lsp flow #1528

Merged
merged 5 commits into from
Nov 3, 2023
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,
holzeis marked this conversation as resolved.
Show resolved Hide resolved
..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>,
Comment on lines +110 to +112
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙃 Perhaps not worth it here, but it's nice to think about ways to avoid optional fields.

For instance, we could extend the PaymentFlow enum to something like:

enum PaymentType {
    Inbound,
    Outbound,
    Funding {
        funding_txid: Txid,
    }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

opted to not do the change as it became too big of a change very quickly :/

}

#[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
Loading