跳至主要內容
進階

TestMempoolAccept

學習使用 testmempoolaccept RPC 在廣播前驗證交易是否會被 mempool 接受。

8 分鐘

testmempoolaccept 是 Bitcoin Core 提供的 RPC 命令,用於在不實際廣播交易的情況下 測試交易是否會被本地 mempool 接受。這對於交易驗證和調試非常有用。

基本用法

# 測試單個交易
bitcoin-cli testmempoolaccept '["<raw_tx_hex>"]'

# 返回結果
[
  {
    "txid": "abc123...",
    "wtxid": "def456...",
    "allowed": true,
    "vsize": 141,
    "fees": {
      "base": 0.00001410
    }
  }
]

# 如果交易被拒絕
[
  {
    "txid": "abc123...",
    "wtxid": "def456...",
    "allowed": false,
    "reject-reason": "insufficient fee"
  }
]

測試交易包(Package)

從 Bitcoin Core 24.0 開始,支持測試交易包:

# 測試 CPFP 交易包
bitcoin-cli testmempoolaccept '[
  "<parent_tx_hex>",
  "<child_tx_hex>"
]'

# 返回結果包含 package 信息
[
  {
    "txid": "parent_txid...",
    "wtxid": "parent_wtxid...",
    "allowed": true,
    "vsize": 110,
    "fees": {
      "base": 0.00000110
    }
  },
  {
    "txid": "child_txid...",
    "wtxid": "child_wtxid...",
    "allowed": true,
    "vsize": 141,
    "fees": {
      "base": 0.00002820,
      "effective-feerate": 0.00011678,      // sat/vB
      "effective-includes": ["parent_wtxid", "child_wtxid"]
    }
  }
]

常見拒絕原因

reject-reason 說明
insufficient fee 手續費低於 minrelaytxfee
mempool min fee not met mempool 已滿,費率不夠
txn-mempool-conflict 與 mempool 中交易衝突
missing-inputs 找不到輸入 UTXO
bad-txns-inputs-missingorspent 輸入已被花費
too-long-mempool-chain 超出祖先/後代限制
non-BIP68-final 相對時間鎖未滿足
dust 輸出低於灰塵限制
scriptpubkey 非標準腳本類型

參數詳解

testmempoolaccept ["rawtx",...] ( maxfeerate )

參數:
1. rawtxs (array, required)
   - 原始交易的 hex 字符串數組
   - 可以是單個交易或交易包

2. maxfeerate (numeric, optional, default=0.10)
   - 最大可接受的費率 (BTC/kvB)
   - 用於防止意外的高手續費
   - 設為 0 表示不檢查

# 示例: 限制費率為 0.001 BTC/kvB
bitcoin-cli testmempoolaccept '["<hex>"]' 0.001

實際應用場景

1. 錢包交易驗證

import requests
import json

def validate_transaction(raw_tx):
    """在廣播前驗證交易"""
    rpc_data = {
        "jsonrpc": "1.0",
        "method": "testmempoolaccept",
        "params": [[raw_tx]],
    }

    response = requests.post(
        "http://127.0.0.1:8332",
        auth=("user", "password"),
        json=rpc_data
    )

    result = response.json()["result"][0]

    if result["allowed"]:
        print(f"交易有效! vsize: {result['vsize']}")
        print(f"手續費: {result['fees']['base']} BTC")
        return True
    else:
        print(f"交易被拒絕: {result['reject-reason']}")
        return False

2. 費率檢查

# 檢查交易是否會因費率問題被拒絕

# 獲取當前 mempool 最低費率
bitcoin-cli getmempoolinfo
{
  ...
  "mempoolminfee": 0.00001000,
  "minrelaytxfee": 0.00001000,
  ...
}

# 測試交易
result=$(bitcoin-cli testmempoolaccept '["<hex>"]')

# 檢查結果
if echo "$result" | jq -e '.[0].allowed' > /dev/null; then
    echo "交易會被接受"
    echo "費率: $(echo "$result" | jq '.[0].fees.base / .[0].vsize * 100000000') sat/vB"
else
    echo "交易被拒絕: $(echo "$result" | jq -r '.[0]["reject-reason"]')"
fi

3. RBF 測試

# 測試 RBF 替換交易

# 原始交易已在 mempool 中
# 創建替換交易(更高費率)

# 測試替換交易
bitcoin-cli testmempoolaccept '["<replacement_tx_hex>"]'

# 如果返回 "txn-mempool-conflict",
# 需要確保:
# 1. 原交易有 RBF 信號 (nSequence < 0xfffffffe)
# 2. 新交易費用足夠高
# 3. 滿足 BIP-125 規則

與 submitpackage 的關係

# testmempoolaccept 是只讀的
# submitpackage 會實際提交到 mempool

# 工作流程
1. testmempoolaccept 驗證
2. 如果通過,使用 submitpackage 提交
3. submitpackage 返回更詳細的結果

# submitpackage 示例
bitcoin-cli submitpackage '["<parent>", "<child>"]'

注意事項

  • 時效性:mempool 狀態隨時變化,測試結果可能很快失效
  • 節點差異:不同節點可能有不同的 mempool 策略
  • 非共識:通過 testmempoolaccept 不保證被礦工打包
  • 費率波動:網路擁塞時最低費率會提高

調試技巧

# 啟用詳細日誌
bitcoin-cli logging '["mempool"]'

# 查看詳細的拒絕原因
tail -f ~/.bitcoin/debug.log | grep -i "reject\|accept"

# 檢查交易的具體問題
bitcoin-cli decoderawtransaction <hex>

# 驗證輸入 UTXO 是否存在
bitcoin-cli gettxout <txid> <vout>
已複製連結
已複製到剪貼簿