比特币--交易脚本和脚本语言

比特币交易在比特币网络中广播传送时,每个比特币客户端收到交易后,都会先进行验证,验证交易有效时,才再继续传送。验证就是通过执行解锁脚本和锁定脚本执行来进行的。

简介

  • 比特币脚本语言是一种基于逆波兰式表示法的基于栈执行的脚本语言。
  • 图灵非完备的语言,即没有复杂流程控制功能,保证其安全性。
  1. 锁定脚本被写入UTXO。通常包含一个收款人公钥被Hash160后的哈希值,即该脚本指向一个比特币地址。
  2. 解锁脚本存在交易输入列表中。通常为私钥签名+公钥

基于栈的脚本执行过程

下面脚本“2 3 OP_ADD 5 OP_EQUAL”演示了2+3是否等于5的执行过程:

image

如上所示:

  1. 脚本语言从左至右的方式处理脚本中的每一项,数字一般会直接入栈。
  2. 操作符一般会出栈需要个数的参数并对它们进行处理,可能会再将结果入栈,如OP_ADD会使出栈栈顶的两个元素,然后对它们相加,再将结果入栈。
  3. 条件操作符评估一项条件,产生一个真或假的结果。如OP_EQUAL出栈两个元素,两者相等则再入栈true,否则入栈false.

再如:计算2+7-3+1的结果是否等于7的脚本为:

1
2 7 OP_ADD 3 OP_SUB 1 OP_ADD 7 OP_EQUAL

解锁和锁定脚本组合执行举例

如果下面的脚本作为锁定脚本:

1
3 OP_ADD 5 OP_EQUAL

则它的相应解锁脚本应该为:2

验证引擎将解锁脚本和锁定脚本组合起来形成:

1
2 3 OP_ADD 5 OP_EQUAL

脚本执行完成后,如果栈结果为真,则说明交易有效,相反若为假则说明交易无效,另外脚本被操作符禁止也为无效,如OP_VERIFY、OP_RETURN,或有条件终止如OP_ENDIF,则交易无效。

标准交易

支付给谁,即输出 包含收款人能够解锁的锁定脚本的UTXO。

目前有下列五大锁定脚本标准:P2PKH、P2PK、MS、P2SH、OP_RETURN。

P2PKH(支付给公钥哈希)

比特币网络上的大多数交易都是P2PKH交易,此类交易都含有一个锁定脚本,该脚本由公钥哈希实现阻止输出功能,公钥哈希即为广为人知的比特币地址。由P2PKH脚本锁定的输出可以通过键入公钥和由相应私钥创设的数字签名得以解锁。

  • 如下解锁脚本

    1
    OP_DUP OP_HASH160 <Public Key Hash> OP_EQUAL OP_CHECKSIG

    脚本中的Public Key Hash即为收款人的比特币地址,但这个地址不是基于Base58Check编码的。事实上,大多数比特币地址都显示为十六进制码,而不是大家所熟知的以1开头的基于Bsase58Check编码的比特币地址。

  • 相应解锁脚本如下:

1
<Signature> <Public Key>

即为收款人私钥签名和公钥

  • 将解锁脚本和锁定脚本组合起来,基于栈执行

image

image

最后一步验证签名的原理是公私钥非对称加密,即私钥加密的内容只有公钥才能解密。

P2PK(支付给公钥)

与P2PKH相比,P2PK模式更为简单。与P2PKH模式含有公钥哈希的模式不同,在P2PK脚本模式中,公钥本身已经存储在锁定脚本中,而且代码长度也更短。

P2PK锁定版脚本形式如下:

1
<Public Key A> OP_CHECKSIG

用于解锁的脚本是一个简单签名:

1
<Signature from Private Key A>

经由交易验证软件确认的组合脚本为:

1
<Signature from Private Key A> <Public Key A> OP_CHECKSIG

该脚本只是CHECKSIG操作符的简单调用,该操作主要是为了验证签名是否正确,如果正确,则返回为真(Ture)。

MS(多重签名)

多重签名脚本设置了这样一个条件,假如记录在脚本中的公钥个数为N,则至少需提供其中的M个公钥才可以解锁。这也被称为M-N组合,其中,N是记录在脚本中的公钥总个数,M是使得多重签名生效的公钥数阀值(最少数目)。例如,对于一个2-3多重签名组合而言,存档公钥数为3个,至少同时使用其中2个或者2个以上的公钥时,才能生成激活交易的签名,通过验证后才可使用这笔资金。最初,标准多重签名脚本的最大存档公钥数被限定为15个,这意味着可采用1-1乃至15-15的任意多重签名组合,或者组合的组合来激活交易。

通用的M-N多重签名锁定脚本形式为:

1
M <Public Key 1> <Public Key 2> ... <Public Key N> N OP_CHECKMULTISIG

其中,N是存档公钥总数,M是要求激活交易的最少公钥数。

2-3多重签名条件:

1
2 <Public Key A> <Public Key B> <Public Key C> 3 OP_CHECKMULTISIG

上述锁定脚本可由含有签名和公钥的脚本予以解锁:

1
OP_0 <Signature B> <Signature C>

或者由3个存档公钥中的任意2个相一致的私钥签名组合予以解锁。

两个脚本组合将形成一个验证脚本:

1
OP_0 <Signature B> <Signature C> 2 <Public Key A> <Public Key B> <Public Key C> 3 OP_CHECKMULTISIG

当执行时,只有当未解锁版脚本与解锁脚本设置条件相匹配时,组合脚本才显示得到结果为真(Ture)。上述例子中相应的设置条件即为未解锁脚本是否含有与3个公钥中的任意2个相一致的私钥的有效签名。

