比特币内部:交易和脚本。第8部分

比特币交易脚本

本文是第八篇,这是专门针对事务和脚本的,这是有关比特币技术性更高的部分的一系列深入解释的第八篇,甚至对于那些不是编码专家的人也可以使用。

下面继续介绍一种旨在逐步进入许多人称为“兔子洞”的指南。

就书目而言,有必要提及Andreas M. Antonopoulos所著的“ Mastering Bitcoin”(精通比特币)一书,并从中拍摄了图像。

多重签名

多重签名脚本(或更简单地说是多重签名)设置了一个条件,其中N个公钥存储在脚本中,并且至少M个公钥必须签名才能解锁付款。它们也称为M-of-N方案,其中N是密钥总数,M是验证所需的签名阈值。目前,标准multisig脚本最多可使用3个公钥,但是此限制仅适用于标准multisig脚本(称为“裸”),不适用于Pay-to-Script-Hash(PS2H)中盘点的multisig脚本,限制为15个按键(因此最多允许15个按键中的15个)。

设置M-of-N多重签名的条件的块脚本的一般形式为:

中号 N CHECKMULTISIG

其中N是列出的公共密钥总数,M是花费输出所需的签名阈值。设置条件2之3的块脚本具有以下形式:

2 3 CHECKMULTISIG

可以使用包含成对签名和公钥的解锁脚本来解决: 或来自与列出的三个公钥相对应的私钥的两个签名的组合。这两个脚本共同构成了验证脚本的组合:

2 3 CHECKMULTISIG

由于存在错误(已成为共识规则的一部分,因此将ergo永久复制),因此采用了一种变通方法,该脚本修改了脚本以规避该错误(只需在开头添加0),因此这是正确的格式:

0 2 3 CHECKMULTISIG

按脚本付费(P2SH)

P2SH于2012年推出,是一种功能强大的新型交易,可大大简化复杂交易脚本的使用。

想象一下,对每个客户使用多重签名脚本(应收账款或应收帐款的财务语言),该脚本会阻止付款,以便至少需要两个签名来解锁(例如所有者和律师或合伙人)才能提供保证免受攻击,盗窃等。

2 5 CHECKMULTISIG

这将导致问题:

  • 所有者应在所有客户付款之前将此脚本传达给所有客户;
  • 每个客户都应使用能够创建自定义交易脚本的“特殊”钱包(并能够这样做);
  • 结果交易(或更确切地说是目的地址)可能比简单的支付交易重5倍(此脚本包含很长的公钥);
  • 就费用而言,交易费用将由客户承担;
  • 一个繁重(长)的事务脚本将保留在每个完整节点的RAM中的UTXO集合中(尽管不一定)(直到花完为止)。

P2SH旨在通过用哈希替换复杂脚本来解决(部分)这些问题。当交易尝试花费UTXO时,除了解锁脚本外,它还必须包含与哈希匹配的脚本ergo“为与该哈希匹配的脚本付费,一个脚本将在花费此输出时稍后显示” 。块脚本被赎回时提供给系统的哈希代替,而不是赎回脚本。

兑换脚本 2 PubKey1 PubKey2 PubKey3 PubKey4 PubKey5 5 CHECKMULTISIG
锁定脚本 哈希160 <20-byte hash of redeem script> 等于
解锁脚本 信号1信号2

在块脚本中不存在定义输出支出条件的复杂脚本(兑现脚本):相反,只有散列,稍后显示赎回脚本,作为支出支出时解锁脚本的一部分(这修改了佣金负担等)。

P2SH地址

后来,BIP 13定义了将脚本的哈希编码为Base58Check中的地址的功能,使用前缀5(在Base58Check中变为3),例如39RF6JqABiHdYHkfChV6USGMe6Nsr66Gzw,它可以像正常情况一样接收付款(并由付款人来构造付款)比特币地址。重要的是要记住,费用负担已从付款人转移到了收款人,当收款人包括用于花费输出的脚本时,收款人将承担费用。

由于规范不是递归的,因此无法将P2SH插入P2SH兑换脚本中,而从技术上讲,可以在兑换脚本中包含RETURN(没有规则可排除),但是交易被报告为无效。请注意,由于直到您尝试花费P2SH输出之前,赎回脚本都不会呈现给网络,因此,如果您使用无效事务的哈希值锁定输出,则无论如何都将对其进行处理。

数据记录输出(返回)

区块链除了支付以外还可以有其他用途,许多人已经尝试将脚本语言用于公证,智能合约等应用程序。为这些目的使用比特币脚本语言的首次尝试涉及创建交易输出来存储数据在区块链上(存在证明)。许多开发人员认为这是一种滥用,不鼓励此类使用,因为它通过向运行全节点的用户收取数据存储成本来“膨胀”区块链。此外,这些交易还会使用目标比特币地址作为20字节的空闲字段来创建无法使用的UTXO:输入的数据与任何私钥都不匹配,并且最终的UTXO不会被使用,ergo永远不会从中删除。 UTXO集的数据库正好注定要“膨胀”区块链。

