UTXO 模型詳解

比特幣的未花費交易輸出模型與帳戶模型比較。

UTXO 模型詳解:比特幣帳本的核心機制

比特幣採用 UTXO(Unspent Transaction Output)模型,這與傳統銀行帳戶模型有本質區別。理解 UTXO 模型是掌握比特幣運作原理的關鍵基礎,本文將深入探討其技術細節、實現原理與實際應用場景。

UTXO 模型基礎概念

什麼是 UTXO?

UTXO = Unspent Transaction Output(未花費的交易輸出)

每次比特幣交易都會:

  1. 消耗一個或多個輸入(UTXO)
  2. 創造一個或多個輸出(新的 UTXO)

這種模型類似現金鈔票的運作方式:当你使用一张 10 元钞票购买 3 元的商品时,你会给出 10 元,找零 7 元。原来的 10 元钞票被「花费」消失了,变成了找零的 7 元和商家的 3 元(假设商家不需要找零)。

UTXO 的生命週期

每個 UTXO 都會經歷以下階段:

創建(Generation)
    ↓
未花費狀態(Unspent)
    ↓
花費狀態(Spent)→ 成為新交易的輸入
    ↓
最終可能成為新的 UTXO 或永遠保持花費狀態

UTXO vs 帳戶模型

比特幣(UTXO 模型)

以太坊(帳戶模型)

兩種模型的對比

特性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):包含所有未花費的交易輸出

UTXO 壓縮:UTxO Commitment(已提議但未完全部署)

比特幣核心的 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)

驗證過程

交易驗證涉及以下步驟:

  1. 輸入驗證:確認每個輸入引用的 UTXO 存在
  2. 腳本驗證:執行解鎖腳本與鎖定腳本
  3. 金額驗證:輸入總額 ≥ 輸出總額 + 費用
  4. 簽名驗證:確認交易被正確授權
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 時,會造成以下問題:

  1. 交易費用較高:每個輸入都需要費用
  2. 錢包管理複雜:追蹤大量小額 UTXO
  3. 隱私風險:碎片化的 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 月)

根據最新的比特幣網路數據:

UTXO 模型的安全性分析

雙花攻擊

UTXO 模型天然防止雙花攻擊:

  1. 每個 UTXO 只能被花費一次
  2. 區塊鏈共識確保最長鏈
  3. 51% 攻擊是理論上唯一的雙花方式

重放攻擊

比特幣交易包含:

這些機制防止交易被重放:

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 模型是比特幣帳本的核心設計,具有以下關鍵特性:

  1. 簡單性:狀態就是 UTXO 集合,無需複雜的帳戶管理
  2. 隱私性:每次交易可生成新地址,難以追蹤資金流向
  3. 可擴展性:交易驗證可並行處理
  4. 安全性:雙花攻擊難以實現

理解 UTXO 模型對於比特幣開發者、資深用戶和投資者都至關重要。隨著比特幣網路的发展,UTXO 集合將繼續成長,管理 UTXO 的技術也將持續演進。


相關文章

本文包含

延伸閱讀與來源

這篇文章對您有幫助嗎?

評論

發表評論

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

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