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

OP_CHECKSIG是用于验证ECDSA签名的操作码。它从堆栈中获取两个输入:一个是公钥(在堆栈顶部);一个是ECDSA签名,该签名的DER_CANONISED格式与签名标志连接。对签名的检验是通过还是失败,对应在堆栈上输出TURE或FALSE。
OP_CHECKSIG的参数
除了堆栈参数,OP_CHECKSIG还需要
- 当前交易TXcurrent;
- 签名被检查的交易输入的索引i;
- 这个OP_CHECKSIG所属的scriptPubKey属于previousScriptPubKey;
- outpoint中的值(以聪为单位):amout.
请注意,previousScriptPubKey来自先前交易,那个交易里的输出在当前的交易里将被花费。
运行原理
简而言之,OP_CHECKSIG会调用一个名为“sighash”的函数,该函数会生成序列化的交易的哈希值。此哈希值是一段信息,它表明哪个签名需要被验证。验证所需要的签名和公钥是从堆栈中获取的。
具体方法:
- 检查堆栈大小是否不小于2。
- 公钥和签名作为栈顶的2项弹出。
- 检查签名编码的格式是否正确[<DER signature><hashtype>]。一个例子:47304402205a2b556c71ee1c12d8e0b460c3446aeca0e3ee71b7bc11c6ddd3da8beeec99c60220783a1f0c0158674df8904022ec30fab5154c4fc4c7e8467086f0204cc8e16cbb01,其中47是用十六进制表示的字节数(用十进制表示字节数为71),接下来的46个字节(这是十六进制表示的字节数,如果用十进制表示是70字节)是ECDSA签名(R,S),最后1个字节是签名标识,在这个例子中,使用的是“ALL”。
- 检查公钥编码格式是否正确。压缩的公钥和未压缩的公钥都可以接受。一个例子:210220798b9772a8ae06d13027e6f501d09ea07f6dfc4b7afc3db3a6d6c57bf24239,其中21表示公钥的十六进制字节数,02表示这是一个压缩的公钥,且公钥的y轴坐标是偶数。剩余部分是公钥的x轴坐标。请注意,如果第二个字节是04,则表示公钥是未压缩的形式。
- 一个新的脚本在previousScriptPubKey的基础上创建,该子脚本从最近的 OP_CODESEPARATOR(此处执行的 OP_CHECKSIG 之前的那个OP_CODESEPARATOR)开始,到previousScriptPubKey的末端结束。如果没有OP_CODESEPARATOR,则整个previousScriptPubKey就成为了子脚本。
- 从子脚本中删除所有剩余的OP_CODESEPARATORS。
- 根据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字节小端)。
- 上述步骤中以字节为单位的序列化数据将被输入到double SHA256函数中以生成一段32字节的消息。此消息连同公钥和堆栈中获得的签名,共同用于检验ECDSA签名的有效性。请注意,我们使用secp256k1椭圆曲线对给定的公钥进行验证。
返回值
如果检查通过,OP_CHECKSIG会从堆栈中返回true,若未通过则返回false。 OP_CHECKSIGVERIFY不会在堆栈上留下任何内容,但如果检查未通过,则会导致脚本验证立即失败。
参考资料
https://github.com/bitcoin-sv/bitcoin-sv/blob/master/src/script/interpreter.cpp