在0.9版的Bitcoin Core客户端中,通过引入RETURN运算符达成了妥协,该运算符允许将80字节的非支付数据添加到输出中。与使用“ UTXO伪造品”不同,RETURN创建了一个明显可证明不可花费的东西,不需要将其保存在UTXO中心化。 RETURN输出保存在区块链上(它们会占用空间并增加区块链的大小),但不会保存在UTXO中心化,因此它们不会膨胀UTXO的内存矿池,也不会向节点收取RAM成本。 RETURN脚本如下所示:

返回 其中数据空间限制为80个字节,并且通常表示一个散列:许多应用程序添加前缀以标识应用程序的类型:存在证明使用8字节前缀DOCPROOF,该前缀以十六进制的ASCII编码44 4f 43 50 52 4f 4f 46.应该重申的是,没有解锁脚本可以花费RETURN输出(通常是零比特币输​​出)。如果将RETURN引用到事务输入,则脚本验证引擎将停止执行并将该事务标记(标记)为无效。

符合IsStandard()的标准事务只能有一个RETURN输出,但是单个RETURN输出可以在事务中与另一个输出关联。

Bitcoin Core 0.10中添加了两个新的命令行选项,数据载体控制RETURN交易的转发和挖矿,默认情况下设置为1即可; datacarriersize接受一个数字参数,该参数指定RETURN脚本的最大大小(以字节为单位),默认情况下为83个字节,这允许最大80个字节的RETURN数据加上1个字节的RETURN操作码和2个字节的PUSHDATA操作码。

时间锁

时间锁是对事务(或输出)的限制,以使其仅在一定时间后才可使用。从一开始,交易级别的时间锁就存在于比特币中,在nLocktime字段中实现。在2015年和2016年,在UTXO级别引入了两个新的时间锁功能:CHECKLOCKTIMEVERIFY和CHECKSEQUENCEVERIFY。时间锁可用于在特定的将来日期进行交易后交易和锁定价值:甚至更多,它们将比特币脚本扩展到时间维度,为复杂的多步骤智能合约打开了大门。

交易锁定时间(nLocktime)

交易锁定时间是交易级别的配置(交易数据结构中的一个字段),它定义交易有效后的第一时刻,可以将该交易转发到网络或添加到区块链中。从比特币核心代码库中使用的变量的名称也称为nLocktime。在大多数事务中,它配置为0(表示立即传播和执行):如果它不为0且小于500,000,000,则该值将解释为块的高度,这意味着该事务无效并且不会转发或包含在特定区块之前的区块链中。如果事务在指定的nLocktime之前传输到网络,则第一个接收该事务的节点将其拒绝为无效事务,而不转发给其他人。

nLocktime的局限性在于,尽管它可以使将来花费一些输出,但并不能使在那一刻之前花费它们:仍然有可能在将来的3个月内发送交易,并花费双倍的费用。发送方使用相同的UTXO,而接收方未在此时间之前注意到任何内容。唯一的保证是接收者不能在时间之前花钱。

检查锁定时间验证(CLTV)

2015年12月,借助软分叉,基于BIP-65中的规范引入了新的时间锁定形式,新的脚本运算符CHECKLOCKTIMEVERIFY(CLTV)被添加到脚本语言中。 CLTV是输出前的时间锁(而不是每个事务的时间锁):在输出的赎回脚本中添加CLTV操作码仅限于输出本身,因此不能在设置的时间之前花费。 CLTV不会替代nLocktime,但会限制UTXO规范,以便在该值等于或大于nLocktime之前无法使用它们。 CLTV操作码将一个参数作为输入,以与nLocktime(块高度或Unix纪元时间)相同的格式表示为数字,并且如后缀VERIFY所示,它是操作码的类型,如果结果出现则阻止脚本执行(结果)为FALSE。为了阻止输出,将CLTV插入到创建该输出的事务中的输出兑换脚本中。如果正常(P2PKH),则有:

DUP HASH160 从现在开始,EQUILVERIFY CHECKSIG会阻止输出三个月,该事务应该是带有赎回脚本的P2SH:

CHECKLOCKTIMEVERIFY DROP DUP HASH160 均等检查 是区块的高度或从开采交易之日起3个月时估算的时间值:当前区块高度+ 12,960(区块)或当前Unix纪元时间+ 7,760,000(秒)。

