UTXO 模型詳解
比特幣的未花費交易輸出模型與帳戶模型比較。
UTXO 模型詳解:比特幣帳本的核心機制
比特幣採用 UTXO(Unspent Transaction Output)模型,這與傳統銀行帳戶模型有本質區別。理解 UTXO 模型是掌握比特幣運作原理的關鍵基礎,本文將深入探討其技術細節、實現原理與實際應用場景。
UTXO 模型基礎概念
什麼是 UTXO?
UTXO = Unspent Transaction Output(未花費的交易輸出)
每次比特幣交易都會:
- 消耗一個或多個輸入(UTXO)
- 創造一個或多個輸出(新的 UTXO)
這種模型類似現金鈔票的運作方式:当你使用一张 10 元钞票购买 3 元的商品时,你会给出 10 元,找零 7 元。原来的 10 元钞票被「花费」消失了,变成了找零的 7 元和商家的 3 元(假设商家不需要找零)。
UTXO 的生命週期
每個 UTXO 都會經歷以下階段:
創建(Generation)
↓
未花費狀態(Unspent)
↓
花費狀態(Spent)→ 成為新交易的輸入
↓
最終可能成為新的 UTXO 或永遠保持花費狀態
UTXO vs 帳戶模型
比特幣(UTXO 模型)
- 每筆交易引用之前的輸出作為輸入
- 餘額 = 所有可花費 UTXO 的總和
- 更好的隱私性(每次交易可使用新地址)
- 交易驗證可並行處理
- 無法實現複雜的帳戶狀態邏輯
以太坊(帳戶模型)
- 餘額直接存儲在帳戶狀態中
- 狀態資料庫管理所有帳戶餘額(MPT 樹)
- 更適合智慧合約邏輯
- 狀態更新需要順序處理
- 實現更簡單但隱私性較差
兩種模型的對比
| 特性 | UTXO 模型(比特幣) | 帳戶模型(以太坊) |
|---|---|---|
| 餘額表示 | UTXO 集合總和 | 帳戶狀態字段 |
| 狀態存储 | UTXO 集合 | 狀態樹(MPT) |
| 交易驗證 | 可並行 | 需順序處理 |
| 隱私性 | 較高 | 較低 |
| 智慧合約 | 有限支持 | 完全支持 |
| 擴展性 | 較好 | 較差 |
UTXO 集合的技術實現
UTXO 資料結構
比特幣中的 UTXO 由以下組成:
class UTXO:
def __init__(self, txid, index, amount, scriptPubKey, coinbase=False):
self.txid = txid # 交易 ID(256 位元雜湊)
self.index = index # 輸出索引(0, 1, 2...)
self.amount = amount # 金額(以 satoshi 為單位)
self.scriptPubKey = scriptPubKey # 鎖定腳本
self.coinbase = coinbase # 是否為 coinbase 交易
self.height = 0 # 區塊高度
self.confirmations = 0 # 確認數
UTXO 集合的存儲
比特幣節點使用多種資料結構來高效管理 UTXO 集合:
UTXO 集(UTXO Set):包含所有未花費的交易輸出
- 截至 2026 年 2 月,比特幣 UTXO 集合約有 1.5 億個 UTXO
- 總大小約 6-7 GB
UTXO 壓縮:UTxO Commitment(已提議但未完全部署)
- 允許輕客戶端驗證 UTXO 集合的 Merkle 證明
- 減少全節點的硬碟空間需求
比特幣核心的 UTXO 管理
比特幣核心(Bitcoin Core)使用以下資料結構:
UTXO 集合
│
├── 內存池(Memory Pool / Mempool)
│ └── 尚未打包到區塊的交易輸出
│
└── 資料庫(LevelDB)
└── 已確認的 UTXO
// 比特幣核心的 UTXO 視圖介面
class CCoinsView {
public:
// 獲取某個 UTXO
virtual bool GetCoin(const COutPoint &outpoint, Coin &coin) const;
// 獲取 UTXO 集合的頭部雜湊
virtual uint256 GetBestBlock() const;
// 批量獲取多個 UTXO
virtual bool GetCoins(const std::vector<COutPoint> &outpoints,
std::vector<Coin> &coins) const;
};
交易驗證中的 UTXO
輸入輸出的對應關係
比特幣交易的輸入輸出結構:
交易結構:
├── 版本號(4 bytes)
├── 輸入數量(1-9 bytes)
├── 輸入列表
│ ├── 前置交易 ID(32 bytes)
│ ├── 前置輸出索引(4 bytes)
│ ├── 解鎖腳本長度
│ ├── 解鎖腳本(signature script)
│ └── 序列號(4 bytes)
├── 輸出數量(1-9 bytes)
├── 輸出列表
│ ├── 金額(8 bytes)
│ ├── 鎖定腳本長度
│ └── 鎖定腳本(scriptPubKey)
└── 見證數據(如果是 SegWit)
驗證過程
交易驗證涉及以下步驟:
- 輸入驗證:確認每個輸入引用的 UTXO 存在
- 腳本驗證:執行解鎖腳本與鎖定腳本
- 金額驗證:輸入總額 ≥ 輸出總額 + 費用
- 簽名驗證:確認交易被正確授權
def verify_transaction(tx, utxo_set):
# 步驟 1:驗證所有輸入引用的 UTXO 存在
total_input = 0
for input in tx.inputs:
utxo = utxo_set.get(input.prev_outpoint)
if utxo is None:
return False, "UTXO not found"
# 步驟 2:驗證腳本
if not verify_script(input.unlock_script, utxo.lock_script):
return False, "Script verification failed"
total_input += utxo.amount
# 步驟 3:驗證金額
total_output = sum(tx.outputs.amount)
fees = total_input - total_output
if fees < MINIMUM_FEE:
return False, "Insufficient fees"
return True, "Transaction valid"
費用計算
比特幣費用基於交易大小(vbytes)而非金額:
def calculate_fee(tx_size_vbytes, fee_rate_sat_per_vbyte):
"""
fee_rate_sat_per_vbyte: 每 vbyte 的 satoshi 數量
典型值:1-10 sat/vbyte(根據網路擁塞程度)
"""
return tx_size_vbytes * fee_rate_sat_per_vbyte
# 費用範例(2026 年 2 月數據):
# - 網路閒置:1-5 sat/vbyte
# - 網路繁忙:10-50 sat/vbyte
# - 網路擁塞:50-200 sat/vbyte
錢包如何管理 UTXO
餘額計算
比特幣錢包通過掃描區塊鏈來計算餘額:
class Wallet:
def __init__(self):
self.utxo_cache = {}
def calculate_balance(self, addresses):
"""
計算錢包餘額:所有屬於該錢包的 UTXO 總和
"""
balance = 0
for address in addresses:
# 錢包需要追蹤所有可能屬於自己的 UTXO
for utxo in self.iterate_utxo_set():
if utxo.matches_address(address):
balance += utxo.amount
return balance # 單位:satoshi
def get_balance_breakdown(self, addresses):
"""
獲取餘額細分:已確認 vs 未確認
"""
confirmed = 0
unconfirmed = 0
for address in addresses:
for utxo in self.iterate_utxo_set():
if utxo.matches_address(address):
if utxo.confirmations >= 1:
confirmed += utxo.amount
else:
unconfirmed += utxo.amount
return {
'confirmed': confirmed,
'unconfirmed': unconfirmed,
'total': confirmed + unconfirmed
}
UTXO 選擇策略
錢包在構造交易時需要選擇使用哪些 UTXO:
First-In-First-Out (FIFO):最先收到的 UTXO 優先花費
Highest-First:金額最大的 UTXO 優先花費
Coin Selection Algorithm(比特幣核心):
def coin_selection(target_amount, utxo_set):
"""
比特幣核心的 Coin Selection 演算法
目標:最小化交易費用 + 最小化 UTXO 碎片化
"""
selected = []
target_with_fees = target_amount + estimate_fees()
# 嘗試小金額 UTXO
for utxo in utxo_set.small_first():
if sum(selected) >= target_with_fees:
break
selected.append(utxo)
# 如果不足,嘗試中等金額
if sum(selected) < target_with_fees:
# 切換到 BnB 演算法
selected = branch_and_bound(target_with_fees, utxo_set)
return selected
UTXO 碎片化問題
碎片化的成因
當餘額分散在多個小額 UTXO 時,會造成以下問題:
- 交易費用較高:每個輸入都需要費用
- 錢包管理複雜:追蹤大量小額 UTXO
- 隱私風險:碎片化的 UTXO 可能透露餘額資訊
碎片化範例
假設用戶有 0.1 BTC,分散在 10 個 0.01 BTC 的 UTXO:
- 普通交易(2 輸入 2 輸出):約 400 vbytes
- 費用(10 sat/vbyte):4,000 satoshi = 0.00004 BTC
- 佔比:0.04%
相比單一 UTXO:
- 單一 UTXO 交易:約 200 vbytes
- 費用:2,000 satoshi = 0.00002 BTC
- 佔比:0.02%
費用增加一倍!
解決方案:CoinJoin
CoinJoin 是一種將多個用戶的交易合併的技術:
def coinjoin(transactions):
"""
合併多個用戶的交易輸入和輸出
外部觀察者無法確定資金流向
"""
combined_inputs = []
combined_outputs = []
for tx in transactions:
combined_inputs.extend(tx.inputs)
combined_outputs.extend(tx.outputs)
# 重新分配輸出金額,保持總額不變
# 但輸入輸出對應關係被打亂
return create_merged_transaction(combined_inputs, combined_outputs)
進階主題:UTXO 與比特幣腳本
常見的鎖定腳本類型
P2PKH(Pay to Public Key Hash):
# 鎖定腳本:OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
# 解鎖腳本:<signature> <pubKey>
P2WPKH(Pay to Witness Public Key Hash):
# 鎖定腳本( witness program):OP_0 <pubKeyHash>
# 解鎖數據(witness):<signature> <pubKey>
P2SH(Pay to Script Hash):
# 鎖定腳本:OP_HASH160 <scriptHash> OP_EQUAL
# 解鎖腳本:<redeemScript> <signature1> <signature2>...
P2WSH(Pay to Witness Script Hash):
# 鎖定腳本:OP_0 <scriptHash>
# 解鎖數據(witness):<redeemScript> <witness>...
腳本類型的選擇
| 腳本類型 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| P2PKH | 簡單 | 較大交易 | 兼容性優先 |
| P2WPKH | 費用低 | 較新 | 推薦使用 |
| P2SH | 可嵌套 | 費用較高 | 智能合約 |
| P2WSH | 最低費用 | 複雜 | 高隱私需求 |
比特幣網路數據(2026 年 2 月)
根據最新的比特幣網路數據:
- 總節點數量:約 19,000 個公開可訪問節點
- 每日交易量:約 500,000 - 1,000,000 筆交易
- 平均區塊大小:2-4 MB(SegWit)
- 平均區塊交易數:2,000-4,000 筆
- UTXO 集合大小:約 1.5 億個 UTXO
- 內存池大小:根據網路擁塞程度波動
- 平均交易費用:5-15 sat/vbyte(閒置)/ 20-100 sat/vbyte(繁忙)
UTXO 模型的安全性分析
雙花攻擊
UTXO 模型天然防止雙花攻擊:
- 每個 UTXO 只能被花費一次
- 區塊鏈共識確保最長鏈
- 51% 攻擊是理論上唯一的雙花方式
重放攻擊
比特幣交易包含:
- 前置交易的特定引用(txid + index)
- 簽名綁定到特定交易
- 序列號(nSequence)
這些機制防止交易被重放:
def is_replay_protected(tx, blockchain):
"""
檢查交易是否有重放保護
"""
# BIP-125:Opt-In RBF(Replace-By-Fee)
if tx.is_opt_in_rbf:
# nSequence < 0xFFFFFFFF - 1
return True
# Sighash type 影響簽名範圍
# SIGHASH_ALL:整個交易
# SIGHASH_NONE:只簽名輸入
# SIGHASH_SINGLE:輸入 + 對應輸出
return True
結論
UTXO 模型是比特幣帳本的核心設計,具有以下關鍵特性:
- 簡單性:狀態就是 UTXO 集合,無需複雜的帳戶管理
- 隱私性:每次交易可生成新地址,難以追蹤資金流向
- 可擴展性:交易驗證可並行處理
- 安全性:雙花攻擊難以實現
理解 UTXO 模型對於比特幣開發者、資深用戶和投資者都至關重要。隨著比特幣網路的发展,UTXO 集合將繼續成長,管理 UTXO 的技術也將持續演進。
相關文章:
本文包含
相關文章
- Merkle 樹與 SPV 驗證 — 理解比特幣區塊頭的 Merkle 根與簡化支付驗證。
- UTXO 隱私管理完整指南 — 深入介紹比特幣 UTXO 隱私管理策略,包括避免合併、金額標準化、PayJoin 與 CoinJoin 技術。
- 比特幣腳本語言入門 — 理解 Bitcoin Script 的基本指令與運作原理。
- Bitcoin Core 節點運作 — 運行完整節點,理解比特幣網路的運作機制。
- 比特幣與以太坊:完整技術比較 — 從共識機制、帳戶模型、智慧合約、擴展性等維度全面比較比特幣與以太坊的技術架構差異。
延伸閱讀與來源
- UTXO 模型說明 比特幣開發者文檔
這篇文章對您有幫助嗎?
請告訴我們如何改進:
評論
發表評論
注意:由於這是靜態網站,您的評論將儲存在本地瀏覽器中,不會公開顯示。
目前尚無評論,成為第一個發表評論的人吧!