[Lightning-dev] Hold fee rates as DoS protection (channel spamming and jamming)

Joost Jager joost.jager at gmail.com
Thu Feb 11 14:28:14 UTC 2021

Hi all,

Things have been quiet around channel jamming lately, but the vulnerability
it still there as much as it was before. I've participated in an (isolated)
mainnet channel jamming experiment (
which only confirmed the seriousness of the issue.


Of all the proposals that have been presented, t-bast's remix of forward
and backward upfront payments (
indicates in my opinion the most promising direction.

One characteristic of the proposal is that the `hold_fees` are
time-independent. If an htlc doesn't resolve within the `grace_period`, the
receiver of the htlc will be forced to pay the full hold fee. The hold fee
should cover the expenses for locking up an htlc for the maximum duration
(could be 2000 blocks), so this can be a significant penalty. Applications
such as atomic onchain/offchain swaps (Lightning Loop and others) rely on
locking funds for some time and could get expensive with a fixed hold fee.


In this post I'd like to present a variation of bidirectional upfront
payments that uses a time-proportional hold fee rate to address the
limitation above. I also tried to come up with a system that aims to relate
the fees paid more directly to the actual costs incurred and thereby reduce
the number of parameters.

In a Lightning channel, the sender of an htlc always incurs the cost. The
htlc value is deduced from their balance and the money can't be used for
other purposes when the htlc is in flight. Therefore ideally a routing node
is compensated for the time that their outgoing htlc is in flight.

To communicate this cost to the outside world, routing nodes advertise a
`hold_fee_rate` as part of their channel forwarding policy. An example
would be "0.3 msat per sat per minute". So if someone wants to forward 10k
sat through that channel and the htlc remains in flight for 5 minutes, the
routing node would like to see a compensation of 0.3msat * 10k sat * 5 mins
= 15 sat. (it is possible to extend the model with a base fee rate to also
cover the cost of an occupied slot on the commitment tx)

The question here again is who is going to pay the hold fee. The answer is
that it is primarily the receiver of the htlc who is going to pay. They are
the ones that can fail or settle the htlc and are therefore in control of
the hold time ("Reverse upfront payment")

But this would also mean that anyone can send out an htlc and collect hold
fees unconditionally. Therefore routing nodes advertise on the network
their `hold_grace_period`. When routing nodes accept an htlc to forward,
they're willing to pay hold fees for it. But only if they added a delay
greater than `hold_grace_period` for relaying the payment and its response.
If they relayed in a timely fashion, they expect the sender of the htlc to
cover those costs themselves. If the sender is also a routing node, the
sender should expect the node before them to cover it. Of course, routing
nodes can't be trusted. So in practice we can just as well assume that
they'll always try to claim from the prior node the maximum amount in

This is the basic idea. Routing nodes have real costs for the lock up of
their money and will be compensated for it.

To coordinate the payment of the fees, the `update_add_htlc` message is
extended with:
* `hold_fee_rate`: the fee rate that the sender charges for having the htlc
in-flight (msat per sat per min)
* `hold_fee_discount`: the absolute fee discount (sat) that the receiver
gets as a compensation for hold fees that couldn't be claimed downstream
because of the grace periods (the worst case amount).
(the previous `hold_grace_period` in `update_add_htlc` is no longer needed)

When an htlc is resolved, the receiver of the htlc will pay the sender the
`hold_fee_rate` minus `hold_fee_discount` (exact details of how to
integrate this into the channel state machine and deal with clock shift

It is up to the sender of a payment to construct the onion payloads such
that all nodes along the route will have their costs covered.


A ----> B ----> C ----> D
Every node charges 0.6 msat/sat/minute with a hold grace period of 1
minute. In this example, the routing fees are zero.
A wants to send 1000 sat to D.

A will charge B a hold fee rate of 0.6 sat/min (1000 sat at 0.6
msat/sat/min). B will charge C a hold fee rate of 1.2 sat/min to cover both
its own cost and what must be paid back to A. C will charge D a hold fee
rate of 1.8 sat/min to cover the costs of A, B and C.

D has a grace period of 1 minute. At the 1.8 sat/min fee rate that C
charges, D would need to pay a maximum of 1.8 sat if it meets its grace
deadline just in time. C pays the 1.8 sats to D as a discount on its hold
fee (assuming D will settle right before the deadline anyway).

C also has a grace period of 1 minute. But because D has a grace period
too, it could be that C needs to hold on to the htlc for a total of 2
minutes. At the 1.2 sat/min fee rate B charges, C would need to pay a
maximum of 2.4 sats, plus the hold fee that it needs to pay to D (1.8
sats). Therefore B gives C a hold fee discount of 2.4+1.8 = 4.2 sats.

The same logic applies to A and B. A offers a hold fee discount of 0.6 * 3
min + 4.2 = 6 sats to cover the worst case cost of B, C and D.

If A is just spamming/probing, it will cost hem 6 sats per htlc. If D is
trying to channel-jam by hodling htlcs, it will cost them 1.8 sat/min. If
an intermediate hop is delaying the payment, they will pay at least 0.6
sat/min (depending on the position in the route).

In the happy flow, A is still paying 6 sat per payment attempt which is
used to compensate B, C and D for the short unavailability of their funds.
To me, this seems only fair.


Even though the proposal above is not fundamentally different from what was
known already, I do think that it adds the flexibility that we need to not
take a step back in terms of functionality (fair pricing for hodl invoices
and its applications). Plus that it simplifies the parameter set.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.linuxfoundation.org/pipermail/lightning-dev/attachments/20210211/491e64e5/attachment.html>

More information about the Lightning-dev mailing list