术语表 /开发者参考
OP_EQUALVERIFY
- OP_EQUALVERIFY 是什么?
- OP_EQUALVERIFY 比较栈顶的两个元素,若二者不同则立即终止脚本,传统(legacy)支出正是以此证明其出示的公钥无误。
字节0x88 是比特币最古老的脚本模板中间的检查点。比较通过时它不留下任何东西,失败时则使执行当场停止,因此,提供了错误密钥的输入不会产生一笔失败的付款,而是产生一笔任何节点都不会转发的无效交易。您的钱包究竟有没有用正确的密钥签名,通常就在这里见分晓。
运作方式
OP_EQUALVERIFY 从栈中取出两个元素,逐字节比较,然后要么悄无声息地继续,要么终止脚本。
在传统支出中执行到它时,栈中有两个20字节的字符串。一个是币到账时(可能是多年以前)该输出所承诺的指纹,另一个是支出方刚刚提供的公钥的指纹。这20个字节中只要有一位不同,评估即告结束,且无法挽回:Bitcoin Script 没有异常处理,也没有第二次机会。
成功时它不会向栈中压回任何内容。这正是存在这种合并形式的全部原因,也是25字节的 pay-to-public-key-hash 脚本能以签名检查结尾、而不必留下一个无人需要的布尔值的原因。Bitcoin Core 的解释器按字面实现了这种合并:先运行比较的分支,再顺势进入通用的断言分支,因此两者是同一条代码路径,而不是两条相似的路径。
这一模式在整个语言中反复出现。每个合并的 VERIFY 操作码的字节值都恰好比其对应的普通操作码大1:相等性检查是0x87 和0x88,签名检查是0xac 和0xad,旧式多重签名操作码是0xae 和0xaf。当某个条件必须先成立、其他事情才能发生时,脚本作者就会选用较高的那个字节。
在哪里会遇到它
遇到 OP_EQUALVERIFY 最清楚的地方是一条拒绝信息,而不是区块浏览器。
如果广播一笔用与地址不匹配的密钥签名的交易,Bitcoin Core 会返回 mandatory-script-verify-flag-failed,并在随后的括号中指明失败的 OP_EQUALVERIFY 操作。实际上,这个错误几乎总是意味着一件事:签名设备所派生的密钥,来自与持有这些币的路径或种子不同的另一条路径或另一个种子。用错误的派生路径恢复钱包再尝试支出,产生的正是这种情况。
解码后的脚本也能清楚地显示它。任何支付到以1开头的地址的输出,都会呈现为一个由五个标记组成的脚本,这个操作码排在第四位,而 bitcoin-cli decodescript 对您粘贴的赎回脚本会打印出相同的汇编。
OP_EQUALVERIFY vs OP_VERIFY
OP_EQUALVERIFY 是附带了断言的特定检验,而 OP_VERIFY 只是断言本身。通用形式(字节0x69)并不知道它所检查的值是由什么产生的;它弹出一个元素,并要求该元素为真。OP_EQUALVERIFY 用一个字节同时完成比较和这一要求,因此二者很少被分开书写。当条件来自算术运算、时间锁检查,或不是单纯相等的原像检验时,请使用通用形式;只要问题确实是两个字节字符串是否一致,就使用合并形式,而在单密钥支出中情况始终如此。