最佳循序渐进的比特币脚本指南第2部分

这是我们的最佳比特币脚本指南的第2部分。强烈建议您先阅读第1部分,然后再继续进行此操作.

最佳比特币脚本指南第2部分

在第1部分中,我们介绍了以下内容:

  • 比特币脚本简介.
  • 比特币交易如何工作?
  • 脚本如何工作?
  • 脚本中的锁定和解锁游戏.
  • 比特币脚本中的ECDSA加密.

注意:从现在开始,我们不会经常使用“ OP_”命令,因为应该理解,“ OP_”将始终作为每个操作码的前缀。请记住这一点。我们没有使用“ OP_”来增强可读性,当您执行脚本时,请记住使用“ OP_”.

多重签名交易

到目前为止,我们所看到的交易都非常简单(本质上是一对一的交易)。但是,交易会变得更加复杂和分层.

首先,我们将检查多签名交易。在多签名交易中,可以解锁比特币输出的唯一方法是如果多人验证交易.

所以,这在哪里有用?

想象有一个巨大的跨国公司。显然,他们不会让一个人控制所有资金,对吗?他们将有一个董事会负责这些资金.

现在,如何在比特币脚本交易的背景下工作?

多重签名脚本设置了一个条件,其中脚本中记录了N个公钥,并且其中至少M个必须提供签名以解锁资金。这也称为M-of-N方案,其中N是密钥总数,M是验证所需的最少签名数。交易也称为M-of-N multisig.

multisig输出的脚本格式如下所示:

M…N CHECKMULTISIG

让我们来看一个例子.

假设我们正在向一家由3个人(爱丽丝,鲍勃和查理)领导的公司汇款,这3个人中有2个人需要验证交易才能通过。此交易也称为2-of-3 multisig.

输出如何?

2 3 CHECKMULTISIG

好了,这就是输出。公司将如何释放产出并获得资金使用权?请记住,这是2之3的多重签名,涉及的3个人中有2个人必须出示签名.

因此,使用的签名组合可以是以下任意一种:

假设Bob和Charlie是验证交易的人。完整的验证脚本将如下所示:

2 3 CHECKMULTISIG

如果上述条件成立且签名正确,则 交易 将为TRUE,它将通过。但是,如果签名不正确,则交易将失败.

但是,如果您查看多次签名交易的任何示例,您会注意到我们使用的格式:

2 3 CHECKMULTISIG

…是不正确的.

之所以如此,是因为CHECKMULTISIG操作码中存在错误.

CHECKMULTISIG操作码中的错误

理想情况下,CHECKMULTISIG操作码应从堆栈中弹出M + N + 2个元素。让我们以到目前为止一直在使用的示例为例:

2 3 CHECKMULTISIG

在执行CHECKMULTISIG之前,堆栈将如下所示:

最佳比特币脚本指南第2部分

本质上,CHECKMULTISIG弹出堆栈中的所有元素.

在此示例中,M = 3,N = 2.

CHECKMULTISIG弹出的项目为:3(M)公钥,2(N)签名和两个常量,这基本上意味着理想情况下应弹出的项目总数为(M + N + 2 =)3 + 2 + 2 = 7个物品.

但是,CHECKMULTISIG操作码中有一个小故障,使它弹出的项目比堆栈中可用的多。显然这最终导致堆栈错误.

为了避免此错误,使用了一种解决方法来解决它。每当我们具有组合的验证脚本时,我们总是以“ 0”开头。这意味着脚本现在将如下所示:

0 2 3 CHECKMULTISIG

随后,我们的堆栈如下所示:

最佳比特币脚本指南第2部分

通过在开头添加一个额外的元素“ 0”,我们确保我们不会遇到任何错误.

这也意味着代替使用此解锁脚本:

我们最终使用了这个:

0

什么是按脚本哈希支付或P2SH?

尽管多重签名交易为您的交易提供了很大的灵活性,但它们却可能变得有些复杂。想象一下,一家有5个合作伙伴参与运营的公司。如果爱丽丝(Alice)向该公司发送了一些比特币,则她的输出脚本将如下所示(假设涉及的5个人中有2个人需要验证交易):

2 5 CHECKMULTISIG

如您所见,这变得非常麻烦并且具有很多缺点:

  • 首先,公司实际上必须将这些信息和脚本传达给客户.

  • 然后,客户将需要使用能够创建自定义交易脚本的特殊比特币钱包软件.

  • 产生的交易将是正常交易的五倍,并且需要更多费用.

需要一种解决方案来使此比特币脚本变得不太复杂。决定将复杂的multisig脚本进行哈希处理,并且人们将在哈希表中包含哈希值而不是脚本。.

为了解锁和兑换交易,接收方将需要出示原始脚本以及签名。由于发件人将钱发送到哈希而不是公共地址,因此这种类型的交易称为“付给公共脚本哈希”或“ P2SH”.

