雖然數字簽名能夠滿足普通的交易需求,但沒有太多擴展性。比特幣中創建了一種腳本語言,來滿足交易中的一些多樣性的需求,如:
- 制造一枚的在指定時間才能使用比特幣
- 制造一枚任何人可以花費的比特幣
- 作廢一枚比特幣
比特幣腳本
比特幣腳本是一種基于棧(Stack)的、從左到右運行的、非圖靈的腳本語言,用于校驗交易。
棧是一種數據結構,只有兩種基本操作:push 和 pop:
- push:將數據放入棧的頂端。
- pop:將棧的頂端的數據推出。
image.png
腳本會從左到右執行,每次操作都會修改全局的棧。如果執行完成后,沒有錯誤且棧頂的值為真,那么就交易校驗通過,否則交易校驗不通過。一個最簡單的例子是:
OP_0 OP_1 OP_ADD
棧 | 腳本 | 描述 |
---|---|---|
空 | OP_0 OP_1 OP_ADD | script 的含義是 0 + 1 |
0 | OP_1 OP_ADD | 將 0 push 到 stack 中 |
0 1 | OP_ADD | 將 1 push 到 stack 中 |
1 | 空 | pop 兩個 stack 的值,并進行相加,然后結果 push 到 stack 中 |
該 script 運行的結果是 1,因此通過了驗證通過。
鎖定腳本與解鎖腳本
用于驗證交易是否通過的腳本由兩部分組成:
- 解鎖腳本:本次交易的 input 中的 scriptSig
- 鎖定腳本:上次交易的 output 中的 scriptPubKey
在比特幣交易的最初的設計中,使用的是 pay-to-pubkey。那時候,并沒有引入地址 address 的概念。驗證交易是否合法,就是驗證由 scriptSig 腳本和
scriptPubKey 組成的腳本執行結果是否為 1。
scriptSig: <sig>
scriptPubKey: <pubKey> OP_CHECKSIG
棧 | 腳本 | 描述 |
---|---|---|
空 | <sig> <pubKey> OP_CHECKSIG | 將 scriptSig 和 scriptPubKey 結合成腳本 |
<sig> <pubKey> | OP_CHECKSIG | 將 <sig> <pubKey> push 到 stack 中 |
1 | OP_CHECKSIG | pop stack 頂端的連個參數,并使用數字簽名驗證函數驗證,并將結果 push 到 stack 中。 |
這種 pay-to-pubkey 腳本,在上一筆交易中就將電子貨幣所有者的公鑰暴露出來了,這降低了數字簽名的安全性。比如,可以利用提早暴露公鑰,暴力來破解私鑰。
checkSig(pubKey, tryToKnowPrivateKey)
P2PKH(Pay-to-Public-Key-Hash)
為了解決提前暴露公鑰帶來的安全性隱患,BitCoin Core 團隊引入了地址 Address 的概念。比特幣網絡處理的大多數交易都是 P2PKH 這種模式。
image.png
scriptPubKey: OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
scriptSig: <sig> <pubKey>
棧 | 腳本 | 描述 |
---|---|---|
空 | <sig> <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG | 將 scriptSig 和 scriptPubKey 結合成腳本 |
<sig> <pubKey> | OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG | 將 <sig> <pubKey> push 入棧 |
<sig> <pubKey> <pubKey> | OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG | 復制一份棧頂的值 |
<sig> <pubKey> <pubHashA> | <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG | 對棧頂的值進行一次 hash160 運算 |
<sig> <pubKey> <pubHashA> <pubKeyHash> | OP_EQUALVERIFY OP_CHECKSIG | 將 <pubKeyHash> push 入棧 |
<sig> <pubKey> | OP_CHECKSIG | 判斷棧頂的兩個值是否相等 |
true | 空 | 使用數字簽名驗證函數驗證棧頂的兩個值 |
image.png
腳本帶來的多樣性
由于腳本的存在,所以比特幣交易的多樣性就變得更多了,比如
- 制造一枚的在指定時間才能使用比特幣
scriptPubKey: <expiry time> OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
scriptSig: <sig> <pubKey>
- 制造一枚任何人可以花費的比特幣
scriptPubKey: (empty)
scriptSig: OP_TRUE
- 作廢一枚比特幣
scriptPubKey: OP_RETURN {zero or more ops}
總結
- 比特幣腳本用于校驗交易
- 比特幣腳本包括:scriptSig 和 scriptPubKey
- 比特幣腳本常用的是 P2PKH 模式
JavaScript implementation of Script, Bitcoin's scripting language.