[Lightning-dev] Disclosure of a fee blackmail attack that can make a victim loose almost all funds of a non Wumbo channel and potential fixes

ZmnSCPxj ZmnSCPxj at protonmail.com
Sun Jun 21 23:30:45 UTC 2020


Good morning Jeremy,

> My understanding is that you can use the CTV deferral to also get independent HTLC relative timelocks start points per output. This would help with this sort of issue right?
>
> And you're correct that there's overhead of indirection, but it's not super large (minimally complicated something like an extra 100 bytes per output, if you were to have a flat array where each entry is a CTV output so that each out gets its own clock).
>
> Essentially something like this:
>
> Chan
>      |
>      ------------------------------------
>      |      |      |       |            |
>    CTV(A) CTV(B) CTV(C)  CTV(D)      (Optional CPFP Anchor?)
>      |      |      |       | 
> 1 block  1 block 1 block  1 block
>      |      |      |       |
>     A       B      C       D
>
> Where A B C and D are all HTLCs.
>
> Now because of the one-hop indirection, A B C and D can all expand independently. It's also possible for the Channel Operator to do something like:
>
> Chan
>      |
>      -----------------------------------
>      |      |      |      |            |
>    CTV(A) CTV(B) CTV(C) CTV(D)      (Optional CPFP Anchor?)
>      |      |      |      |
> 1 block  1 block 1 block 10 blocks
>      |      |      |      |
>     A       B      C      D
>
> To make D have a further out resolution time to prevent the simultaneous-ness issue (trees or a linear-chain rather than total fan-out can also be used but I think it's a bit more confusing for a basic example).

The Lightning HTLCs use absolute timelocks, and the timelocks are pre-arranged by the original sender.
A forwarding node has to ensure that the outgoing HTLC timeout is respected, or else it could lose funds (by having the outgoing HTLC be claimed by outgoing peer hashlock and the incoming HTLC be calimed by the incoming peer timelock).

(We cannot use relative timelocks in the timelock branches of the HTLCs because we are coordinating possibly up to 20 different nodes, and do not want to leak the entire route to any of the intermediate nodes, so everyone has to use the same clock --- the absolute blockheight --- to measure time)

So, if my understanding of your above graph is correct, you are suggesting that HTLC D could have a relative timelock of 10 blocks instead of 1.

But all that means is that if the timelock of D is at height L, then the forwarder has to ensure that the commitment transaction appears onchain no later than height L - 10 (in practice I have to publish it at L - 11 so it propagates to miners who are building L - 10).
If not, the HTLC cannot be published at height L and the timelock cannot be enforced, risking fund loss.

This seems to *tighten* whatever leeway I might have bought by using CTV.
In current C-Lightning, for instance, for a timelock in my favor at height L, I have to broadcast the commitment transaction at time L - 1 so it goes into block L and I can claim it.
Thus, I have the option to publish from now up to L - 1.
With a further delay of 10 on the HTLC tx D, I now only have the option to publish from now up to L - 11, thus I have *less* leeway in when I can publish the commitment tx.

Basically the fund-security of the forwarding node is based on the absolute timelock of every HTLC it offers, so the timelock is an absolute bound on whatever techniques I might use to reduce fees.


> The benefit of trees is that I can do something like:
>
> Chan
>      |
>      --------------------------------------------------------
>      |      |      |      |                          |
>    CTV(A) CTV(B) CTV(C) CTV(400 HTLC)      (Optional CPFP Anchor?)
>      |      |      |      |                          |
> 1 block 1 block  1 block 10 blocks         (Optional CPFP Anchor?)
>      |      |      |      |
>      |      |      |   / ....\
>     A       B      C  | ..... |
>
> Which makes it so that the low-value new HTLCs can be deprioritized fee wise. So that the attack, which occurs during a fee spike, doesn't end up *requiring* substantial fees to be added to the channel to support a burst of HTLCS.

If the HTLCs have a timelock L, then I *need* to publish the HTLCs at timelock L or else the timelock cannot be enforced.

This means I need to publish the big `| ..... |` transaction with 400 HTLCs before timelock L, where L is `min (L) for all 400 HTLCs`.

The attacker can arrange to have the 400 low-value HTLCs have the same timelock L.
So even if the `| ..... |` is a tree of CTVs, I have to publish the entire tree at the same time so that the final HTLCs appear at timelock L and I can reclaim my funds.

If I do not publish, I run the risk that the total fund going to `CTV(400 HTLC)` gets stolen from me by publication of the hashlock on the outgoing and publication of the timelock at the incoming.
Not publishing this due to fee spikes is basically trusting that the next peer is not going to steal the fund by hashlock branch.
And the next peer is an attacker in this attack, so obviously cannot be trusted.

So it seems to me that this is better done by just rate-limiting simultaneous HTLCs, to limit what can be stolen.

A better solution might be to allow only one HTLC at each absolute timelock, and use a single CTV tree, with one leaf for each of the absolute timelocks.
Then I can publish parts of the CTV tree at my leisure, with my only constraint being the absolute timelock of each HTLC.


    Chan
      |
     CTV
      |
      +------+
      |      |
     CTV    HTLC(L = now + 1)
      |
      +------+
      |      |
     CTV    HTLC(L = now + 2)
      |
      +------+
      |      |
     CTV    HTLC(L = now + 3)
      |
     ...

Such a singly-linked list would take up even more absolute block space, incidentally, and makes high-fee spikes more likely.

Regards,
ZmnSCPxj


More information about the Lightning-dev mailing list