進階
ScanTxOutSet
深入了解 Bitcoin Core 的 scantxoutset RPC,快速掃描 UTXO 集合查找特定輸出。
8 分鐘
什麼是 ScanTxOutSet?
scantxoutset 是一個強大的 RPC 命令,可以直接掃描 UTXO 集合 來查找屬於特定地址或描述符的未花費輸出,無需導入錢包或重新掃描區塊鏈。
使用場景
快速餘額查詢
- • 無需導入地址
- • 無需重新掃描區塊
- • 即時獲取結果
錢包恢復驗證
- • 驗證種子詞的餘額
- • 查找丟失的資金
- • 審計地址活動
基本用法
# 掃描單個地址
bitcoin-cli scantxoutset start '["addr(bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq)"]'
# 掃描多個地址
bitcoin-cli scantxoutset start '[
"addr(bc1q...)",
"addr(3J98...)",
"addr(1A1z...)"
]'
# 使用描述符掃描(推薦)
bitcoin-cli scantxoutset start '[
"wpkh([d34db33f/84h/0h/0h]xpub.../0/*)",
"wpkh([d34db33f/84h/0h/0h]xpub.../1/*)"
]'
# 輸出示例
{
"success": true,
"txouts": 125000000,
"height": 800000,
"bestblock": "00000000000000000002...",
"unspents": [
{
"txid": "abc123...",
"vout": 0,
"scriptPubKey": "0014...",
"desc": "wpkh([d34db33f/84'/0'/0'/0/5]02...)#...",
"amount": 0.5,
"height": 750000
}
],
"total_amount": 1.23456789
} 支持的描述符
# 地址
addr(ADDRESS)
# 原始腳本(十六進制)
raw(HEX)
# 公鑰
pk(PUBKEY)
# P2PKH
pkh(PUBKEY)
# P2SH
sh(SCRIPT)
# P2WPKH (Native SegWit)
wpkh(PUBKEY)
# P2WSH
wsh(SCRIPT)
# P2TR (Taproot)
tr(PUBKEY)
# 多簽
multi(K, KEY1, KEY2, ...)
sortedmulti(K, KEY1, KEY2, ...)
# 組合
sh(wpkh(PUBKEY))
sh(wsh(multi(2, KEY1, KEY2, KEY3)))
# 派生路徑(用於 HD 錢包)
wpkh([fingerprint/path]xpub.../0/*) # 外部地址
wpkh([fingerprint/path]xpub.../1/*) # 找零地址 派生範圍
# 指定派生範圍
# 格式: "descriptor"#range(START, END)
# 掃描前 100 個地址
bitcoin-cli scantxoutset start '[
{"desc": "wpkh([d34db33f/84h/0h/0h]xpub.../0/*)", "range": 100}
]'
# 掃描索引 50-150
bitcoin-cli scantxoutset start '[
{"desc": "wpkh([d34db33f/84h/0h/0h]xpub.../0/*)", "range": [50, 150]}
]'
# 大範圍掃描(尋找丟失資金)
bitcoin-cli scantxoutset start '[
{"desc": "wpkh([d34db33f/84h/0h/0h]xpub.../0/*)", "range": 10000}
]' 注意: 範圍越大,掃描時間越長。預設範圍是 1000。
掃描控制
# 開始掃描
bitcoin-cli scantxoutset start '[...]'
# 中止掃描
bitcoin-cli scantxoutset abort
# 查看掃描狀態
bitcoin-cli scantxoutset status
# 狀態輸出
{
"progress": 0.456, # 0-1 的進度
"scantype": "start"
} 實用範例
驗證種子詞餘額
# 從種子詞派生 xpub(使用其他工具)
# 然後掃描所有標準派生路徑
# BIP-44 (Legacy)
bitcoin-cli scantxoutset start '[
{"desc": "pkh([fp/44h/0h/0h]xpub.../0/*)", "range": 100},
{"desc": "pkh([fp/44h/0h/0h]xpub.../1/*)", "range": 100}
]'
# BIP-49 (Nested SegWit)
bitcoin-cli scantxoutset start '[
{"desc": "sh(wpkh([fp/49h/0h/0h]xpub.../0/*))", "range": 100},
{"desc": "sh(wpkh([fp/49h/0h/0h]xpub.../1/*))", "range": 100}
]'
# BIP-84 (Native SegWit)
bitcoin-cli scantxoutset start '[
{"desc": "wpkh([fp/84h/0h/0h]xpub.../0/*)", "range": 100},
{"desc": "wpkh([fp/84h/0h/0h]xpub.../1/*)", "range": 100}
]'
# BIP-86 (Taproot)
bitcoin-cli scantxoutset start '[
{"desc": "tr([fp/86h/0h/0h]xpub.../0/*)", "range": 100},
{"desc": "tr([fp/86h/0h/0h]xpub.../1/*)", "range": 100}
]' 查找多簽餘額
# 2-of-3 多簽
bitcoin-cli scantxoutset start '[
"wsh(sortedmulti(2,[fp1/48h/0h/0h/2h]xpub1.../*,[fp2/48h/0h/0h/2h]xpub2.../*,[fp3/48h/0h/0h/2h]xpub3.../*))#checksum"
]' 性能考慮
掃描性能因素:
1. UTXO 集大小
- 當前約 8000 萬個 UTXO
- 掃描需要遍歷整個集合
2. 描述符複雜度
- 簡單地址:最快
- 單個描述符:快
- 帶範圍的描述符:需要更多計算
3. 範圍大小
- 範圍 100:快(秒級)
- 範圍 1000:中等
- 範圍 10000+:慢(分鐘級)
4. 硬體
- SSD vs HDD:顯著差異
- RAM:更多緩存更快
典型掃描時間(SSD):
- 單個地址:1-5 秒
- 100 個派生地址:5-15 秒
- 1000 個派生地址:30-60 秒 腳本整合
import subprocess
import json
def scan_utxos(descriptors: list) -> dict:
"""掃描 UTXO 集合"""
cmd = [
'bitcoin-cli',
'scantxoutset',
'start',
json.dumps(descriptors)
]
result = subprocess.run(cmd, capture_output=True, text=True)
return json.loads(result.stdout)
def check_balance(xpub: str, path: str = "84'/0'/0'") -> float:
"""檢查 xpub 餘額"""
descriptors = [
{"desc": f"wpkh([{path}]{xpub}/0/*)", "range": 100},
{"desc": f"wpkh([{path}]{xpub}/1/*)", "range": 100},
]
result = scan_utxos(descriptors)
return result.get('total_amount', 0)
def find_utxos_for_address(address: str) -> list:
"""查找地址的 UTXO"""
result = scan_utxos([f"addr({address})"])
return result.get('unspents', [])
# 使用
balance = check_balance("xpub6...")
print(f"餘額: {balance} BTC")
utxos = find_utxos_for_address("bc1q...")
for utxo in utxos:
print(f"UTXO: {utxo['txid']}:{utxo['vout']} = {utxo['amount']} BTC") 總結
- ✓ 即時查詢:無需導入錢包或重新掃描
- ✓ 描述符支持:支持所有標準描述符類型
- ✓ 範圍掃描:可掃描 HD 錢包的派生地址
- ⚠ 注意:大範圍掃描耗時較長
已複製連結