比特幣腳本操作碼完整參考指南

比特幣腳本語言操作碼的完整參考,涵蓋所有 opcode 的功能、語義與實際應用,包括流程控制、堆疊操作、密碼學驗證等。

比特幣腳本操作碼完整參考指南

比特幣腳本語言(Bitcoin Script)是一種基於堆疊的簡單程式語言,用於定義交易的鎖定與解鎖條件。每一筆比特幣交易都包含一個腳本,其中定義了花費該輸出所需的滿足條件。本文提供比特幣腳本操作碼(Opcode)的完整參考,涵蓋其功能、參數、語義以及在實際交易中的應用。

比特幣腳本語言概述

腳本執行模型

比特幣腳本採用基於堆疊的執行模型(Stack-Based Execution Model)。指令按照從左到右的順序依次執行大多數操作碼會從堆疊頂部彈出操作數,執行運算後將結果壓回堆疊。這種設計使得腳本語言極為簡單,但仍能實現複雜的支付條件。

腳本執行模型示意:

    ┌─────────────────────────────────────────┐
    │              輸入腳本                    │
    │         (scriptSig / 解鎖腳本)           │
    └──────────────────┬──────────────────────┘
                       │
                       ▼
    ┌─────────────────────────────────────────┐
    │              輸出腳本                    │
    │        (scriptPubKey / 鎖定腳本)         │
    └──────────────────┬──────────────────────┘
                       │
                       ▼
    ┌─────────────────────────────────────────┐
    │            腳本驗證引擎                   │
    │     (比特幣虛擬機 / 腳本執行器)           │
    └──────────────────┬──────────────────────┘
                       │
              ┌────────┴────────┐
              ▼                 ▼
         成功(True)      失敗(False)

操作碼編號與分類

比特幣腳本中的操作碼使用單字節(8位元)表示,範圍從 0x00 到 0xff。操作碼可分為以下幾類:

常數操作碼(Constant Opcodes)

常數操作碼用於將數值或資料直接壓入堆疊。這些操作碼不從堆疊彈出任何元素,僅執行壓入操作。

OP0 / OPFALSE(0x00)

功能:將數值 0 壓入堆疊。

語義:相當於推送一個空字節串(長度為 0 的向量)到堆疊。在布爾語境中,OP_0 代表「假」值。

示例

OP_0
# 堆疊: [0]

用途

OP1 至 OP16(0x51-0x60)

功能:將數字 1 至 16 壓入堆疊。

對應關係

操作碼數值
OP_11
OP_22
OP_33
OP_44
OP_55
OP_66
OP_77
OP_88
OP_99
OP_1010
OP_1111
OP_1212
OP_1313
OP_1414
OP_1515
OP_1616

用途

OP_PUSHBYTES 系列(0x01-0x4b)

功能:從下一個位元組讀取資料長度,然後將指定長度的資料壓入堆疊。

語義

資料推送格式

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 簽名)

用途

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。

語義

  1. 從堆疊彈出一個值
  2. 如果值為 0,則跳過到下一個 OPELSE 或 OPENDIF
  3. 如果值非 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)

功能:驗證堆疊頂部值是否為真。

語義

  1. 彈出堆疊頂部值
  2. 如果值為 0,則立即終止腳本並返回失敗
  3. 如果值非 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)

功能:複製堆疊頂部兩個元素。

語義

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)

功能:連接兩個字節串。

語義

歷史:OPCAT 在比特幣早期版本(2009-2010)中存在,後於 2010 年被中本聰禁用,理由是防止「堆疊元素過大」攻擊。然而,社群正在討論重新啟用 OPCAT,因為它可以實現更強大的智慧合約功能。

現代應用

BIP 提議:OP_CAT 正在作為 BIP 進行標準化討論。

OP_SPLIT(0x7f)

功能:將一個字節串拆分為兩部分。

語義

位元運算操作碼(Bitwise Opcodes)

OP_EQUAL(0x87)

功能:檢查兩個值是否相等。

語義

OP_EQUALVERIFY(0x88)

功能:OPEQUAL 後跟 OPVERIFY。

語義:如果不相等,立即終止腳本並返回失敗。

算術操作碼(Arithmetic Opcodes)

算術操作碼對堆疊上的大整數進行運算。所有運算都以小端序、大端整數(首位為符號位)格式處理。

OP_ADD(0x93)

功能:將兩個值相加。

語義

OP_SUB(0x94)

功能:將兩個值相減。

語義

OP_MUL(0x95)

功能:將兩個值相乘。

注意:此操作碼已被禁用,無法在標準腳本中使用。

OP_DIV(0x96)

功能:將兩個值相除。

注意:此操作碼已被禁用。

OP_MOD(0x97)

功能:取模運算。

注意:此操作碼已被禁用。

OP_BOOLAND(0x9a)

功能:邏輯 AND。

語義

OP_BOOLOR(0x9b)

功能:邏輯 OR。

語義

OP_NUMEQUAL(0x9c)

功能:數值相等比較。

語義

OP_NUMNOTEQUAL(0x9d)

功能:數值不相等比較。

OP_LESSTHAN(0x9f)

功能:小於比較。

語義

OP_GREATERTHAN(0xa0)

功能:大於比較。

OP_LESSTHANOREQUAL(0xa1)

功能:小於或等於比較。

