《精通比特币第二版》中文版第六章交易3/3

精力有限,后期修订以github为主,建议大家移步github链接阅读更新版本,感谢理解:
https://github.com/tianmingyun/MasterBitcoin2CN

邀请你的加入,和我一起研读

本文约5900字。

6.4.3.3单独执行解锁和锁定脚本

在先前的比特币客户端中,解锁和锁定脚本是以连锁的形式存在的,并且是被依次执行的。出于安全因素考虑,在2010 年比特币开发者们修改了这个特性——因为存在“允许异常解锁脚本推送数据入栈并且污染锁定脚本”的漏洞。在当今的 比特币世界中,这两个脚本是随着堆栈的传递被分别执行的,后续将会详细介绍。
首先,使用堆栈执行引擎执行解锁脚本。如果解锁脚本在执行过程中未报错(没有悬空操作符),主堆栈(非其它堆 栈)将被复制,然后脚本将被执行。如果采用从解锁脚本处复制而来的数据执行锁定脚本的结果为真,那么解锁脚本就 成功地满足了锁定脚本所设置的条件,因而,该输入是一个能使用该UTXO的有效授权。如果在执行完组合脚本后的结 果不是真,那么输入就不是有效的,因为它并未能满足UTXO中所设置的使用该笔资金的条件。

6.4.4 P2PKH(Pay-to-Public-Key-Hash)

比特币网络上的大多数交易都是P2PKH交易,此类交易都含有一个锁定脚本,该脚本由公钥哈希实现阻止输出功能,公 钥哈希之后即为广为人知的比特币地址。由P2PKH脚本锁定的输出可以通过键入公钥和由相应私钥创设的数字签名得以解 锁。参见数字签名ECDSA相关内容。
例如,我们可以再次回顾一下Alice向Bob咖啡馆支付的案例。Alice下达了向Bob咖啡馆的比特币地址支付0.015比特币 的支付指令,该笔交易的输出内容为以下形式的锁定脚本:
OP_DUP OP_HASH160 <Cafe Public Key Hash> OP_EQUAL OP_CHECKSIG
脚本中的 Cafe Public Key Hash 即为咖啡馆的比特币地址,但这个地址不是基于Base58Check编码的。事实上,大多数 比特币地址都显示为十六进制码,而不是大家所熟知的以1开头的基于Bsase58Check编码的比特币地址。
锁定脚本的解锁版脚本是:
<Cafe Signature> <Cafe Public Key>
将两个脚本结合起来可以形成如下有效组合脚本:
<Cafe Signature> <Cafe Public Key> OP_DUP OP_HASH160 <Cafe Public Key Hash> OP_EQUAL OP_CHECKSIG
只有当解锁版脚本与锁定版脚本的设定条件相匹配时,执行组合有效脚本时才会显示结果为真(Ture)。即只有当解锁 脚本得到了咖啡馆的有效签名,交易执行结果才会被通过(结果为真),该有效签名是从与公钥哈希相匹配的咖啡馆的 私钥中所获取的。
图6-5和图6-6(分两部分)显示了组合脚本一步步检验交易有效性的过程。

图6-5评估P2PKH事务的脚本(第1部分,共2部分)
图6-6评估P2PKH事务的脚本(第2部分,共2部分)

6.5数字签名(ECDSA)

到目前为止,我们还没有深入了解“数字签名”的细节。在本节中,我们将研究数字签名的工作原理,以及如何在不揭示私钥的情况下提供私钥的所有权证明。
比特币中使用的数字签名算法是椭圆曲线数字签名算法或ECDSA。 ECDSA是用于基于椭圆曲线私钥/公钥对的数字签名的算法,如椭圆曲线章节所述。 ECDSA由脚本函数OP_CHECKSIG,OP_CHECKSIGVERIFY,OP_CHECKMULTISIG和OP_CHECKMULTISIGVERIFY使用。每当你看到锁定脚本时,解锁脚本都必须包含一个ECDSA签名。

