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