比特幣腳本操作碼完整參考指南
比特幣腳本語言操作碼的完整參考,涵蓋所有 opcode 的功能、語義與實際應用,包括流程控制、堆疊操作、密碼學驗證等。
比特幣腳本操作碼完整參考指南
比特幣腳本語言(Bitcoin Script)是一種基於堆疊的簡單程式語言,用於定義交易的鎖定與解鎖條件。每一筆比特幣交易都包含一個腳本,其中定義了花費該輸出所需的滿足條件。本文提供比特幣腳本操作碼(Opcode)的完整參考,涵蓋其功能、參數、語義以及在實際交易中的應用。
比特幣腳本語言概述
腳本執行模型
比特幣腳本採用基於堆疊的執行模型(Stack-Based Execution Model)。指令按照從左到右的順序依次執行大多數操作碼會從堆疊頂部彈出操作數,執行運算後將結果壓回堆疊。這種設計使得腳本語言極為簡單,但仍能實現複雜的支付條件。
腳本執行模型示意:
┌─────────────────────────────────────────┐
│ 輸入腳本 │
│ (scriptSig / 解鎖腳本) │
└──────────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ 輸出腳本 │
│ (scriptPubKey / 鎖定腳本) │
└──────────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ 腳本驗證引擎 │
│ (比特幣虛擬機 / 腳本執行器) │
└──────────────────┬──────────────────────┘
│
┌────────┴────────┐
▼ ▼
成功(True) 失敗(False)
操作碼編號與分類
比特幣腳本中的操作碼使用單字節(8位元)表示,範圍從 0x00 到 0xff。操作碼可分為以下幾類:
- 常數操作碼(0x00-0x4f):用於將常數值壓入堆疊
- 流程控制操作碼(0x51-0x63):用於條件分支和迴圈
- 堆疊操作碼(0x64-0x6f):用於堆疊元素的操縱
- 字串操作碼(0x70-0x7f):用於位元組串操作
- 位元運算操作碼(0x80-0x8f):用於位元層級的邏輯運算
- 算術操作碼(0x90-0x9f):用於算術運算
- 密碼學操作碼(0xa0-0xaf):用於密碼學運算
- 鎖定時間操作碼(0xb0-0xb9):用於時間約束
- 備用操作碼(0xba-0xff):保留或未定義的操作碼
常數操作碼(Constant Opcodes)
常數操作碼用於將數值或資料直接壓入堆疊。這些操作碼不從堆疊彈出任何元素,僅執行壓入操作。
OP0 / OPFALSE(0x00)
功能:將數值 0 壓入堆疊。
語義:相當於推送一個空字節串(長度為 0 的向量)到堆疊。在布爾語境中,OP_0 代表「假」值。
示例:
OP_0
# 堆疊: [0]
用途:
- 表示未使用 timelock 的預設值
- 在 P2PKH 腳本中作為簽名類型的前綴
- 初始化多重簽名的閾值計數器
OP1 至 OP16(0x51-0x60)
功能:將數字 1 至 16 壓入堆疊。
對應關係:
| 操作碼 | 數值 |
|---|---|
| OP_1 | 1 |
| OP_2 | 2 |
| OP_3 | 3 |
| OP_4 | 4 |
| OP_5 | 5 |
| OP_6 | 6 |
| OP_7 | 7 |
| OP_8 | 8 |
| OP_9 | 9 |
| OP_10 | 10 |
| OP_11 | 11 |
| OP_12 | 12 |
| OP_13 | 13 |
| OP_14 | 14 |
| OP_15 | 15 |
| OP_16 | 16 |
用途:
- 多重簽名腳本中指定閾值(OP_2 表示需要 2 個簽名中的 1 個)
- 指定 OPIF / OPELSE 條件分支的分支索引
OP_PUSHBYTES 系列(0x01-0x4b)
功能:從下一個位元組讀取資料長度,然後將指定長度的資料壓入堆疊。
語義:
- 0x01 到 0x4b:直接表示要推送的位元組數(1-75)
- 0x4c:後跟一個位元組表示長度(OP_PUSHDATA1)
- 0x4d:後跟兩個位元組表示長度(OP_PUSHDATA2)
- 0x4e:後跟四個位元組表示長度(OP_PUSHDATA4)
資料推送格式:
0x10 [16 bytes data] # OP_PUSHBYTES16,推送 16 位元組
0x14 [20 bytes data] # OP_PUSHBYTES20,推送 20 位元組(如 RIPEMD-160 哈希)
0x20 [32 bytes data] # OP_PUSHBYTES32,推送 32 位元組(如 SHA-256 哈希)
0x47 [71 bytes data] # OP_PUSHBYTES71,推送 71 位元組(如 DER 簽名)
用途:
- 推送公鑰(33 位元組或 65 位元組)
- 推送簽名(71-73 位元組,DER 編碼)
- 推送哈希值(20 位元組或 32 位元組)
OP_PUSHDATA1(0x4c)
功能:特殊資料推送操作碼,後跟一個位元組表示要推送的資料長度。
語義:第二個位元組表示長度 L(0-255),隨後的 L 個位元組被推送至堆疊。
示例:
OP_PUSHDATA1 0x10 [16 bytes data]
# 推送 16 位元組的資料
OP_PUSHDATA2(0x4d)
功能:推送最多 65535 位元組的資料。
語義:後跟兩個位元組(小端序)表示長度。
OP_PUSHDATA4(0x4e)
功能:推送最多 4294967295 位元組的資料。
語義:後跟四個位元組(小端序)表示長度。
流程控制操作碼(Flow Control Opcodes)
流程控制操作碼用於實現條件分支結構。比特幣腳本不支援迴圈(loop),這是設計上的安全考量,防止無限迴圈導致區塊驗證停滯。
OP_IF(0x63)
功能:如果堆疊頂部值為非零(真),則執行其後的指令;否則跳過到對應的 OPELSE 或 OPENDIF。
語義:
- 從堆疊彈出一個值
- 如果值為 0,則跳過到下一個 OPELSE 或 OPENDIF
- 如果值非 0,則繼續執行直到遇到 OPELSE 或 OPENDIF
示例 - P2WPKH 見證程式:
<signature> <pubkey> OP_IF OP_CHECKSIG OP_ENDIF
OP_NOTIF(0x64)
功能:與 OP_IF 相反,如果堆疊頂部值為零則執行。
語義:邏輯非運算的條件分支。
OP_ELSE(0x67)
功能:標識 OPIF 或 OPNOTIF 條件為假時執行的程式碼區塊起始。
語義:必須與 OPIF 或 OPNOTIF 配對使用。
OP_ENDIF(0x68)
功能:結束條件區塊。
語義:標識 if-else-endif 結構的結束。
OP_VERIFY(0x69)
功能:驗證堆疊頂部值是否為真。
語義:
- 彈出堆疊頂部值
- 如果值為 0,則立即終止腳本並返回失敗
- 如果值非 0,則繼續執行
用途:
- 確保簽名驗證成功後才繼續執行
- 實現「失敗即終止」的驗證邏輯
示例 - P2PKH 完整腳本:
<signature> <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
OP_RETURN(0x6a)
功能:無條件終止腳本並返回失敗。
語義:
- 立即停止腳本執行
- 標記該輸出為「可證明不可花費」
- 常用於嵌入額外資料到區塊鏈
示例 - OP_RETURN 輸出:
OP_RETURN <data>
# 常見長度:40-80 位元組
# 可承載:區塊鏈不可篡改記錄、承諾、證明
重要安全性考量:自 OPRETURN 之後的任何指令都不會被執行,因此在 OPRETURN 之後的資料不會影響腳本驗證結果。
堆疊操作碼(Stack Opcodes)
堆疊操作碼用於操縱堆疊中的元素,包括複製、刪除、交換等操作。
OP_DUP(0x76)
功能:複製堆疊頂部元素。
語義:彈出堆疊頂部值,然後壓入兩個相同的副本。
示例:
# 執行前堆疊: [x]
OP_DUP
# 執行後堆疊: [x, x]
用途:P2PKH 和 P2SH 腳本中用於複製公鑰或腳本哈希。
OP_DROP(0x75)
功能:刪除(拋棄)堆疊頂部元素。
語義:彈出堆疊頂部值並丟棄。
示例:
# 執行前堆疊: [x, y]
OP_DROP
# 執行後堆疊: [x]
OP_DUP2(0x77)
功能:複製堆疊頂部兩個元素。
語義:
- 彈出 top1 和 top2
- 壓入 top2, top1, top2, top1
OP_DUP3(0x78)
功能:複製堆疊前三個元素。
OP_SWAP(0x7c)
功能:交換堆疊頂部兩個元素的位置。
語義:
# 執行前堆疊: [bottom, top]
OP_SWAP
# 執行後堆疊: [top, bottom]
OP_ROT(0x7a)
功能:將堆疊頂部第三個元素旋轉到頂部。
語義:
# 執行前堆疊: [a, b, c] (c 為頂部)
OP_ROT
# 執行後堆疊: [b, c, a]
OP_TUCK(0x7d)
功能:在堆疊頂部元素下方插入一個副本。
語義:
# 執行前堆疊: [a, b]
OP_TUCK
# 執行後堆疊: [a, b, a]
OP_NIP(0x77)
功能:刪除堆疊頂部下方(第二個)的元素。
OP_OVER(0x78)
功能:複製堆疊第二個元素到頂部。
語義:
# 執行前堆疊: [a, b]
OP_OVER
# 執行後堆疊: [a, b, a]
OP_PICK(0x7a)
功能:根據堆疊頂部值 n,複製堆疊中第 n 個元素到頂部。
語義:堆疊索引從 0 開始(0 為頂部)。
OP_ROLL(0x7b)
功能:根據堆疊頂部值 n,將堆疊中第 n 個元素移動到頂部。
字串操作碼(String Opcodes)
OP_CAT(0x7e)
功能:連接兩個字節串。
語義:
- 彈出 top1 和 top2
- 壓入 top2 || top1(連接結果)
歷史:OPCAT 在比特幣早期版本(2009-2010)中存在,後於 2010 年被中本聰禁用,理由是防止「堆疊元素過大」攻擊。然而,社群正在討論重新啟用 OPCAT,因為它可以實現更強大的智慧合約功能。
現代應用:
- 實現樹狀簽名驗證
- 實現 covenants(合約)限制
- 增強腳本的可表達性
BIP 提議:OP_CAT 正在作為 BIP 進行標準化討論。
OP_SPLIT(0x7f)
功能:將一個字節串拆分為兩部分。
語義:
- 彈出要拆分的字節串和分割位置 n
- 壓入前 n 位元組和剩餘位元組
位元運算操作碼(Bitwise Opcodes)
OP_EQUAL(0x87)
功能:檢查兩個值是否相等。
語義:
- 彈出 top1 和 top2
- 如果相等,壓入 1;否則壓入 0
OP_EQUALVERIFY(0x88)
功能:OPEQUAL 後跟 OPVERIFY。
語義:如果不相等,立即終止腳本並返回失敗。
算術操作碼(Arithmetic Opcodes)
算術操作碼對堆疊上的大整數進行運算。所有運算都以小端序、大端整數(首位為符號位)格式處理。
OP_ADD(0x93)
功能:將兩個值相加。
語義:
- 彈出 a 和 b
- 壓入 a + b
OP_SUB(0x94)
功能:將兩個值相減。
語義:
- 彈出 a 和 b
- 壓入 a - b
OP_MUL(0x95)
功能:將兩個值相乘。
注意:此操作碼已被禁用,無法在標準腳本中使用。
OP_DIV(0x96)
功能:將兩個值相除。
注意:此操作碼已被禁用。
OP_MOD(0x97)
功能:取模運算。
注意:此操作碼已被禁用。
OP_BOOLAND(0x9a)
功能:邏輯 AND。
語義:
- 彈出 a 和 b
- 如果 a 和 b 都非零,壓入 1;否則壓入 0
OP_BOOLOR(0x9b)
功能:邏輯 OR。
語義:
- 彈出 a 和 b
- 如果 a 或 b 任意一個非零,壓入 1;否則壓入 0
OP_NUMEQUAL(0x9c)
功能:數值相等比較。
語義:
- 彈出 a 和 b
- 如果 a == b,壓入 1;否則壓入 0
OP_NUMNOTEQUAL(0x9d)
功能:數值不相等比較。
OP_LESSTHAN(0x9f)
功能:小於比較。
語義:
- 彈出 a 和 b
- 如果 a < b,壓入 1;否則壓入 0
OP_GREATERTHAN(0xa0)
功能:大於比較。
OP_LESSTHANOREQUAL(0xa1)
功能:小於或等於比較。
OP_GREATERTHANOREQUAL(0xa2)
功能:大於或等於比較。
OP_MIN(0xa3)
功能:返回兩個值中較小者。
OP_MAX(0xa4)
功能:返回兩個值中較大者。
OP_WITHIN(0xa5)
功能:檢查值是否在指定範圍內。
語義:
- 彈出 x, min, max
- 如果 min <= x < max,壓入 1;否則壓入 0
密碼學操作碼(Cryptographic Opcodes)
密碼學操作碼是比特幣腳本的核心,用於驗證簽名、哈希值等關鍵安全操作。
OP_SHA256(0xa8)
功能:計算 SHA-256 哈希。
語義:
- 彈出輸入資料
- 計算 SHA256(input)
- 壓入結果(32 位元組)
用途:
- 承諾方案
- 智慧合約中的哈希驗證
OP_SHA256D(0xa9)
功能:計算 SHA-256 雙重哈希(SHA256(SHA256(input)))。
語義:
- 彈出輸入資料
- 計算 SHA256(SHA256(input))
- 壓入結果
用途:
- 比特幣區塊頭哈希計算
- 交易 ID 計算
- P2PKH 腳本中的公鑰哈希驗證
OP_RIPEMD160(0xa6)
功能:計算 RIPEMD-160 哈希。
語義:
- 彈出輸入資料
- 計算 RIPEMD160(input)
- 壓入結果(20 位元組)
OP_HASH160(0xa9)
功能:計算 RIPEMD160(SHA256(input)) 組合哈希。
語義:
- 彈出輸入資料
- 先計算 SHA256(input)
- 再計算 RIPEMD160(sha256_result)
- 壓入結果(20 位元組)
重要用途:這是比特幣地址的核心哈希函數。
P2PKH 腳本示例:
OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
OP_CHECKSIG(0xac)
功能:驗證交易的 ECDSA 簽名。
語義:
- 彈出簽名(sig)和公鑰(pubkey)
- 根據腳本類型,從簽名中提取簽名類型標誌
- 使用 ECDSA 驗證演算法驗證簽名
- 如果驗證成功,壓入 1;否則壓入 0
驗證過程:
驗證輸入:
- sig: DER 編碼的 ECDSA 簽名 + sighash 類型標誌
- pubkey: 未壓縮(65 位元組)或壓縮(33 位元組)公鑰
驗證演算法:
1. 解析 sighash 類型(可選擇是否驗證所有輸入、所有輸出等)
2. 構建交易的 sighash 版本
3. 使用公鑰驗證簽名
4. 返回結果
Sighash 類型:
| 類型 | 值 | 說明 |
|---|---|---|
| SIGHASH_ALL | 0x01 | 簽名覆蓋所有輸入和輸出 |
| SIGHASH_NONE | 0x02 | 簽名不保護任何輸出 |
| SIGHASH_SINGLE | 0x03 | 簽名只保護對應的輸出 |
| SIGHASH_ANYONECANPAY | 0x80 | 簽名只保護當前輸入 |
Sighash 标志组合:
- 0x01: SIGHASH_ALL(完整簽名)
- 0x02: SIGHASH_NONE(無輸出)
- 0x03: SIGHASH_SINGLE(單一輸出)
- 0x81: SIGHASHALL | SIGHASHANYONECANPAY(支付給任何人)
- 0x82: SIGHASHNONE | SIGHASHANYONECANPAY
OP_CHECKSIGVERIFY(0xad)
功能:OPCHECKSIG 後跟 OPVERIFY。
語義:如果簽名驗證失敗,立即終止腳本。
OP_CHECKMULTISIG(0xae)
功能:驗證多重簽名。
語義:
- 彈出簽名數量 n
- 彈出 n 個簽名
- 彈出公鑰數量 m
- 彈出 m 個公鑰
- 驗證至少 m 個簽名對應有效的公鑰
Bug 注意:比特幣腳本引擎中有一個著名的 bug,即在 OPCHECKMULTISIG 執行前會彈出一個額外的元素(由於歷史原因)。這個額外元素可以是任何值,通常用 OP0 來確保正確執行。
標準多重簽名腳本結構:
OP_m <pubkey1> <pubkey2> ... <pubkeyn> OP_n OP_CHECKMULTISIG
其中 m 是閾值(需要的最少簽名數),n 是公鑰總數。
示例 - 2-of-3 多重簽名:
OP_2 <pubkey1> <pubkey2> <pubkey3> OP_3 OP_CHECKMULTISIG
OP_CHECKMULTISIGVERIFY(0xaf)
功能:OPCHECKMULTISIG 後跟 OPVERIFY。
OP_CHECKSIGADD(0xba)
功能:Schnorr 簽名驗證並累加。
語義:
- 彈出簽名、公鑰和先前的累加值
- 如果簽名有效,累加值 +1
- 壓入累加結果
用途:
- 批次簽名驗證
- 與 Schnorr 簽名結合使用
這是 Taproot 升級(2021年)引入的新操作碼,僅在 Tapscript 中可用。
鎖定時間操作碼(Locktime Opcodes)
OP_CHECKLOCKTIMEVERIFY(0xb1,CLTV)
功能:確保交易鎖定時間已滿足。
語義:
- 獲取交易的黑手黨用時間(nLockTime)或相對時間
- 與腳本中指定的時間進行比較
- 如果時間條件不滿足,終止腳本
BIP 定義:BIP-65
參數格式:
- OPCHECKLOCKTIMEVERIFY 本身不從堆疊彈出任何值(OPDROP 行為已被棄用)
- 參數通過前面的 OP_PUSH 操作碼提供
用途:
- 托管合約
- 時間鎖定釋放
- 支付通道的時間鎖
示例 - 時間鎖定輸出:
<expiry_time> OP_CHECKLOCKTIMEVERIFY OP_DROP <pubkey> OP_CHECKSIG
OP_CHECKSEQUENCEVERIFY(0xb2,CSV)
功能:確保相對時間鎖定條件已滿足。
語義:
- 獲取輸入的序列時間(nSequence)
- 與腳本中指定的值進行比較
- 如果時間條件不滿足,終止腳本
BIP 定義:BIP-112
用途:
- 閃電網路通道
- 費用代扣(CPFP)
- 相對時間鎖定
相對時間格式:
- 區塊數(最多 65535 區塊)
- 時間(512 秒顆粒度)
已禁用的操作碼
以下操作碼在比特幣早期版本中存在,但後來被禁用,出於安全考慮:
OPMUL、OPDIV、OPMOD、OPLSHIFT、OP_RSHIFT
禁用原因:這些操作碼可能被用於算術溢位攻擊,導致不確定的腳本行為。
OP_CAT(待重新啟用)
現狀:正在討論重新啟用作為比特幣腳本升級的一部分(通過軟分叉)。
OP_XOR
功能:位元組 XOR 運算。
狀態:已禁用。
現代腳本類型與操作碼使用
P2PKH(Pay to Public Key Hash)
解鎖腳本:<signature> <pubKey>
鎖定腳本:OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
P2SH(Pay to Script Hash)
解鎖腳本:<sig1> <sig2> ... <redeemScript>
鎖定腳本:OP_HASH160 <redeemScriptHash> OP_EQUAL
P2WPKH(Pay to Witness Public Key Hash)
見證:<signature> <pubkey>
鎖定腳本:OP_0 <pubKeyHash>
P2WSH(Pay to Witness Script Hash)
見證:<witnessScript> <args>
鎖定腳本:OP_0 <scriptHash>
P2TR(Pay to Taproot)
見證:<control> <signature(s)>
鎖定腳本:OP_1 <taproot_output_key>
操作碼安全最佳實踐
腳本驗證規則
- 長度限制:單個腳本最大 10,000 位元組
- 堆疊限制:最大堆疊元素數量和大小有限制
- 操作碼計數:每個腳本最多 201 個操作碼(非資料推送)
常見攻擊向量
- 堆疊溢位:過大的資料推送導致記憶體耗盡
- 認證繞過:不正確使用 OP_VERIFY
- 時間鎖繞過:不正確使用 CLTV/CSV
防禦措施
- 使用標準腳本模板
- 驗證所有簽名後再轉移資金
- 使用相對時間鎖定實現資金回收機制
結論
比特幣腳本操作碼是理解比特幣交易機制的基礎。雖然腳本語言設計簡單(圖靈不完備,無迴圈),但通過組合不同的操作碼,可以實現豐富的支付條件,包括多重簽名、時間鎖定、哈希鎖定等。隨著 Taproot 升級的部署,Schnorr 簽名和 MAST 結構為比特幣腳本帶來了更強大的表達能力和隱私保護。
理解每個操作碼的功能和語義對於比特幣開發者、審計人員和安全研究者至關重要。通過掌握這些基礎知識,可以構建更安全、更靈活的比特幣應用。
相關文章
- 比特幣腳本語言入門 — 理解 Bitcoin Script 的基本指令與運作原理。
- 比特幣腳本協定層級深度解析 — 從密碼學證明到實際實現,深入分析比特幣腳本語言的數學基礎、協定規範與安全特性。
- 比特幣合約 (Covenants) — 理解比特幣腳本限制與合約實現的可能性。
- Miniscript 應用完全指南 — 理解比特幣腳本的高級表示法 Miniscript,包括語法、類型系統與實際應用場景。
- 比特幣腳本語言深度教學:P2TR、P2WSH 與進階腳本 — 深入探討比特幣腳本語言的進階主題,涵蓋 Pay-to-Taproot(P2TR)、Pay-to-Witness-Script-Hash(P2WSH)的運作原理與實際應用,以及現代比特幣腳本的最新發展。
延伸閱讀與來源
這篇文章對您有幫助嗎?
請告訴我們如何改進:
評論
發表評論
注意:由於這是靜態網站,您的評論將儲存在本地瀏覽器中,不會公開顯示。
目前尚無評論,成為第一個發表評論的人吧!