因此,P2SH如何更改交易(对于上面给出的示例)?

在P2SH之前

锁定脚本:2 5 CHECKMULTISIG

解锁脚本:

P2SH之后

兑换脚本:2 5 CHECKMULTISIG

锁定脚本:HASH160等于

解锁脚本:

可以看出,提供条件以赎回交易的责任从发送方转移到提供赎回脚本的赎回方.

那么,如果不使用P2SH,我们公司的脚本会是什么样? Sans P2SH他们将一直使用的比特币脚本是这样的:

2 5 CHECKMULTISIG

这将转化为以下内容:

2 04C16B8698A9ABF84250A7C3EA7EEDEF9897D1C8C6ADF47F06CF73370D74DCCA01CDCA79DCC5C395D7EEC6984D83F1F50C900A24DD47F569FD4193AF5DE762C58704A2192968D8655D6A935BEAF2CA23E3FB87A3495E7AF308EDF08DAC3C1FCBFC2C75B4B0F4D0B1B70CD2423657738C0C2B1D5CE65C97D78D0E34224858008E8B49047E63248B75DB7379BE9CDA8CE5751D16485F431E46117B9D0C1837C9D5737812F393DA7D4420D7E1A9162F0279CFC10F1E8E8F3020DECDBC3C0DD389D99779650421D65CBD7149B255382ED7F78E946580657EE6FDA162A187543A9D85BAAA93A4AB3A8F044DADA618D087227440645ABE8A35DA8C5B73997AD343BE5C2AFD94A5043752580AFA1ECED3C68D446BCAB69AC0BA7DF50D56231BE0AABF1FDEEC78A6A45E394BA29A1EDF518C022DD618DA774D207D137AAB59E0B000EB7ED238F4D800 5 CHECKMULTISIG

不,没有人吐出这些数字和字母,这就是5个公钥组合的样子!

想象一下,客户发送该比特币脚本以发送其比特币UTXO.

现在,如果通过SHA 256和RIPEMD160解析了相同的十六进制块,则看起来像这样:

54c557e07dde5bb6cb791c7a540e0a4796f5e97e

如此整洁和易于管理,对吧?

现在,锁定脚本的P2SH版本如下所示:

HASH160 54c557e07dde5bb6cb791c7a540e0a4796f5e97e等于

为了解锁,解锁脚本现在看起来像:

: <2公钥1公钥2公钥3公钥4公钥5 5 MULTISIG>

这两个比特币脚本的组合分两个阶段进行.

首先,将赎回脚本与哈希进行匹配,以查看其是否匹配:

<2公钥1公钥2公钥3公钥4公钥5 5 MULTISIG> HASH160相等.

如果此比特币脚本返回TRUE,则解锁的第二部分将通过这段自动发生的代码进行。这是我们传统的multisig解锁:

 2公钥1公钥2公钥3公钥4公钥5 5 CHECKMULTISIG

P2SH地址始终以3而不是1开头.

3KP3okFKoGs53JqgyGB27pqaum8tCz2BvW <- P2sh地址.

什么是流量控制?

编程中最有趣的方面之一是流控制。通过使用某些条件,可以检测执行哪些命令以及何时执行。任何具有一定编程基础的人都熟悉IF-ELSE编程的概念.

这是最简单,最基本的流量控制形式.

在比特币脚本中,以下用于状态控制:

  • 如果
  • 埃尔塞夫
  • 万一
  • 通知

在正常程序中,IF-ELSE条件如下所示:

如果(条件)

{

报表A

}

别的

{

报表B

}

报表C

所以,这里发生了什么?

  • 如果条件为True,则执行STATEMENT A.
  • 否则,执行STATEMENT B.
  • 之后,无论一个人使用哪种条件,都会执行STATEMENT C.

但是,在比特币脚本中,它具有不同的外观。请记住,比特币脚本的主要功能是它是基于堆栈的语言。这就是为什么这种情况在IF语句之前出现的原因.

因此,它看起来像这样:

健康)状况

如果

报表A

别的

报表B

万一

报表C

该脚本块的执行将是什么样子?

步骤1:条件被弹出堆栈:

第2步:IF操作码从条件中弹出,并检查其是否为TRUE.

第三步:如果为真,则执行STATEMENT A,并且比特币脚本跳过ELSE语句,跳至ENDIF并将STATEMENT C压入堆栈.

步骤4:如果IF操作码返回FALSE,则执行ELSE块,并将STATEMENT B压入堆栈.

第5步:在将STATEMENT B推入堆栈后,ENDIF条件被激活,并且STATEMENT C继续被推入堆栈.

边注:

如前所述,可以通过将VERIFY语句附加到某些条件来建立流控制.

2 4均等3

