在前一篇博客中,我们介绍了比特币签名机制的基础知识。本篇博客我们将从原理层介绍签名流程。下一篇博客从btcd
源码层面讲解签名流程。
III. 签名流程——原理层
正如我们在第II节中所述,比特币主要包含6种组合签名类型。对应于每一种签名类型,签名的流程也不同。 本节将针对两大类(无修饰类和有修饰类)进行分别介绍。对于每一大类,也将首先讲解各种签名类型下共有的一些签名流程,然后按小节分别讲解每一种签名类型种特有的流程。 本节主要从原理层面进行介绍,下一节将展示对应的源码实现。 此外,需要声明的是,本小节使用到的多幅图片都摘自电子书Bitcoin Developer Reference的III.E节。
A. 无修饰类
本小节首先介绍无修饰类中一些共有的签名流程。 如上篇博客中的II.B小节所述,无修饰类中的message
是包含了所有input
的。但这里的包含并不是简单直接的包含,而是对所有input
进行处理后的包含。 我们以图1为例进行共有签名流程的介绍:
- 在后面的内容中,我们都是以第一个
input
(vin[0]
)为例进行介绍,其他input
也是同理。 - 签名部分填充在
vin[0]
的的scriptSigLen
和scriptSig
中,也即图中红色框中。 - 对于
vin[0]
而言,签名之前scriptSigLen
和scriptSig
中是没有内容的。其借助于vout[0]
中的scriptPubkey
进行填充。具体而言,将vout[0]
中的scriptPubkey
去除OP_CODESEP
操作码后,将其内容和长度分别填充到scriptSig
和scriptSigLen
中。如图2中黄色框所示。 - 对于其他
input
(如vin[1]
)而言,scriptSigLen
和scriptSig
分别填充为0值和空值,如图2中暗绿色框所示。


1. SIGHASH_ALL
类型
如前所述,SIGHASH_ALL
类型中的message
包含了全部的outputs
和修改后的inputs
。 如图2所示,其中TxNew
的灰色部分即为message
的内容。
2. SIGHASH_NONE
类型
如前所述,SIGHASH_NONE
类型中的message
包含全部的input
但不包含任何output
。 如图3所示,output
的数目被置为0,message
中不包含任何output
。此外,nSequence
也被置为0值。 
3. SIGHASH_SINGLE
类型
如前所述,SIGHASH_NONE
类型中的message
包含全部的input
,且只包含对应当前input
的output
。 如图4所示,黄色框表示message
中只包含vout[0]
的内容。此外,nSequence
也被置为0值,output
的数目被置为当前input
的index+1
(如红色框所示)。 
B. 有修饰类
本小节首先介绍有修饰类中一些共有的签名流程。如前所述,SIGHASH_ANYONECANPAY
修饰后的message
不包含其他input
. 如图5所示:
- 对于
vin[0]
而言,scriptSigLen
和scriptSig
也分别填充scriptPubkey
去除OP_CODESEP
操作码后的内容。 - 其他
input
(如vin[1]
) 的内容不被包含 input
的数目被置为1,如图5中的红色框所示。图5
以下分小节分别介绍每种特定类型的签名流程。
1. SIGHASH_ALL | SIGHASH_ANYONECANPAY
类型
图5中TxNew
的灰色部分也表示了SIGHASH_ALL | SIGHASH_ANYONECANPAY
类型的message
内容。 对比III.A小节中的图1,两者除了input
外,message
中的其他内容完全一致。
2. SIGHASH_NONE | SIGHASH_ANYONECANPAY
类型
该类型和III.B.1小节的区别主要在output
部分,其message
内容如图6的灰色部分所示。 
3. SIGHASH_SINGLE | SIGHASH_ANYONECANPAY
类型
该类型和III.B.1.小节的区别也是在output
部分,其message
内容如图7的灰色部分所示。 
C. 示例
本篇博客的最后,强烈推荐读者阅读比特币中对交易进行签名的详细过程. 该博客以SIGHASH_ALL
类型为例,非常详细清晰地介绍了交易的签名流程。 当然,也强烈推荐读者继续阅读下一篇博客btcd源码解析 —— 签名机制(3) —— 源码分析.