特币客端通过执一个类Forth脚本语言编写的脚本验证比特币交易。锁定脚本被写入UTXO,同时它往往包含一个用
同种脚本语言编写的签名。当一笔比特币交易被验证时,每一个输入值中的解锁脚本被与其对应的锁定脚本同时(互不干扰
地)执行,从而查看这笔交易是否满足使用条件。
比特币交易验证并不基于一个不变的模式,而是通过运行脚本语言来实现。这种语言可以表达出多到数不尽的条件变种。这也是比特币作为一种“可编程的货币”所拥有的权力。
比特币脚本语言被称为基于栈语言,因为它使用的数据结构被称为栈。栈是一个非常简单的数据结构,它可以被理解成为一堆卡片。栈允许两类操作:入栈和出栈。入栈是在栈顶部增加一个项目,出栈则是从栈顶部移除一个项目。
脚本分类
比特币的交易验证引擎依赖于两类脚本来验证比特币交易:一个锁定脚本和一个解锁脚本。
锁定脚本是一个放在一个输出值上的“障碍”,同时它明确了今后花费这笔输出的条件。由于锁定脚本往往含有一个公钥(即比特币地址)。
解锁脚本是一个“解决”或满足被锁定脚本在一个输出上设定的花费条件的脚本,同时它将允许输出被消费。解锁脚本是每一笔比特币交易输出的一部分,而且往往含有一个被用户的比特币钱包(通过用户的私钥)生成的数字签名。由于解锁脚本常常包含一个数字签名,因此被称作 ScriptSig 。
每一个比特币客户端会通过同时执行锁定和解锁脚本来验证一笔交易。对于比特币交易中的每一个输入,验证软件会先检索输入所指向的UTXO。这个UTXO包含一个定义了花费条件的锁定脚本。接下来,验证软件会读取试图花费这个UTXO的输入中所包含的解锁脚本,并执行这两个脚本。
脚本特性
1、图灵非完备性, 这意味着脚本的复杂性有限,交易可执行的次数也可预见。施加的这些限制确保该语言不被用于创造无限循环或其它类型的逻辑炸弹隐患,这样的炸弹可以植入交易中,拒绝攻击比特币网络。防止薄弱环节被利用。
2、主权验证,比特币交易脚本语言是无国家主权的,没有国家能凌驾于脚本之上,也没有国家会在脚本被执行后对其进行保存。所以 需要执行脚本的所有信息都已包含在脚本中。可以预见的是,一个脚本能在任何系统上以相同的方式执行。这意味着一个有效的交易对 每个人而言都是有效的,而且每一个人都明白这一点。这种对于结果的可预见性是比特币系统的一项重要良性特征。
3、脚本语言,脚本是一种非常简单的语言,这种语言被设计为能在有限的硬件上执行,它仅需最少的处理即可,而且不能做许多现代编程语言可以做的事情。当涉及可编程的钱时,这是它的一个基于深思熟虑的安全特性。
标准交易脚本
五中标准脚本分别为P2PKH、P2PK、MS(限15个密钥)、P2SH和OP_Return.
P2PKH(Pay-to-Public-Key-Hash)
比特币网络上的大多数交易都是P2PKH交易,此类交易都含有一个锁定脚本,该脚本由公钥哈希实现阻止输出功能,公钥哈希即比特币地址。由P2PKH脚本锁定的输出可以通过键入公钥和由相应私钥创设的数字签名得以解锁。
P2PK(Pay-to-Public-Key)
与P2PKH相比,P2PK模式更为简单。与P2PKH模式含有公钥哈希的模式不同,在P2PK脚本模式中,公钥本身已经存储在锁定脚本中,而且代码长度也更短。P2PKH是由Satoshi创建的,主要目的一方面为使比特币地址更简短,另一方面也使之更方便使用。P2PK目前在Coinbase交易中最为常见,Coinbase交易由老的采矿软件产生,目前还没更新至P2PKH。
锁定版脚本:<Public Key A> OP_CHECKSIG
解锁的脚本<Signature from Private Key A>
验证组合脚本:<Signature from Private Key A> <Public Key A> OP_CHECKSIG
多重签名
多重签名脚本设置了这样一个条件,假如记录在脚本中的公钥个数为N,则至少需提供其中的M个公钥才可以解锁。这也被称为M-N组合,其中,N是记录在脚本中的公钥总个数,M是使得多重签名生效的公钥数阀值(最少数目)。
M-N多重签名锁定脚本: M <Public Key 1> <Public Key 2> ... <Public Key N> N OP_CHECKMULTISIG
解锁脚本:OP_0 <Signature B> <Signature C>
两个脚本组合将形成⼀个验证脚本:OP_0 <Signature B> <Signature C> 2 <Public Key A> <Public Key B> <Public Key C> 3 OP_CHECKMULTIS
数据输出(OP_RETURN操作符)
OP_Return允许开发者在交易输出上增加40字节的非交易数据。然后,与伪交易型的UTXO不同,OP_Return创造了一种明确的可复查的非交易型输出,此类数据无需存储于UTXO集。OP_Return输出被记录在区块链上,它们会消耗磁盘空间,也会导致区块链规模的增加,但它们不存储在UTXO集中,因此也不会使得UTXO内存膨胀,更不会以消耗代价高昂的内存为代价使全节点都不堪重负。
OP_RETURN 脚本的样式:OP_RETURN <data>
P2SH(Pay-to-Script-Hash)
多重签名会有如下问题:
1.交易臃肿,N个公钥都要包含在交易的输出中(锁定脚本中),增加了交易的大小同时增加了交易费用,另外还增加了矿工维护UTXO的负担。
2.付款用户必须根据你提供的所有公钥信息对交易中的锁定脚本进行定制,给支付带来极大的不便利。
P2SH的出现即是为了解决多重签名存在的这些问题,P2SH增加赎回脚本(Redeem Script)概念,P2SH脚本内容示例:
赎回脚本: 2 PubKey1 PubKey2 PubKey3 PubKey4 PubKey5 5 CHECKMULTISIG
锁定脚本: HASH160 <20-byte hash of redeem script> EQUAL
解锁脚本: Sig1 Sig2 <redeem script>
从脚本内容可以看到,锁定脚本从原来的多重签名锁定脚本变成了原脚本的哈希,而赎回脚本内容即为原来的多重签名 锁定脚本内容,解锁脚本中增加了赎回脚本的内容。
所以执行的情况变成如下:
1.先对比解锁脚本中的赎回脚本内容哈希与锁定脚本中是否一致
Sig1 Sig2 <redeem script> HASH160 <20-byte hash of redeem script> EQUAL
2.如果上面的对比结果一致,则变成执行如下内容(回到了多重脚本验证的情况)
Sig1 Sig2 2 PubKey1 PubKey2 PubKey3 PubKey4 PubKey5 5 CHECKMULTISIG
优点:
1.锁定脚本简化,减小了交易的空间占用
2.P2SH地址使付款人无需关心复杂的操作,只需向地址支付即可
3.P2SH使多重签名脚本的负担转移到收款人身上,而不是付款人
(1)多重签名导致的交易大小扩大仍然存在,只是由锁定脚本转移到了解锁脚本上。
(2)只有当需要解锁P2SH地址上的比特币进行付款时才会发生,延迟了占用较多空间交易发生的时间。
(2)交易大小导致的交易速度减慢,交易费增加等负担转移到收款人承担。
比特币交易P2PKH(Pay-to-Public-Key-Hash)解锁过程示例
解锁脚本:<Sig> <PubKey>
锁定脚本:OP_DUP OP_HASH160 <PubkeyHash> OP_EQUALVERIFY OP_CHECKSIG
从上图可知,比特币将解锁脚本与锁定脚本拼接后,使用堆栈语言按后进先出的顺序执行,最后完成CHECK,如果返回结果为TRUE,代表解锁成功,用户可以使用该笔输出作为新交易的输入进行交易。如果返回为FALSE或者执行过程中出现问题,则花费这笔输出的请求被拒绝。