协议演进 / BIP/比特币改进提案 / BIP-120

BIP-120 付款证明

定义 Proof of Payment:用与原支付交易相同的输入重新签名一笔永不上链的特殊交易,以证明自己确实付过款。本 BIP 目前处于已关闭状态。

一、档案卡

档案卡
编号BIP-120
标题Proof of Payment
作者Kalle Rosenbaum <[email protected]>
指定日期2015-07-28
层级Applications(应用)
类型Specification(规范类)
状态Closed(已关闭)
阅读版https://bips.dev/120
官方原文https://github.com/bitcoin/bips/blob/master/bip-0120.mediawiki

二、放在哪一族

应用层的支付凭证族。它与 BIP-70(支付协议)相邻:支付协议解决“怎么付得明白”,BIP-120 解决“付完之后怎么向第三方证明我付过”。

它还有一个配套文档:请求如何送达钱包,由 BIP-121 的 btcpop: URI 方案单独规定,本 BIP 只管证明本身的数据结构、流程与验证。更早的替代思路——用付款私钥签服务器指定的消息——没有被标准化,也难以覆盖 P2SH 等脚本类型;本提案刻意把证明做成一笔“交易形状”的对象,好让各种脚本类型一视同仁。

三、它要解决什么

3.1 付款之后需要一张“收据”

原文列举的场景都指向同一件事:付款本身即凭证,不必再引入用户名、密码、邮箱等个人信息——

3.2 当时办法为什么不够

原文盘点了既有做法。BIP-70 的 PaymentRequest 加上履行它的交易勉强算证明,但只能用于经 BIP-70 付的款,且没有标准的请求/出示方式。用付款私钥签消息可以按需生成、防复用,但未标准化,且难以覆盖所有脚本类型。

原文为付款证明定下五条目标性质:按需生成;只能用一次(防被盗后复用);对任何脚本类型的付款都能生成(P2SH、P2PKH 等);能证明持有解锁原交易全部输入所需的凭证;钱包与服务器都容易实现。

对多签还有一条细则:P2SH 的 M-of-N 只要求任一组合法的 M 把密钥即可,不必是当初实际签名的那 M 把——否则多签的意义就被证明环节抵消了。

四、规则本身

4.1 PoP 的数据结构

交易 T 的付款证明 PoP(T) 与一笔比特币交易结构完全相同:输入与 T 相同、同序,但每个输入的 sequence 号一律置 0;输出恰好一个,金额为 0,格式为:

OP_RETURN <version> <txid> <nonce>

其中 version 为 2 字节小端(当前为 0x01 0x00),txid 为 32 字节的被证明交易,nonce 为 6 字节随机数据。

PoP 的 lock_time 必须设为 499999999,使其即便误入比特币 P2P 网络也无法被打包进区块;sequence 全置 0 正是为了让这个 lock_time 生效(若为 0xffffffff,lock_time 会被忽略)。PoP 用与普通交易相同的签名流程签署。nonce 由服务器为每次请求新生成,证明一旦送达服务器即作废,偷到的证明无法再用。

4.2 流程

  1. 服务器向钱包发出 PoP 请求,含:随机 nonce、PoP 的回送目的地(如 https URL)、帮助钱包定位交易的提示(如已知的 txid、BIP-70 的 merchant_data、或 BIP-21 URI 中的金额/标签/消息);
  2. 钱包据提示找出交易 T,找不到唯一答案时让用户在匹配项中选;
  3. 钱包造出未签名的 PoP 并请用户确认签名;
  4. 签名后把 PoP 发往请求中给定的目的地;
  5. 服务器验证并回复 “valid” 或 “invalid”,钱包把结果展示给用户。

请求本身如何传输不在本 BIP 范围内,见 BIP-121。

4.3 服务器如何验证

任一步失败即判 invalid:格式须通过常规交易检查(输入已花费除外);lock_time 须为 499999999;输出须恰好一个、金额 0 且符合上述 OP_RETURN 格式;nonce 须与本次请求的相同;输入须与 T 完全一致、同序,唯 sequence 全为 0;逐一运行全部输入脚本,结果须全为真;输出中的 txid 须确为要证明的那笔交易(或核对该交易确实购买了所交付的商品/服务)。

4.4 安全注意事项

原文提醒:PoP 请求的任何参数都可能被中间人篡改(改回送地址偷证明、改标签骗签、改 nonce 使验证失败),应使用安全连接,且签名之前务必核对。被盗 PoP 被暴力试中的概率为每次 1/2^48,服务器应有防爆破机制或适当延迟。另外,即便钱包已无余额,它仍能生成 PoP,空钱包的安全也不能松懈;交易可锻性可能使服务器与钱包记录的 txid 不一致,钱包应以网络上实际出现的交易为准。

五、谁必须动

普通持币人:无协议层面变化。只在使用支持 PoP 的钱包向支持 PoP 的服务付款时,才会多一步“确认签一份证明”。

钱包开发者:需实现按提示定位交易、构造并签署 PoP、发送并展示结果;签名前的核对提示不可省略。

服务端开发者:需实现生成 nonce、接收 PoP、按 4.3 逐项验证并防爆破。

全节点与矿工/共识层:完全不动。PoP 不改变比特币协议,lock_time 的设计恰恰保证它不会被打包上链;它只借用交易与脚本验证的既有 machinery 在链下核验证明。

六、现在算不算数,以及一个常见误读

状态为 Closed(已关闭)。原文附有演示服务器与支持 PoP 的 Mycelium 分支钱包作为参考实现,但该方案没有成为比特币生态通行的付款凭证标准;今天向商家证明付款,通常仍靠交易在链上的确认本身,而不是出示一笔 PoP。

常见误读:“付款证明是一笔真的付款,会再花一次钱。”不对。PoP 的输出金额为 0、lock_time 设为 499999999、sequence 全置 0,它被设计为永远不能上链成交;它复用原交易的输入只是为了证明“能解锁这些输入的凭证在我手里”,不构成第二次支付。

七、延伸

本页内容整理自 bitcoin/bips 仓库与 bips.dev,事实已与仓库核对;解读仅供学习参考。