What is Nostr?
ZmnSCPxj [ARCHIVE] /
npub1g5z…ms3l
2023-06-09 12:57:15
in reply to nevent1q…jhvl

ZmnSCPxj [ARCHIVE] on Nostr: 📅 Original date posted:2019-11-05 📝 Original message: Good morning Rusty, and ...

📅 Original date posted:2019-11-05
📝 Original message:
Good morning Rusty, and list,

Thank you Rusty.
Below is a quick and dirty review; I doubt I found whatever handwaves you are using.

First, please confirm my understanding of the message flow.
Suppose I have a donation offer on my website and Rusty wants to donate to me.
Then:

ZmnSCPxj Rusty
| |
+---------- `lno` ---------->+ (via non-Lightning communication channel e.g. https)
| |
+<---- `invoice_request` ----+ (via a normal Rusty->ZmnSCPxj payment)
| |
+---- `invoice_or_error` --->| (by failing the above payment and embedding in the failure blob)
| |
+<------- `sendpay` ---------+ (via a normal Rusty->ZmnSCPxj payment)

Is it approximately correct?

>
> BOLT #12: Offer Protocols for Lightning Payments
>
> =================================================
>
> An higher-level, QR-code-ready protocol for dealing with invoices over
> Lightning. There are two simple flows supported: in one, a user gets
> an offer (`lno...`) and requests an invoice over the lightning
> network, obtaining one (or an error) in reply. In the other, a user
> gets an invoice request (`lni...`), and sends the invoice over the
> lightning network, retreiving an empty reply.

Here are completely pointless counterproposals for the offer and invoice-request HRPs:

* Offers:
* `lnpayme`
* `lnbuyit`
* `lnforsale`
* Invoice Requests:
* `lnpaying`
* `lnbuying`
* `lnshutupandtakemymoney`

`lno` and `lni` feel wrong to me.
Their juxtaposition implies `lno` == output and `lni` == input to me, due to the use of `o` and `i`, though `lno` is where you get money in exchange for product and `lni` is the request-for-service.

>
> Table of Contents
>
> ==================
>
> - Offers
> - Encoding
> - TLV Fields
> - Invrequests
> - Encoding
> - TLV Fields

Definite handwave, does not match the structure of the document *at all*.

> Encoding
>
> ---------
>
> The human-readable part of a Lightning offer is`lno`. The data part
> consists of three parts:
>
> 1. 0 or more TLV encoded fields.
> 2. A 32-byte nodeid[1]
> 3. 64-byte signature of SHA256(hrp-as-utf8 | tlv | nodeid).
>
> TLV Fields
>
> -----------
>
> The TLV fields define how to get the invoice, and what it's for.
> Each offer has a unique `offer_idenfitier` so the offering node can
> distinguish different invoice requests.
>
> Offers can request recurring payments of various kinds, and specify
> what base currency they are calculated in (the actual amount will be
> in the invoice).
>
> `additional_data` is a bitfield which indicates what information the
> invoice requester should (odd) or must (even) supply:
>
> 1. Bits `0/1`: include `delivery_address`
> 2. Bits `2/3`: include `delivery_telephone_number`
> 3. Bits `4/5`: include `voucher_code`
> 4. Bits `6/7`: include `refund_proof`
>
> `refund_for` indicates an offer for a (whole or part) refund for a
> previous invoice, as indicated by the `payment_hash`.
>
> 5. tlvs: `offer`
> 6. types:
> 1. type: 1 (`paths`)
> 2. data:
> - [`u16`:`num_paths`]
> - [`num_paths*path`:`path`]
> 3. type: 2 (`description`)
> 4. data:
> - [`...*byte`:`description`]

UTF-8?
Null-terminated?

