跳转到正文
buybitcoinsmart

术语表 /闪电网络与 Layer 2

BOLT12 offer

又称 offer。

BOLT12 offer 是什么?
BOLT12 offer 是一种以 lno1 开头、可重复使用的闪电网络支付码,任意数量的付款方都可以通过闪电网络本身向发行方请求,将其转换为各自全新的发票。

offer 是一种可以在付款后继续有效的收款请求,因此一个打印出来的二维码即可服务所有客户。offer 不含签名,也不含校验和,其字段占用 TLV 类型2至22,长度有意控制得足够短,以便低端手机的摄像头也能扫描。如果您是收款方,这就是只需打印一次的二维码与由其生成的发票之间的区别,后者会在7200秒后过期。

运作方式

BOLT12 offer 是一串类型-长度-值记录,以人类可读前缀 lno、分隔符1,再加上按顺序承载这些记录的 bech32 风格字符写成。

末尾没有六个字符的校验和。规范取消了它,理由是二维码自带校验和,而且损坏的 offer 只会得到一个无法解析的字符串,而不是一笔丢失的付款。较长的 offer 可以用加号断开,加号后可以跟空白字符,这样粘贴到有字符数限制的文本框时仍能保持完整,读取方在解码前必须去掉加号和空白字符。写入方必须全部使用小写或全部使用大写,用于二维码时应选择大写。

这些字段本身是有编号的。offer_chains 为2,offer_metadata 为4,offer_currency 为6,offer_amount 为8,offer_description 为10,offer_features 为12,offer_absolute_expiry 为14,offer_paths 为16,offer_issuer 为18,offer_quantity_max 为20,offer_issuer_id 为22。写入方必须保持在类型1至79之内,另有1000000000至1999999999的第二个范围留作实验之用。该列表中没有任何一项是签名,这是有意为之:签名会增加字符串长度而没有任何好处,因为每个非签名字段都会被复制到随后的请求中,所以被篡改的 offer 不会产生任何发票。

付款还需要再发送两条消息。您的钱包通过洋葱消息发送前缀为 lnr 的 invoice_request,复制 offer 的所有字段(包括它不理解的字段),并用对 Merkle 根的 BIP340 签名对结果签名。发行方回复一张已签名的发票。Merkle 结构将每个字段的叶子与一个 nonce 叶子配对,这使付款方日后可以只披露有争议发票中的某一个字段,而不暴露相邻字段,这是对整个字符串的 BOLT11 签名做不到的。

这三条消息中有两条在退款和取款机场景中方向相反。商户发布一个 invoice_request,注明它想发送的金额,您回复一张发票,商户在付款前确认 invoice_node_id。

购买比特币时为何重要

offer 改变的是您发布收款方式的方法,对收款成本没有任何改变。

以本站的 Phoenix 评测为例。ACINQ 公布了一份手续费表,而不是让您自己去发现:通过闪电网络发送的费用为0.4%加4聪,在已有入站流动性时接收免费,在钱包必须上链以腾出空间时接收的费用为1%加链上交易手续费,新建通道的费用为1,000聪。提供 offer 而不是发票,并不影响上述任何数字。它省去的是为每位付款方生成新二维码的步骤,而不是有人为流动性付费的步骤。

隐私方面的好处是真实的,但范围有限。闪电地址会把每次发票请求经由某个域名下的网络服务器转发,该运营方能看到金额和时间。offer 则以洋葱消息的形式经闪电网络转发请求,offer_paths 让通道全部为私有的节点无需公布节点 ID 也能保持可达。但这并不能让您对自己的服务商保密:本站的 Phoenix 评测引用了 ACINQ 的常见问题,其中明确说明它知道付款的最终目的地和金额。

实际使用中的提醒与粘贴有关。交易所的提币框要求填写闪电发票,而 lno1 字符串不是发票。Strike 是此处63家交易所记录之一,原生支持闪电网络,在超过100个国家的转账不收取自身的手续费,正是这类流程容易让人混淆两种格式。本站的41款钱包评测和63家交易所记录目前都没有把对 offer 的支持记录为一项功能,因此请在您自己钱包的发行说明中确认,不要想当然。

帽子摊的 offer 及其变成的发票

一个以25美元一顶出售帽子的摊位,写了一个 offer,offer_currency 设为 USD,offer_amount 设为2500。

