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

ZmnSCPxj ZmnSCPxj at protonmail.com
Wed Nov 28 03:51:04 UTC 2018

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")

> 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?

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?

>     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.

> 8.  TLVs follow unknown-odd-is-ok rule.
> 9.  No 0-type; that terminates (backwards compat with 0-filled padding).
>     New onion error value:
> 10.  type: PERM|22 (`tlv_element_invalid`)
> 11.  `2`:`offset`
>     The writer MUST set `offset` to a byte offset within the `tlv` field
>     of the tlv element it rejected. It SHOULD use the offset of the `type` byte of the TLV
>     element if it didn't understand it, the offset the `len` byte of the TLV
>     element if it was an incorrect length, or otherwise within the `value`
>     if the value was somehow invalid.
>     TLVs defined for initial onion:
> -   type 2: `switch_chain`
>     length: 32
>     value: chain_id of new chain.
>     Used to switch chains during transit or at final hop.
> 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?

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)

- 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.

>     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.


More information about the Lightning-dev mailing list