鎖進微型謎題盒的幣
想像一個有巧思的行李寄存櫃:它沒有固定的鑰匙,而是在櫃門上印著一道小小的謎題。誰能答出謎題,誰就能打開它。大多數謎題都很簡單——*「證明你擁有配對的鑰匙」*——但造櫃人原則上也能印上更古怪的題目。
比特幣幾乎就是這樣運作的。你持有的每一枚幣,實際上是鏈上一個未花費輸出,每個輸出都附帶一個小程式——鎖定腳本——上面寫著那道謎題。要花掉它,你得提供一個解鎖腳本,也就是你的答案。網路把這兩段腳本拼在一起執行,如果最終給出「通過」,這枚幣就歸你支配。書寫這些謎題所用的語言,就叫 Script。
Script 如何執行:一疊盤子
Script 是一門以堆疊為基礎的語言,而堆疊不過是一疊盤子:你只能往最上面加一個盤子(壓入 push),或把最上面那個拿走(彈出 pop)。腳本就是一串從左到右讀取的指令。有些指令負責壓入資料——一個數字、一段簽章、一把密鑰;另一些是操作碼(opcode),會彈出一兩個盤子,做點運算,再把結果壓回去。
要校驗一次花費,節點先擺上你的解鎖腳本,再接上鎖定腳本,然後整段一起執行。最後的判定規則簡單得令人愉快:如果堆疊頂端的盤子是「真」(一個非零值),幣就解鎖;如果堆疊最終為空、為假,或腳本撞上了被禁止的動作,這次花費就被拒絕。
unlocking: <push 3> <push 4> locking: OP_ADD <push 7> OP_EQUAL stack walk-through (top is rightmost): push 3 -> [ 3 ] push 4 -> [ 3, 4 ] OP_ADD -> [ 7 ] # pop 3 and 4, push 3+4 push 7 -> [ 7, 7 ] OP_EQUAL -> [ true ] # pop both, equal? push true Top plate is true -> coin unlocks.
日常謎題:付款給公鑰雜湊
幾乎所有真實的幣都使用一種標準謎題,付款給公鑰雜湊(P2PKH)。用大白話說就是:*「要花掉我,請出示一把雜湊後等於這個位址的公鑰,外加一段由其配對私鑰簽出的有效簽章。」* 它把幣綁定在唯一的所有者身上,而且直到花費那一刻才暴露公鑰——這在隱私與安全上都是漂亮的一手。
locking (on the coin): OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG unlocking (you provide): <signature> <pubKey> idea: 1. duplicate your pubKey, hash it 2. EQUALVERIFY: must match the address baked in 3. CHECKSIG: signature must be valid for that key all pass -> true -> spend allowed
請留意這道謎題做的事其實少得可憐:複製、雜湊、比較、驗證一段簽章。沒有迴圈,沒有「如果價格高於 X」,也不會向網際網路發起呼叫。這種簡約並不是缺了功能——它本身就是核心用意,下一節會解釋。
刻意做小:沒有迴圈,沒有意外
Script 是刻意設計成非圖靈完備的。尤其是它沒有迴圈、不能向後跳轉——一段腳本總是筆直、有限地走完,然後停下。這聽起來像缺點,卻換來兩條無價的保證。其一,每個節點都知道腳本會很快結束;沒法寫出一段永遠執行、把網路卡死的腳本。其二,校驗一筆交易的成本在執行前就是可預測的。
即便如此,Script 也不止於「單一所有者」的謎題。一種流行的模式是多重簽章(multisig)——「N 把密鑰裡必須有 M 把簽章」。一個共享的企業錢包可以這樣鎖定資金:需要 3 選 2 的公司董事才能放款,從而消除任何單點故障。這道謎題只是收集幾段簽章,再數一數其中有效的有幾段。
2-of-3 multisig locking script: OP_2 <pubKey_A> <pubKey_B> <pubKey_C> OP_3 OP_CHECKMULTISIG unlocking (any two valid signatures): OP_0 <sig_from_A> <sig_from_C> meaning: "release the coin only if at least 2 of these 3 named keys each sign." (the leading OP_0 is a dummy: OP_CHECKMULTISIG has an old off-by-one bug that pops one extra item.)
天花板——以及通往以太坊的橋
多重簽章,再加上少數幾種時間鎖和雜湊鎖的小花招,差不多就是純 Script 所能表達的極限了。你無法寫出「只有當某隊贏了比賽才付款」,或「每月把這筆房租分給十位租客」,或「營運一個小型借貸市場」。Script 能用巧妙的鎖守住一枚幣,卻撐不起一個持續存在、帶狀態、能持有資金並隨時間作出反應的程式。
正是這道天花板,催生了下一個大想法。既然一枚幣能攜帶一個*小*程式,為什麼不能攜帶一個完整的程式——帶迴圈、帶記憶體,能自由表達任何規則呢?這個問題,給了我們智慧合約,以及圍繞它建構的各種網路。比特幣選擇了一把緊緻、極度安全的鎖;下一條學習線則選擇了純粹的可程式化能力,並用另一套方式去管理隨之而來的新風險。