协议演进 / 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 流程
- 服务器向钱包发出 PoP 请求,含:随机 nonce、PoP 的回送目的地(如 https URL)、帮助钱包定位交易的提示(如已知的 txid、BIP-70 的 merchant_data、或 BIP-21 URI 中的金额/标签/消息);
- 钱包据提示找出交易 T,找不到唯一答案时让用户在匹配项中选;
- 钱包造出未签名的 PoP 并请用户确认签名;
- 签名后把 PoP 发往请求中给定的目的地;
- 服务器验证并回复 “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,它被设计为永远不能上链成交;它复用原交易的输入只是为了证明“能解锁这些输入的凭证在我手里”,不构成第二次支付。
七、延伸
- 阅读版:https://bips.dev/120
- 官方原文:https://github.com/bitcoin/bips/blob/master/bip-0120.mediawiki
- 相关:BIP-121 付款证明 URI 方案、BIP-70 支付协议、BIP-21 URI 方案
- 仓库总目录:https://github.com/bitcoin/bips
