知识库详情
知识库

以“词条释义”的形式对比特币区块链技术中经常涉及的术语及基本概念进行专业化的阐释和解读。

OP_CHECKSIG
返回上级
BSV区块链编辑 2022-04-14 18:21 61

OP_CHECKSIG是用于验证ECDSA签名的操作码。它从堆栈中获取两个输入:一个是公钥(在堆栈顶部);一个是ECDSA签名,该签名的DER_CANONISED格式与签名标志连接。对签名的检验是通过还是失败,对应在堆栈上输出TURE或FALSE。

OP_CHECKSIG的参数

除了堆栈参数,OP_CHECKSIG还需要

  1. 当前交易TXcurrent;
  2. 签名被检查的交易输入的索引i;
  3. 这个OP_CHECKSIG所属的scriptPubKey属于previousScriptPubKey;
  4. outpoint中的值(以聪为单位):amout.

请注意,previousScriptPubKey来自先前交易,那个交易里的输出在当前的交易里将被花费。

运行原理

简而言之,OP_CHECKSIG会调用一个名为“sighash”的函数,该函数会生成序列化的交易的哈希值。此哈希值是一段信息,它表明哪个签名需要被验证。验证所需要的签名和公钥是从堆栈中获取的。

具体方法:

  1. 检查堆栈大小是否不小于2。
  2. 公钥和签名作为栈顶的2项弹出。
  3. 检查签名编码的格式是否正确[<DER signature><hashtype>]。一个例子:47304402205a2b556c71ee1c12d8e0b460c3446aeca0e3ee71b7bc11c6ddd3da8beeec99c60220783a1f0c0158674df8904022ec30fab5154c4fc4c7e8467086f0204cc8e16cbb01,其中47是用十六进制表示的字节数(用十进制表示字节数为71),接下来的46个字节(这是十六进制表示的字节数,如果用十进制表示是70字节)是ECDSA签名(R,S),最后1个字节是签名标识,在这个例子中,使用的是“ALL”。
  4. 检查公钥编码格式是否正确。压缩的公钥和未压缩的公钥都可以接受。一个例子:210220798b9772a8ae06d13027e6f501d09ea07f6dfc4b7afc3db3a6d6c57bf24239,其中21表示公钥的十六进制字节数,02表示这是一个压缩的公钥,且公钥的y轴坐标是偶数。剩余部分是公钥的x轴坐标。请注意,如果第二个字节是04,则表示公钥是未压缩的形式。
  5. 一个新的脚本在previousScriptPubKey的基础上创建,该子脚本从最近的 OP_CODESEPARATOR(此处执行的 OP_CHECKSIG 之前的那个OP_CODESEPARATOR)开始,到previousScriptPubKey的末端结束。如果没有OP_CODESEPARATOR,则整个previousScriptPubKey就成为了子脚本。
  6. 从子脚本中删除所有剩余的OP_CODESEPARATORS。
  7. 根据sighash的类型调用序列化算法 (sighash)生成double SHA256的输入:
    • TXcurrent 里的nVersion (4 字节小端)。
    • 所有输入输出点序列化后的double SHA256(32字节的哈希值)。如果设置了ANYONECANPAY标识,那么此处应该是一个32字节的零。
    • 所有输入的nSequence序列化后的double SHA256(32 字节的哈希值)。如果设置了ANYONECANPAY标识,那么此处应该是一个32 字节的零。
    • 被花费的outpoint(32 字节的交易ID加4字节小端索引)。
    • 子脚本的字节长度(大端)。
    • 子脚本。
    • amount(8字节小端)。
    • 此输出点的nSequence(4字节小端)。
    • 使用scriptPubKey对所有输出量(8字节小端)进行序列化后的double SHA256(这些是TXcurrent中的输出)。如果设置了SINGLE系列的签名标识并且输入索引小于输出数量,那么此处应该是输出的double SHA256,其中scriptPubKey与输入具有相同的索引。如果设置了NONE系列的签名标识,那么此处应该是一个32字节的零。
    • 交易TXcurrent的nLocktime(4 字节小端)。
    • 签名的sighash类型(4字节小端)。
  1. 上述步骤中以字节为单位的序列化数据将被输入到double SHA256函数中以生成一段32字节的消息。此消息连同公钥和堆栈中获得的签名,共同用于检验ECDSA签名的有效性。请注意,我们使用secp256k1椭圆曲线对给定的公钥进行验证。

返回值

如果检查通过,OP_CHECKSIG会从堆栈中返回true,若未通过则返回false。 OP_CHECKSIGVERIFY不会在堆栈上留下任何内容,但如果检查未通过,则会导致脚本验证立即失败。

参考资料

https://github.com/bitcoin-sv/bitcoin-sv/blob/master/src/script/interpreter.cpp

脚本
False Return
脚本
Pushdata操作码
比特币脚本操作码
R-Puzzle脚本
OP_CHECKSIG
流控制脚本(条件语句)
OP_CODESEPARATOR
OP_RETURN