尝试使用此UTXO时,将建立一个以UTXO为输入的交易。使用该输入的解锁脚本中的签名和公钥,并且事务的nLocktime配置为等于或大于CHECKLOCKTIMEVERIFY中配置的时间锁。然后,将交易“广播”到比特币网络。如果发件人配置的CHECKLOCKTIMEVERIFY参数小于或等于费用交易的nLocktime,则脚本执行继续(就像执行了no操作或NOP操作码一样)。否则,脚本执行将停止并且事务被视为无效。更具体地说,如果(BIP-65),CLTV将阻止执行,将交易标记为无效:

  • 堆栈是空的;
  • 最上面的项目小于0;
  • 堆栈顶部对象的锁定时间类型(块高度与时间戳)和nLocktime字段不相等;
  • 堆栈顶部的对象大于事务的nLocktime字段;
  • nSequence输入字段为0xffffffff。

执行之后,如果满足CLTV,则时间参数将保留在堆栈的顶部,并且可能需要通过DROP“删除”,以正确执行以下操作码脚本。

nLocktime和CLTV是绝对时间锁,用于指定绝对时间点。还有一些相对的时间锁指定从确认区块链中的输出开始花费一定时间作为输出条件。它们之所以有用,是因为它们允许将两个或多个相互依存的交易链保持脱链状态,同时对交易施加时间限制,该时间限制取决于从确认先前交易起经过的时间。

换句话说,直到UTXO记录在区块链上,时钟才开始计时。此功能特别用于双向通道状态和闪电网络。与绝对时间锁一样,相对时间锁在事务级别和脚本操作码级别都实现。事务级别被实现为关于nSequence值的共识规则,nSequence是在每个事务输入中配置的事务字段。在脚本级别,使用操作码CHECKSEQUENCEVERIFY(CSV)(BIP-68和BIP-112,于2016年5月启用,并使用共识规则的软分叉激活)来实现相关的时间锁定。

n序列

可以通过nSequence字段在每个事务输入中配置相对时间锁,最初(但在此上下文中从未实现)以允许更改内存矿池中的事务:包含nSequence输入小于232-1(0xFFFFFFFF)的事务表示尚未进行事务处理“最终”。该事务将一直保存在内存矿池中,直到被另一个具有相同输入和更高nSequence值的“支出”事务替换为止。一旦接收到其输入的nSequence值为232-1(0xFFFFFFFF)的事务,就将其视为完成并挖矿。原始意义从未实现,并且在不使用时间锁的事务中,nSequence的值基本上配置为(0xFFFFFFFF)。对于使用nLocktime或CLTV的事务,必须将值配置为小于231,以使时间锁起作用。

像CLTV和nLocktime一样,有一个用于相对时间锁的脚本操作码,它利用了脚本中nSequence的值。操作码是CHECKSEQUENCEVERIFY(CSV)。 CSV相对时间锁定在创建和签名许多事务但不传播时,ergo保持“脱链”状态时特别有用。在“父母”被传播,挖矿并且相对时间锁中指定的时间“到期”之前,不能使用“女儿”事务。在闪电网络中可以看到这种用例的应用。

过去时间中位数

在比特币中,挂墙时间和共识时间之间存在细微但重要的差异,因为在去中心化网络中,每个人都有自己的时间观点:事件不是同时发生的,因此必须从同一角度考虑延迟。每个人之间的同步(创建一个通用的分类帐)每隔10分钟就可以实现同一分类帐在过去的存在方式。区块头中的时间戳由矿工配置,但共识规则允许一定程度的自由度,以考虑去中心化节点之间时钟精度的差异。

不幸的是,这刺激了矿工通过将尚未成熟的“时间锁定”交易包括在区块中的时间中来赚取额外的费用。 BIP-113定义了一种新的共识时间度量,称为Median-Time-Past:它是通过获取最后11个块的时间戳并取平均值而得出的,该平均值即成为共识时间,并用于所有时间锁定计算。通过从大约两个小时后取中点,可以减少块时间戳的影响。结合11个区块,任何矿工都无法通过输入尚未成熟的交易来影响时间戳以赚取费用。

Median-Time-Past更改了nLocktime,CLTV,nSequence和CSV的时间计算的实现(共识时间比时钟晚了大约一小时)。在创建具有时间锁定的事务时,在估计要以nLocktime,CLTV,nSequence和CSV编码的期望值时应考虑到这一点。

比特币内幕:交易和脚本。第8部分首先出现在《密码学家》上。

资讯来源:由0x资讯编译自CRYPTONOMIST。版权归作者Alessio Salvetti所有,未经许可,不得转载
提示:投资有风险,入市需谨慎,本资讯不作为投资理财建议。请理性投资,切实提高风险防范意识;如有发现的违法犯罪线索,可积极向有关部门举报反映。
你可能还喜欢