数字签名在比特币中有三个目的(见下面的侧栏)。首先,签名证明,私钥的所有者,暗示资金所有者已经授权支出这些资金。其次,授权证明是不可否认的(不可否认性)。第三,签字证明交易(或交易的具体部分)在签字之后没有也不能被任何人修改。

请注意,每个交易输入都是独立签署的。这是至关重要的,因为签名和投入都不得属于或由同一“所有者”应用。事实上,一个名为“CoinJoin”的特定交易方案使用这个事实来创建多方交易来保护隐私。
注意每个交易输入和它可能包含的任何签名完全独立于任何其他输入或签名。 多方可以协作构建事务,并且只签一个输入。
维基百科的“数字签名”定义
数字签名是用于证明数字消息或文档的真实性的数学方案。 有效的数字签名给予接收者理由认为该消息是由已知的发送者(认证)创建的,即发送方不能拒绝发送消息(不可否认),并且消息在传输(完整性)中未被更改。
来源: https://en.wikipedia.org/wiki/Digital_signature*

6.5.1数字签名如何工作

数字签名是由两部分组成的数学方案。 第一部分是使用私钥(签名密钥)从消息(事务)创建签名的算法。 第二部分是允许任何人验证签名的算法,给定消息和公钥。

6.5.1.1创建数字签名

在比特币的ECDSA算法的实现中,被签名的“消息”是交易,或更确切地说,交易中数据的特定子集的散列(参见签名哈希类型(SIGHASH))。 签名密钥是用户的私钥。 结果是签名:
((Sig = F_ {sig}(F_ {hash}(m),dA)))
这里的:
dA是签名私钥
m是交易(或其部分)
Fhash是散列函数
Fsig是签名算法
Sig是结果签名
ECDSA数学的更多细节可以在ECDSA Math章节中找到。
函数Fsig产生由两个值组成的签名Sig,通常称为R和S:
Sig = (R, S)
现在已经计算了两个值R和S,它们使用称为分辨编码规则的国际标准编码方案或DER将其序列化为字节流。

6.5.1.2签名序列化(DER)

我们来看看Alice再次创建的交易。 在交易输入中有一个解锁脚本,其中包含Alice的钱包中的以下DER编码签名:
3045022100884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb02204b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e381301
该签名是Alice的钱包生成的R和S值的序列化字节流,以证明她拥有授权花费该输出的私钥。 序列化格式由以下九个元素组成:
0x30表示DER序列的开始
0x45 - 序列的长度(69字节)
0x02 - 一个整数值
0x21 - 整数的长度(33字节)
R-00884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb
0x02 - 接下来是一个整数
0x20 - 整数的长度(32字节)
S-4b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e3813
后缀(0x01)指示使用的散列的类型(SIGHASH_ALL)

看看您是否可以使用此列表解码Alice的序列化(DER编码)签名。 重要的数字是R和S; 数据的其余部分是DER编码方案的一部分。

6.5.2验证签名

要验证签名,必须具有签名(R和S),序列化事务和公钥(对应于用于创建签名的私钥)。基本上,签名的验证意味着“只有生成此公钥的私钥的所有者才能在此事务上产生此签名。”
签名验证算法采用消息(事务的一部分或其部分的散列),签名者的公钥和签名(R和S值),如果签名对该消息和公钥有效,则返回TRUE。

6.5.3签名哈希类型(SIGHASH)

数字签名被应用于在比特币的情况下是交易本身的消息。签名意味着签字人对特定交易数据的承诺。在最简单的形式中,签名适用于整个交易,从而提交所有输入,输出和其他交易领域。但是,签名只能提交到一个交易中的一个子集的数据,这对于我们将在本节中看到的一些场景是有用的。

比特币签名具有指示交易数据的哪一部分包含在使用SIGHASH标志的私钥签名的哈希中的方式。 SIGHASH标志是附加到签名的单个字节。每个签名都有一个SIGHASH标志,该标志可以不同于一个输入到另一个输入。具有三个签名输入的交易可以具有不同SIGHASH标志的三个签名,每个签名(提交)交易的不同部分。

