比特幣腳本語言深度教學

深入理解比特幣腳本語言的運作原理、常見腳本類型與進階應用場景。

比特幣腳本語言深度教學

比特幣腳本語言(Bitcoin Script)是比特幣系統中定義比特幣所有權與轉移規則的程式語言。不同於傳統的圖靈完備程式語言,比特幣腳本刻意設計為簡單、確定且受限的語言,這種設計選擇是比特幣安全模型的基石。本篇文章將深入探討比特幣腳本的技術細節、常見應用場景以及進階使用模式。

腳本語言設計理念

比特幣腳本採用堆疊式執行模型(Stack-based execution model),這個設計靈感來自於 FORTH 語言。選擇這種模型的原因在於其簡單性與可預測性:指令從左到右依序執行,資料與運算元都被推入堆疊中,運算結果再從堆疊彈出。這種執行模型使得腳本驗證過程極度高效,且容易在資源受限的環境中執行。

比特幣腳本被刻意設計為非圖靈完備(Non-Turing Complete)的語言。這意味著腳本語言缺乏迴圈(loop)與無條件跳轉(unconditional jump)指令。這個限制看似是一種缺陷,實際上是經過深思熟慮的安全設計:透過排除迴圈,腳本的執行時間與記憶體消耗都能被精確計算與限制,避免了像是智慧合約中常見的 Gas 耗盡攻擊與無限迴圈問題。這也確保了節點在驗證交易時不會陷入計算泥沼,維持了比特幣網路的可預測性與穩定性。

從密碼學角度來看,比特幣腳本依賴橢圓曲線數位簽章演算法(ECDSA)與 SHA-256、RIPEMD-160 雜湊函數。隨著 Taproot 升級,Schnorr 簽章也成為比特幣支援的簽章方案。這些密碼學原語構成了比特幣腳本驗證的基礎,確保了未經授權的使用者無法動用他人的比特幣。

Opcode 完整指南

比特幣腳本由一系列的操作碼(Opcode)與資料構成。每個 Opcode 都執行特定的運算,以下是完整的分類說明。

資料推送指令

資料推送指令用於將資料推入堆疊。比特幣腳本提供多種資料推送方式:

堆疊操作指令

堆疊操作指令用於操縱堆疊中的資料:

雜湊運算指令

雜湊運算指令是比特幣腳本的核心:

驗證指令

驗證指令用於確認條件是否滿足:

流程控制指令

流程控制指令實現條件分支:

時間鎖定指令

時間鎖定指令實現時間條件:

算術運算指令

比特幣腳本支援基本的算術運算:

腳本類型詳解

比特幣腳本隨著比特幣的演進發展出多種格式,每種格式都有其特定的應用場景與安全特性。

P2PK:Pay to Public Key

P2PK 是比特幣早期使用的腳本類型,直接將比特幣支付給公鑰。其鎖定腳本格式為:

<pubKey> OP_CHECKSIG

解鎖腳本只需要提供對應的簽章:

<signature>

P2PK 的主要問題在於公鑰直接暴露在區塊鏈上,如果量子電腦能夠破解 ECDSA,這種格式將面臨風險。此外,P2PK 不支援壓縮格式的公鑰,導致交易資料量較大。由於這些安全與效率問題,P2PK 已幾乎不再使用。

P2PKH:Pay to Public Key Hash

P2PKH 是最傳統的比特幣地址格式,支援壓縮公鑰,廣泛用於 2017 年之前的比特幣交易。其鎖定腳本為:

OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

其中 是公鑰的 RIPEMD-160(SHA-256) 雜湊值,長度為 20 位元組。解鎖腳本為:

<signature> <pubKey>

執行過程如下:首先 OPDUP 複製公鑰,然後 OPHASH160 計算其雜湊值,接著與鎖定腳本中的 pubKeyHash 比較(OPEQUALVERIFY),最後 OPCHECKSIG 驗證簽章。

P2PKH 地址以數字「1」開頭(如 1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2),辨識度高,至今仍在使用。

P2SH:Pay to Script Hash

P2SH 允許將比特幣支付給任意腳本的雜湊值,這使得複雜的鎖定條件可以被壓縮成固定長度的地址。鎖定腳本為:

OP_HASH160 <scriptHash> OP_EQUAL

其中 是腳本的 SHA-256 雜湊值再進行 RIPEMD-160 的 20 位元組雜湊。

P2SH 地址以數字「3」開頭(如 3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy)。這種格式的強大之處在於,收款方可以構建任意複雜的腳本(如多重簽名),而付款方只需要知道一個固定的地址。

典型的 P2SH 解鎖腳本包含一個或多個簽章,後面跟著完整的腳本(稱為贖回腳本,Redeem Script):

