{"type":"rich","version":"1.0","title":"ZmnSCPxj [ARCHIVE] wrote","author_name":"ZmnSCPxj [ARCHIVE] (npub1g5…3ms3l)","author_url":"https://yabu.me/npub1g5zswf6y48f7fy90jf3tlcuwdmjn8znhzaa4vkmtxaeskca8hpss23ms3l","provider_name":"njump","provider_url":"https://yabu.me","html":"📅 Original date posted:2019-11-05\n📝 Original message:\nGood morning Rusty, and list,\n\nThank you Rusty.\nBelow is a quick and dirty review; I doubt I found whatever handwaves you are using.\n\nFirst, please confirm my understanding of the message flow.\nSuppose I have a donation offer on my website and Rusty wants to donate to me.\nThen:\n\n         ZmnSCPxj                      Rusty\n            |                            |\n            +---------- `lno` ----------\u003e+ (via non-Lightning communication channel e.g. https)\n            |                            |\n            +\u003c---- `invoice_request` ----+ (via a normal Rusty-\u003eZmnSCPxj payment)\n            |                            |\n            +---- `invoice_or_error` ---\u003e| (by failing the above payment and embedding in the failure blob)\n            |                            |\n            +\u003c------- `sendpay` ---------+ (via a normal Rusty-\u003eZmnSCPxj payment)\n\nIs it approximately correct?\n\n\u003e\n\u003e BOLT #12: Offer Protocols for Lightning Payments\n\u003e\n\u003e =================================================\n\u003e\n\u003e An higher-level, QR-code-ready protocol for dealing with invoices over\n\u003e Lightning. There are two simple flows supported: in one, a user gets\n\u003e an offer (`lno...`) and requests an invoice over the lightning\n\u003e network, obtaining one (or an error) in reply. In the other, a user\n\u003e gets an invoice request (`lni...`), and sends the invoice over the\n\u003e lightning network, retreiving an empty reply.\n\nHere are completely pointless counterproposals for the offer and invoice-request HRPs:\n\n* Offers:\n  * `lnpayme`\n  * `lnbuyit`\n  * `lnforsale`\n* Invoice Requests:\n  * `lnpaying`\n  * `lnbuying`\n  * `lnshutupandtakemymoney`\n\n`lno` and `lni` feel wrong to me.\nTheir 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.\n\n\u003e\n\u003e Table of Contents\n\u003e\n\u003e ==================\n\u003e\n\u003e -   Offers\n\u003e     -   Encoding\n\u003e     -   TLV Fields\n\u003e -   Invrequests\n\u003e     -   Encoding\n\u003e     -   TLV Fields\n\nDefinite handwave, does not match the structure of the document *at all*.\n\n\u003e Encoding\n\u003e\n\u003e ---------\n\u003e\n\u003e The human-readable part of a Lightning offer is`lno`. The data part\n\u003e consists of three parts:\n\u003e\n\u003e 1.  0 or more TLV encoded fields.\n\u003e 2.  A 32-byte nodeid[1]\n\u003e 3.  64-byte signature of SHA256(hrp-as-utf8 | tlv | nodeid).\n\u003e\n\u003e TLV Fields\n\u003e\n\u003e -----------\n\u003e\n\u003e The TLV fields define how to get the invoice, and what it's for.\n\u003e Each offer has a unique `offer_idenfitier` so the offering node can\n\u003e distinguish different invoice requests.\n\u003e\n\u003e Offers can request recurring payments of various kinds, and specify\n\u003e what base currency they are calculated in (the actual amount will be\n\u003e in the invoice).\n\u003e\n\u003e `additional_data` is a bitfield which indicates what information the\n\u003e invoice requester should (odd) or must (even) supply:\n\u003e\n\u003e 1.  Bits `0/1`: include `delivery_address`\n\u003e 2.  Bits `2/3`: include `delivery_telephone_number`\n\u003e 3.  Bits `4/5`: include `voucher_code`\n\u003e 4.  Bits `6/7`: include `refund_proof`\n\u003e\n\u003e     `refund_for` indicates an offer for a (whole or part) refund for a\n\u003e     previous invoice, as indicated by the `payment_hash`.\n\u003e\n\u003e 5.  tlvs: `offer`\n\u003e 6.  types:\n\u003e     1.  type: 1 (`paths`)\n\u003e     2.  data:\n\u003e         -   [`u16`:`num_paths`]\n\u003e         -   [`num_paths*path`:`path`]\n\u003e     3.  type: 2 (`description`)\n\u003e     4.  data:\n\u003e         -   [`...*byte`:`description`]\n\nUTF-8?\nNull-terminated?\n\n\u003e     5.  type: 3 (`expiry`)\n\u003e     6.  data:\n\u003e         -   [`tu64`:`seconds_from_epoch`]\n\u003e     7.  type: 4 (`offer_identifier`)\n\u003e     8.  data:\n\u003e         -   [`...*byte`:`id`]\n\u003e     9.  type: 5 (`amount`)\n\u003e     10.  data:\n\u003e         -   [`4*byte`:`currency`]\n\u003e         -   [`tu64`:`amount`]\n\u003e     11.  type: 6 (`additional_data`)\n\u003e     12.  data:\n\u003e         -   [`...*byte`:`rbits`]\n\u003e     13.  type: 7 (`recurrance`)\n\u003e     14.  data:\n\u003e         -   [`byte`:`time_unit`]\n\u003e         -   [`u32`:`period`]\n\u003e         -   [`tu32`:`number`]\n\u003e     15.  type: 8 (`recurrance_base`)\n\u003e     16.  data:\n\u003e         -   [`u32`:`basetime`]\n\u003e         -   [`tu32`:`paywindow`]\n\u003e     17.  type: 9 (`quantity`)\n\u003e     18.  data:\n\u003e         -   [`tu64`:`max`]\n\u003e     19.  type: 10 (`refund_for`)\n\u003e     20.  data:\n\u003e         -   [`32*byte`:`payment_hash`]\n\u003e 7.  subtype: `path`\n\u003e 8.  data:\n\u003e     -   [`u16`:`num_hops`]\n\u003e     -   [`num_hops*hop`:`hops`]\n\u003e 9.  subtype: `hop`\n\u003e 10.  data:\n\u003e     -   [`pubkey`:`nodeid`]\n\u003e     -   [`short_channel_id`:`short_channel_id`]\n\u003e     -   [`u16`:`flen`]\n\u003e     -   [`flen*byte`:`features`]\n\u003e\n\u003e Requirements For Offers And Invrequests\n\u003e\n\u003e ----------------------------------------\n\u003e\n\u003e A writer of an offer or an invrequest:\n\u003e\n\u003e -   if it is connected only by private channels:\n\u003e     -   MUST include `paths` containing a path to the node.\n\u003e -   otherwise:\n\u003e     -   MAY include `paths` containing a path to the node.\n\u003e -   MUST describe the item(s) being offered or purpose of invoice in `description`.\n\u003e -   MUST include `expiry` if the offer/invrequest will not be valid after some time.\n\u003e -   if it includes `expiry`:\n\u003e     -   MUST set `seconds_from_epoch` to the expiry time in seconds since 1970 UTC.\n\u003e\n\u003e Requirements For Offers\n\u003e\n\u003e ------------------------\n\u003e\n\u003e A writer of an offer:\n\u003e\n\u003e -   MUST use a unique `offer_idenfitier` for each offer.\n\u003e -   MAY include `recurrence` to indicate offer should trigger time-spaced\n\u003e     invoices.\n\u003e\n\u003e -   MUST include `amount` if it includes `recurrence`.\n\u003e -   if it includes `amount`:\n\u003e     -   MUST specify `currency` as the ISO 4712 or BIP-0173, padded with zero bytes if required\n\nI cannot find ISO 4712, but could find ISO 4217.\nBIP-173 does not have a list of currencies, but refers to SLIP-0173.\nSome of the listed currencies there seem to have more than 4 characters.\n\nShould I assume encoding is ASCII?\nWe will \"never\" see a non-ASCII currency code?\n\n\u003e     -   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`).\n\u003e -   if it requires specific fields in the invoice:\n\u003e     -   MUST set the corresponding even bits in the `additional_data` field\n\u003e\n\u003e         A reader of an offer:\n\u003e\n\u003e -   SHOULD gain user consent for recurring payments.\n\u003e -   SHOULD allow user to view and cancel recurring payments.\n\u003e -   SHOULD gain user consent to send `delivery_` fields.\n\u003e -   if it uses `amount` to provide the user with a cost estimate:\n\u003e     -   MUST warn user if amount of actual invoice differs significantly\n\u003e         from that expectation.\n\u003e\n\u003e -   FIXME: more!\n\u003e\n\u003e Recurrance\n\u003e\n\u003e -----------\n\u003e\n\u003e Some offers areperiodic, such as a subscription service or monthly\n\u003e dues, in that payment is expected to be repeated. There are many\n\u003e different flavors of repetition, consider:\n\u003e\n\u003e -   Payments due on the first of every month, for 6 months.\n\u003e -   Payments due on every Monday, 1pm Pacific Standard Time.\n\u003e -   Payments due once a year:\n\u003e     -   which must be made on January 1st, or\n\u003e     -   which are only valid if started January 1st 2020, or\n\u003e     -   which if paid after January 1st you (over) pay the full rate first year, or\n\u003e     -   which if paid after January 1st are paid pro-rata for the first year, or\n\u003e     -   which repeat from whenever you made the first payment\n\u003e\n\u003e         Thus, each payment has:\n\u003e\n\u003e\n\u003e 1.  A `time_unit` defining 0 (seconds), 1 (days), 2 (months), 3 (years).\n\u003e 2.  A `period`, defining how often (in `time_unit`) it has to be paid.\n\u003e 3.  An optional `number` of total payments to be paid.\n\u003e 4.  An optional `basetime`, defining when the first payment applies\n\u003e     in seconds since 1970-01-01 UTC.\n\u003e\n\u003e 5.  An optional `paywindow`, defining how many seconds into the period\n\u003e     a payment will be accepted: 0xFFFFFFFF being a special value meaning\n\u003e     \"any time during the period, but you will have to pay proportionally\n\u003e     to the remaining time in the period\".\n\u003e\n\u003e     Note that the `expiry` field covers the case where an offer is no longer\n\u003e     valid after January 1st 2020.\n\u003e\n\u003e\n\u003e Default Offer\n\u003e\n\u003e --------------\n\u003e\n\u003e The \"default offer\" of a node is a nominal offer used to send\n\u003e unsolicited payments. It is generally not actually sent, but can be\n\u003e used by any other node as if it has been. It has the following\n\u003e fields:\n\u003e\n\u003e -   `offer_idenfitier`: zero-length\n\u003e -   `d`: any\n\u003e -   `n`: the node id of the recipient.\n\nIn 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?\n\n\u003e\n\u003e Invoice Request Encoding\n\u003e\n\u003e -------------------------\n\u003e\n\u003e Once it has an offer, the node can request an actual invoice using the\n\u003e `invoice_req` message inside `directed`'s `onion_routing_packet`. It\n\u003e would expect an `invoice_or_error_tlv` inside the `directed_reply`\n\u003e message.\n\u003e\n\u003e This includes a `tag` it can use to identify replies, the\n\u003e `offer_idenfitier` from the offer, a `key` it can use to prove it was\n\u003e the requester of this invoice, a `recurrence` number if this\n\u003e is a payment in a recurring series, and other codes as required.\n\u003e\n\u003e The `refund_proof` refers to a previous invoice paid by the sender for\n\u003e the specific case of a `refund_for` offer. It provides proof of\n\u003e payment (the `payment_preimage` and also a signature of the\n\u003e `payment_hash` from the `key` which requested the being-refunded\n\u003e invoice (which does not have to be the same as this `key`!).\n\nAn earlier requirement mentions that writers of offers or invoice request MUST have `paths` in some condition.\nThe below does not have `paths`, but there is a \"human-readable\" alternate encoding which *does* have `paths`.\nIt might be better to clarify this point.\n\n\u003e\n\u003e 1.  tlvs: `invoice_request_tlv`\n\u003e 2.  types:\n\u003e\n\u003e     1.  type: 1 (`tag`)\n\u003e     2.  data:\n\u003e         -   [`...*byte`:`tag`]\n\u003e     3.  type: 2 (`offer_identifier`)\n\u003e     4.  data:\n\u003e         -   [`...*byte`:`id`]\n\u003e     5.  type: 3 (`key`)\n\u003e     6.  data:\n\u003e\n\u003e     -   [`32`:`key`]\n\u003e\n\u003e     1.  type: 4 (`recurrence`)\n\u003e     2.  data:\n\u003e\n\u003e     -   [`tu64`:`number`]\n\u003e\n\u003e     1.  type: 5 (`quantity`)\n\u003e     2.  data:\n\u003e\n\u003e     -   [`tu64`:`n`]\n\u003e\n\u003e     1.  type: 6 (`delivery_address_name`)\n\u003e     2.  data:\n\u003e\n\u003e     -   [`...*byte`:`name`]\n\u003e\n\u003e     1.  type: 7 (`delivery_address1`)\n\u003e     2.  data:\n\u003e\n\u003e     -   [`...*byte`:`address1`]\n\u003e\n\u003e     1.  type: 8 (`delivery_address2`)\n\u003e     2.  data:\n\u003e\n\u003e     -   [`...*byte`:`address2`]\n\u003e\n\u003e     1.  type: 9 (`delivery_city`)\n\u003e     2.  data:\n\u003e\n\u003e     -   [`...*byte`:`city`]\n\u003e\n\u003e     1.  type: 10 (`delivery_state_province_or_region`)\n\u003e     2.  data:\n\u003e\n\u003e     -   [`...*byte`:`state_province_or_region`]\n\u003e\n\u003e     1.  type: 11 (`delivery_zip_or_postal_code`)\n\u003e     2.  data:\n\u003e\n\u003e     -   [`...*byte`:`zip_or_postal_code`]\n\u003e\n\u003e     1.  type: 12 (`delivery_country`)\n\u003e     2.  data:\n\u003e\n\u003e     -   [`2*byte`:`country_code`]\n\u003e\n\u003e     1.  type: 13 (`delivery_telephone_number`)\n\u003e     2.  data:\n\u003e\n\u003e     -   [`...*byte`:`tel`]\n\u003e\n\u003e     1.  type: 14 (`voucher_code`)\n\u003e     2.  data:\n\u003e\n\u003e     -   [`...*byte`:`code`]\n\u003e\n\u003e     1.  type: 15 (`refund_proof`)\n\u003e     2.  data:\n\u003e         -   [`32*byte`:`payment_preimage`]\n\u003e         -   [`signature`:`signature`]\n\u003e\n\u003e Requirements\n\u003e\n\u003e -------------\n\u003e\n\u003e FIXME: many more\n\u003e Sender MUST use ISO 3166 alpha-2 code for `delivery_country`.\n\nWhat 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?\nI suppose it would become immaterial then...\n\n\u003e\n\u003e Directed Messages\n\u003e\n\u003e ==================\n\u003e\n\u003e Directed messages allow peers to use existing connections to query for\n\u003e invoices (see BOLT 12). Like gossip messages,\n\u003e they are not associated with a particular local channel.\n\u003e\n\u003e The `id` is a unique, transient identifier between the peers, used to\n\u003e identify match messages and replies.\n\u003e\n\u003e The `directed` and `directed_reply` Messages\n\u003e\n\u003e ---------------------------------------------\n\u003e\n\u003e 1.  type: 384 (`directed`) (`option_directed_messages`)\n\u003e 2.  data:\n\u003e     -   [`chain_hash`:`chain_hash`]\n\u003e     -   [`u64`:`id`]\n\u003e     -   [`1366*byte`:`onion_routing_packet`]\n\u003e 3.  type: 384 (`directed_reply`) (`option_directed_messages`)\n\u003e 4.  data:\n\u003e     -   [`chain_hash`:`chain_hash`]\n\u003e     -   [`u64`:`id`]\n\u003e     -   [`u16`:`len`]\n\u003e     -   [`len*byte`:`reply`]\n\nThis new `directed` message will be the mechanism for sending invoice requests and receiving invoice request responses?\nWhat incentive is there for a forwarding node to actually forward a `directed` message?\n\n\nRegards,\nZmnSCPxj"}
