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
_______________________________________________
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev

Reply via email to