跳转到正文
buybitcoinsmart

术语表 /交易与手续费

SIGHASH_SINGLE

SIGHASH_SINGLE 是什么?
SIGHASH_SINGLE 是将签名仅与一个输出绑定的标志,该输出在列表中的位置与被签名输入的位置相同。

输入0与输出0配对,输入1与输出1配对,交易中的其余部分均不签名。这一设计让多方可以在同一笔共享交易中,各自保证自己的收款。它同时带有比特币最臭名昭著的签名漏洞,而旧版输入中仍然存在这一漏洞。

运作方式

摘要保留被签名的输入、交易版本、锁定时间,以及恰好一个输出:索引与该输入的索引一致的那个输出。

该索引之后的输出在计算哈希之前会从副本中移除。该索引之前的输出作为占位保留,但内容被清空,金额设为负一,脚本为空,因此其真实内容同样不在签名覆盖范围之内。所有其他输入的序列号被置零,与无输出标志下的处理相同。

接下来就是那个漏洞。在原始算法中,如果被签名输入的索引大于或等于输出的数量,就没有可供计算哈希的匹配输出。代码并不报错,而是返回一个固定的摘要:32字节的数值1。落在这个位置的每一位签名者,都会对完全相同的摘要生成签名,因此该签名不与任何特定交易绑定,任何能够安排一个输入处于相同索引的人都可以提取并重放它。这一分支至今仍保留在 Bitcoin Core 中,因为删除它会改变已在链上的币的有效性。

签名哈希算法的两次重写都堵上了这一漏洞。BIP143 规定,对于没有匹配输出的隔离见证版本0输入,摘要中的输出部分为32个零字节,而摘要的其余部分仍然承诺该特定输入,因此无法重放。BIP341 则更进一步:在 Taproot 输入上,这种类型的签名如果索引超出输出数量,验证会直接失败。

在哪里会遇到它

该标志在签名末尾表现为 03,您几乎只会在预签名的报价中见到它,而不是在普通付款中。

其模式是将半笔交易作为邀约发布。卖方签署这样一条声明:“我的这个输入加入交易,且索引相匹配的输出向我支付我的要价”,然后将交易的其余部分留空,供买方填写。由于卖方的签名不涵盖其他所有输入和输出,买方可以加入自己的资金、自己的找零,以及按内存池要求的费率设定的手续费,而卖方的保障依然成立。Ordinals 和符文市场正是建立在这一机制之上,以 PSBT 的形式分发,这也是比特币在没有任何第三方居中的情况下支持的少数真正无需信任的交易之一。

它几乎总是与 ANYONECANPAY 搭配使用,因为单独使用时,该标志仍然承诺完整的输入列表,这就违背了将交易留给他人完成的初衷。

SIGHASH_SINGLE vs SIGHASH_ANYONECANPAY

SIGHASH_SINGLE 是基础模式,SIGHASH_ANYONECANPAY 是修饰符,二者回答的是不同的问题。基础模式决定签名覆盖输出一侧的多少内容:全部、无,或一个匹配的输出。修饰符决定签名覆盖输入一侧的多少内容:所有输入,或仅被签名的那一个。您先选择一种基础模式,再另行决定是否加上修饰符,因此实际签名上的标志字节通常是二者之和,而不是其中任何一个。

请勿混淆

常见问题

SIGHASH_SINGLE 漏洞是什么?

在原始签名算法中,输入索引没有匹配的输出时,不会报错,而是生成一个数值为1的固定摘要。针对该摘要的签名不与任何交易绑定,他人可以重复使用,因此钱包绝不能在这一位置签名。

该漏洞目前仍可被利用吗?

仅限旧版输入,它们仍运行原始算法。隔离见证输入遵循 BIP143,改为对零字节计算哈希,而 Taproot 输入则依据 BIP341 直接拒绝这种情况,因此存放在 bc1 地址中的币不受影响。

相关术语

交易与手续费中的更多术语

阅读本页英文版