Bastien TEINTURIER [ARCHIVE] on Nostr: 📅 Original date posted:2020-10-23 📝 Original message: Hey Joost and Z, I ...
📅 Original date posted:2020-10-23
📝 Original message:
Hey Joost and Z,
I brought up the question about the amounts because it could be that
> amounts high enough to thwart attacks are too high for honest users or
> certain uses.
I don't think this is a concern for this proposal, unless there's an attack
vector I missed.
The reason I claim that is that the backwards upfront payment can be made
somewhat big without any
negative impact on honest nodes. If you're an honest intermediate node,
only two cases are possible:
* your downstream peer settled the HTLC quickly (before the grace period
ends): in that case you
refund him his upfront fee, and you have time to settle the HTLC upstream
while still honoring
the grace period, so it will be refunded to you as well (unless you delay
the settlement upstream
for whatever reason, in which case you deserve to pay the hold_fee)
* your grace period has expired, so you can't get a refund upstream: if
that happens, the grace
period with your downstream node has also expired, so you're earning money
downstream and paying
money upstream, and you'll usually even take a small positive spread so
everything's good
The only node that can end up loosing money on the backwards upfront
payment is the last node in
the route. But that node should always settle the HTLC quickly (or decide
to hodl it, but in that
case it's normal that it pays the hold_fee).
But what happens if the attacker is also on the other end of the
> uncontrolled spam payment? Not holding the payment, but still collecting
> the forward payments?
That's what I call short-lived `controlled spam`. In that case the attacker
pays the forward fee at
the beginning of the route but has it refunded at the end of the route. If
the attacker doesn't
want to lose any money, he has to release the HTLC before the grace period
ends (which is going to
be short-lived - at least compared to block times). This gives an
opportunity for legitimate payments
to use the HTLC slots (but it's a race between the attacker and the
legitimate users).
It's not ideal, because the attacker isn't penalized...the only way I think
we can penalize this
kind of attack is if the forward fee decrements at each hop, but in that
case it needs to be in the
onion (to avoid probing) and the delta needs to be high enough to actually
penalize the attacker.
Time to bikeshed some numbers!
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.
You're right to dive into these, there may be something here.
But I think your example doesn't work, let me know if I'm mistaken.
D is the one who decides whether he'll be refunded or not, because D is the
first to send the
`commit_sig` that removes the HTLC. I think we would extend `commit_sig`
with a tlv field that
indicates "I refunded myself for HTLC N" to help C compute the same commit
tx and verify sigs.
I agree with you that the details of how we'll implement the grace period
may have griefing attacks
depending on how we do it, it's worth exploring further.
Cheers,
Bastien
Le ven. 23 oct. 2020 à 12:50, ZmnSCPxj <ZmnSCPxj at protonmail.com> a écrit :
> 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.linuxfoundation.org/pipermail/lightning-dev/attachments/20201023/87e456f4/attachment.html>
📝 Original message:
Hey Joost and Z,
I brought up the question about the amounts because it could be that
> amounts high enough to thwart attacks are too high for honest users or
> certain uses.
I don't think this is a concern for this proposal, unless there's an attack
vector I missed.
The reason I claim that is that the backwards upfront payment can be made
somewhat big without any
negative impact on honest nodes. If you're an honest intermediate node,
only two cases are possible:
* your downstream peer settled the HTLC quickly (before the grace period
ends): in that case you
refund him his upfront fee, and you have time to settle the HTLC upstream
while still honoring
the grace period, so it will be refunded to you as well (unless you delay
the settlement upstream
for whatever reason, in which case you deserve to pay the hold_fee)
* your grace period has expired, so you can't get a refund upstream: if
that happens, the grace
period with your downstream node has also expired, so you're earning money
downstream and paying
money upstream, and you'll usually even take a small positive spread so
everything's good
The only node that can end up loosing money on the backwards upfront
payment is the last node in
the route. But that node should always settle the HTLC quickly (or decide
to hodl it, but in that
case it's normal that it pays the hold_fee).
But what happens if the attacker is also on the other end of the
> uncontrolled spam payment? Not holding the payment, but still collecting
> the forward payments?
That's what I call short-lived `controlled spam`. In that case the attacker
pays the forward fee at
the beginning of the route but has it refunded at the end of the route. If
the attacker doesn't
want to lose any money, he has to release the HTLC before the grace period
ends (which is going to
be short-lived - at least compared to block times). This gives an
opportunity for legitimate payments
to use the HTLC slots (but it's a race between the attacker and the
legitimate users).
It's not ideal, because the attacker isn't penalized...the only way I think
we can penalize this
kind of attack is if the forward fee decrements at each hop, but in that
case it needs to be in the
onion (to avoid probing) and the delta needs to be high enough to actually
penalize the attacker.
Time to bikeshed some numbers!
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.
You're right to dive into these, there may be something here.
But I think your example doesn't work, let me know if I'm mistaken.
D is the one who decides whether he'll be refunded or not, because D is the
first to send the
`commit_sig` that removes the HTLC. I think we would extend `commit_sig`
with a tlv field that
indicates "I refunded myself for HTLC N" to help C compute the same commit
tx and verify sigs.
I agree with you that the details of how we'll implement the grace period
may have griefing attacks
depending on how we do it, it's worth exploring further.
Cheers,
Bastien
Le ven. 23 oct. 2020 à 12:50, ZmnSCPxj <ZmnSCPxj at protonmail.com> a écrit :
> 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.linuxfoundation.org/pipermail/lightning-dev/attachments/20201023/87e456f4/attachment.html>