比特幣指令碼及交易分析 - 智慧合約雛形

Tiny熊發表於2017-11-13

最新內容會更新在主站深入淺出區塊鏈社群
原文連結:比特幣指令碼及交易分析 - 智慧合約雛形

大家都有轉過賬,每筆交易是這樣的:張三賬上減¥200,李四賬上加¥200。
在比特幣區塊鏈中,交易不是這麼簡單,交易實際是通過指令碼來完成,以承載更多的功能個,這也是為什麼比特幣被稱為是一種“可程式設計的貨幣”。
本文就來分析一下交易是如何實現可程式設計的。

未花費的交易輸出(UTXO)

先引入一個概念:未花費的交易輸出——UTXO(Unspent Transaction Output)

其實比特幣的交易都是基於UTXO上的,即交易的輸入是之前交易未花費的輸出,這筆交易的輸出可以被當做下一筆新交易的輸入。

挖礦獎勵屬於一個特殊的交易(稱為coinbase交易),可以沒有輸入。
UTXO是交易的基本單元,不能在分割。
在比特幣沒有餘額概念,只有分散到區塊鏈裡的UTXO

隨著錢從一個地址被移動到另一個地址的同時形成了一條所有權鏈,像這樣:
own_chain

比特幣指令碼

比特幣交易是首先要提供一個用於解鎖UTXO(用私鑰去匹配鎖定指令碼)的指令碼(常稱為解鎖指令碼:Signature script),這也叫交易輸入,
交易的輸出則是指向一個指令碼(稱為鎖定指令碼:PubKey script),這個指令碼表達了:誰的簽名(簽名是常見形式,並不一定必須是簽名)能匹配這個輸出地址,錢就支付給誰。

每一個比特幣節點會通過同時執行這解鎖和鎖定指令碼(不是當前的鎖定指令碼,是指上一個交易的鎖定指令碼)來驗證一筆交易,指令碼組合結果為真,則為有效交易。

當解鎖版指令碼與鎖定版指令碼的設定條件相匹配時,執行組合有效指令碼時才會顯示結果為真

如最為常見型別的比特幣交易指令碼(支付到公鑰雜湊:P2PKH(Pay-to-Public-Key-Hash))組合是這樣:
script

常見交易指令碼驗證過程

比特幣交易指令碼語言是一種基於逆波蘭表示法的基於棧的執行語言(不知道逆波蘭和棧的同學去翻大學資料結構課本,你也可跳過這個部分)。

比特幣指令碼語言包含基本算數計算、基本邏輯(比如if…then)、報錯以及返回結果和一些加密指令,不支援迴圈。想了解更多語言細節可參考:比特幣指令碼

指令碼語言通過從左至右地處理每個專案的方式執行指令碼。

下面用兩個圖說明下常見型別的比特幣交易指令碼驗證執行過程:
script_run1
上圖為解鎖指令碼執行過程(主要是入棧)
script_run2
上圖為鎖定指令碼執行過程(主要是出棧),最後的結果為真,說明交易有效。

交易分析

實際上比特幣的交易被設計為可以納入多個輸入和輸出。

交易結構

我們來看看完整的交易結構,
比特幣指令碼及交易分析 - 智慧合約雛形

交易的鎖定時間定義了能被加到區塊鏈裡的最早的交易時間。在大多數交易裡,它被設定成0,用來表示立即執行。
如果鎖定時間不是0並且小於5億,就被視為區塊高度,意指在這個指定的區塊高度之前,該交易不會被包含在區塊鏈裡。
如果鎖定時間大於5億,則它被當作是一個Unix紀元時間戳(從1970年1月1日以來的秒數),並且在這個指定時間之前,該交易不會被包含在區塊鏈裡。

交易的資料結構沒有交易費的欄位,交易費通過所有輸入的總和,以及所有輸出的總和之間的差來表示,即:

交易費 = 求和(所有輸入) - 求和(所有輸出)

交易輸入結構

剛剛我們提過輸入需要提供一個解鎖指令碼,現在來看看一個交易的輸入結構:
比特幣指令碼及交易分析 - 智慧合約雛形

我們結合整個交易的結構裡看輸入結構就是這樣子:
比特幣指令碼及交易分析 - 智慧合約雛形

交易輸出結構

剛剛我們提過輸出是指向一個解鎖指令碼,具體交易的輸出結構為:
比特幣指令碼及交易分析 - 智慧合約雛形
我們結合整個交易的結構裡看輸出結構就是這樣子:
比特幣指令碼及交易分析 - 智慧合約雛形

交易雜湊計算

比特幣區塊結構Merkle 樹及簡單支付驗證分析 講到區塊結構,區塊結構包含多個交易的雜湊。
那麼交易雜湊是怎麼計算的呢?

  1. 交易結構各欄位序列化為位元組陣列
  2. 把位元組陣列拼接為支付串
  3. 對支付串計算兩次SHA256 得到交易hash

瞭解詳情可進一步參考如何計算交易Hash?如何建立Hash?

現在是不是對完整的交易到區塊有了更清晰的認識。

智慧合約雛形 - 應用場景說明

由於交易是通過指令碼來實現,指令碼語言可以表達出無數的條件變種。

比特幣的指令碼目前常用的主要分為兩種,一種是常見的P2PKH(支付給公鑰雜湊),另一種是P2SH(Pay-to-Script-Hash支付指令碼雜湊)。
P2SH支付中,鎖定指令碼被密碼學雜湊所取代,當一筆交易試圖支付UTXO時,要解鎖支付指令碼,它必須含有與雜湊相匹配的指令碼。

這裡不展開技術細節,下面說明一些應用場景,以便大家有更直觀的認識。

  • 多重簽名應用
    合夥經營中,如只有一半以上的的股東同意簽名就可以進行支付,可為公司治理提供管控便利,同時也能有效防範盜竊、挪用和遺失。

用於擔保和爭端調解,一個買家想和他不認識或不信任的某人交易,在一般情況交易正常進行時,買家不想任何第三方參與。那交易雙方可以發起支付,但如果交易出現問題時,那第三方就可以根據裁定,使用自己的簽名和裁定認可的一方共同簽名來兌現這筆交易。

  • 保證合同
    保證合同是建造公眾商品時的集資辦法,公眾商品是指一旦建成,任何人都可以免費享受到好處。標準的例子是燈塔,所有人都認同應該建造一個,但是對於個人航海者來說燈塔太貴了,燈塔同時也會方便其他航海者。
    一個解決方案是向所有人集資,只有當籌集的資金超過所需的建造成本時,每個人才真正付錢,如果集資款不足,則誰都不用付錢。
  • 依靠預言
    假如老人想讓他孫子繼承遺產,繼承時間是在他死後或者在孫子年滿18歲時(也是一個帶鎖定時間交易),無論哪個條件先滿足,他的孫子都可以得到遺產。
    因為比特幣節點可依靠預言對死亡條件進行判斷,預言是指具有金鑰對的伺服器,當使用者自定義的表示式被證明是真的,它能按照要求對交易簽名。

相信隨著區塊鏈的普及,會對未來的交易模式和商業結構帶來巨大的影響。不過由於比特幣的指令碼語言不是圖靈完備的,交易模式依舊有限,以太坊就是為解決這一問題而出現,後面我們會有大量介紹以太坊的文章。

參考文獻 & 補充閱讀

  1. 精通比特幣
  2. 廖雪峰的深入理解比特幣交易的指令碼
  3. 比特幣合同

相關文章