scriptSig
即解锁脚本, 是交易输入里面, 用来证明自己所有权一个私钥签名scriptPubKey
即锁定脚本, 即上一笔交易输出(本次交易的输入)里面用来锁定所有权的字节序列
OP_CHECKSIG
is Script opcode used to verify that the signature for a tx input is valid. OP_CHECKSIG
expects two values to be on the stack. These are, in order of stack depth, the public key and the signature of the script. These two values are normally obtained by running the scriptSig
script of the transaction input we are attempting to validate. The scriptSig
script is deleted after it is run, but the stack is left as is. Then, the scriptPubKey
script from the previous transaction output that is now being spent is run, generally concluding in an OP_CHECKSIG
.
The standard scriptPubKey
checks that the public key (actually a hash of) is a particular value, and that OP_CHECKSIG
passes.
花费者需要能给 ScriptPubKey 提供一个恰当的签名, 就认为这个花费者有权使用此输出.
For normal transaction inputs, if the creator of the current transaction can successfully create a ScriptSig signature that uses the right public key for the ScriptPubKey of the transaction output they are attempting to spend, that transaction input is considered valid.
作为栈的辅助参数, 我们需要知道当前交易以及当前交易输入中的索引(index).
In addition to the stack parameters and the script code itself, in order to operate correctly OP_CHECKSIG
needs to know the current transaction and the index of current transaction input.
Firstly always this (the default) procedure is applied:
- 公钥和签名从栈中依次弹出, 签名格式为
<DER signature> <1 byte hash-type>
. 签名最后一字节是签名格式. - 脚本剩余的部分, 从
OP_CODESEPARATOR
开始往后知道脚本结束部分作为子脚本, 如果没有OP_CODESEPARATOR
, 整个脚本就是子脚本. 子脚本记做subScript
(A new subscript is created from the instruction from the most recently parsedOP_CODESEPARATOR
(last one in script) to the end of the script. If there is noOP_CODESEPARATOR
the entire script becomes the subscript (hereby referred to as subScript)) - 从子脚本里面删除签名(如果有的话).
- 从子脚本里面移除所有的
OP_CODESEPARATORS
- 签名最后一字节类型标记被移除, 并保存.
- 复制当前交易, 记做: txCopy.
- txCopy 里面所有交易的 script, 都置为空(准确说是 1 字节 0x00)
- txCopy 里面当前交易的 input 脚本被设定为 subScript, 前缀
var-integer
长度
Now depending on the hashtype various things can happen to txCopy, these will be discussed individually.
Name | Value |
---|---|
SIGHASH_ALL |
0x00000001 |
SIGHASH_NONE |
0x00000002 |
SIGHASH_SINGLE |
0x00000003 |
SIGHASH_ANYONECANPAY |
0x00000080 |
If (hashtype&31) = SIGHASH_NONE
then apply the SIGHASH_NONE-procedureIf (hashtype&31) = SIGHASH_SINGLE
then apply the SIGHASH_SINGLE-procedureIf hashtype & SIGHASH_ANYONECANPAY
then apply the SIGHASH_ANYONECANPAY-procedure
于是, SIGHASH_ANYONECANPAY
程序可能被添加到任何其他的 hashtype, 上述四个 hashtype 之外还有一个 0 类型, 在主链中出现过几次, 他们的处理和 SIGHASH_ALL
一致
No special further handling occurs in the default case. Think of this as "sign all
of the outputs." Which is already done by the default procedure.
- txCopy 的输出被设定成一个空数组
- 非当前输入索引对应的输入的 nSequence 被设置为 0.
Think of this as "sign none
of the outputs-- I don't care where the bitcoins go."
- txCopy 的输出, 北条征程 index + 1 大小
- 输出序列里面, 索引不是 index 的输出, 设置成空脚本和一个 long 类型的 -1 值(
TransactionOutput
的 default 值) - 输入的数据, 索引不是 index 的, nSequence 被设置为 0
Think of this as "sign one
of the outputs-- I don't care where the other outputs go".
The transaction that uses
SIGHASH_SINGLE
type of signature should not have more inputs than outputs. However if it does (because of the pre-existing implementation), it shall not be rejected, but instead for every "illegal" input (meaning: an input that has an index bigger than the maximum output index) the node should still verify it, though assuming the hash of 0000000000000000000000000000000000000000000000000000000000000001 [https://bitcointalk.org/index.php?topic=260595.0]
- The txCopy input vector is resized to a length of one.
- The subScript (lead in by its length as a var-integer encoded!) is set as the first and only member of this vector.
Think of this as "Let other people add inputs to this transaction, I don't care where the rest of the bitcoins come from."
===Final signature check===
An array of bytes is constructed from the serialized txCopy appended by four bytes for the hash type. This array is sha256 hashed twice, then the public key is used to check the supplied signature against the hash. The secp256k1 elliptic curve is used for the verification with the given public key.
== Return values ==
OP_CHECKSIG will push true to the stack if the check passed, false otherwise. OP_CHECKSIG_VERIFY leaves nothing on the stack but will cause the script eval to fail immediately if the check does not pass.
== Code samples and raw dumps ==
Taking the first transaction in Bitcoin which is in block number 170, we would get after serialising the transaction but before we hash+sign (or verify) it:
- http://blockexplorer.com/block/00000000d1145790a8694403d4063f323d499e655c83426834d4ce2f8dd4a2ee
- http://blockexplorer.com/tx/f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16
See also [https://gitorious.org/libbitcoin/libbitcoin libbitcoin] for code samples.
01 00 00 00 version 01 number of inputs (var_uint) input 0: c9 97 a5 e5 6e 10 41 02 input address hash fa 20 9c 6a 85 2d d9 06 60 a2 0b 2d 9c 35 24 23 ed ce 25 85 7f cd 37 04 00 00 00 00 input index 48 size of script (var_uint) 47 push 71 bytes to stack 30 44 02 20 4e 45 e1 69 32 b8 af 51 49 61 a1 d3 a1 a2 5f df 3f 4f 77 32 e9 d6 24 c6 c6 15 48 ab 5f b8 cd 41 02 20 18 15 22 ec 8e ca 07 de 48 60 a4 ac dd 12 90 9d 83 1c c5 6c bb ac 46 22 08 22 21 a8 76 8d 1d 09 01 ff ff ff ff sequence 02 number of outputs (var_uint) output 0: 00 ca 9a 3b 00 00 00 00 amount = 10.00000000 43 size of script (var_uint) script for output 0: 41 push 65 bytes to stack 04 ae 1a 62 fe 09 c5 f5 1b 13 90 5f 07 f0 6b 99 a2 f7 15 9b 22 25 f3 74 cd 37 8d 71 30 2f a2 84 14 e7 aa b3 73 97 f5 54 a7 df 5f 14 2c 21 c1 b7 30 3b 8a 06 26 f1 ba de d5 c7 2a 70 4f 7e 6c d8 4c ac OP_CHECKSIG output 1: 00 28 6b ee 00 00 00 00 amount = 40.00000000 43 size of script (var_uint) script for output 1: 41 push 65 bytes to stack 04 11 db 93 e1 dc db 8a 01 6b 49 84 0f 8c 53 bc 1e b6 8a 38 2e 97 b1 48 2e ca d7 b1 48 a6 90 9a 5c b2 e0 ea dd fb 84 cc f9 74 44 64 f8 2e 16 0b fa 9b 8b 64 f9 d4 c0 3f 99 9b 86 43 f6 56 b4 12 a3 ac OP_CHECKSIG 00 00 00 00 locktime 01 00 00 00 hash_code_type (added on) result = 01 00 00 00 01 c9 97 a5 e5 6e 10 41 02 fa 20 9c 6a 85 2d d9 06 60 a2 0b 2d 9c 35 24 23 ed ce 25 85 7f cd 37 04 00 00 00 00 43 41 04 11 db 93 e1 dc db 8a 01 6b 49 84 0f 8c 53 bc 1e b6 8a 38 2e 97 b1 48 2e ca d7 b1 48 a6 90 9a 5c b2 e0 ea dd fb 84 cc f9 74 44 64 f8 2e 16 0b fa 9b 8b 64 f9 d4 c0 3f 99 9b 86 43 f6 56 b4 12 a3 ac ff ff ff ff 02 00 ca 9a 3b 00 00 00 00 43 41 04 ae 1a 62 fe 09 c5 f5 1b 13 90 5f 07 f0 6b 99 a2 f7 15 9b 22 25 f3 74 cd 37 8d 71 30 2f a2 84 14 e7 aa b3 73 97 f5 54 a7 df 5f 14 2c 21 c1 b7 30 3b 8a 06 26 f1 ba de d5 c7 2a 70 4f 7e 6c d8 4c ac 00 28 6b ee 00 00 00 00 43 41 04 11 db 93 e1 dc db 8a 01 6b 49 84 0f 8c 53 bc 1e b6 8a 38 2e 97 b1 48 2e ca d7 b1 48 a6 90 9a 5c b2 e0 ea dd fb 84 cc f9 74 44 64 f8 2e 16 0b fa 9b 8b 64 f9 d4 c0 3f 99 9b 86 43 f6 56 b4 12 a3 ac 00 00 00 00 01 00 00 00
To understand where that raw dump has come from, it may be useful to examine tests/ec-key.cpp in [https://gitorious.org/libbitcoin/libbitcoin libbitcoin],
[https://gitorious.org/libbitcoin/libbitcoin libbitcoin] has a unit test under tests/ec-key.cpp (make ec-key && ./bin/tests/ec-key). There is also a working OP_CHECKSIG
implementation in src/script.cpp under script::op_checksig(). See also the unit test: tests/script-test.cpp
==References==
[[Category:Technical]] [[Category:Developer]] {{DISPLAYTITLE:OP_CHECKSIG}}