记住,每个输入可能在其解锁脚本中包含一个签名。因此,包含多个输入的交易可以具有不同的SIGHASH标志的签名,这些标志在每个输入中提交交易的不同部分。还要注意,比特币交易可能包含来自不同“所有者”的输入,他们只能在部分构建(和无效)的交易中签署一个输入,与他人协作收集所有必要的签名以进行有效的交易。如果您想到多个参与者在比特币网络之外进行协作并更新部分签名的交易,则许多SIGHASH标志类型才有意义。
有三个SIGHASH标志:ALL,NONE和SINGLE,如下表所示。

表6-3 SIGHASH类型和意义

另外还有一个修饰符标志SIGHASH_ANYONECANPAY,它可以与前面的每个标志组合。 当设置ANYONECANPAY时,只有一个输入被签名,其余的(及其序列号)打开以进行修改。 ANYONECANPAY的值为0x80,并通过按位OR运算,得到如下所示的组合标志

表6-4 带修饰符的SIGHASH类型及其含义

SIGHASH标志在签名和验证期间应用的方式是进行交易的副本,并且其中的某些字段被截断(设置为零长度并清空)。 生成的交易被序列化。 SIGHASH标志被添加到序列化交易的结尾,并且结果被哈希。 哈希本身是被签名的“消息”。 根据使用的SIGHASH标志,交易的不同部分将被截断。 所得到的散列取决于交易中数据的不同子集。 通过将SIGHASH作为哈希前的最后一步,签名也提交SIGHASH类型,因此不能更改(例如,由矿工)。
提升所有SIGHASH类型对应交易nLocktime字段(请参阅[transaction_locktime_nlocktime]部分)。 此外,SIGHASH类型本身在签名之前附加到交易,因此一旦签名就不能修改它。
在Alice的交易(参见序列化签名(DER)的列表)的例子中,我们看到DER编码签名的最后一部分是01,这是SIGHASH_ALL标志。 这会锁定交易数据,因此Alice的签名正在提交所有输入和输出的状态。 这是最常见的签名形式。

我们来看看其他一些SIGHASH类型,以及如何在实践中使用它们:
ALL | ANYONECANPAY
这种构造可以用来做“众筹”的交易,试图筹集资金的人可以用单笔输出来构建一个交易,单笔输出将“目标”金额付给众筹发起人。这样的交易显然是无效的,因为它没有输入,但是现在其他人可以通过添加自己的输入作为捐赠来修改它们,他们用ALL | ANYONECANPAY签署自己的输入,除非收集到足够的输入以达到输出的价值,交易无效,每次捐赠是一项“质押”,直到募集整个目标金额才能由募款人收取。

NONE
该结构可用于创建特定数量的“承载支票”或“空白支票”。它提交输入,但允许输出锁定脚本被更改。任何人都可以将自己的比特币地址写入输出锁定脚本并兑换交易。然而,输出值本身被签名锁定。

NONE | ANYONECANPAY
这种构造可以用来建造一个“吸尘器”。在他们的钱包中拥有微小UTXO的用户无法花费这些费用,因为手续费用超过了这些微小UTXO的价值。借助这种类型的签名,灰尘UTXO可以为任何人捐赠,以便随时随地收集和消费。

有一些修改或扩展SIGHASH系统的建议。作为Elements项目的一部分,一个这样的提案是Blockstream的Glenn Willen的Bitmask Sighash模式。这旨在为SIGHASH类型创建一个灵活的替代品,允许“任意的,可重复使用的输入和输出位掩码”来表示“更复杂的合同预付款方案,例如已分配的资产交换中的变更签名的报价”。

注意您不会在用户的钱包应用程序中看到作为选项提供的SIGHASH标志。 除了少数例外,钱包构造了P2PKH脚本,并使用SIGHASH_ALL标志进行签名。 要使用不同的SIGHASH标志,您必须编写软件来构造和签署交易。 更重要的是,SIGHASH标志可以被专用的比特币应用程序使用,从而实现新颖的用途。

