[Lightning-dev] [DRAFT] Multi-cell-hop onion with TLV (and example for multi-part-payment)

Rusty Russell rusty at rustcorp.com.au
Thu Nov 29 06:33:06 UTC 2018

ZmnSCPxj <ZmnSCPxj at protonmail.com> writes:
> Good morning Rusty,
>> There's a kinda-neat intersection between the "use TLV" proposal and the
>> "multi-cell-onion" idea, so I want to make a concrete proposal (wording
>> needs formalization):
>> Multi-cell structure:
>> 1.  `realm` (or `per_hop_type` if you prefer) meaning expanded.
>> 2.  Lower 4 bits is `num_extra_cells` to use (ie. total 1-17 cells).
>> 3.  Upper 4 bits reserved: if set, drop.
> What does drop mean exactly?
> Or an error with `BADONION` bit set? ("drop the HTLC as a failure")
> Or should we try to consume the next 65 bytes? ("drop this cell and process the next cell")

`invalid_realm` is the current error for this; ie. fail the HTLC, tell
them we didn't understand.

>> 4.  HMAC on end covers that many per-hops.
>> 5.  Padding is thus 12 bytes + 64 * `num_extra_cells`.
> Is it not multiple of 65?

Yes, you're right.

> Also, it seems to me that the existing `per_hop_type`/`realm`/`packet_type` of 0 implies that only a single 65-byte section is used (as is current behavior).  Then a byte of 1 indicates two 65-byte sections are used, and so on.
> I broadly approve of this design.
> However with only 4 bits it seems to me:
>>(ie. total 1-17 cells).
> is inaccurate? Only 1->16 cells?

Yes, you're right again.

>>     Structure of padding changes:
>> 6.  We make the onion `padding` contain TLV, rename to `tlv`.
>> 7.  TLVs (as always!) are in lexicographical order (with shortest-wins on
>>     tiebreak).
> If types are unique, then "shortest-wins" would not matter.
> I believe there was a vague agreement that types would have to be unique in a TLV sequence, and that if a type could be variadic, it would be variadic within its own value-blob.

Agreed, but this seemed more general.  It's impossible to know whether
multiples would make sense in future, and ruling them out now forces us
to do strange things later (like nested TLV) if we want it later.

Since it's a writer rule, (readers should simply ignore TLVs they don't
understand, ignoring order), it doesn't matter until/if we allow some
type to be multipled.

>> Use with multi-part payment ("base AMP"):
>> -   type 4: `total_payment`
>>     length: variable, <= 8
>>     value: amount of total payment, in msat (big-endian of course).
>>     Writer must only use for final hop, and only if bolt11 flagged it as
>>     available (bolt11-multi_part_available). May use even if this payment
>>     meets the total_payment requirement.
>>     Reader MUST reject if not final hop, MAY reject if invoice was not
>>     `bolt11-multi_part_available`. Reader SHOULD wait until total parts
>>     meet or exceed `total_payment` (exceed may be due to fuzzing) [rest
>>     as per previous posts].
> Can we use the existence of this tlv to signal use of base AMP, instead of a separate flags byte?

Exactly :)

> On another topic, how about:
> - type 6: `application_data`
>   length: variable
>   value: unknown
> Writer MUST only use for final hop, and only if it knows that the final hop has a specific application that it is compatible with.
> Reader MUST pass this application data to higher layers.
> The application is responsible for identifying the correctness and validity of the attached value.
> (It seems to me that this would work for spontaneous payments to identify who the sender is, e.g. exchanges might provide a userkey and authorization that will be wrapped in this TLV; a corresponding new field in BOLT11 invoices (or multi-use offers) can specify the `application_data` to use for the payment, for example)

I don't think that the BOLT11 invoice should specify it; the invoice is
uniquely tied to the payment already, and having another one just adds
confusion and seems like it might tempt people to do dumb things.

I can imagine using this for (non-provable) games of chance
(LightningDice anyone?); the user picks a random number and puts it in
here.  Some new lightning RPC API allows them to provide this as well as
the bolt11 invoice: the merchant pays out if the random number matches
the preimage.

> - type 8: `spontaneous_payment`
>   length: 32
>   value: preimage
> Writer MUST only use for final hop, and sacrifices proof-of-payment.
> Reader MUST claim the HTLC using the given preimage.

s/MUST/MAY/?  Reader can reject spontaneous payments.

>>     PS. I prefer 'multi-part-payment' to 'base AMP' in the spec. It's more
>>     explicit, and leaves the namespace clear for more atomicy AMPs.
> I would argue that "base" AMP is sufficiently atomic to merit the full name of "atomic multipath payment".
> Indeed, even if we switch to points and their generation scalars (pubkey/privkey), the same "base AMP" can be used as-is, with the added security of decorrelation within paths and between paths by taking advantage of homomorphisms.
> However, this is getting to color-of-the-bikeshed territory and I will just call it by whatever name sticks to my mind, preferring Base AMP just as I prefer sipa.

Adding nomenclature must be done carefully; it should only be done where
real nuance is required.  I think "multi-part-payment" is descriptive
and also currently unused, even if it's pronounced "bass AMP".


More information about the Lightning-dev mailing list