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

Configurable Gateway Fees #2246

Merged
merged 10 commits into from
May 19, 2023
Merged

Conversation

okjodom
Copy link
Contributor

@okjodom okjodom commented Apr 18, 2023

Enable configurable gateway fees for routing outgoing payments.
Fees are declared using known RoutingFees structure from lightning crate, and can be configured when setting up the gateway.

Example: export FM_GATEWAY_FEES= "10,2000" means the gateway will run declare a 10 msat base fee and a 2% liquidity based fee to federations served

By default, gatewayd configures a base fee of 0 msat and a marginal fee of 1%, which is on par with current behavior.

Next, we need to introduce a gateway API for configuring routing fees

Longer term, we need more comprehensive definition for gateway fees, as tracked by Discussion #2392

@m1sterc001guy
Copy link
Contributor

Is the next step making an API so that the fees are configurable?

@okjodom
Copy link
Contributor Author

okjodom commented Apr 18, 2023

Is the next step making an API so that the fees are configurable?

Yes. Left that out because I believe we have opportunity to introduce better configurable fee declaration before we introduce the api to configure the fees.

Additionally, we might want to make design decisions like supporting dynamic fee configuration per federation, vs some global fee configuration, vs automated fee configuration (based on route hints?)

@okjodom okjodom force-pushed the configurable-gw-fees branch from b133005 to b2faeaa Compare April 18, 2023 20:11
@codecov
Copy link

codecov bot commented Apr 18, 2023

Codecov Report

Patch coverage: 64.16% and project coverage change: +0.03 🎉

Comparison is base (ca46c3a) 61.18% compared to head (c7c5e05) 61.22%.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2246      +/-   ##
==========================================
+ Coverage   61.18%   61.22%   +0.03%     
==========================================
  Files         180      180              
  Lines       36185    36286     +101     
==========================================
+ Hits        22141    22217      +76     
- Misses      14044    14069      +25     
Impacted Files Coverage Δ
fedimint-testing/src/gateway.rs 93.10% <ø> (ø)
gateway/ln-gateway/src/bin/gatewayd.rs 0.99% <0.00%> (-0.28%) ⬇️
gateway/ln-gateway/src/rpc/mod.rs 81.81% <ø> (ø)
modules/fedimint-ln-client/src/lib.rs 9.31% <0.00%> (-0.07%) ⬇️
modules/fedimint-ln-server/src/lib.rs 70.33% <0.00%> (-0.35%) ⬇️
gateway/ln-gateway/src/lib.rs 56.77% <87.50%> (+0.97%) ⬆️
modules/fedimint-ln-common/src/lib.rs 76.47% <92.85%> (+7.13%) ⬆️
fedimint-client-legacy/src/ln/mod.rs 71.81% <94.44%> (+0.86%) ⬆️
fedimint-client-legacy/src/lib.rs 74.95% <100.00%> (+0.02%) ⬆️
fedimint-core/src/encoding/mod.rs 87.94% <100.00%> (+0.47%) ⬆️
... and 1 more

... and 7 files with indirect coverage changes

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

@okjodom okjodom marked this pull request as ready for review April 18, 2023 20:27
@okjodom okjodom requested review from a team as code owners April 18, 2023 20:27
m1sterc001guy
m1sterc001guy previously approved these changes Apr 19, 2023
gateway/ln-gateway/src/lib.rs Outdated Show resolved Hide resolved
@okjodom okjodom marked this pull request as draft April 20, 2023 06:14
@okjodom okjodom force-pushed the configurable-gw-fees branch from b2faeaa to 544ff96 Compare April 20, 2023 12:02
@okjodom okjodom force-pushed the configurable-gw-fees branch 2 times, most recently from b833c5f to b9906aa Compare April 20, 2023 13:07
@okjodom okjodom marked this pull request as ready for review April 20, 2023 13:20
@@ -379,6 +379,29 @@ impl Encodable for lightning_invoice::Invoice {
}
}

