UTXO 模型的介紹
作者:閃電豹貓 原創文章,轉載需注明出處。
“哪有什么比特幣,不過是一堆 UTXO 的相加罷了”,我說到。
0. TL;DR
UTXO, 全稱 Unspent Transaction Output,即“未花費的交易輸出”。UTXO 的概念來自比特幣,是比特幣網絡的最基本、最重要的組成之一。與 UTXO 模型相對的是 “賬戶-余額 (Account - Balance)” 模型,后者是我們日常生活中常見的模型,如銀行賬戶和支付寶微信的余額賬戶,同時后者也是第二大區塊鏈網絡——以太坊所采用的模型。本隨筆主要研究這種極具創新性的 UTXO 模型。
所謂的 UTXO 是指關聯在某個比特幣地址的比特幣金額的集合,是一個包含了數據和可執行代碼的數據結構。一個 UTXO 的最小單位是 1 聰, 即 1x10^-8 比特幣,在比特幣網絡中,1 聰即是比特幣的基本單位,1 聰不可再拆分成更小數額的比特幣。一個 UTXO 創建后就不可分割,只能將其花掉,而花掉 UTXO 又會產生新的 UTXO, 這樣子周而復始地實現比特幣價值的轉移。
本文所有提到的 “交易”,若無特殊說明外,全部指的是比特幣網絡鏈上交易。一筆交易由輸入和輸出組成,而 UTXO 是這個交易輸入輸出的一部分,所以我們也稱 UTXO 是交易最基本的組成單元。
每一個 UTXO 都含有一定數量的資產(即比特幣),同時伴隨着一個鎖定腳本。鎖定腳本其實就是資產指向一個比特幣地址而設置的花費條件,只有滿足了這個花費條件的人,才可以花掉這個 UTXO 所包含的資金。通俗的來講,只有持有某個地址的私鑰的人才可以花掉該地址的 UTXO,沒有私鑰的人無法花費該地址的 UTXO。
一般來說,交易都是包含了許多(或者一個)輸入和輸出。特殊的,有些交易沒有輸入、只有輸出,這樣的交易我們稱之為 coinbase 交易(這個 coinbase 和上市公司 Coinbase 沒有關系)。一筆 coinbase 交易也被成為創幣交易,因為這筆交易為比特幣系統創造了比特幣,這筆創造出來的比特幣就是系統對於礦工的工作量證明的獎勵,也就是所說的比特幣礦工的 “爆塊獎勵”。
下面給出幾筆比特幣鏈上交易的實例的鏈接:
- 一筆普通的交易,輸入1個UTXO,輸出2個UTXO
- 另一筆普通的交易,輸入61個UTXO,輸出28個UTXO
- 比特幣網絡的第一筆交易,發生於2009年1月4日,同時也是一個coinbase交易,沒有輸入,輸出1個UTXO
UTXO 模型原理簡單,每一筆 UTXO 的輸入都來自上一筆 UTXO 的輸出,直到 coinbase 交易為止。UTXO 模型隱匿性強,可以說原生支持洗qian。UTXO 模型支持高度並行處理,這是賬戶余額模型所做不到的。還有,UTXO 緊湊,賬本空間小,最適合去中心化,也最適合存儲和驗證。但是,以 UTXO 模型為底層,開發錢包十分費勁;查詢賬戶余額還需要從創世區塊開始統計所有與該地址相關聯的 UTXO,也十分費勁。
1. 比特幣網絡鏈上轉賬
假設 Alice 給 Bob 轉賬,則轉賬可分為三個階段:
- 假設 Alice 之前通過挖礦獲得了 6.25 個比特幣,那么在她的地址中,這 6.25 個比特幣是某個 coinbase 交易的 UTXO。
- Alice 發起一筆交易,輸入是自己的上一筆交易,輸出是 Bob 的地址,數量為 6.25 BTC,不考慮礦工手續費。Alice 對該交易用自己的私鑰進行簽名。
- 當交易被全網確認后,Alice 的 UTXO 就變成了 0。而 Bob 的地址則新增了一個 UTXO,來自 Alice 且包含 6.25 BTC。
這里只是一個非常簡化的情況,即交易只有一個輸入的情況。按照比特幣系統的設計,比特幣交易還要遵循一個原則:輸入的 UTXO 的必須全部花掉,不能只花掉 UTXO 的一部分。比如 Alice 還是只擁有來自 coinbase 交易的 6.25 BTC,如果她只想轉出 4 BTC 給 Bob,那么她需要讓這筆交易包含兩個輸出,這兩個輸出分別是 1) Alice 轉給 Bob 的 4 BTC;2) Alice 轉給 Alice 的 2.25 BTC。這樣,交易確認后,Alice 擁有 1 個 UTXO,來自 Alice 且 包含 2.25 BTC;Bob 則新增了一個 UTXO,來自 Alice 且包含 4 BTC。
任何擁有 Alice 和 Bob 比特幣地址人都可以在比特幣網絡上查詢 Alice 和 Bob 的地址現在所持有的 UTXO 和所有歷史交易。而只有持有 Bob 地址對應私鑰的人,才可以花掉 Bob 地址所持有的 UTXO,哪怕不是 Bob 本人。如果 Bob 想發起轉賬,那就重復上述過程。所以,私鑰很重要,別告訴別人你的私鑰;還有別拿私鑰對來源不明的消息進行加密或簽名,這樣可以避免密文攻擊導致的比特幣被非授權使用。
2. UTXO 模型基本規則
- 所有比特幣都必須來源於前面某一個或者幾個交易的 UTXO,除非是爆塊獎勵的比特幣。
- 任何一筆交易的輸入比特幣之和必須等於輸出比特幣之和(礦工費視為包含在輸出里的話)。可以看成 “等式兩邊必須配平”。
數字資產(包括加密貨幣和你的銀行卡余額)無法像實物貨幣(如金、銀、紙幣和硬幣)一樣能夠物理轉移——即當 Alice 將一根金條交給 Bob 后,Alice 必然不再擁有這根金條。而 Alice 將數字資產簽名再轉賬給 Bob 后,因為 Alice 掌握自己地址的私鑰,Alice 完全可以在交易未被確認時,再簽名轉賬給 Carl。因為 Alice 的這兩份簽名都是有效簽名,所以這可能導致 “雙花”,即雙重花費數字資產。對於銀行和支付寶等機構,需要引入成本代價高昂且可信任的第三方來驗證一筆錢是否被雙花,這個第三方機構如果不可信或作惡,則會給該數字資產網絡帶來可逆轉的危害;而對於比特幣網絡而言,從 UTXO 原理來看,雙花發生概率很低而且極易被全網驗證時所發現並剔除。比特幣這種機制就是 UTXO 模型的基本規則。每一筆輸入同時也需要上一筆輸出所對應的私鑰進行簽名,而且每個礦工都存儲着比特幣網絡所有 UTXO 的信息,全網礦工通過 UTXO 規則及簽名算法就可以驗證新交易的合法性,這樣,礦工就不需要追溯歷史交易就可以驗證一筆新交易了。有關雙花攻擊的防御,不是本文的重點,以后可能會專門開篇隨筆來討論。
3. 技術原理
3.1 比特幣交易的基本單位
比特幣鏈上交易的基本單位是 UTXO。
3.2 交易的輸入與輸出
交易的本質是結構體:
字段 | 名稱 | 描述 | 類型 | 大小 |
---|---|---|---|---|
版本 | version | 這筆交易參照的規則 | uint32 | 4 字節 |
輸入數量 | tx_in_count | 交易輸入列表中的數量 | uint | 1 - 9 字節 |
輸入列表 | tx_in | 一個或多個交易輸入 | tx_in | 不定 |
輸出數量 | tx_out_count | 交易輸出列表中的數量 | uint | 1 - 9 字節 |
輸出列表 | tx_out | 一個或多個交易輸出 | tx_out | 不定 |
鎖定時間 | lock_time | 鎖定時間 | uint32 | 4 字節 |
從結構來看,交易主要的兩個單元字段就是交易的輸入和輸出。輸入標識着交易的發送方,輸出標識着交易的接收方及給自己的 “找零”,在各類區塊鏈瀏覽器上能看到的輸入比特幣之和與輸出比特幣之和之差就是這筆交易的礦工費。由於所有交易的輸入必然是前面某筆交易的輸出,所以交易最核心的字段是交易的輸出。
一個示例交易的數據分析如下:
01000000 ................................... Version
01 ......................................... Number of inputs
|
| 7b1eabe0209b1fe794124575ef807057
| c77ada2138ae4fa8d6c4de0398a14f3f ......... Outpoint TXID
| 00000000 ................................. Outpoint index number
|
| 49 ....................................... Bytes in sig. script: 73
| | 48 ..................................... Push 72 bytes as data
| | | 30450221008949f0cb400094ad2b5eb3
| | | 99d59d01c14d73d8fe6e96df1a7150de
| | | b388ab8935022079656090d7f6bac4c9
| | | a94e0aad311a4268e082a725f8aeae05
| | | 73fb12ff866a5f01 ..................... Secp256k1 signature
|
| ffffffff ................................. Sequence number: UINT32_MAX
01 ......................................... Number of outputs
| f0ca052a01000000 ......................... Satoshis (49.99990000 BTC)
|
| 19 ....................................... Bytes in pubkey script: 25
| | 76 ..................................... OP_DUP
| | a9 ..................................... OP_HASH160
| | 14 ..................................... Push 20 bytes as data
| | | cbc20a7664f2f69e5355aa427045bc15
| | | e7c6c772 ............................. PubKey hash
| | 88 ..................................... OP_EQUALVERIFY
| | ac ..................................... OP_CHECKSIG
00000000 ................................... locktime: 0 (a block height)
3.2.1 交易輸入
每個非 coinbase 交易都是之前某個交易的交易輸出。
交易輸入的結構如下:
大小(字節) | 名稱 | 數據類型 | 描述 |
---|---|---|---|
32 | previous_output_hash | outpoint | 前置交易hash |
4 | previous_output_index | uint32 | 前置交易index |
varint 不定 | script_bytes | uint | 解鎖腳本長度 |
varies 不定 | signature_script | char[] | 解鎖腳本 |
4 | sequence | uint32 | 序列號 |
3.2.2 交易輸出
結構如下:
大小(字節) | 名稱 | 數據類型 | 描述 |
---|---|---|---|
8 | value | int64 | 比特幣數量,單位是聰 |
1+ | pk_script_size | uint | pubkey 腳本中的字節數量 |
varies 不定 | pk_script | char[] | 花費這筆輸出需要滿足的條件 |
3.3 可變長度整數 varint
一筆交易中,用可變長度整數來表示下一條字段的字符數。對於不同的數值,可變長度整數所占用的空間大小不一樣。
值范圍 | 空間(字節) | 實際數據類型 |
---|---|---|
[0, 252] | 1 | uint8_t |
[253, 0xffff] | 3 | 后 2 個字節 uint16_t |
[0x10000, 0xffffffff] | 5 | 后 4 個字節 uint32_t |
[0x100000000, 0xffffffffffffffff] | 9 | 后8個字節 uint64_t |
這樣,有關 UTXO 模型的內容也就差不多介紹完了,歡迎在評論區留言討論來補充;若本文存在錯誤,也歡迎指出,咱們一起進步啊。