这是规范对比特币以外的货币所定的规则:使用三个字母的 ISO 4217代码,金额以按 ISO 4217指数调整后的货币单位表示,对美元而言就是美分。只要设置了 offer_amount,offer_description 就是必填项,因为被收取具体费用的付款方必须知道这笔费用是什么。如果还剩三顶帽子,offer_quantity_max 为3,如果摊位没有固定上限,则为0。明确允许值为1,尽管看起来有些别扭,这样库存系统就不需要为最后一件商品设置特殊情况。offer_issuer 可以写成 hats@example.com Hat Stall,因为规范要求先写域名,空格之后可以是任何便于识别的文字。

您的钱包读取后,向您报价25美元,并发送 invoice_request,其中 invreq_quantity 为2(两顶帽子)、一个 invreq_payer_id,另可选择附带 invreq_payer_note。返回的是一张发票,包含支付哈希、创建时间戳、至少一条盲化路径,以及每条路径的费用报价,涵盖基础手续费、比例手续费、CLTV delta 以及其可承载的最小和最大 HTLC。这里有两条规则保护您。如果0至159范围内的任何字段与您所发送的不一致,您的钱包必须拒绝该发票;如果毫聪金额与 offer 给出的美元估值相差较大,钱包必须向您发出警告。除非发行方设置了 invoice_relative_expiry,否则发票必须在创建后7200秒被拒绝。

BOLT12 offer vs BOLT11 发票

BOLT12 offer 是对收款请求的请求;BOLT11 发票才是收款请求本身。

BOLT12 的文本开头列出了对其前身的八项不满,付款方能感受到的是以下几项。BOLT11 发票作为一个整体签名,因此要证明其中一个字段就必须披露全部字段。规范认为其人类可读的金额问题多多:p 乘数经常被误处理,而以皮比特币计数比以聪计数更困难。它的 payment_secret 只有在发票仅在付款方和收款方之间保持私密时才能阻止探测,而公开发布的发票并非如此。而且,用规范自己的话说,发票必须按用户分别提供,如果为同一用户发起两次付款尝试则有实际危险。offer 通过根本不是发票,解决了这四个问题。

BOLT12 offer vs 闪电地址

BOLT12 offer 是一个自包含的字符串;闪电地址是一个由他人的服务器为您解析的名称。

两者都可重复使用,因此容易混淆。闪电地址依赖域名、证书和一个让服务持续运行的运营方,三者中任何一个失效,它就失效。offer 只依赖双方节点支持洋葱消息,别无其他,故障面更小,不过您需要确认自己的钱包支持,而不是想当然。闪电地址的优势在于可以口头说出。很长的 lno1 字符串是二维码,而不是可以对着麦克风念出来的东西。

请勿混淆

常见问题

我可以多次支付同一个 BOLT12 offer 吗?

可以,这正是它的意义所在。每次支付都会发起一次新的发票请求,因此同一个 lno1 字符串每次都会生成一张带有全新支付哈希的新发票。BOLT11 发票做不到这一点,因为它锁定的是单个支付哈希,一旦原像被披露,该哈希即告用尽。

BOLT12 offer 与闪电地址有何区别?

offer 是一个自包含的字符串,不需要任何 Web 服务器;而闪电地址是一个名称,您的钱包需要通过 HTTPS 在他人的域名上对其进行解析。两者都可重复使用。域名或其运营方失效之日,地址即不能再用;而如果任一节点不支持洋葱消息,offer 就不能再用。

BOLT12 offer 可以用美元或欧元计价吗?

可以。offer 将 offer_currency 设为三个字母的 ISO 4217代码,并以该货币的最小单位设置 offer_amount,因此25美元写作2500。该数字只是参考:发行方在生成发票时会将其换算为毫聪,如果发票金额与该估算值相差较大,您的钱包必须向您发出警告。

为什么 BOLT12 offer 不带签名?

因为签名不会带来任何好处,反而增加长度。offer 中除签名外的每个字段都会被复制到随后的发票请求中,因此被篡改的 offer 只会导致无法生成发票;省去签名则可使字符串足够短,在低端摄像头上也能通过二维码扫描。

接着阅读

相关术语

闪电网络与 Layer 2中的更多术语

阅读本页英文版