[Lightning-dev] Hold fees: 402 Payment Required for Lightning itself

ZmnSCPxj ZmnSCPxj at protonmail.com
Thu Oct 22 17:56:12 UTC 2020


Good morning t-bast,

> Sorry in advance for the lengthy email,

Come on, ZmnSCPxj writes lengthier.

> but I think it's worth detailing my hybrid proposal
> (bidirectional upfront payments), it feels to me like a workable solution that builds on
> previous proposals. You can safely ignore the details at the end of the email and focus only on
> the high-level mechanism at first.
>
> Let's consider the following route: A -----> B -----> C -----> D
>
> We add a `hold_grace_period_delta` field to `channel_update` (in seconds).
> We add two new fields in the tlv extension of `update_add_htlc`:
>
> * `hold_grace_period` (seconds)
> * `hold_fees` (msat)
>
> We add an `outgoing_hold_grace_period` field in the onion per-hop payload.
>
> When nodes receive an `update_add_htlc`, they verify that:
>
> * `hold_fees` is not unreasonable large
> * `hold_grace_period` is not unreasonably small or large
> * `hold_grace_period` - `outgoing_hold_grace_period` >= `hold_grace_period_delta`
>
> Otherwise they immediately fail the HTLC instead of relaying it.
>
> For the example we assume all nodes use `hold_grace_period_delta = 10`.
>
> We add a forward upfront payment of 1 msat (fixed) that is paid unconditionally when offering an HTLC.
> We add a backwards upfront payment of `hold_fees` that is paid when receiving an HTLC, but refunded
> if the HTLC is settled before the `hold_grace_period` ends (see footnotes about this).

My first instinct is that additional complications are worse in general.

However, it looks like simpler solutions are truly not enough, so adding the complication may very well be necessary.

Possibly one of the issues with previous proposals is that we considered the source as the payer of upfront fees always, without considering the possibility of the destination paying upfront fees.

We should consider *why* we did so.
Is it only because of lack of imagination?

The succeeding text refers to HTLCs "settling".
What does this mean exactly?
Does it refer to the preimage being revealed only?
Or does it refer to *either* `update_fulfill_htlc` **OR** `update_fail_htlc`?

If "settling" does not include failing the HTLC, I can extract hold fees from my peers by giving them HTLCs to random hashes that with very high probability has a preimage unknown to my peer.

Thus, "settling" here must also include failing the HTLC.


Can we arrange the HTLC as below?

* The HTLC is lower by the from-destination hold fee than what it "should" be.
  * So in your example, A would offer an HTLC that is 5 msat lower than what it "should" be, to represent the from-destination hold-fee.
* When the HTLC is fulfilled offchain, we move the hold fee amount from offerrer to acceptor, thus "refunding" the hold fee.
* If the HTLC is failed offchain, we just delete the HTLC.

The above would disincentivize dropping the channel onchain for whatever shenanigans might be possible there.

Note that if hold fees are always from the "main output" of the acceptor, then we cannot use single-funded channel opening.
Single-funded channel opening is significantly lower-risk as, if somebody opens a channel to you and then goes offline forever, you would not care, none of your funds are in the channel.
(Sure they could move funds out of the channel and *then* go offline forever, but you got paid for that by the forwarding fees in the first place.)
Dual-funding requires some amount of trust/reputation, where you would only be willing to put funds on the initiating peer if you are reasonably sure that they would remain online so that the funds you put in the channel are not uselessly locked.

If we also require that the hold fee be funded from the main output, then we cannot use single-funded channels, except perhaps with `push_msat`.

On the other hand, it might be useful to require that though, as a promise from the funder that yes, it *is* committed to making that channel work, and will thus `push_msat` at you so you can pay for hold fees.


>
> * A sends an HTLC to B:
> * `hold_grace_period = 100 sec`
> * `hold_fees = 5 msat`
> * `next_hold_grace_period = 90 sec`
> * forward upfront payment: 1 msat is deduced from A's main output and added to B's main output
> * backwards upfront payment: 5 msat are deduced from B's main output and added to A's main output
> * B forwards the HTLC to C:
> * `hold_grace_period = 90 sec`
> * `hold_fees = 6 msat`
> * `next_hold_grace_period = 80 sec`
> * forward upfront payment: 1 msat is deduced from B's main output and added to C's main output
> * backwards upfront payment: 6 msat are deduced from C's main output and added to B's main output
> * C forwards the HTLC to D:
> * `hold_grace_period = 80 sec`
> * `hold_fees = 7 msat`
> * `next_hold_grace_period = 70 sec`
> * forward upfront payment: 1 msat is deduced from C's main output and added to D's main output
> * backwards upfront payment: 7 msat are deduced from D's main output and added to C's main output

