BOLT 12 是在 Lightning Network 上协商付款的协议。它区分报价 offer、发票请求 invoice_request 和最终发票 invoice。报价可以持续公开供多次付款使用,而每张发票规定当前这笔付款的具体条件。
想象一家咖啡馆希望在柜台放一个二维码,供顾客自愿捐助。重复支付同一张普通 BOLT 11 发票会带来问题。BOLT 12 改为公开 offer。顾客的钱包据此发送 invoice_request,请求自己的发票,收款方再回复一张新的 invoice,然后才能付款。这样,一个印好的二维码就能服务不同的人,而不必让大家支付同一张发票。取得发票,例如调用 fetchinvoice,并没有发送资金。报价本身也不授权咖啡馆继续从别人的钱包中扣钱。 [1] [3] [4]
报价可以用比特币,也可以用其他货币定价。offer_currency 字段采用 ISO 4217 代码,例如 USD 金额以美分表示。生成发票时,购买数量和汇率换算都可能影响价格。但最终的比特币 invoice_amount 以 millisatoshi 表示,也就是 satoshi 的千分之一:1000 msat = 1 sat。付款前,付款人需要知道这个金额和手续费,而不只是原先的价签。如果请求指定了确切的 invreq_amount,发票金额就必须一致。否则,钱包应检查授权范围,超出范围时应重新征求同意。货币换算不应变成对任意价格的无声授权。 [1] [3]
印好的代码可以留在柜台,但报价本身也能通过 offer_absolute_expiry 设定截止时间。每张发票还有自己的创建时间 invoice_created_at 和有效时长 invoice_relative_expiry。没有后一个字段时,默认是 7200 秒,即两小时。因此,旧发票不是永久有效的联系方式。钱包还必须理解消息要求的必需功能。未知的偶数位表示必需功能,需要拒绝;未知的奇数位为可选功能,可以忽略。这是在保障兼容性,不是让用户手动改写代码去绕过的障碍。 [1]
付款后,应保存发票和钱包给出的结果。结算证据还包括 preimage,即付款完成时获得的秘密值。钱包根据这个值计算哈希,也就是用于核对的校验值,再与发票中的支付哈希比较。结合发票,这可以证明发票已支付,但不能单独确定是哪个人付的钱。如果应用断线或丢失回复,重试前先查上一笔付款的状态;新发票可能导致再次付款。对“定期付款”的宣传也要这样区分。支持 BOLT 12 并不自动等于支持所有扩展,更不等于允许自动扣款。要分别确认钱包能否通过报价收款、能否支付别人的报价,以及你给连接的应用授予了哪些权限。 [1] [3]
请求发票和转移资金使用网络的目的不同。offer_paths 指定请求消息的路径,invoice_paths 则提供付款路径。BOLT 12 使用 blinded paths,也就是隐藏部分收款方连接信息的路径。减少网络结构信息的公开有助于隐私,却不承诺完全匿名。隐藏路径也不保证收款方在线,或具有足够的流动性——即支付通道所需一侧有足够资金。技术上,当前 invoice 必须包含这些路径和对应的 invoice_blindedpay 支付参数,即使路径直接通向收款方也是如此。请求发票不需要传统的 HTTPS 支付服务器。 [1] [2]
商家想给顾客退款时,协商方向会反过来。准备付款的一方可以在没有先前 offer 的情况下公开 invoice_request。顾客作为未来收款方,用自己的 invoice 回复,再由商家支付。这不是删除或撤销原付款,而是一笔方向相反的新付款。商家必须确认发票属于预期收款方,有时需要在协议之外沟通。仅仅扫描请求,既不能证明退款资格,也没有批准转账。技术流程只是帮助沟通,并不替双方决定钱该退给谁。 [1]
BOLT 12 用 TLV 保存数据:每个字段说明类型、长度和值。文本报价以 lno 开头,请求以 lnr 开头。字符集看起来像 Bech32,但没有它末尾的校验和。单凭这点,无法判断谁应当收款。Offer 本身没有签名。BIP340 Schnorr 数字签名用于验证发票以及回应报价的普通请求。没有先前报价而单独公开的请求,例如用于退款的请求,不包含签名。签名对应 Merkle 结构的根,即根据相关字段共同计算出的校验值。因此,可以证明选定字段而不必每次公开所有细节。这并不允许修改已签名条件,也不证明商家的法定身份。 [1]
钱包必须确认收到的是自己请求的回复,而不只是某张签名有效的发票。它会比对从 invoice_request 复制到 invoice 的字段,并检查网络、金额和签名。invoice_node_id 公钥应与 offer_issuer_id 一致;如果报价没有该标识而改用相应的隐藏路径,则核对该路径末端的 blinded_node_id。这就像检查账单是不是你这一桌的,而不只是看印章是否真实。Merkle 结构支持对选定信息的证明,却不能免除钱包检查付款所需全部条件的责任。别人的有效发票不会因为通过签名检查就变成正确的那一张。 [1]
要获得更完整的理解,请将本词条与以下词条结合阅读: BOLT 11, Lightning Network, Lightning Routing, Bitcoin 隐私, Satoshi, LNURL. 反向关联还来自: BOLT 11, LNURL, Just-in-Time Channels.