在这种情况下,由于2不等于4,因此脚本将停止执行,然后甚至不执行3.

在比特币脚本中使用流控制

流控制的最常见应用之一是创建具有多个执行路径的兑换脚本.

我们已经看到了使用Multisignatures进行多级执行的示例。现在让我们看看如何通过Flow Control语句编写相同的multisig事务.

假设我们要执行1比2的Multisig。参与multisig的2个人是Alice和Bob,只有这两个需要验证交易才能通过.

因此,对于此multisig,如何使用流控件设计锁定脚本?

锁定比特币脚本

如果

CHECKSIG

别的

CHECKSIG

万一

如您所见,这是一个简单明了的if-else循环。但是这里有问题.

你认为缺少什么?

没错….情况!

条件本身不存在……那是一个错误吗?真的现在就考虑一下…为什么我们不把条件放到锁定脚本中?

有条件将解锁IF-ELSE脚本,并允许您访问语句,而无需提供验证。请记住,只有满足某些条件才能解锁IF-ELSE脚本.

这就是为什么在锁定脚本中我们提供不带条件的IF-ELSE代码的原因.

解锁比特币脚本

在解锁脚本中,Bob或Alice提供其签名以及解锁脚本所需的条件.

根据脚本,如果条件为TRUE,爱丽丝的代码将被解锁,如果条件为FALSE,则Bob的代码将被解锁。我们使用“ 1”表示TRUE,使用“ 0”表示FALSE.

因此,请记住所有这些信息,爱丽丝的解锁脚本将是:

1个

鲍勃的解锁脚本是:

0

脚本执行

假设Bob想要解锁UTXO,这就是组合的验证脚本的样子(在本示例中,我们将使用整个IF-ELSE代码来增强理解):

0

步骤1:Bob的签名将被压入堆栈.

最佳比特币脚本指南第2部分

步骤3:现在有趣的部分开始了.

现在是时候执行了,它看起来像这样:

如果

奇克西格

别的

CHECKSIG

万一

首先,IF条件从堆栈中弹出“ 0”.

最佳比特币脚本指南第2部分

步骤5:执行CHECKSIG,从堆栈中同时弹出签名和公钥,并对它们运行CHECKSIG操作.

好了,所以这是一个简单的2合1多重信号.

但是,让我们再加一点赌注,看看在脚本中增加Flow Control时会发生什么.

如果

报表A

别的

如果

报表B

别的

报表C

万一

万一

好了,因此我们有三个要执行的语句。为了执行特定的语句,我们需要输入某些条件才能达到要求.

要执行语句B,需要输入什么条件?条件将是:1、0或{TRUE,FALSE}.

但是,语句B,等一ELSE和一IF之后吧?因此,条件序列不应为0,1或{FALSE,TRUE}?

好吧……请记住,Script是一种基于堆栈的编程语言。因此,{TRUE,FALSE}的输入将在堆栈上显示如下:

最佳比特币脚本指南第2部分

那么,首先弹出的是什么?

错权?

此FALSE条件将使脚本跳过IF并直接跳至ELSE.

这就是为什么当我们需要放置条件时,请记住堆栈的工作方式.

什么是时间锁?

时间锁是一种原始的智能合约,对比特币支出施加基于时间的限制。比特币中使用的三个时间锁:

  • 交易锁定时间(nLocktime).
  • CHECKLOCKTIMEVERIFY或CLTV.
  • CHECKSEQUENCEVERIFY或CSV

锁定时间

基本上,“ nLocktime”是一个参数,它定义了不能接受交易进入区块的时间。每个事务集都包含nLocktime。 nLocktime可以采用三种可能的路线:

  • 如果nLocktime设置为0,则事务将立即传播.

  • 如果0

  • 如果nLocktime> 5亿,那么它将被解释为Unix Epoch时间戳,并且直到指定的时间过去,交易才有效.

尽管nLocktime在纸上看起来不错,但存在一个非常明显的缺点.

假设爱丽丝想给鲍勃发送一些BTC,锁定时间为1周。在1个星期(锁定时间为0)过去之前,爱丽丝有可能使用相同的UTXO创建另一笔交易.

因此,接收者完全依赖于发送者的道德.

闭路电视

nLocktime的问题在于时间锁定已应用于事务,这使其容易受到恶意用户的攻击。因此,CLTV或CHECKLOCKTIMEVERIFY使锁定适用于单个输出。因此,简单来说,CLTV使交易的各个输出对时间锁定负责.