The fact that the hold fees are incrementing with distance from the source means intermediate nodes now have an unreliable oracle for distance-from-source, though I guess you mention that later.

It seems to me that we have no escape here, and we really do need to leak some more information, sigh.


>
> * Scenario 1: D settles the HTLC quickly:
> * all backwards upfront payments are refunded (returned to the respective main outputs)
> * only the forward upfront payments have been paid (to protect against `uncontrolled spam`)
>
> * Scenario 2: D settles the HTLC after the grace period:
> * D's backwards upfront payment is not refunded
> * If C and B relay the settlement upstream quickly (before `hold_grace_period_delta`) their backwards
> upfront payments are refunded

And in this case C earns.

Can C delay the refund to D to after the grace period even if D settled the HTLC quickly?
Hopefully the only way C can do that would be if it refused to respond to D giving the result of the HTLC, in which case --- would D be justified in dropping the channel onchain and hurting the connectivity of C (but also hurting its own connectivity, which might not be symmetric)?


> * all the forward upfront payments have been paid (to protect against `uncontrolled spam`)
>
> * Scenario 3: C delays the HTLC:
> * D settles before its `grace_period`, so its backwards upfront payment is refunded by C
> * C delays before settling upstream: it can ensure B will not get refunded, but C will not get
> refunded either so B gains the difference in backwards upfront payments (which protects against
> `controlled spam`)
> * all the forward upfront payments have been paid (to protect against `uncontrolled spam`)
>
> * Scenario 4: the channel B <-> C closes:
> * D settles before its `grace_period`, so its backwards upfront payment is refunded by C
> * for whatever reason (malicious or not) the B <-> C channel closes
> * this ensures that C's backwards upfront payment is paid to B
> * if C publishes an HTLC-fulfill quickly, B may have his backwards upfront payment refunded by A
> * if B is forced to wait for his HTLC-timeout, his backwards upfront payment will not be refunded
> but it's ok because B got C's backwards upfront payment
> * all the forward upfront payments have been paid (to protect against `uncontrolled spam`)
>
> If done naively, this mechanism may allow intermediate nodes to deanonymize sender/recipient.
> If the base `grace_period` and `hold_fees` are randomized, I believe this attack vector disappears,
> but it's worth exploring in more details.
>
> The most painful part of this proposal will be handling the `grace_period`:
>
> * when do you start counting: when you send/receive `update_add_htlc`, `commit_sig` or
> `revoke_and_ack`?
> * what happens if there is a disconnection (how do you account for the delay of reconnecting)?

You do not: a reliable peer would not have disconnected in the first place, in which case, it is the fault of the peer for getting disconnected and having a delay in reconnecting, possibly forfeiting the hold fee because of that.

> * what happens if the remote settles after the `grace_period`, but refunds himself when sending his
> `commit_sig` (making it look like from his point of view he settled before the `grace_period`)?
> I think in that case the behavior should be to give your peers some leeway and let them get away
> with it, but record it. If they're doing it too often, close channels and ban them; stealing
> upfront fees should never be worth losing channels.

Right, because there is the risk that communications latency delays a response that was *sent out* at the correct time but was *received in* after the grace period.

>
> I chose to make the backwards upfront payment fixed instead of scaling it based on the time an HTLC
> is left pending; it's slightly less penalizing for spammers, but is less complex and introduces less
> potential griefing against honest nodes. With the scaling approach, an honest node that has its
> channel unilaterally closed is too heavily penalized IMHO (because it has to pay for the maximum
> hold duration).
>
> I also chose to make the forward upfront payment constant (1 msat). Is it going to be a pain to
> bikeshed this constant? Do we need to add a mechanism to upgrade it? We don't want to make this
> more complex than it should.

Is 1msat going to even deter anyone?
I can make a thousand probes and just get charged a measly satoshi, which will not even buy a single piece of fish ball at a local street vendor (we call them "fish ball" as a courtesy, but in reality they are "flour disks" made with flour that was processed in equipment that was once in contact with fish at some unknown point in the past; still delicious when deep-fried and dipped in vinegar though), would that really deter anyone?

Regards,
ZmnSCPxj


More information about the Lightning-dev mailing list