跳转到正文
buybitcoinsmart

术语表 /开发者参考

签名脚本

又称 scriptSig、解锁脚本。

签名脚本是什么?
签名脚本是输入所携带的解锁数据,用于满足其所花费输出的公钥脚本,在现代 SegWit 输入中该脚本为空。

交易中的每个输入都指向一个先前的输出,并且必须证明自己有权花费它。Bitcoin Core 将这个字段称为 scriptSig;在传统的 pay-to-public-key-hash 输入中,它包含一个71或72字节的签名和一个33字节的公钥,合计约107字节。自 SegWit 起,这一证明通常存放在别处,这也是 bech32 提币手续费更低的主要原因。

运作方式

签名脚本先运行,并把结果留在栈上,供输出的脚本使用。两者并不是作为一个拼接起来的程序运行:它们按顺序依次执行,栈在两者之间传递,这种分离是在2010年原始设计被证明可被利用之后引入的。

转发策略要求该字段只包含数据推入。不得有条件语句,不得有算术运算,也不得有执行任何实际操作的操作码。之所以有这一限制,是因为花费者对这些字节拥有完全的控制权,若允许攻击者在输入时运行逻辑,就会重新带来网络早已解决的问题。Pay-to-script-hash 使这条规则成为共识要求,而不只是一种偏好,因为赎回脚本必须作为最后一个普通推入送达。

它的大小完全取决于所解锁的内容。传统的单密钥输入携带一个签名和一个密钥。嵌套 SegWit 输入恰好携带23字节,即对22字节见证程序的一次推入,其余内容全部放入见证数据。原生 bech32 或 bech32m 输入则什么都不携带:序列化后的字段只是一个表示长度为零的字节。

有一种输入的签名脚本并不用于证明任何事。币基交易的唯一输入没有可解锁的先前输出,因此该字段被改作自由空间,长度在2至100字节之间,并且自 BIP-34起必须以区块高度开头。自2009年以来,矿工一直在其中签署消息、投票和玩笑。

在哪里会遇到它

解码任意一笔交易,每个输入都会显示一个 scriptSig 对象,含汇编视图和十六进制视图。在原生 SegWit 或 Taproot 输入中,两者都是空字符串,而数据存放在另一个见证字段中,这种视觉上的不对称是一眼判断旧交易使用了哪种地址格式的最快方法。

它也解释了一段常被误读的历史。由于 scriptSig 被计入交易 ID,第三方可以在不使签名失效的情况下对其重新编码,从而改变已广播交易的 ID。Mt. Gox 于2014年2月暂停比特币提币,并将原因归咎于这种行为,但后来学术界对区块链的分析发现,被延展性篡改的交易数量远不足以解释丢失的币。SegWit 于2017年8月将解锁数据完全移出 ID 的计算,结束了这场争论。

签名脚本 vs 见证数据

签名脚本和见证数据携带的是同一种证明,SegWit 把这项工作从前者转移到后者,并没有改变签名的含义。对您而言,重要的差别在于价格和持久性。见证字节按每字节一个权重单位计费,而签名脚本字节为四个,因此同样的单密钥花费,证明放在 scriptSig 中时约为148虚拟字节,放在见证数据中时约为68虚拟字节。见证数据还位于交易 ID 之外,因此花费交易的标识符无法在传输途中被篡改。传统输入仍使用旧字段,所以存放在以1开头的地址上的币,每次转移时都会悄悄多花费用。

请勿混淆

常见问题

为什么我的 SegWit 交易中签名脚本是空的?

因为签名和公钥已移入见证字段,而该字段按四分之一的权重计费。bech32 输入上的 scriptSig 为空是正确且正常的,并不表示出了任何问题。

广播之后,别人能修改我的签名脚本吗?

在传统输入中,第三方曾可以对签名重新编码,在不使该笔花费失效的情况下改变交易 ID。SegWit 通过将解锁数据排除在标识符之外,消除了见证输入的这种可能性。

相关术语

开发者参考中的更多术语

阅读本页英文版