> 5. type: 3 (`expiry`)
> 6. data:
> - [`tu64`:`seconds_from_epoch`]
> 7. type: 4 (`offer_identifier`)
> 8. data:
> - [`...*byte`:`id`]
> 9. type: 5 (`amount`)
> 10. data:
> - [`4*byte`:`currency`]
> - [`tu64`:`amount`]
> 11. type: 6 (`additional_data`)
> 12. data:
> - [`...*byte`:`rbits`]
> 13. type: 7 (`recurrance`)
> 14. data:
> - [`byte`:`time_unit`]
> - [`u32`:`period`]
> - [`tu32`:`number`]
> 15. type: 8 (`recurrance_base`)
> 16. data:
> - [`u32`:`basetime`]
> - [`tu32`:`paywindow`]
> 17. type: 9 (`quantity`)
> 18. data:
> - [`tu64`:`max`]
> 19. type: 10 (`refund_for`)
> 20. data:
> - [`32*byte`:`payment_hash`]
> 7. subtype: `path`
> 8. data:
> - [`u16`:`num_hops`]
> - [`num_hops*hop`:`hops`]
> 9. subtype: `hop`
> 10. data:
> - [`pubkey`:`nodeid`]
> - [`short_channel_id`:`short_channel_id`]
> - [`u16`:`flen`]
> - [`flen*byte`:`features`]
>
> Requirements For Offers And Invrequests
>
> ----------------------------------------
>
> A writer of an offer or an invrequest:
>
> - if it is connected only by private channels:
> - MUST include `paths` containing a path to the node.
> - otherwise:
> - MAY include `paths` containing a path to the node.
> - MUST describe the item(s) being offered or purpose of invoice in `description`.
> - MUST include `expiry` if the offer/invrequest will not be valid after some time.
> - if it includes `expiry`:
> - MUST set `seconds_from_epoch` to the expiry time in seconds since 1970 UTC.
>
> Requirements For Offers
>
> ------------------------
>
> A writer of an offer:
>
> - MUST use a unique `offer_idenfitier` for each offer.
> - MAY include `recurrence` to indicate offer should trigger time-spaced
> invoices.
>
> - MUST include `amount` if it includes `recurrence`.
> - if it includes `amount`:
> - MUST specify `currency` as the ISO 4712 or BIP-0173, padded with zero bytes if required

I cannot find ISO 4712, but could find ISO 4217.
BIP-173 does not have a list of currencies, but refers to SLIP-0173.
Some of the listed currencies there seem to have more than 4 characters.

Should I assume encoding is ASCII?
We will "never" see a non-ASCII currency code?