OP_GREATERTHANOREQUAL(0xa2)

功能:大於或等於比較。

OP_MIN(0xa3)

功能:返回兩個值中較小者。

OP_MAX(0xa4)

功能:返回兩個值中較大者。

OP_WITHIN(0xa5)

功能:檢查值是否在指定範圍內。

語義

密碼學操作碼(Cryptographic Opcodes)

密碼學操作碼是比特幣腳本的核心,用於驗證簽名、哈希值等關鍵安全操作。

OP_SHA256(0xa8)

功能:計算 SHA-256 哈希。

語義

用途

OP_SHA256D(0xa9)

功能:計算 SHA-256 雙重哈希(SHA256(SHA256(input)))。

語義

用途

OP_RIPEMD160(0xa6)

功能:計算 RIPEMD-160 哈希。

語義

OP_HASH160(0xa9)

功能:計算 RIPEMD160(SHA256(input)) 組合哈希。

語義

重要用途:這是比特幣地址的核心哈希函數。

P2PKH 腳本示例

OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

OP_CHECKSIG(0xac)

功能:驗證交易的 ECDSA 簽名。

語義

  1. 彈出簽名(sig)和公鑰(pubkey)
  2. 根據腳本類型,從簽名中提取簽名類型標誌
  3. 使用 ECDSA 驗證演算法驗證簽名
  4. 如果驗證成功,壓入 1;否則壓入 0

驗證過程

驗證輸入:
  - sig: DER 編碼的 ECDSA 簽名 + sighash 類型標誌
  - pubkey: 未壓縮(65 位元組)或壓縮(33 位元組)公鑰

驗證演算法:
  1. 解析 sighash 類型(可選擇是否驗證所有輸入、所有輸出等)
  2. 構建交易的 sighash 版本
  3. 使用公鑰驗證簽名
  4. 返回結果

Sighash 類型

類型說明
SIGHASH_ALL0x01簽名覆蓋所有輸入和輸出
SIGHASH_NONE0x02簽名不保護任何輸出
SIGHASH_SINGLE0x03簽名只保護對應的輸出
SIGHASH_ANYONECANPAY0x80簽名只保護當前輸入

Sighash 标志组合

OP_CHECKSIGVERIFY(0xad)

功能:OPCHECKSIG 後跟 OPVERIFY。

語義:如果簽名驗證失敗,立即終止腳本。

OP_CHECKMULTISIG(0xae)

功能:驗證多重簽名。

語義

  1. 彈出簽名數量 n
  2. 彈出 n 個簽名
  3. 彈出公鑰數量 m
  4. 彈出 m 個公鑰
  5. 驗證至少 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 簽名驗證並累加。

語義

用途

這是 Taproot 升級(2021年)引入的新操作碼,僅在 Tapscript 中可用。

鎖定時間操作碼(Locktime Opcodes)

OP_CHECKLOCKTIMEVERIFY(0xb1,CLTV)

功能:確保交易鎖定時間已滿足。

語義

  1. 獲取交易的黑手黨用時間(nLockTime)或相對時間
  2. 與腳本中指定的時間進行比較
  3. 如果時間條件不滿足,終止腳本

BIP 定義:BIP-65

參數格式

用途

示例 - 時間鎖定輸出

<expiry_time> OP_CHECKLOCKTIMEVERIFY OP_DROP <pubkey> OP_CHECKSIG

OP_CHECKSEQUENCEVERIFY(0xb2,CSV)

功能:確保相對時間鎖定條件已滿足。

語義

  1. 獲取輸入的序列時間(nSequence)
  2. 與腳本中指定的值進行比較
  3. 如果時間條件不滿足,終止腳本

BIP 定義:BIP-112

用途

相對時間格式

已禁用的操作碼

以下操作碼在比特幣早期版本中存在,但後來被禁用,出於安全考慮:

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>

操作碼安全最佳實踐

腳本驗證規則

  1. 長度限制:單個腳本最大 10,000 位元組
  2. 堆疊限制:最大堆疊元素數量和大小有限制
  3. 操作碼計數:每個腳本最多 201 個操作碼(非資料推送)

常見攻擊向量

  1. 堆疊溢位:過大的資料推送導致記憶體耗盡
  2. 認證繞過:不正確使用 OP_VERIFY
  3. 時間鎖繞過:不正確使用 CLTV/CSV

防禦措施

  1. 使用標準腳本模板
  2. 驗證所有簽名後再轉移資金
  3. 使用相對時間鎖定實現資金回收機制

結論

比特幣腳本操作碼是理解比特幣交易機制的基礎。雖然腳本語言設計簡單(圖靈不完備,無迴圈),但通過組合不同的操作碼,可以實現豐富的支付條件,包括多重簽名、時間鎖定、哈希鎖定等。隨著 Taproot 升級的部署,Schnorr 簽名和 MAST 結構為比特幣腳本帶來了更強大的表達能力和隱私保護。

理解每個操作碼的功能和語義對於比特幣開發者、審計人員和安全研究者至關重要。通過掌握這些基礎知識,可以構建更安全、更靈活的比特幣應用。

延伸閱讀與來源

這篇文章對您有幫助嗎?

評論

發表評論

注意:由於這是靜態網站,您的評論將儲存在本地瀏覽器中,不會公開顯示。

目前尚無評論,成為第一個發表評論的人吧!