<oembed><type>rich</type><version>1.0</version><title>Rusty Russell [ARCHIVE] wrote</title><author_name>Rusty Russell [ARCHIVE] (npub1zw…hkhpx)</author_name><author_url>https://yabu.me/npub1zw7cc8z78v6s3grujfvcv3ckpvg6kr0w7nz9yzvwyglyg0qu5sjsqhkhpx</author_url><provider_name>njump</provider_name><provider_url>https://yabu.me</provider_url><html>📅 Original date posted:2019-11-08&#xA;📝 Original message:&#xA;Yaacov Akiba Slama &lt;ya at slamail.org&gt; writes:&#xA;&gt; Hi Rusty,&#xA;&gt;&#xA;&gt; It seems that there are two kind of TLV fields in your proposition:&#xA;&gt; 1) LN specific fields like `num_paths` and `payment_preimage`.&#xA;&gt; 2) &#34;Business&#34; fields like `address1` and `currency`.&#xA;&gt; I understand the need to define and include the first category, but I &#xA;&gt; don&#39;t think that we need or can define the second category. These fields &#xA;&gt; already exists in software like crm, erp, etc.. and are well defined by &#xA;&gt; standard body.&#xA;&gt; My suggestion is to have a generic field containing well defined &#xA;&gt; structured and standardized data. See for instance &#xA;&gt; https://en.wikipedia.org/wiki/EDIFACT and/or &#xA;&gt; https://en.wikipedia.org/wiki/Universal_Business_Language.&#xA;&#xA;Hi Yaacov,&#xA;&#xA;        I&#39;ve been pondering this since reading your comment on the PR!&#xA;&#xA;        As a fan of standards, I am attracted to UBL (I&#39;ve chaired an&#xA;OASIS TC in the past and have great respect for them); as a fan of&#xA;simplicity I am not.  Forcing UBL implementation on wallet providers is&#xA;simply not going to happen, whatever I were to propose.&#xA;&#xA;&#x9;We also don&#39;t want duplication; what if the &#34;UBL field&#34; were to&#xA;say I were selling you a bridge for $1 and the description and amount&#xA;fields actually said I was selling you a coffee for $3?&#xA;&#xA;&#x9;However, since invoices/offers and UBL are both structures, we&#xA;should have an explicit mapping between the two.  What fields should&#xA;have their own existence in the invoice/offer and what should be in a&#xA;general UBL field is a question we have to think on further.&#xA;&#xA;        Anyway, you&#39;ll have to bear with me as I read this 172 page&#xA;standard...&#xA;&#xA;Cheers,&#xA;Rusty.&#xA;&#xA;&gt; What do you think?&#xA;&gt; PS: Sorry for crossposting here and in &#xA;&gt; https://github.com/lightningnetwork/lightning-rfc/pull/694&#xA;&gt; --yas&#xA;&gt;&#xA;&gt; On 05/11/2019 06:23, Rusty Russell wrote:&#xA;&gt;&gt; Hi all,&#xA;&gt;&gt;&#xA;&gt;&gt;          This took longer than I&#39;d indicated; for that I&#39;m sorry.&#xA;&gt;&gt; However, this should give us all something to chew on.  I&#39;ve started&#xA;&gt;&gt; with a draft &#34;BOLT 12&#34; (it might be BOLT 13 by the time it&#39;s finalized&#xA;&gt;&gt; though!).&#xA;&gt;&gt;&#xA;&gt;&gt; I&#39;ve also appended indications where we touch other BOLTs:&#xA;&gt;&gt; 1. BOLT 7 gains a message/reply system, encoded like htlc onions and&#xA;&gt;&gt;     failure messages.&#xA;&gt;&gt; 2. BOLT 11 gains a `q` field for quantity; this avoids changing the&#xA;&gt;&gt;     description when the user requests an invoice for more than one of something&#xA;&gt;&gt;     (since changing the description between offer and invoice requires user&#xA;&gt;&gt;     interaction: it&#39;s the *invoice* which you are committing to).&#xA;&gt;&gt;&#xA;&gt;&gt; There&#39;s definite handwaving in here; let&#39;s see if you can find it!&#xA;&gt;&gt;&#xA;&gt;&gt; Cheers,&#xA;&gt;&gt; Rusty.&#xA;&gt;&gt;&#xA;&gt;&gt; # BOLT #12: Offer Protocols for Lightning Payments&#xA;&gt;&gt;&#xA;&gt;&gt; An higher-level, QR-code-ready protocol for dealing with invoices over&#xA;&gt;&gt; Lightning.  There are two simple flows supported: in one, a user gets&#xA;&gt;&gt; an offer (`lno...`) and requests an invoice over the lightning&#xA;&gt;&gt; network, obtaining one (or an error) in reply.  In the other, a user&#xA;&gt;&gt; gets an invoice request (`lni...`), and sends the invoice over the&#xA;&gt;&gt; lightning network, retreiving an empty reply.&#xA;&gt;&gt;&#xA;&gt;&gt; # Table of Contents&#xA;&gt;&gt;&#xA;&gt;&gt;    * [Offers](#offers)&#xA;&gt;&gt;      * [Encoding](#encoding)&#xA;&gt;&gt;      * [TLV Fields](#tlv-fields)&#xA;&gt;&gt;    * [Invrequests](#invrequests)&#xA;&gt;&gt;      * [Encoding](#encoding)&#xA;&gt;&gt;      * [TLV Fields](#tlv-fields)&#xA;&gt;&gt;&#xA;&gt;&gt; # Offers&#xA;&gt;&gt;&#xA;&gt;&gt; Offers supply a reader with enough information to request one or more&#xA;&gt;&gt; invoices via the lightning network itself.&#xA;&gt;&gt;&#xA;&gt;&gt; ## Encoding&#xA;&gt;&gt;&#xA;&gt;&gt; The human-readable part of a Lightning offer is `lno`.  The data part&#xA;&gt;&gt; consists of three parts:&#xA;&gt;&gt;&#xA;&gt;&gt; 1. 0 or more [TLV](01-messaging.md#type-length-value-format) encoded fields.&#xA;&gt;&gt; 2. A 32-byte nodeid[1]&#xA;&gt;&gt; 3. 64-byte signature of SHA256(hrp-as-utf8 | tlv | nodeid).&#xA;&gt;&gt;&#xA;&gt;&gt; ## TLV Fields&#xA;&gt;&gt;&#xA;&gt;&gt; The TLV fields define how to get the invoice, and what it&#39;s for.&#xA;&gt;&gt; Each offer has a unique `offer_idenfitier` so the offering node can&#xA;&gt;&gt; distinguish different invoice requests.&#xA;&gt;&gt;&#xA;&gt;&gt; Offers can request recurring payments of various kinds, and specify&#xA;&gt;&gt; what base currency they are calculated in (the actual amount will be&#xA;&gt;&gt; in the invoice).&#xA;&gt;&gt;&#xA;&gt;&gt; `additional_data` is a bitfield which indicates what information the&#xA;&gt;&gt; invoice requester should (odd) or must (even) supply:&#xA;&gt;&gt; 1. Bits `0/1`: include `delivery_address`&#xA;&gt;&gt; 2. Bits `2/3`: include `delivery_telephone_number`&#xA;&gt;&gt; 3. Bits `4/5`: include `voucher_code`&#xA;&gt;&gt; 4. Bits `6/7`: include `refund_proof`&#xA;&gt;&gt;&#xA;&gt;&gt; `refund_for` indicates an offer for a (whole or part) refund for a&#xA;&gt;&gt; previous invoice, as indicated by the `payment_hash`.&#xA;&gt;&gt;&#xA;&gt;&gt; 1. tlvs: `offer`&#xA;&gt;&gt; 2. types:&#xA;&gt;&gt;      1. type: 1 (`paths`)&#xA;&gt;&gt;      2. data:&#xA;&gt;&gt;          * [`u16`:`num_paths`]&#xA;&gt;&gt;          * [`num_paths*path`:`path`]&#xA;&gt;&gt;      1. type: 2 (`description`)&#xA;&gt;&gt;      2. data:&#xA;&gt;&gt;          * [`...*byte`:`description`]&#xA;&gt;&gt;      1. type: 3 (`expiry`)&#xA;&gt;&gt;      2. data:&#xA;&gt;&gt;          * [`tu64`:`seconds_from_epoch`]&#xA;&gt;&gt;      1. type: 4 (`offer_identifier`)&#xA;&gt;&gt;      2. data:&#xA;&gt;&gt;          * [`...*byte`:`id`]&#xA;&gt;&gt;      1. type: 5 (`amount`)&#xA;&gt;&gt;      2. data:&#xA;&gt;&gt;          * [`4*byte`:`currency`]&#xA;&gt;&gt;          * [`tu64`:`amount`]&#xA;&gt;&gt;      1. type: 6 (`additional_data`)&#xA;&gt;&gt;      2. data:&#xA;&gt;&gt; &#x9;    * [`...*byte`:`rbits`]&#xA;&gt;&gt;      1. type: 7 (`recurrance`)&#xA;&gt;&gt;      2. data:&#xA;&gt;&gt; &#x9;    * [`byte`:`time_unit`]&#xA;&gt;&gt; &#x9;&#x9;* [`u32`:`period`]&#xA;&gt;&gt; &#x9;&#x9;* [`tu32`:`number`]&#xA;&gt;&gt;      1. type: 8 (`recurrance_base`)&#xA;&gt;&gt;      2. data:&#xA;&gt;&gt; &#x9;&#x9;* [`u32`:`basetime`]&#xA;&gt;&gt; &#x9;&#x9;* [`tu32`:`paywindow`]&#xA;&gt;&gt;      1. type: 9 (`quantity`)&#xA;&gt;&gt;      2. data:&#xA;&gt;&gt; &#x9;&#x9;* [`tu64`:`max`]&#xA;&gt;&gt;      1. type: 10 (`refund_for`)&#xA;&gt;&gt;      2. data:&#xA;&gt;&gt;          * [`32*byte`:`payment_hash`]&#xA;&gt;&gt;&#xA;&gt;&gt; 1. subtype: `path`&#xA;&gt;&gt; 2. data:&#xA;&gt;&gt;     * [`u16`:`num_hops`]&#xA;&gt;&gt;     * [`num_hops*hop`:`hops`]&#xA;&gt;&gt;&#xA;&gt;&gt; 1. subtype: `hop`&#xA;&gt;&gt; 2. data:&#xA;&gt;&gt;     * [`pubkey`:`nodeid`]&#xA;&gt;&gt;     * [`short_channel_id`:`short_channel_id`]&#xA;&gt;&gt;     * [`u16`:`flen`]&#xA;&gt;&gt;     * [`flen*byte`:`features`]&#xA;&gt;&gt;&#xA;&gt;&gt; ## Requirements For Offers And Invrequests&#xA;&gt;&gt;&#xA;&gt;&gt; A writer of an offer or an invrequest:&#xA;&gt;&gt;    - if it is connected only by private channels:&#xA;&gt;&gt;      - MUST include `paths` containing a path to the node.&#xA;&gt;&gt;    - otherwise:&#xA;&gt;&gt;      - MAY include `paths` containing a path to the node.&#xA;&gt;&gt;    - MUST describe the item(s) being offered or purpose of invoice in `description`.&#xA;&gt;&gt;    - MUST include `expiry` if the offer/invrequest will not be valid after some time.&#xA;&gt;&gt;    - if it includes `expiry`:&#xA;&gt;&gt;      - MUST set `seconds_from_epoch` to the expiry time in seconds since 1970 UTC.&#xA;&gt;&gt;&#xA;&gt;&gt; ## Requirements For Offers&#xA;&gt;&gt;&#xA;&gt;&gt; A writer of an offer:&#xA;&gt;&gt;    - MUST use a unique `offer_idenfitier` for each offer.&#xA;&gt;&gt;    - MAY include `recurrence` to indicate offer should trigger time-spaced&#xA;&gt;&gt;      invoices.&#xA;&gt;&gt;    - MUST include `amount` if it includes `recurrence`.&#xA;&gt;&gt;    - if it includes `amount`:&#xA;&gt;&gt;      - MUST specify `currency` as the ISO 4712 or BIP-0173, padded with zero bytes if required&#xA;&gt;&gt; &#x9;- MUST specify `amount` to the amount expected for the invoice, as the ISO 4712 currency unit multiplied by exponent, OR the BIP-0173 minimum unit (eg. `satoshis`).&#xA;&gt;&gt;    - if it requires specific fields in the invoice:&#xA;&gt;&gt;      - MUST set the corresponding even bits in the `additional_data` field&#xA;&gt;&gt;&#xA;&gt;&gt; A reader of an offer:&#xA;&gt;&gt;    - SHOULD gain user consent for recurring payments.&#xA;&gt;&gt;    - SHOULD allow user to view and cancel recurring payments.&#xA;&gt;&gt;    - SHOULD gain user consent to send `delivery_` fields.&#xA;&gt;&gt;    - if it uses `amount` to provide the user with a cost estimate:&#xA;&gt;&gt; &#x9;- MUST warn user if amount of actual invoice differs significantly&#xA;&gt;&gt; &#x9;&#x9;from that expectation.&#xA;&gt;&gt;    - FIXME: more!&#xA;&gt;&gt;&#xA;&gt;&gt; ## Recurrance&#xA;&gt;&gt;&#xA;&gt;&gt; Some offers are *periodic*, such as a subscription service or monthly&#xA;&gt;&gt; dues, in that payment is expected to be repeated.  There are many&#xA;&gt;&gt; different flavors of repetition, consider:&#xA;&gt;&gt;&#xA;&gt;&gt; * Payments due on the first of every month, for 6 months.&#xA;&gt;&gt; * Payments due on every Monday, 1pm Pacific Standard Time.&#xA;&gt;&gt; * Payments due once a year:&#xA;&gt;&gt;     * which must be made on January 1st, or&#xA;&gt;&gt;     * which are only valid if started January 1st 2020, or&#xA;&gt;&gt;     * which if paid after January 1st you (over) pay the full rate first year, or&#xA;&gt;&gt;     * which if paid after January 1st are paid pro-rata for the first year, or&#xA;&gt;&gt;     * which repeat from whenever you made the first payment&#xA;&gt;&gt;&#xA;&gt;&gt; Thus, each payment has:&#xA;&gt;&gt; 1. A `time_unit` defining 0 (seconds), 1 (days), 2 (months), 3 (years).&#xA;&gt;&gt; 2. A `period`, defining how often (in `time_unit`) it has to be paid.&#xA;&gt;&gt; 3. An optional `number` of total payments to be paid.&#xA;&gt;&gt; 4. An optional `basetime`, defining when the first payment applies&#xA;&gt;&gt;     in seconds since 1970-01-01 UTC.&#xA;&gt;&gt; 5. An optional `paywindow`, defining how many seconds into the period&#xA;&gt;&gt;     a payment will be accepted: 0xFFFFFFFF being a special value meaning&#xA;&gt;&gt;     &#34;any time during the period, but you will have to pay proportionally&#xA;&gt;&gt;     to the remaining time in the period&#34;.&#xA;&gt;&gt;&#xA;&gt;&gt; Note that the `expiry` field covers the case where an offer is no longer&#xA;&gt;&gt; valid after January 1st 2020.&#xA;&gt;&gt;&#xA;&gt;&gt; ## Default Offer&#xA;&gt;&gt;&#xA;&gt;&gt; The &#34;default offer&#34; of a node is a nominal offer used to send&#xA;&gt;&gt; unsolicited payments.  It is generally not actually sent, but can be&#xA;&gt;&gt; used by any other node as if it has been.  It has the following&#xA;&gt;&gt; fields:&#xA;&gt;&gt;&#xA;&gt;&gt; * `offer_idenfitier`: zero-length&#xA;&gt;&gt; * `d`: any&#xA;&gt;&gt; * `n`: the node id of the recipient.&#xA;&gt;&gt;&#xA;&gt;&gt; ## Invoice Request Encoding&#xA;&gt;&gt;&#xA;&gt;&gt; Once it has an offer, the node can request an actual invoice using the&#xA;&gt;&gt; `invoice_req` message inside `directed`&#39;s `onion_routing_packet`.  It&#xA;&gt;&gt; would expect an `invoice_or_error_tlv` inside the `directed_reply`&#xA;&gt;&gt; message.&#xA;&gt;&gt;&#xA;&gt;&gt; This includes a `tag` it can use to identify replies, the&#xA;&gt;&gt; `offer_idenfitier` from the offer, a `key` it can use to prove it was&#xA;&gt;&gt; the requester of this invoice, a `recurrence` number if this&#xA;&gt;&gt; is a payment in a recurring series, and other codes as required.&#xA;&gt;&gt;&#xA;&gt;&gt; The `refund_proof` refers to a previous invoice paid by the sender for&#xA;&gt;&gt; the specific case of a `refund_for` offer.  It provides proof of&#xA;&gt;&gt; payment (the `payment_preimage` and also a signature of the&#xA;&gt;&gt; `payment_hash` from the `key` which requested the being-refunded&#xA;&gt;&gt; invoice (which does *not* have to be the same as this `key`!).&#xA;&gt;&gt;&#xA;&gt;&gt; 1. tlvs: `invoice_request_tlv`&#xA;&gt;&gt; 2. types:&#xA;&gt;&gt;     1. type: 1 (`tag`)&#xA;&gt;&gt;     2. data:&#xA;&gt;&gt;        * [`...*byte`:`tag`]&#xA;&gt;&gt;     1. type: 2 (`offer_identifier`)&#xA;&gt;&gt;     2. data:&#xA;&gt;&gt;        * [`...*byte`:`id`]&#xA;&gt;&gt;     1. type: 3 (`key`)&#xA;&gt;&gt;     2. data:&#xA;&gt;&gt;       * [`32`:`key`]&#xA;&gt;&gt;     1. type: 4 (`recurrence`)&#xA;&gt;&gt;     2. data:&#xA;&gt;&gt;       * [`tu64`:`number`]&#xA;&gt;&gt;     1. type: 5 (`quantity`)&#xA;&gt;&gt;     2. data:&#xA;&gt;&gt;       * [`tu64`:`n`]&#xA;&gt;&gt;     1. type: 6 (`delivery_address_name`)&#xA;&gt;&gt;     2. data:&#xA;&gt;&gt; &#x9; * [`...*byte`:`name`]&#xA;&gt;&gt;     1. type: 7 (`delivery_address1`)&#xA;&gt;&gt;     2. data:&#xA;&gt;&gt; &#x9; * [`...*byte`:`address1`]&#xA;&gt;&gt;     1. type: 8 (`delivery_address2`)&#xA;&gt;&gt;     2. data:&#xA;&gt;&gt; &#x9; * [`...*byte`:`address2`]&#xA;&gt;&gt;     1. type: 9 (`delivery_city`)&#xA;&gt;&gt;     2. data:&#xA;&gt;&gt; &#x9; * [`...*byte`:`city`]&#xA;&gt;&gt;     1. type: 10 (`delivery_state_province_or_region`)&#xA;&gt;&gt;     2. data:&#xA;&gt;&gt; &#x9; * [`...*byte`:`state_province_or_region`]&#xA;&gt;&gt;     1. type: 11 (`delivery_zip_or_postal_code`)&#xA;&gt;&gt;     2. data:&#xA;&gt;&gt; &#x9; * [`...*byte`:`zip_or_postal_code`]&#xA;&gt;&gt;     1. type: 12 (`delivery_country`)&#xA;&gt;&gt;     2. data:&#xA;&gt;&gt; &#x9; * [`2*byte`:`country_code`]&#xA;&gt;&gt;     1. type: 13 (`delivery_telephone_number`)&#xA;&gt;&gt;     2. data:&#xA;&gt;&gt; &#x9; * [`...*byte`:`tel`]&#xA;&gt;&gt;     1. type: 14 (`voucher_code`)&#xA;&gt;&gt;     2. data:&#xA;&gt;&gt; &#x9; * [`...*byte`:`code`]&#xA;&gt;&gt;     1. type: 15 (`refund_proof`)&#xA;&gt;&gt;     2. data:&#xA;&gt;&gt;        * [`32*byte`:`payment_preimage`]&#xA;&gt;&gt;        * [`signature`:`signature`]&#xA;&gt;&gt;&#xA;&gt;&gt; ## Requirements&#xA;&gt;&gt;&#xA;&gt;&gt; FIXME: many more&#xA;&gt;&gt; Sender MUST use ISO 3166 alpha-2 code for `delivery_country`.&#xA;&gt;&gt; Sender MUST set offer_identifier to match offer.&#xA;&gt;&gt; Sender MUST include `key`&#xA;&gt;&gt;     - SHOULD use a transient unpredictable key&#xA;&gt;&gt;     - MUST reuse key for successive recurring invoices.&#xA;&gt;&gt; Sender MUST set `recurrence` for recurring invoices.&#xA;&gt;&gt;&#xA;&gt;&gt; Receiver MUST check `offer_identifier`&#xA;&gt;&gt; Receiver MUST check `delivery_` fields.&#xA;&gt;&gt; Receiver MUST check `recurrence`.&#xA;&gt;&gt; Receiver MUST check `amount`.&#xA;&gt;&gt;&#xA;&gt;&gt; 1. tlvs: `invoice_or_error_tlv`&#xA;&gt;&gt; 2. types:&#xA;&gt;&gt;     1. type: 1 (`tag`)&#xA;&gt;&gt;     2. data:&#xA;&gt;&gt;       * [`...*byte`:`tag`]&#xA;&gt;&gt;     1. type: 3 (`omitted`)&#xA;&gt;&gt;     2. data:&#xA;&gt;&gt; &#x9; * [`...*u64`:`omitted_fields`]&#xA;&gt;&gt;     1. type: 4 (`invoice`)&#xA;&gt;&gt;     2. data:&#xA;&gt;&gt;       * [`...*byte`:`invoice`]&#xA;&gt;&gt;     1. type: 5 (`message`)&#xA;&gt;&gt;       * [`...*byte`:`message`]&#xA;&gt;&gt;     1. type: 6 (`replacement`)&#xA;&gt;&gt;     2. data:&#xA;&gt;&gt;       * [`signature`:`signature`]&#xA;&gt;&gt;       * [`...*byte`:`offer`]&#xA;&gt;&gt;&#xA;&gt;&gt; Sender:&#xA;&gt;&gt; - MUST copy `tag` from sender.&#xA;&gt;&gt; - MUST omit fields it does not use, and place number in order in `omitted_fields`.&#xA;&gt;&gt; - if it includes `invoice`:&#xA;&gt;&gt;    - MUST not include `message`&#xA;&gt;&gt;    - MUST not include `replacement`&#xA;&gt;&gt;    - MUST [merkle fields it used](#merkle-calculation) and place that in invoice `s` field.&#xA;&gt;&gt; - otherwise, if it includes `replacement`:&#xA;&gt;&gt;    - MAY include `message`&#xA;&gt;&gt; - otherwise:&#xA;&gt;&gt;    - MUST include `message` describing the error.&#xA;&gt;&gt;&#xA;&gt;&gt; Receiver:&#xA;&gt;&gt; - MUST check that `tag` matches req.&#xA;&gt;&gt; - if `replacement`:&#xA;&gt;&gt;    - MUST fail if `signature` does not sign `offer` with same key as original.&#xA;&gt;&gt;    - MUST only fetch once (no double-redirects!)&#xA;&gt;&gt; - if description or amount significantly changes, must re-ask user.&#xA;&gt;&gt;    - SHOULD note if description simply has something appended (eg &#34;+ postage&#34;).&#xA;&gt;&gt; - within invoice:&#xA;&gt;&gt;      - MUST check that `s` matches merkle of fields, minus `omitted`.&#xA;&gt;&gt; &#x9;- MUST check that no vital fields are in `omitted`.&#xA;&gt;&gt; &#x9;- MUST check that `d` matches `description`&#xA;&gt;&gt;      - MUST check that `q` DNE if `quantity` DNE, otherwise is equal.&#xA;&gt;&gt;      - Must check valid signature, etc.&#xA;&gt;&gt;&#xA;&gt;&gt; ## Merkle Calculation&#xA;&gt;&gt;&#xA;&gt;&gt; 1. For each `invoice_req_tlv` field in ascending `tlv` type order:&#xA;&gt;&gt;     1. If the field was omitted, it is added to `omitted_fields`.&#xA;&gt;&gt;     2. Otherwise, the immediate parent merkle is:&#xA;&gt;&gt;     &#xA;&gt;&gt;        SHA256(SHA256(`tag` | `be64-n`) | SHA256(`tlv-value`))&#xA;&gt;&gt;&#xA;&gt;&gt;        Where `be64-n` is a 64-bit big-endian counter starting at 0 and&#xA;&gt;&gt;        incrementing for each leaf.&#xA;&gt;&gt;&#xA;&gt;&gt;     3. Order these nodes in increasing SHA256(`tag` | `be64-n`) order.&#xA;&gt;&gt;&#xA;&gt;&gt; 2. Create additional leaves until `be64-n` is the next power of 2:&#xA;&gt;&gt;&#xA;&gt;&gt;        SHA256(`tag` | `be64-n`)&#xA;&gt;&gt;&#xA;&gt;&gt; 3. Combine adjacent leaves using SHA256(leaf1 | leaf2) until none remain.&#xA;&gt;&gt;&#xA;&gt;&gt; By creating adjacent leaves using the `tag` field and a counter, and&#xA;&gt;&gt; sorting the leaves, the only significant information revealed by a&#xA;&gt;&gt; merkle proof on a node is the depth of tree (which implies the total&#xA;&gt;&gt; number of TLV fields).&#xA;&gt;&gt;&#xA;&gt;&gt; # InvRequests&#xA;&gt;&gt;&#xA;&gt;&gt; There are times when it makes sense to request an invoice over another&#xA;&gt;&gt; medium, such as HTTP or a QR code.&#xA;&gt;&gt;&#xA;&gt;&gt; ## Encoding&#xA;&gt;&gt;&#xA;&gt;&gt; The human-readable part of a Lightning invrequest is `lni`.  The data part&#xA;&gt;&gt; consists of three parts:&#xA;&gt;&gt;&#xA;&gt;&gt; 1. 0 or more [TLV](01-messaging.md#type-length-value-format) encoded fields.&#xA;&gt;&gt; 2. A 32-byte nodeid[1]&#xA;&gt;&gt; 3. 64-byte signature of SHA256(hrp-as-utf8 | tlv | nodeid).&#xA;&gt;&gt;&#xA;&gt;&gt; ## TLV Fields&#xA;&gt;&gt;&#xA;&gt;&gt; 1. tlvs: `invreq`&#xA;&gt;&gt; 2. types:&#xA;&gt;&gt;      1. type: 1 (`paths`)&#xA;&gt;&gt;      2. data:&#xA;&gt;&gt;          * [`u16`:`num_paths`]&#xA;&gt;&gt;          * [`num_paths*path`:`path`]&#xA;&gt;&gt;      1. type: 2 (`description`)&#xA;&gt;&gt;      2. data:&#xA;&gt;&gt;          * [`...*byte`:`description`]&#xA;&gt;&gt;      1. type: 3 (`expiry`)&#xA;&gt;&gt;      2. data:&#xA;&gt;&gt;          * [`tu64`:`seconds_from_epoch`]&#xA;&gt;&gt;      1. type: 4 (`amount`)&#xA;&gt;&gt;      2. data:&#xA;&gt;&gt;          * [`tu64`:`millisatoshis`]&#xA;&gt;&gt;&#xA;&gt;&gt; The fields `paths`, `description`, and `expiry` fields are the&#xA;&gt;&gt; same as those for offers; the optional `amount` field describes the&#xA;&gt;&gt; amount an invoice will be accepted for.&#xA;&gt;&gt;&#xA;&gt;&gt; Upon parsing and accepting an `invreq`, the node sends an&#xA;&gt;&gt; `invoice_or_error_tlv` within an onion.  The reply is empty.&#xA;&gt;&gt;&#xA;&gt;&gt; ## Requirements&#xA;&gt;&gt;&#xA;&gt;&gt; The requirements for `paths`, `description` and `expiry` are&#xA;&gt;&gt; [described above](#requirements-for-offers-and-invrequests).&#xA;&gt;&gt;&#xA;&gt;&gt; FIXME: More.&#xA;&gt;&gt;&#xA;&gt;&gt; [1] Assuming we go for Schnorr sigs and 32-byte pubkeys.&#xA;&gt;&gt; ----&#xA;&gt;&gt; Addendum: BOLT #7: P2P Node and Channel Discovery and Directed Messages&#xA;&gt;&gt; ...&#xA;&gt;&gt; # Directed Messages&#xA;&gt;&gt;&#xA;&gt;&gt; Directed messages allow peers to use existing connections to query for&#xA;&gt;&gt; invoices (see [BOLT 12](12-offer-encoding.md)).  Like gossip messages,&#xA;&gt;&gt; they are not associated with a particular local channel.&#xA;&gt;&gt;&#xA;&gt;&gt; The `id` is a unique, transient identifier between the peers, used to&#xA;&gt;&gt; identify match messages and replies.&#xA;&gt;&gt;&#xA;&gt;&gt; ## The `directed` and `directed_reply` Messages&#xA;&gt;&gt;&#xA;&gt;&gt; 1. type: 384 (`directed`) (`option_directed_messages`)&#xA;&gt;&gt; 2. data:&#xA;&gt;&gt;      * [`chain_hash`:`chain_hash`]&#xA;&gt;&gt;      * [`u64`:`id`]&#xA;&gt;&gt;      * [`1366*byte`:`onion_routing_packet`]&#xA;&gt;&gt;&#xA;&gt;&gt; 1. type: 384 (`directed_reply`) (`option_directed_messages`)&#xA;&gt;&gt; 2. data:&#xA;&gt;&gt;      * [`chain_hash`:`chain_hash`]&#xA;&gt;&gt;      * [`u64`:`id`]&#xA;&gt;&gt;      * [`u16`:`len`]&#xA;&gt;&gt;      * [`len*byte`:`reply`]&#xA;&gt;&gt;&#xA;&gt;&gt; ## Requirements&#xA;&gt;&gt;&#xA;&gt;&gt; FIXME: similar to update_add_htlc and update_fail_htlc.&#xA;&gt;&gt; FIXME: define reasonable timeout after which you can forget if not replied?&#xA;&gt;&gt; _______________________________________________&#xA;&gt;&gt; Lightning-dev mailing list&#xA;&gt;&gt; Lightning-dev at lists.linuxfoundation.org&#xA;&gt;&gt; https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev</html></oembed>