Re: [Lightning-dev] Ask First, Shoot (PTLC/HTLC) Later

2021-10-21 Thread Joost Jager
>If it is a multipart and we have the preimage, wait for all the parts to
arrive, then say yes to all of them.

Without actual reservations made in the channels, is this going to work?
For example: a 10M payment and a route that contains a channel with only 5M
balance. The sender's multi-path algorithm will try to split and send the
first 5M. Then they'll do the second 5M, but because there is no actual
reservation, the second 5M seems to be passing alright through the
bottleneck channel too. When the payment is then executed, it will fail.

Or do nodes keep track of all the unresolved probes and deduct the total
amount from the available balance? Of course only for the available balance
for probes. When a real htlc comes through, outstanding probes are ignored.
Although the problem with that could be that someone can spam you with
probes so that your available 'probe' balance is zero and you'll receive no
real traffic anymore.

Perhaps an alternative is to let senders attach a random identifier to a
probe. For multi-part probes, each probe will carry the same identifier.
Routing nodes will deduct the outstanding probe amounts from the available
balance, but only for probes within the same group (same id). That way each
probe(group) is isolated from everything else that is going on.

Joost

On Wed, Sep 29, 2021 at 5:40 AM ZmnSCPxj via Lightning-dev <
lightning-dev@lists.linuxfoundation.org> wrote:

> Good morning list,
>
> While discussing something tangentially related with aj, I wondered this:
>
> > Why do we shoot an HTLC first and then ask the question "can you
> actually resolve this?" later?
>
> Why not something like this instead?
>
> * For a payer:
>   * Generate a path.
>   * Ask first hop if it can resolve an HTLC with those specs (passing the
> encrypted onion).
>   * If first hop says "yes", actually do the `update_add_htlc` dance.
> Otherwise try again.
> * For a forwarder:
>   * If anybody asks "can you resolve this path" (getting an encrypted
> onion):
> * Decrypt one layer to learn the next hop.
> * Check if the next hop is alive and we have the capacity towards it,
> if not, answer no.
> * Ask next hop if it can resolve the next onion layer.
> * Return the response from the next hop.
> * For a payee:
>   * If anybody asks "can you resolve this path":
> * If it is not a multipart and we have the preimage, say yes.
> * If it is a multipart and we have the preimage, wait for all the
> parts to arrive, then say yes to all of them.
> * Otherwise say no.
>
> Now, the most obvious reason against this, that comes to mind, is that
> this is a potential DoS vector.
> Random node can trigger a lot of network activity by asking random stuff
> of random nodes.
> Asking the question is free, after all.
>
> However, we should note that sending *actual* HTLCs is a similar DoS
> vector **today**.
> This is still "free" in that the asker has no need to pay fees for failed
> HTLCs; they just lose the opportunity cost of the amount being locked up in
> the HTLCs.
> And presumably the opportunity cost is low since Lightning forwarding
> earnings are so tiny.
>
> One way to mitigate against this is to make generating an onion costly but
> validating and decrypting it cheap.
> We could use an encryption scheme that is more computationally expensive
> to encrypt but cheap to decrypt, for example.
> Or we could require proof-of-work on the onion: each unwrapped onion
> layer, when hashed, has to have a hash that is less than some threshold
> (this scales according to the number of hops in the onion, as well).
> Ultimate askers need to grind the shared secret until the onion layer hash
> achieves the target.
>
> Obviously just because you asked a few milliseconds ago if a path is
> viable does not mean that the path *remains* viable right now when you
> actually send out an HTLC, but presumably that risk is now lessened.
> Unexpected shutdowns or loss of connectivity has to appear in a smaller
> and shorter time frame to negatively affect intermediate nodes.
>
> Another thought is: Does the forwarding node have an incentive to lie?
> Suppose the next hop is alive but the forwarding node has insufficient
> capacity towards the next hop.
> Then the forwarding node can lie and claim it can still resolve the HTLC,
> in the hope that a few milliseconds later, when the actual HTLC arrives,
> the capacity towards the next hop has changed.
> Thus, even if the capacity now is insufficient, the forwarding node has an
> incentive to lie and claim sufficient capacity.
>
> Against the above, we can mitigate this by accepting "no" from *any* node
> along the path, but only accepting "yes" from the actual payee.
> We already have a mechanism where any node along a route can report a
> forwarding or other payment error, and the sender is able to identify which
> node along the path raised it.
> Thus, the payer can identify which node along the route responded with a
> "yes", and check that it 

