Good morning t-bast,

> > 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?
>
> Yes C earns, but D has misbehaved. As a final recipient, D isn't dependent on 
> anyone downstream.
> An honest D should settle the HTLC before the `grace_period` ends. If D 
> chooses to hold the HTLC
> for a while, then it's fair that he pays C for this.


Okay, now let us consider the case where the supposedly-delaying party is not 
the final destination.

So, suppose D indicates to C that it should fail the HTLC.
In this case, C cannot immediately propagate the `update_fail_htlc` upstream, 
since the latest commitment transaction for the C<->D channel still contains 
the HTLC.

In addition, our state machine is hand-over-hand, i.e. there is a small window 
where there are two valid commitment transactions.
What happens is we sign the next commitment transaction and *then* revoke the 
previous one.

So I think C can only safely propagate its own upstream `update_fail_htlc` once 
it receives the `revoke_and_ack` from D.

So the time measured for the grace period between C and D should be from C 
sending `update_add_htlc` to C receiving `revoke_and_ack` from D, in case the 
HTLC fails.
This is the time period that D is allowed to consume, and if it exceeds the 
grace period, it is penalized.

(In this situation, it is immaterial if D is the destination: C cannot know 
this fact.)

So let us diagram this better:

     C                       D
     |----update_add_htlc--->| ---
     |---commitment_signed-->|  ^
     |<----revoke_and_ack----|  |
     |<--commitment_signed---|  |
     |-----revoke_and_ack--->|  |
     |                       | grace period
     |<--update_fail_htlc----|  |
     |<--commitment_signed---|  |
     |-----revoke_and_ack--->|  |
     |---commitment_signed-->|  v  <--- grief point!
     |<----revoke_and_ack----| ---

(somebody *else* better make sure my understanding of the state machine is 
correct!)

C can trivially grief D here, making it look like D is delaying, by delaying 
its own `commitment_signed` containing the *removal* of the HTLC.
D cannot send its own `revoke_and_ack` until it receives the signature for its 
own next commitment, as if it did so, it would lose the ability to close the 
channel unilaterally; it has to wait for C to send the `commitment_signed`.

Thus, it seems to me that C can grief D here.

The question is: does the above C-can-grief-D matter?

I think D does have a defense against C griefing in the above case:

* If the time between D->`update_fail_htlc`->C and the corresponding 
C->`commitment_signed`->D becomes too long:
  * D drops the channel onchain.
    * The dropped commitment tx still contains the HTLC, since it is the 
"previous" commitment that D happens to hold that has not yet had the 
`update_fail_htlc` committed.

If D performs the above, then C is forced to wait *even longer* (it has to wait 
out the HTLC timelock) before it can safely propagate the `update_fail_htlc`: D 
could be fooling with it and actually knows the preimage and claim it onchain, 
so C for its own safety *must* wait out the onchain timelock.

Does that make sense?
Does it sensibly protect against this griefing?
Is it too much of a punishment and could potentially hurt D more than it hurts 
C if C is a heavily-connected node that will not miss the channel while D has 
fewer channels and opened the C<->D channel in the first place?

--

For success case `update_fulfill_htlc`, I believe C can immediately propagate 
this back to its upstream since it can now.
Thus, in that case, we can stop the timer at the `update_fulfill_htlc`.

So at least for the *end point* of the grace period, I think the end point 
should be:

* If the HTLC failed:
  * When both participants have sent `revoke_and_ack`.
* If the HTLC succeeded:
  * When the downstream participant has sent `update_fulfill_htlc`.

For the *start point*, it seems the C->`commitment_signed`->D containing the 
HTLC would work as the start point.
In particular, it seems to me that C can also deliberately defer its own 
C->`revoke_and_ack`->D:

     C                       D
     |----update_add_htlc--->|
     |---commitment_signed-->| ---
     |<----revoke_and_ack----|  ^
     |<--commitment_signed---|  |
     |-----revoke_and_ack--->|  |  <--- grief point!
     |                       | grace period
     |<--update_fail_htlc----|  |
     |<--commitment_signed---|  |
     |-----revoke_and_ack--->|  |
     |---commitment_signed-->|  v
     |<----revoke_and_ack----| ---

(If D deliberately delays, then it is penalized, so we should consider the case 
where C attempts to trigger the reverse case).
D cannot safely fulfill the HTLC until after the previous commitment 
transactions of *both* sides have been revoked ("irrevocably committed" state).
So D can use the same defense, I think: if C is taking too long to send the 
`revoke_and_ack` pointed at above, it drops the channel onchain with the HTLC 
instantiated (which is why the *start time* has to be the 
C->`commitment_signed`->D that contains the new HTLC).

Thus the D grace period has two smaller grace periods that D imposes on C, 
using the threat of channel drop to protect against the C-side griefing.



Sorry for dropping into details already but so far this is the only griefing 
attack I can think of right now.



Regards,
ZmnSCPxj
_______________________________________________
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev

Reply via email to