impl Encodable for lightning::routing::gossip::RoutingFees {
Copy link
Contributor

@dpc dpc Apr 20, 2023

Choose a reason for hiding this comment

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

Not sure if it"s a good idea to depend for our own encodings on data-structures from external crates (that possibly could change).

Also how we are going to implement gateway fees and LN gateway fees, are probably two different things.

Could have fees paid in different currencies supported by federation, or maybe "no gateway fee tuesdays", or some other things? If not, then whatever, let"s just go with this, seems reasonable. If possibly yes, maybe we should go with an enum. But the main variant of that enum should probably be this thing. Not sure if we should copy&paste or use directly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

RE: Also how we are going to implement gateway fees and LN gateway fees, are probably two different things.

Could have fees paid in different currencies supported by federation, or maybe "no gateway fee tuesdays", or some other things? If not, then whatever, let"s just go with this, seems reasonable. If possibly yes, maybe we should go with an enum. But the main variant of that enum should probably be this thing. Not sure if we should copy&paste or use directly.

Fantastic idea IMO. If I adopt it as a proposal, we"d have

#[non_exhaustive]
pub enum FeeStructure {
  LnRouting { fees: RoutingFees }
}

To open up future possibility of:

#[non_exhaustive]
pub enum FeeStructure {
  LnRouting { fees: RoutingFees },
  Discount { ... }
}

Because "Free Gateway Tuesdays" is a fantastic thing :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

RE: Not sure if it"s a good idea to depend for our own encodings on data-structures from external crates (that possibly could change).

We are also guilty in these other accounts, and I"m not keen on maintaining a variant of RoutingFees because we already have a dependency on the crate and type in other scenarios.

Can we fully rely on version control to alert breaks in encodings? Is maintaining our own types the only way to avoid encoding extern types?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Proposing flexible fee structure as a quick follow up to the current PR: #2287

@okjodom okjodom marked this pull request as draft April 21, 2023 06:07
@okjodom okjodom mentioned this pull request Apr 21, 2023
@okjodom okjodom marked this pull request as ready for review April 21, 2023 09:03
@okjodom okjodom added the waiting-on-review PR needs review label Apr 21, 2023
@justinmoon
Copy link
Contributor

justinmoon commented Apr 23, 2023

Thinking about this a little more, I think we need to achieve the following:

  • Clients are presented a fee that will be charged for the payment before creating outgoing / incoming contract . They can use this fee to choose a gateway, display this fee to the user, and calculate the amount needed for the outgoing / incoming contracts.
  • For outgoing payments, gateways can set a fee they will charge for routing payments a given payment, net of routing fees they pay. For incoming payments, gateways can set a separate fee to receive a payment for the user compensating them for locking up capital in channel capacity and ecash balance.

So the first conclusion is that I think we need separate fees for incoming and outgoing payments. They fundamentally represent costs of different resources: outgoing lightning liquidity, and incoming lightning liquidity + cost and risk of holding ecash.

Another conclusion is that no matter how we express these fees in the outgoing case, we need to take them into consideration when the gateway pays the actual invoice. We’ll need to pass these fee calculations on to PayInvoiceRequest.max_fee_percent field in our gRPC spec. Without doing this, the gateway only controls the fees they charge the end-user, but could still lose money routing the payment if routing fees exceed fees charged to the user.

I’m also not sure if lightning::routing::gossip::RoutingFees is the best way to encode our fees, because it seems like it’s intended to express the cost for forwarding a payment across a single channel. The gateway’s job is different: completing the entire payment no matter how many hops it takes. And if we do use RoutingFees to express gateway fees, we"ll need another parameter expressing how much of these fees the gateway will reserve for itself when paying the invoice. For example, if RoutingFees translates to a fee of x for a given invoice, the gateway might want to use a value less than x when calculating PayInvoiceRequest.max_fee_percent to guarantee that they make a profit.

Edit: Client currently hard-codes a routing fee of 0 for the gateway for incoming payments. RoutingFees could be nice to express this fee. Additionally, we would need to have the gateway validate this when it receives an HTLC.

@okjodom okjodom marked this pull request as draft May 3, 2023 15:40
@okjodom okjodom removed the waiting-on-review PR needs review label May 4, 2023
@okjodom okjodom force-pushed the configurable-gw-fees branch from b9906aa to dab8069 Compare May 12, 2023 21:50
@okjodom okjodom force-pushed the configurable-gw-fees branch from dab8069 to 7a99ba0 Compare May 12, 2023 23:20
@okjodom okjodom marked this pull request as ready for review May 13, 2023 00:00
@elsirion elsirion requested a review from m1sterc001guy May 14, 2023 14:22
@@ -47,6 +49,11 @@ pub struct GatewayOpts {
/// Gateway webserver authentication password
#[arg(long = "password", env = "FM_GATEWAY_PASSWORD")]
pub password: String,

/// Configured gateway routing fees
/// Format: <base_msat>,<proportional_millionths>
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: For me I know I would be confused by this format, would probably just prefer separate parameters

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually I would want us to remove this gateway config soon as we have an API from #2271

let fees = gateway.fees;
let base_fee = fees.base_msat as u64;
let margin_fee: u64 = if fees.proportional_millionths > 0 {
let fee_percent = 1000000 / fees.proportional_millionths as u64;
Copy link
Contributor

Choose a reason for hiding this comment

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

What does 1000000 represent? Would prefer constant

Copy link
Contributor Author

Choose a reason for hiding this comment

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

huh. it"s just the number 1 million used to compute percentage here :)

Copy link
Contributor

@m1sterc001guy m1sterc001guy left a comment

Choose a reason for hiding this comment

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

LGTM, let"s iterate on it

@okjodom
Copy link
Contributor Author

okjodom commented May 15, 2023

LGTM, let"s iterate on it

thanks for review.

@justinmoon, take a look if you still need this change asap

@justinmoon justinmoon merged commit 9be58bb into fedimint:master May 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants