高級
Mempool Policy
深入了解 Bitcoin Core 的 mempool 接受策略,交易驗證規則和政策限制。
12 分鐘
什麼是 Mempool Policy?
Mempool Policy 是 Bitcoin Core 決定是否接受交易進入 mempool 的規則集。 這些規則分為兩類:共識規則(必須遵守)和政策規則(可配置的本地限制)。
規則類型
共識規則
- • 有效的簽名
- • 輸入存在且未花費
- • 輸入金額 ≥ 輸出金額
- • 正確的腳本執行
政策規則
- • 最小手續費率
- • 交易大小限制
- • 標準腳本類型
- • RBF 規則
標準性規則
標準腳本類型
// Bitcoin Core 接受的標準腳本類型
enum TxoutType {
NONSTANDARD,
PUBKEY, // P2PK
PUBKEYHASH, // P2PKH
SCRIPTHASH, // P2SH
MULTISIG, // 裸多簽
NULL_DATA, // OP_RETURN
WITNESS_V0_KEYHASH, // P2WPKH
WITNESS_V0_SCRIPTHASH, // P2WSH
WITNESS_V1_TAPROOT, // P2TR
WITNESS_UNKNOWN, // 未來的見證版本
}
function isStandardTx(tx: Transaction): boolean {
// 1. 版本檢查
if (tx.version < 1 || tx.version > 2) {
return false;
}
// 2. 大小限制
if (tx.weight > MAX_STANDARD_TX_WEIGHT) { // 400,000 WU
return false;
}
// 3. 檢查每個輸出
for (const output of tx.outputs) {
if (!isStandardOutput(output)) {
return false;
}
// Dust 檢查
if (isDust(output)) {
return false;
}
}
// 4. 檢查每個輸入
for (const input of tx.inputs) {
if (!isStandardInput(input)) {
return false;
}
}
return true;
} 大小限制
| 限制 | 值 | 說明 |
|---|---|---|
| MAX_STANDARD_TX_WEIGHT | 400,000 WU | 約 100 KB |
| MAX_P2SH_SIGOPS | 15 | P2SH 腳本最大簽名操作 |
| MAX_STANDARD_P2WSH_SCRIPT_SIZE | 3,600 bytes | P2WSH 見證腳本大小 |
| MAX_STANDARD_P2WSH_STACK_ITEMS | 100 | 見證堆疊項目數 |
手續費政策
// 手續費相關常量
const MIN_RELAY_TX_FEE = 1000; // 1 sat/vB(最小中繼費率)
const DUST_RELAY_TX_FEE = 3000; // 3 sat/vB(dust 計算費率)
// 計算 dust 閾值
function getDustThreshold(output: TxOutput): number {
// Dust = 花費這個輸出所需的手續費
let spendSize: number;
if (output.isSegwit()) {
spendSize = 68; // P2WPKH 輸入大小
} else {
spendSize = 148; // P2PKH 輸入大小
}
return spendSize * DUST_RELAY_TX_FEE / 1000;
}
function isDust(output: TxOutput): boolean {
// OP_RETURN 輸出不是 dust
if (output.script.isOpReturn()) {
return false;
}
return output.value < getDustThreshold(output);
}
// Mempool 最小費率(動態調整)
class MempoolFeeEstimator {
private mempoolMinFee: number = MIN_RELAY_TX_FEE;
// 當 mempool 接近滿時,提高最小費率
updateMinFee(mempoolSize: number, maxSize: number): void {
if (mempoolSize > maxSize * 0.9) {
// 提高最小費率
this.mempoolMinFee = this.getBottomFeeRate();
} else {
// 逐漸降低
this.mempoolMinFee = Math.max(
MIN_RELAY_TX_FEE,
this.mempoolMinFee * 0.99
);
}
}
} 祖先/後代限制
| 限制 | 預設值 | 配置選項 |
|---|---|---|
| 祖先數量 | 25 | -limitancestorcount |
| 祖先總大小 | 101 KB | -limitancestorsize |
| 後代數量 | 25 | -limitdescendantcount |
| 後代總大小 | 101 KB | -limitdescendantsize |
交易鏈示例:
TX_A (已確認)
└── TX_B (mempool)
└── TX_C (mempool)
└── TX_D (mempool)
└── TX_E (新交易)
TX_E 的祖先:TX_B, TX_C, TX_D (3 個)
TX_B 的後代:TX_C, TX_D, TX_E (3 個)
如果 TX_E 會導致任何交易超過祖先/後代限制,
則 TX_E 會被拒絕 RBF 政策
// BIP-125 RBF 規則
function canReplaceTransaction(
original: Transaction,
replacement: Transaction
): { allowed: boolean; reason?: string } {
// 規則 1: 原始交易必須有 RBF 信號
if (!isRbfSignaled(original)) {
return { allowed: false, reason: 'Original not replaceable' };
}
// 規則 2: 替換交易支付更高的絕對手續費
if (replacement.fee <= original.fee) {
return { allowed: false, reason: 'Insufficient fee' };
}
// 規則 3: 額外費用至少覆蓋替換交易的最小中繼費用
const minIncrease = replacement.vsize * MIN_RELAY_TX_FEE / 1000;
if (replacement.fee - original.fee < minIncrease) {
return { allowed: false, reason: 'Fee increase too small' };
}
// 規則 4: 替換的交易數量限制
const evictedCount = countEvictedTransactions(original);
if (evictedCount > 100) {
return { allowed: false, reason: 'Too many evictions' };
}
// 規則 5: 不能引入新的未確認輸入
if (hasNewUnconfirmedInputs(original, replacement)) {
return { allowed: false, reason: 'New unconfirmed inputs' };
}
return { allowed: true };
} 配置選項
# bitcoin.conf
# 最小中繼費率(sat/kB)
minrelaytxfee=1000
# Mempool 大小限制(MB)
maxmempool=300
# 交易過期時間(小時)
mempoolexpiry=336
# 祖先限制
limitancestorcount=25
limitancestorsize=101
# 後代限制
limitdescendantcount=25
limitdescendantsize=101
# 允許非標準交易(僅測試網)
# acceptnonstdtxn=1
# Full RBF(允許替換任何交易)
mempoolfullrbf=1 總結
- ✓ 標準性:限制腳本類型和交易大小
- ✓ 手續費:最小中繼費率和 dust 限制
- ✓ 鏈限制:祖先/後代數量和大小限制
- ⚠ 可配置:大部分政策規則可通過配置調整
已複製連結