> - 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`).
> - if it requires specific fields in the invoice:
> - MUST set the corresponding even bits in the `additional_data` field
>
> A reader of an offer:
>
> - SHOULD gain user consent for recurring payments.
> - SHOULD allow user to view and cancel recurring payments.
> - SHOULD gain user consent to send `delivery_` fields.
> - if it uses `amount` to provide the user with a cost estimate:
> - MUST warn user if amount of actual invoice differs significantly
> from that expectation.
>
> - FIXME: more!
>
> Recurrance
>
> -----------
>
> Some offers areperiodic, such as a subscription service or monthly
> dues, in that payment is expected to be repeated. There are many
> different flavors of repetition, consider:
>
> - Payments due on the first of every month, for 6 months.
> - Payments due on every Monday, 1pm Pacific Standard Time.
> - Payments due once a year:
> - which must be made on January 1st, or
> - which are only valid if started January 1st 2020, or
> - which if paid after January 1st you (over) pay the full rate first year, or
> - which if paid after January 1st are paid pro-rata for the first year, or
> - which repeat from whenever you made the first payment
>
> Thus, each payment has:
>
>
> 1. A `time_unit` defining 0 (seconds), 1 (days), 2 (months), 3 (years).
> 2. A `period`, defining how often (in `time_unit`) it has to be paid.
> 3. An optional `number` of total payments to be paid.
> 4. An optional `basetime`, defining when the first payment applies
> in seconds since 1970-01-01 UTC.
>
> 5. An optional `paywindow`, defining how many seconds into the period
> a payment will be accepted: 0xFFFFFFFF being a special value meaning
> "any time during the period, but you will have to pay proportionally
> to the remaining time in the period".
>
> Note that the `expiry` field covers the case where an offer is no longer
> valid after January 1st 2020.
>
>
> Default Offer
>
> --------------
>
> The "default offer" of a node is a nominal offer used to send
> unsolicited payments. It is generally not actually sent, but can be
> used by any other node as if it has been. It has the following
> fields:
>
> - `offer_idenfitier`: zero-length
> - `d`: any
> - `n`: the node id of the recipient.

In essence, this is an implicitly-existing offer that never expires, and which can be used by any node at any time to construct an invoice request?

>
> Invoice Request Encoding
>
> -------------------------
>
> Once it has an offer, the node can request an actual invoice using the
> `invoice_req` message inside `directed`'s `onion_routing_packet`. It
> would expect an `invoice_or_error_tlv` inside the `directed_reply`
> message.
>
> This includes a `tag` it can use to identify replies, the
> `offer_idenfitier` from the offer, a `key` it can use to prove it was
> the requester of this invoice, a `recurrence` number if this
> is a payment in a recurring series, and other codes as required.
>
> The `refund_proof` refers to a previous invoice paid by the sender for
> the specific case of a `refund_for` offer. It provides proof of
> payment (the `payment_preimage` and also a signature of the
> `payment_hash` from the `key` which requested the being-refunded
> invoice (which does not have to be the same as this `key`!).

An earlier requirement mentions that writers of offers or invoice request MUST have `paths` in some condition.
The below does not have `paths`, but there is a "human-readable" alternate encoding which *does* have `paths`.
It might be better to clarify this point.

>
> 1. tlvs: `invoice_request_tlv`
> 2. types:
>
> 1. type: 1 (`tag`)
> 2. data:
> - [`...*byte`:`tag`]
> 3. type: 2 (`offer_identifier`)
> 4. data:
> - [`...*byte`:`id`]
> 5. type: 3 (`key`)
> 6. data:
>
> - [`32`:`key`]
>
> 1. type: 4 (`recurrence`)
> 2. data:
>
> - [`tu64`:`number`]
>
> 1. type: 5 (`quantity`)
> 2. data:
>
> - [`tu64`:`n`]
>
> 1. type: 6 (`delivery_address_name`)
> 2. data:
>
> - [`...*byte`:`name`]
>
> 1. type: 7 (`delivery_address1`)
> 2. data:
>
> - [`...*byte`:`address1`]
>
> 1. type: 8 (`delivery_address2`)
> 2. data:
>
> - [`...*byte`:`address2`]
>
> 1. type: 9 (`delivery_city`)
> 2. data:
>
> - [`...*byte`:`city`]
>
> 1. type: 10 (`delivery_state_province_or_region`)
> 2. data:
>
> - [`...*byte`:`state_province_or_region`]
>
> 1. type: 11 (`delivery_zip_or_postal_code`)
> 2. data:
>
> - [`...*byte`:`zip_or_postal_code`]
>
> 1. type: 12 (`delivery_country`)
> 2. data:
>
> - [`2*byte`:`country_code`]
>
> 1. type: 13 (`delivery_telephone_number`)
> 2. data:
>
> - [`...*byte`:`tel`]
>
> 1. type: 14 (`voucher_code`)
> 2. data:
>
> - [`...*byte`:`code`]
>
> 1. type: 15 (`refund_proof`)
> 2. data:
> - [`32*byte`:`payment_preimage`]
> - [`signature`:`signature`]
>
> Requirements
>
> -------------
>
> FIXME: many more
> Sender MUST use ISO 3166 alpha-2 code for `delivery_country`.

What happens when my army of non-shiny robots rise from their crypts and start annexing entire countries to enforce global peace, prosperity, and greater world optimization?
I suppose it would become immaterial then...

>
> Directed Messages
>
> ==================
>
> Directed messages allow peers to use existing connections to query for
> invoices (see BOLT 12). Like gossip messages,
> they are not associated with a particular local channel.
>
> The `id` is a unique, transient identifier between the peers, used to
> identify match messages and replies.
>
> The `directed` and `directed_reply` Messages
>
> ---------------------------------------------
>
> 1. type: 384 (`directed`) (`option_directed_messages`)
> 2. data:
> - [`chain_hash`:`chain_hash`]
> - [`u64`:`id`]
> - [`1366*byte`:`onion_routing_packet`]
> 3. type: 384 (`directed_reply`) (`option_directed_messages`)
> 4. data:
> - [`chain_hash`:`chain_hash`]
> - [`u64`:`id`]
> - [`u16`:`len`]
> - [`len*byte`:`reply`]

This new `directed` message will be the mechanism for sending invoice requests and receiving invoice request responses?
What incentive is there for a forwarding node to actually forward a `directed` message?


Regards,
ZmnSCPxj
Author Public Key
npub1g5zswf6y48f7fy90jf3tlcuwdmjn8znhzaa4vkmtxaeskca8hpss23ms3l