CLTV已在原始的脱链支付渠道中实施,从而抵制了可能的延展性。 CLTV风格的付款渠道是在BIP 65之后实施的。让我们看看它的工作原理:

  • 爱丽丝(商人)将她的公钥提供给鲍勃(客户).

  • 鲍勃在以下条件下使用他的公钥和爱丽丝的地址创建一个P2SH地址:条件1:爱丽丝和鲍勃都签署了通过该地址发生的任何交易的条件2:只有鲍勃可以自己签署任何交易,但该交易锁定时间必须大于退款押金.

  • 鲍勃立即创建了一笔存款交易,并将其在区块链上广播。由于上述条件2,他可以放心,他几乎可以按需产生退款.

  • 现在,请记住,第一个条件表明Alice和Bob都需要签署P2SH地址中发生的任何交易。因此,鲍勃(客户)可以在交易的一部分上签字,而爱丽丝可以在不向鲍勃透露其签名细节的情况下签字。通过这样做,爱丽丝可以在退款被广播之前将最终付款广播到区块链.

CSV

在我们了解CHECKSEQUENCEVERIFY或CSV的工作方式之前,您需要了解绝对时间锁和相对时间锁之间的区别。.

尽管nLocktime和CLTV是绝对时间锁,这意味着它们特别提到了绝对时间点,但相对时间锁指定了从确认区块链中的输出起经过的时间.

CSV或CHECKSEQUENCEVERIFY是相对时间锁。 CSV操作码指定“ nSequence”变量.

CSV操作码在被调用时将停止脚本的执行,除非nSequence指示经过了比CSV操作码中提到的相等或更多的相对锁定时间。.

好吧,让我们现在玩得开心。让我们利用流控制和CSV脚本!

想象我们有一个由3个人(B,C和D)所拥有的公司。该公司以3之2的Multisig运作,这意味着只有在3个人中至少有2个人出示他们的股份时才能使用公司的资金键.

但是,如果人们最终丢失了钥匙,他们需要进行故障保护,以确保仍然可以通过2 of 3 Multisig激活资金。在这种情况下,他们制作一个备份密钥并交给律师A.

因此,脚本中的外观如何?

如果

如果

2

别的

<30天> 检查序列验证滴 <A的公钥> 检查验证

1个

万一

<B的公钥> 3 CHECKMULTISIG

别的

<90天> 检查序列验证滴 <A的公钥> CHECKSIG

万一

如您所见,流程可以通过三种方式进行:

  • 如果一切都很好,那么它就像一个简单的2 of 3 multisig.
  • 如果其中一位所有者丢失了密钥并在30天内无法生产密钥,那么获得资金所需的条件是律师的密钥以及与3位所有者进行的1比3多重签名.
  • 如果所有3位所有者都丢失了钥匙,则律师可以在90天后使用资金.

条件1:一切都很好

如果一切都很好,并且没有人丢失任何密钥,那么3个所有者中的2个将像在任何普通multisig中一样以其签名验证交易.

解锁脚本:0

注意:不要忘记所有multisig事务都以“ 0”开头,以解决CHECKMULTISIG错误.

完整的验证脚本:0

那么,执行看起来如何?

步骤1:将解锁脚本逐步推入堆栈

最佳比特币脚本指南第2部分

看起来熟悉吗?

是的…那是2之3 multisig,比特币脚本正常执行.

条件2:一个人丢了钥匙

在这种情况下,律师A发挥作用.

解锁脚本:0

完整的验证脚本:0

那么,执行看起来如何?

步骤#1:解锁脚本被推入堆栈.

最佳比特币脚本指南第2部分

步骤3:接下来的顺序是:

<30天> CHECKSEQUENCEVERIFY DROP CHECKSIGVERIFY

这 ”<30天> CHECKSEQUENCEVERIFY DROP”基本上可以激活30天的时间锁定。如果在时间锁定内丢失密钥的所有者无法检索到该密钥,那么脚本将移至堆栈中的下一个元素.

但是,如果他们可以检索密钥并显示证明,则脚本立即停止执行(因为已附加VERIFY代码).

注意:那么什么是DROP?假设已提交满足CHECKSEQUENCEVERIFY所需的参数,该参数位于其前面的时间参数,即“<30天>”仍在堆栈中。在这种情况下,DROP函数会弹出堆栈中的最后一个项目, <30天>.

最佳比特币脚本指南第2部分

现在,这成为1的3多重信号。如果B的签名签出,则脚本会正确执行.

条件#3:所有三个所有者放错了钥匙

在这种情况下,脚本甚至不会执行第一个IF,它将直接跳转到ELSE语句.

解锁脚本:

完整的验证脚本:

所以,执行看起来如何?

步骤#1:解锁脚本被推入堆栈.

最佳比特币脚本指南第2部分

结论

本指南的目的是使您了解各种比特币脚本交易方案背后的逻辑。至少可以说,看到这些交易背后的机制很有趣。如果您尚未阅读《比特币脚本指南》的第1部分,请务必检查一下!

Mike Owergreen Administrator
Sorry! The Author has not filled his profile.
follow me