比特币客户端通过执行一个类forth脚本语言编写的脚本来验证每一笔交易。锁定脚本被写入UTXO,同时它包含一个用同种脚本语言编写的签名。当一笔交易被验证时,每一个输入值中的解锁脚本被与其对应的锁定脚本同时(互不干扰)地执行。从而查看这笔交易是否满足条件。
锁定脚本是放在output中的一个障碍,它明确了今后花费这笔输出的条件。解锁脚本则是满足这个花费条件的脚本,允许输出被消费。
比特币脚本语言是一种基于逆波兰表示法的基于堆栈的执行语言。堆栈允许推送和弹出两种操作。数字和常数被推入堆栈,操作符可以向堆栈推送或者移除一个或多个项目或者将结果推入堆栈,条件操作符评估条件,并产生真假两种结果。
初期的比特币有五大标准交易脚本。后在btc加入了隔离见证之后,增加了两个隔离见证脚本(BCH不含有隔离见证脚本)。
这是比特币网络上最常见的交易脚本形式。PubkeyHash就是我们经常提到的地址(address),该脚本由公钥hash来实现阻止输出的功能。由P2PKH脚本所锁定的输出可以通过输入公钥和相应的私钥创建的签名来得到解锁。
该笔交易的输出形式类似以下的锁定脚本
OP_DUP OP_HASH160 OP_EQUAL OP_CHECKSIG
而收款人(Destination Address)要解锁此脚本并创建新的输出,则需要提供他的签名和公钥。解锁脚本如下:
最终由解锁脚本和锁定脚本所构成的用于验证交易的脚本如下:
OP_DUP OP_HASH160 OP_EQUAL OP_CHECKSIG
执行此脚本会返回true或false来判断交易是否合法。
与P2PkH的交易模式不同。P2PK脚本中,公钥本身已经储存在锁定脚本中,而且代码长度更短。P2PK目前在coinbase交易中最为常见,Coinbase交易由老的采矿软件产生,现在还没有更新到P2PKH
P2PK的锁定脚本形式如下
OP_CHECKSIG
用于解锁的脚本只需要一个简单签名
组合起来可以得到
OP_CHECKSIG
非常简单明了,而且计算步骤较P2PKH要少很多。
多重签名脚本设置了一个条件,假如记录在脚本中的公钥个数为N,则至少需要其中的M个公钥才可以解锁。这也被称为M-N组合,其中,N是记录在脚本中的公钥的数目,M是使得多重签名生效的阈值(最少数目)。最初,标准多重签名脚本的最大公钥数被设定为15个,现在的个数需要从最新版本中确认。
通用M-N多重签名锁定脚本的格式为
M ... N OP_CHECKMULT``ISIG
其中,N是存档公钥总数,M是要求激活交易的最少公钥数。
例如,2-3多重签名的条件:
2 3 OP_CHECKMULTISIG
上述脚本可以由含有签名和公钥的脚本予以解锁
OP_0
注,之所以加上前缀OP_0是因为最早的CHECKMULTISIG在处理含有多个项目的过程中有个小漏洞,脚本会自动忽略这个前缀,它只是一个占位符。
将两个脚本进行组合就可以得到
OP_0 2 3 OP_CHECKMULTISIG
当锁定脚本和解锁脚本匹配的时候,组合脚本的结果为真,就可以花费这笔交易。
P2SH作为一种新型,强大且大大简化了复杂交易脚本类型被引入。有些脚本(例如多重签名)的功能十分有用,但其本身由于过于庞大和复杂,在交易的过程中会带来困难。为了解决脚本本身的复杂性带来的问题,引入了ScriptHash作为交易的锁定脚本。一笔交易如果试图支付UTXO,要解锁支付脚本,就必须要含有与hash相匹配的解锁脚本原文。它将交易费的成本从发送方转移到接受方,接收方一定要拥有脚本原文才可以解锁。
举例说明
假设原始的多重签名赎回脚本(Redeem script)如下
2 PubKey1 PubKey2 PubKey3 PubKey4 PubKey5 5 OP_CHECKMULTISIG
经过hash之后生成的新的锁定脚本(比起原始脚本大大简化)
OP_HASH160 <20byte hash of redeem script> OP_EQUAL
而要解锁上述锁定脚本,需要提供原始的redeem script。解锁脚本如下:
Sig1 Sig2 redeem_script
将解锁脚本和原始脚本链接后
Sig1 Sig2 redeem_script OP_HASH160 <20byte hash of redeem script> OP_EQUAL
执行了OP_Equal的过程会释放出解锁脚本,变成如下的样子
Sig1 Sig2 redeem_script
即
Sig1 Sig2 2 PubKey1 PubKey2 PubKey3 PubKey4 PubKey5 5 OP_CHECKMULTISIG
最终成功解锁脚本。
P2SH的优点:
赎回脚本在旧的客户端中要求必须是标准脚本,但是新版本中可以是任意有效的脚本。不能将P2SH用于自身循环。也不能在赎回脚本中使用OP_RETURN,因为OP_RETURN不能被赎回。如果赎回脚本无效,则永远无法赎回里面的比特币。
p2sh可以将脚本hash预编译成一个地址,采用5做前缀,Base58编码后以3开头,该地址与一个脚本对应,而不是与公钥对应。向该地址支付就是在向脚本支付。P2SH脚本地址隐藏了复杂性,运用此脚本地址支付的的人无法看到脚本。
比特币的分发和时间戳机制(即区块链)的潜在应用大大超过支付领域。从区块链上创造交易输出并储存是一个很大的需求。由于交易输出会使UTXO膨胀,消耗内存资源,因此0.9版的比特币核心客户端采取的妥协方案。OP_RETURN允许开发者在交易输出上增加40字节的非交易数据。与伪交易类型的utxo不同,OP_RETURN创造一种可以明确复查的非交易性输出,此输出不储存在UTXO,但是会被储存在区块链上,占用磁盘空间。
OP_RETURN 的脚本格式如下:
OP_RETURN
data部分被限制为40字节(BCH将此限制提升)。
一笔标准交易只能有一个OP_RETURN输出,但是单个OP_RETURN输出能与任意类型的输出交易进行组合。
这种脚本是随着比特币隔离见证被激活而产生的脚本类型。用于生成隔离见证交易和地址。隔离见证将交易中的解锁脚本中的scriptSig替换为输入中被称为witness的部分中。而签名被拿到了交易的外部。
原本带有scriptKey的脚本如下
OP_DUP OP_HASH160 0067c8970e65107ffbb436a49edd8cb8eb6b567f OP_EQUALVERIFY OP_CHECKSIG
被segwit改造后就变成了如下的形态
0 0067c8970e65107ffbb436a49edd8cb8eb6b567f
对于老节点而言,上面的锁定脚本就是两个推入堆栈的常数,而对于segwit节点而言,0代表隔离见证版本,后面的代表隔离见证脚本。隔离见证节点会从witness中取出对应的脚本进行校验。
功能与P2SH类似,只是将原本的脚本
OP_HASH160 10f400e996c34410d02ae76639cbf64f4bdf2def OP_EQUAL
变成了如下所示的见证脚本
0 e4d3d21bab744d90cd857f56833252000ac0fade318136b713994b9319562467
签名等信息都放在witness中,不打包到交易中。
"in": [
{
"prev_out": {
"hash": "ffa2826ba2c9a178f7ced0737b559410364a62a41b16440beb299754114888c4",
"n": 0
},
"scriptSig": "",
"witness": "304402203a4d9f42c190682826ead3f88d9d87e8c47db57f5c272637441bafe11d5ad8a302206ac21b2bfe831216059ac4c91ec3e4458c78190613802975f5da5d11b55a69c601 210243b3760ce117a85540d88fa9d3d605338d4689bed1217e1fa84c78c22999fe08ac"
}
]