[Lightning-dev] Laundry list of inter-peer wire protocol changes

Rusty Russell rusty at rustcorp.com.au
Tue Apr 12 01:36:51 UTC 2016


"C.J. Plooy" <cjplooy at ultimatestunts.nl> writes:
> CJP schreef op di 02-02-2016 om 18:56 [+0100]:
>> 
>> > > * Reserving before locking: this is an optimization, to reduce the risk
>> > > of locking funds in payment channels on a part of the route, and then
>> > > having to undo the locking when it turns out that the remaining part of
>> > > the route doesn't exist (anymore). Reserving is an informal(*),
>> > > temporary locking of funds for use in the transaction, and can be done
>> > > and undone very fast, without any channel operations. It is done
>> > > together with route searching + establishment.
>> > 
>> > I think that trades one DoS for another, though.  It saves cryptographic
>> > constructs, but latency is the real cost, and this increases it.
>> > 
>> > Of course, we'll have to revisit that if the network in practice proves
>> > subject to these problems...
>> 
>> For one category of channel designs, reserving is absolutely essential:
>> channels where bi-directional payments are made possible with a
>> decrementing lock time. There, you want to make sure that failed routing
>> attempts don't cause lock time decrements, since that would reduce the
>> channel lifetime more than necessary. I'd have to check whether there is
>> still any use case for this channel design, and whether the reserving
>> step is important for some other reason.
>
> After actually implementing some of these things, I'd like to revisit
> this discussion.
>
> The "reserving" stage used to be important for channel types where the
> bi-directional nature of the channel is realized with decreasing lock
> times (see above). Now that a large part of the community has put its
> hope on Lightning, it's more likely that the extensions required for
> better channel types will be included in Bitcoin, so this issue has
> become less important.
>
> Another reason why the "reserving" stage is important, is that it it
> necessary for bi-directional routing. In order to make both payer and
> payee anonymous, we need to provide this feature, where both route to a
> meeting point. For the part between meeting point and payee, routing
> goes from payee to meeting point(*), but locking goes from meeting point
> to payee, so they can't be done in the same stage.

This is an interesting problem.  I previously beleived this could be
done by some tunnelling mechanism in the meeting point (unknown to the
payer), except that the timeouts are a problem.  So it can still be
done, but the payer would have to be told to bump their timeouts.

I fear the complexity of implementing a two-way reservation scheme
up-front, however.  It implies that the payee knows the timing of the
payer, and adds failure modes when that's wrong.

I also dislike meeting points by default: there's a whole extra layer of
deciding what meeting points to use.  Beacons can be bypassed (if you
notice the route is the same to and from, which is more likely if
beacons are less connected).

> Finally, the "reserving" stage allows you to set a tighter value on the
> HTLC time-outs. If you do routing together with locking, then routing
> has to go in the payer->payee direction; the time-out has to be reduced
> on every hop. Assuming(**) the payer doesn't know the number of hops in
> advance, the time-out has to be set to a very high value by the payer,
> to maximize chances of a successful transaction. If you do routing in
> the reverse direction (payee->payer), you can start with a very low
> time-out, and increment it on every hop. This will generally result in
> lower time-out values, which is desirable.

With onioning, we need source routing.  However, we can still get some
of the benefits by splitting the stages, and having a non-binding
propose message.

ie. currently BOLT#2 has a complete HTLC negotiation looking like this:

 update_add_htlc ->
 update_commit ->
                      <- update_revocation
                      <- update_commit
 update_revocation ->                     

The receiver can't forward the htlc until it knows the sender is bound
to honour it, which takes these three trips.

If we introduce a non-binding step before the "add_htlc" (say
"introduce_htlc"), this is possible: the receiver could forward the
"introduce_htlc" instantly.  Then there would be a (non-binding)
feedback message, and a "cancel_htlc".

That would allow faster feedback, such as fee or route changes or
outright failure.

Thoughts?

> That's about it, for the advantages offered by the separate reserving
> stage in Amiko Pay. Let me finish with an attempt to make an ASCII-art
> sequence diagram of reserving, bi-directional routing and locking in
> Amiko Pay:
>
> H(R) = the transaction hash (also included in other messages)
> MR() = MakeRoute message without time info
> MR(t) = MakeRoute message with time info
> HR() = HaveRoute message without time info
> HR(t) = HaveRoute message
> L(t) = Lock message (adds HTLC to channel)
> A = Alice (payer)
> B = Bob (meeting point)
> C = Carol (intermediate node). There can be many intermediate nodes
> between A and B, and between B and D.
> D = Dave (payee)
>
> A               B               C             D
> |<------------------ H(R) --------------------|
> |------MR()---->|               |<-MR(T0+dt)--|
>                 |<-MR(T0+2*dt)--|
> |<-HR(T0+3*dt)--|--HR(T0+2*dt)->|
>                                 |--HR(T0+dt)->|
> |<------------------ HR() --------------------|
> |--L(T0+3*dt)-->|--L(T0+2*dt)-->|--L(T0+dt)-->|
>
> (...and then the sequence continues with removing the HTLCs and
> releasing funds towards payee-side of each channel.)

This is a more interactive protocol.  Which is nice in some ways, but I
feel it's also more complex and more subject to timing analysis.

If we were to extend the protocol later, this would fit fairly nicely,
though.

Cheers,
Rusty.


More information about the Lightning-dev mailing list