<signature1> <signature2> ... <redeemScript>

P2WPKH:Pay to Witness Public Key Hash

SegWit(隔離見證)升級引入的 P2WPKH 是專為見證資料設計的格式。其腳本為:

OP_0 <pubKeyHash>

這是一種「升級版」的 P2PKH,見證資料(簽章與公鑰)被移到稱為「見證」(Witness)的特殊區塊結構中。P2WPKH 地址以「bc1q」開頭,長度為 42 個字元,例如:

bc1qyr8v7q0uj5r8w9x8z8z8z8z8z8z8z8z8z8z8z

這種格式的主要優勢在於:

P2WSH:Pay to Witness Script Hash

P2WSH 是 P2SH 的 SegWit 版本,用於更複雜的鎖定條件。腳本為:

OP_0 <scriptHash>

其中 是 32 位元組的 SHA-256 雜湊值(注意與 P2SH 的 20 位元組區分)。P2WSH 地址同樣以「bc1q」開頭,但長度為 62 個字元。

P2TR:Pay to Taproot

Taproot 升級(2021年11月)帶來了最新的腳本格式,支援 Schnorr 簽章與 Merkelized Alternative Script Trees(MAST)。P2TR 地址以「bc1p」開頭,代表「Taproot」。

OP_1 <taprootTweakedPubKey>

Taproot 的主要特性包括:

多重簽名深度分析

多重簽名(Multisig)是比特幣腳本的重要應用,允許設定 M-of-N 的簽名門檻,即 N 個金鑰中至少需要 M 個簽名才能花費比特幣。

2-of-3 多重簽名

這是最常見的多重簽名配置,提供備援與安全性:

OP_2 <pubKey1> <pubKey2> <pubKey3> OP_3 OP_CHECKMULTISIG

注意:OPCHECKMULTISIG 指令存在一個歷史性的 bug,執行時會從堆疊多消耗一個項目。傳統上需要在簽章列表前添加一個假的 OP0 來修正:

OP_0 <sig1> <sig2> OP_2 <pubKey1> <pubKey2> <pubKey3> OP_3 OP_CHECKMULTISIG

閾值門檻設計

選擇適當的 M-of-N 閾值需要考慮以下因素:

多重簽名的隱私考量

傳統 P2SH 多重簽名交易在區塊鏈上完全公開,不僅揭露參與者的公鑰,也揭露完整的腳本結構。這對隱私構成挑戰:

  1. 所有參與者的公鑰都被公開
  2. 外部觀察者可以識別多重簽名交易(透過腳本模式)
  3. 未使用的備援金鑰也暴露無遺

Taproot 的 MAST 結構部分解決了這個問題:

時間鎖定進階應用

時間鎖定是比特幣腳本中實現條件式釋放的核心機制,分為絕對時間鎖與相對時間鎖兩種。

絕對時間鎖:CHECKLOCKTIMEVERIFY

CLTV 使用絕對時間點作為條件:

<expiryTime> OP_CHECKLOCKTIMEVERIFY OP_DROP <secretKey> OP_CHECKSIG

實際應用場景包括:

  1. 遺囑/繼承安排:設定比特幣在特定日期後可由受益人提取
  2. 延遲釋放:鎖定部分資金,經過冷靜期後才能動用
  3. 支付通道:實現「面對面」閃電網路通道

CLTV 接受的時間格式有兩種:

相對時間鎖:CHECKSEQUENCEVERIFY

CSV 使用相對時間,計算從輸入被區塊確認開始的時間:

<relativeTimeout> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKey> OP_CHECKSIG

這實現了「花費前必須經過 X 個區塊」的條件:

支付通道與 RSV

相對時間鎖是閃電網路與其他第二層解決方案的基礎。通過結合 RSV 與 HTLC,可以構建具有時間限制的支付條件。

HTLC:哈希時間鎖合約

HTLC(Hash Time Locked Contract)是原子交換與閃電網路的核心機制,允許在不信任的對手之間進行擔保支付。

HTLC 腳本結構

# 收款方可以透過揭示原像兌現
OP_SHA256 <hash> OP_EQUALVERIFY OP_IF
    OP_HASH160 <revocationHash> OP_EQUALVERIFY OP_2 <pubKey1> <pubKey2> OP_2 OP_CHECKMULTISIG
OP_ELSE
    <timeout> OP_CHECKSEQUENCEVERIFY OP_DROP OP_2 <pubKey1> <pubKey2> OP_2 OP_CHECKMULTISIG
OP_ENDIF

原子交換實現