[Lightning-dev] Ask First, Shoot (PTLC/HTLC) Later

2021-09-28 Thread ZmnSCPxj via Lightning-dev
Good morning list,

While discussing something tangentially related with aj, I wondered this:

> Why do we shoot an HTLC first and then ask the question "can you actually 
> resolve this?" later?

Why not something like this instead?

* For a payer:
  * Generate a path.
  * Ask first hop if it can resolve an HTLC with those specs (passing the 
encrypted onion).
  * If first hop says "yes", actually do the `update_add_htlc` dance.
Otherwise try again.
* For a forwarder:
  * If anybody asks "can you resolve this path" (getting an encrypted onion):
* Decrypt one layer to learn the next hop.
* Check if the next hop is alive and we have the capacity towards it, if 
not, answer no.
* Ask next hop if it can resolve the next onion layer.
* Return the response from the next hop.
* For a payee:
  * If anybody asks "can you resolve this path":
* If it is not a multipart and we have the preimage, say yes.
* If it is a multipart and we have the preimage, wait for all the parts to 
arrive, then say yes to all of them.
* Otherwise say no.

Now, the most obvious reason against this, that comes to mind, is that this is 
a potential DoS vector.
Random node can trigger a lot of network activity by asking random stuff of 
random nodes.
Asking the question is free, after all.

However, we should note that sending *actual* HTLCs is a similar DoS vector 
**today**.
This is still "free" in that the asker has no need to pay fees for failed 
HTLCs; they just lose the opportunity cost of the amount being locked up in the 
HTLCs.
And presumably the opportunity cost is low since Lightning forwarding earnings 
are so tiny.

One way to mitigate against this is to make generating an onion costly but 
validating and decrypting it cheap.
We could use an encryption scheme that is more computationally expensive to 
encrypt but cheap to decrypt, for example.
Or we could require proof-of-work on the onion: each unwrapped onion layer, 
when hashed, has to have a hash that is less than some threshold (this scales 
according to the number of hops in the onion, as well).
Ultimate askers need to grind the shared secret until the onion layer hash 
achieves the target.

Obviously just because you asked a few milliseconds ago if a path is viable 
does not mean that the path *remains* viable right now when you actually send 
out an HTLC, but presumably that risk is now lessened.
Unexpected shutdowns or loss of connectivity has to appear in a smaller and 
shorter time frame to negatively affect intermediate nodes.

Another thought is: Does the forwarding node have an incentive to lie?
Suppose the next hop is alive but the forwarding node has insufficient capacity 
towards the next hop.
Then the forwarding node can lie and claim it can still resolve the HTLC, in 
the hope that a few milliseconds later, when the actual HTLC arrives, the 
capacity towards the next hop has changed.
Thus, even if the capacity now is insufficient, the forwarding node has an 
incentive to lie and claim sufficient capacity.

Against the above, we can mitigate this by accepting "no" from *any* node along 
the path, but only accepting "yes" from the actual payee.
We already have a mechanism where any node along a route can report a 
forwarding or other payment error, and the sender is able to identify which 
node along the path raised it.
Thus, the payer can identify which node along the route responded with a "yes", 
and check that it definitely reached the payee.
Presumably, when a node receives a question, it checks if the asking node has 
sufficient capacity towards it first, and if not, fails the channel between 
them, since obviously the asking node is not behaving according to protocol and 
is buggy.

Now, this can be used to probe capacities, for free, but again --- we already 
*have* probing capacities, for free, today, by just using random hashes.



Why is this advantageous at all?

One reason for doing this is that it improves payment latency.
Some paths *will* fail, because there is no single consistent view of the 
network and its capacity (which is impossible due to others also possibly 
sending out via the same forwarding nodes you are using, and besides, even if 
such a view could be made to exist, it would be dangerously anti-privacy).
This mechanism does not require that intermediate nodes respond with a 
signature and wait for a replied signature *before* they forward the onion to 
the next hop; when they are *just* asking, there is no HTLC involved, no 
updates to the channel state, and the question can be forwarded as soon as we 
can check locally.
Further, in the current mechanism where we shoot HTLCs first and ask questions 
later, failures also require 1.5 roundtrips due to sharing signatures; with the 
"just ask first" phase there is no need for round trips to respond to questions.

Basically, we replace multiple round trips per hop in case of a failure along a 
route, with a single large round trip from the payer to the