6.5.4ECDSA数学

如前所述,签名由数学函数Fsig创建,该函数产生由两个值R和S组成的签名。在本节中,我们更详细地查看函数Fsig。
签名算法首先生成一个临时(临时)私有公钥对。 在涉及签名私钥和交易哈希的变换之后,该临时密钥对用于计算R和S值。
临时密钥对基于随机数k,用作临时私钥。 从k,我们生成相应的临时公钥P(以P = k * G计算,与派生比特币公钥相同);参见[pubkey]部分)。 数字签名的R值则是临时公钥P的x坐标。
从那里,算法计算签名的S值,使得:


S值

其中:
k是临时私钥
R是临时公钥的x坐标
dA是签名私钥
m是交易数据
p是椭圆曲线的主要顺序
验证是签名生成函数的倒数,使用R,S值和公钥来计算一个值P,该值是椭圆曲线上的一个点(签名创建中使用的临时公钥):

P点关系

其中:
R和S是签名值
Qa是Alice的公钥
m是签署的交易数据
G是椭圆曲线发生器点
如果计算点P的x坐标等于R,则验证者可以得出结论,签名是有效的。
请注意,在验证签名时,私钥既不知道也不显示。
ECDSA的数学很复杂,难以理解。 网上有一些很棒的指南可能有帮助。 搜索“ECDSA解释”或尝试这个:http://bit.ly/2r0HhGB

6.5.5随机性在签名中的重要性

如我们在ECDSA Math中所看到的,签名生成算法使用随机密钥k作为临时私有/公钥对的基础。 k的值不重要,只要它是随机的。如果使用相同的值k在不同的消息(交易)上产生两个签名,那么签名私钥可以由任何人计算。在签名算法中重用相同的k值会导致私钥的暴露!
警告 如果在两个不同的交易中,在签名算法中使用相同的值k,则私钥可以被计算并暴露给世界!

这不仅仅是一个理论上的可能性。我们已经看到这个问题导致私人密钥在比特币中的几种不同实现的交易签名算法中的暴露。人们由于无意中重复使用k值而将资金窃取。重用k值的最常见原因是未正确初始化的随机数生成器。

为了避免这个漏洞,业界最佳实践是不用生成熵的随机数生成k,而是使用与交易数据本身种子相关的确定性随机过程。这确保每个交易产生不同的k。在互联网工程任务组发布的RFC 6979中定义了k的确定性初始化的行业标准算法。

如果您正在实现一种用于在比特币中签署交易的算法,则必须使用RFC 6979或类似的确定性随机算法来确保为每个交易生成不同的k。

6.6比特币地址,余额和其他摘要

我们开始本章,发现交易看起来与“幕后”非常不同,而不是如何在钱包,块链浏览器和其他面向用户的应用程序中呈现。 来自前几章的许多简单而熟悉的概念,如比特币地址和余额,似乎在交易结构中不存在。 我们看到交易本身并不包含比特币地址,而是通过锁定和解锁比特币离散值的脚本进行操作。 这个系统中的任何地方都不存在余额,而每个钱包应用程序显着地显示了用户钱包的余额。