HTLC 使得比特幣與萊特幣等不同區塊鏈之間的原子交換成為可能:

  1. 雙方各自創建指向對方的 HTLC
  2. 收款方揭示原像來兌現資金,同時暴露原像給對方
  3. 對方使用揭示的原像在其區塊鏈上兌現
  4. 如果一方拒絕揭示,原像會在超時後使雙方的 HTLC 都失效

這個機制確保了「要么全部成功,要么全部失敗」的原子性,避免任何一方遭受損失。

腳本執行與驗證機制

比特幣腳本的驗證過程是比特幣網路共識的核心組成部分。

腳本執行環境

比特幣節點在驗證交易時執行以下步驟:

  1. 獲取輸入:從交易輸入中找到對應的未花費交易輸出(UTXO)
  2. 提取腳本:從 UTXO 獲取鎖定腳本(ScriptPubKey),從輸入獲取解鎖腳本(ScriptSig)
  3. 合併腳本:將解鎖腳本與鎖定腳本串接
  4. 執行腳本:從左到右執行每個指令
  5. 驗證結果:執行完成後,堆疊頂端為非零值(即 TRUE)表示驗證成功

驗證失敗處理

腳本執行可能因多種原因失敗:

任何失敗都會導致整筆交易無效,該交易不會被區塊接受。

腳本大小限制

比特幣對腳本大小有嚴格限制:

這些限制確保了腳本執行不會耗盡節點資源。

安全性考量

常見攻擊向量

  1. 交易延展性攻擊:在 SegWit 之前,攻擊者可以修改交易中的簽章而不改變有效性,導致輸出地址的「余額」看起來改變。SegWit 透過將簽章移出交易雜湊計算範圍解決了這個問題。
  1. リプレイ 攻擊:在分叉後,攻擊者可能在一條鏈上重放另一條鏈的交易。隔離簽名(SegWit)和 BIP-125 提出的交易簽名方式有助於防止此類攻擊。
  1. 灰區攻擊:利用交易確認時間的不確定性進行雙花。比特幣網路透過等待多個區塊確認來降低這種風險。

最佳實踐

  1. 避免使用原生 OPRETURN:使用 OPRETURN 嵌入資料時,確保資料不包含敏感資訊。
  1. 驗證所有輸入:不要假設來自網路的腳本是安全的,總是進行完整驗證。
  1. 使用足夠的確認數:根據交易金額選擇適當的確認數。建議:
  1. 離線簽名:對於大額交易,使用離線設備進行簽名,確保私鑰不會暴露在網路連線的設備上。

腳本範例實作

以下展示幾個實際的腳本範例與其應用場景。

範例 1:簡單的時間鎖定輸出

假設 Alice 想將比特幣鎖定一年後才能提取:

# 鎖定腳本
<oneYearFromNow> OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 <AlicePubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

這個腳本確保只有 Alice 本人在一年後才能花費這筆比特幣。

範例 2:2-of-3 信託結構

假設三個受益人需要至少兩人同意才能動用遺產:

# 鎖定腳本
OP_2 <BeneficiaryA_PubKey> <BeneficiaryB_PubKey> <BeneficiaryC_PubKey> OP_3 OP_CHECKMULTISIG

範例 3:離散對數合約(DLC)

DLC 使用比特幣腳本實現對離事件的押注:

# 簡化版 DLC 鎖定腳本
OP_SHA256 <oracleOutcomeHash> OP_EQUALVERIFY
OP_IF
    <winnerPubKey>
OP_ELSE
    <loserPubKey>
OP_ENDIF
OP_CHECKSIG

Oracle 揭示結果的雜湊值後,獲勝方可以提取資金。

未來發展方向

比特幣腳本語言持續演進,以下是幾個值得關注的發展方向:

Script Versioning

未來可能引入腳本版本控制機制,允許在不硬分叉的情況下引入新的腳本功能。

比特幣智慧合約

隨著 RGB、Stacks 等第二層協議的發展,比特幣腳本的應用範圍正在擴展。這些協議在比特幣結算層之上構建了更複雜的智慧合約邏輯。

零知識證明整合

zkSNARK 與 zkSTARK 等零知識證明技術正在被探索應用於比特幣,以實現隱私保護與擴展性提升。

結語

比特幣腳本語言是比特幣系統中最具技術深度的組件之一。儘管其設計簡單、限制嚴格,卻為比特幣提供了足夠的表現力來實現多簽名、時間鎖定、原子交換等進階功能。理解比特幣腳本的運作原理,不僅對於比特幣開發者至關重要,對於希望深入理解比特幣安全模型與應用場景的一般用戶也極具價值。隨著 Taproot 升級的實施與第二層解決方案的成熟,比特幣腳本將在未來的比特幣生態系統中扮演更加重要的角色。


相關文章

延伸閱讀與來源

這篇文章對您有幫助嗎?

評論

發表評論

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

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