P2SH(支付给脚本哈希)

背景

一般公司收款时,都会采用多重签名脚本格式,基于多重签名,公司的收入只有用多个负责人的私钥签名才能够解锁而使用,从而有效防止盗窃挪用。

例如:一个公司要求客户向其付款时,采用多重签名脚本,即客户创建的支付交易的输出是多重签名脚本格式,可能如下:

1
2 <boss Public Key> <Partner1 Public Key> <Partner2 Public Key> <Partner3 Public Key> <Attorney Public Key> 5 OP_CHECKMULTISIG

虽然多重签名的功能非常强大,但是客户支付前,公司都必须将该脚本提前发送客户,另外客户需要支持多重签名的钱包创建交易,还有公钥可能很长,从而使锁定脚本很长,从而使包含该锁定脚本的UTXO很长,存在挖矿节点的UTXO池中,直到被消费也会占用较大的内存空间。

P2SH脚本格式

P2SH就是为了简化多重签名的复杂性而产生的。

  • 不采用P2SH的多重签名脚本
类型 脚本内容 备注
Locking Script 2 PubKey1 PubKey2 PubKey3 PubKey4 PubKey5 5 OP_CHECKMULTISIG 客户付款交易的输出锁定脚本
Unlocking Script Sig1 Sig2 签名
  • P2SH脚本
类型 脚本内容 备注
Redeem Script 2 PubKey1 PubKey2 PubKey3 PubKey4 PubKey5 5 OP_CHECKMULTISIG 赎回脚本
Locking Script OP_HASH160 <20-byte hash of redeem script> OP_EQUAL 客户付款交易的输出锁定脚本
Unlocking Script Sig1 Sig2 收款公司花费时使用的解锁脚本

P2SH支付到脚本哈希,即支付给赎回脚本的哈希,收款人只需展示自己的赎回脚本的哈希,付款人的交易输出的锁定脚本中包含该赎回脚本的哈希,对付款人而言,该脚本的哈希就像收款人的比特币地址一样,使输出的锁定脚本长度有效变短。

解锁时,收款人用多个签名和赎回脚本组合成解锁脚本,再和锁定脚本连接起来,基于栈执行脚本验证。

P2SH地址

P2SH地址是基于Base58Check编码的一个含有20个字节哈希的脚本,就像比特币地址是基于Base58Check编码的一个含有20个字节的公钥。

由于P2SH地址采用5作为前缀,这导致基于Base58编码的地址以“3”开头。以“3”为前缀给予客户这是一种特殊类型的地址的暗示,该地址与一个脚本相对应而非与一个公钥相对应,但是它的效果与比特币地址支付别无二致。

该地址可以发送给客户,这些客户可以采用任何的比特币钱包实现简单支付,就像这是一个比特币地址一样。

如对BaseCheck不清楚,温馨连接

数据输出(OP_RETURN操作符)

OP_RETURN操作符是用来运用比特币区块链存储与比特币支付不相关数据,该做法是一个有争议的话题。

许多开发者认为其有滥用的嫌疑,因而试图予以阻止。另一些开发者则将之视为区块链技术强大功能的有力证明,从而试图给予大力支持。那些反对非支付相关应用的开发者认为这样做将引致“区块链膨胀”,因为所有的区块链节点都将以消耗磁盘存储空间为成本,负担存储此类数据的任务。更为严重的是,此类交易仅将比特币地址当作自由组合的20个字节而使用,进而会产生不能用于交易的UTXO。因为比特币地址只是被当作数据使用,并不与私钥相匹配,所以会导致UTXO不能被用于交易,因而是一种伪支付行为。这样的做法将使得内存中的UTXO不断增加,而且这些不能被用于交易的数据同样也不能被移除,因此比特币节点将永久性地担负这些数据,这无疑是代价高昂的。

在0.9版的比特币核心客户端上,通过采用OP_Return操作符最终实现了妥协。OP_Return允许开发者在交易输出上增加40字节的非交易数据。然后,与伪交易型的UTXO不同,OP_Return创造了一种明确的可复查的非交易型输出,此类数据无需存储于UTXO集。OP_Return输出被记录在区块链上,它们会消耗磁盘空间,也会导致区块链规模的增加,但它们不存储在UTXO集中,因此也不会使得UTXO内存膨胀,更不会以消耗代价高昂的内存为代价使全节点都不堪重负。

OP_RETURN脚本的样式:

1
OP_RETURN <data>

“data”部分被限制为40字节,且多以哈希方式呈现,如32字节的SHA256算法输出。许多应用都在其前面加上前缀以辅助认定。例如,电子公正服务的证明材料采用8个字节的前缀“DOCPROOF”,在十六进制算法中,相应的ASCII码为44f4350524f4f46。

请记住OP_RETURN不涉及可用于支付的解锁脚本的特点,OP_RETURN不能使用其输出中所锁定的资金,因此它也就没有必要记录在蕴含潜在成本的UTXO集中,所以OP_RETURN实际是没有成本的。OP_RETURN常为一个金额为0的比特币输出,因为任何与该输出相对应的比特币都会永久消失。假如一笔OP_RETURN遇到脚本验证软件,它将立即导致验证脚本和标记交易的行为无效。如果你碰巧将OP_RETURN的输出作为另一笔交易的输入,则该交易是无效的。

一笔标准交易(通过了isStandard()函数检验的)只能有一个OP_RETURN输出。但是单个OP_RETURN输出能与任意类型的输出交易进行组合。