现在我们已经探讨了一个比特币交易中实际包含的内容,我们可以检查更高级别的抽象是如何从交易的看似原始的组件派生出来的。
我们再来看看Alice的交易是如何在一个受欢迎的块浏览器(前面章节Alice与Bob's Cafe的交易)中呈现的。

图6-7Alice与Bob's Cafe的交易

在交易的左侧,该块资源管理器将Alice的比特币地址显示为“发送者”。其实这个信息本身并不在交易中。当块链接浏览器检索到交易时,它还检索在输入中引用的先前交易,并从该旧交易中提取第一个输出。在该输出内是一个锁定脚本,将UTXO锁定到Alice的公钥哈希(P2PKH脚本)。块链浏览器提取公钥哈希,并使用Base58Check编码对其进行编码,以生成和显示表示该公钥的比特币地址。

同样,在右侧,区块浏览器显示了两个输出;第一个到Bob的比特币地址,第二个到Alice的比特币地址(作为更改)。再次,为了创建这些比特币地址,块链浏览器从每个输出中提取锁定脚本,将其识别为P2PKH脚本,并从内部提取公钥。最后,块链浏览器重新编码了使用Base58Check的公共密钥哈希生成和显示比特币地址。

如果您要点击Bob的比特币地址,则块链接浏览器将显示Bob的比特币地址的余额。

图6-8Bob的比特币地址的余额

块状资源管理器显示Bob的比特币地址的余额。但是比特币系统中却没有一个“余额”的概念。相反,这里显示的值由块链浏览器构成如下。
为了构建“总接收”数量,块链浏览器首先解码比特币地址的Base58Check编码,以检索在地址中编码的Bob的公钥的160位哈希值。然后,块链浏览器将搜索交易数据库,使用包含Bob公钥密钥的P2PKH锁定脚本寻找输出。通过总结所有输出的值,浏览器可以产生接收的总值。

构建当前余额(显示为“最终余额”)需要更多的工作。块链接浏览器保留当前未用的UTXO集合的输出的单独数据库。为了维护这个数据库,块浏览器必须监视比特币网络,添加新创建的UTXO,并且实时删除已经被使用的UTXO,因为它们出现在未经确认的交易中。这是一个复杂的过程,这取决于在传播时跟踪交易,并保持与比特币网络的共识,以确保遵循正确的链。有时,blockchain的浏览器不同步,从UTXO集的角度来看是不完整或不正确的。
从UTXO集合,块链浏览器总结了引用Bob的公钥哈希的所有未使用输出的值,并产生向用户显示的“最终余额”数目。
为了产生这一个形象,通过这两个“余额”,块浏览器必须对数十,数百甚至数十万笔交易进行索引和搜索。
总之,通过钱包应用程序,块链浏览器和其他比特币用户界面呈现给用户的信息通常由更高层次的抽象组成,这些抽象是通过搜索许多不同的交易,检查其内容以及操纵其中包含的数据而导出的。通过将类似于从一个发送者到一个收件人的银行支票的比特币交易的这种简单的视图呈现,这些应用程序必须抽象许多底层细节。他们主要关注常见的交易类型:每个输入上具有SIGHASH_ALL签名的P2PKH。因此,虽然比特币应用程序可以以易于阅读的方式呈现所有交易的80%以上,但有时候由于偏离了规范的交易而陷入困境。包含更复杂的锁定脚本,或不同SIGHASH标志,或多个输入和输出的交易显示了这些抽象的简单性和弱点。

每天都有数百个不包含P2PKH输出的交易在块上被确认。 blockchain浏览器经常向他们发出红色警告信息,表示无法解码地址。以下链接包含未完全解码的最新的“奇怪事务”:https://blockchain.info/strange-transactions。

正如我们将在下一章中看到的,这些并不一定是奇怪的交易。它们是包含比常见的P2PKH更复杂的锁定脚本的事务。我们将学习如何解码和了解更复杂的脚本及其支持的应用程序。

本章完。

参考内容:
1、本文部分内容摘自《精通比特币》第一版中译本,特此说明并致谢。


我正在发起“和我一起阅读《精通比特币第二版》”活动。
我把这作为一次认知学习法的实践。
我希望将认知学习法与《精通比特币第二版》的研读结合起来,尝试总结出一套可行的区块链知识技能快速入门的方法。
这也将成为我们大家一起合作编写的一本书《认知学习比特币》的雏形(所有有价值的讨论都将成为这本书的素材)。
而且我更希望通过本次认知学习方法论的实践以及迭代,将这种经过实践的学习方法迁移到更多领域的学习中。
所以我们会有第二季,第三季......

欢迎扫描二维码加入。

欲知详情请扫描二维码

推荐阅读更多精彩内容