跳至主要內容
進階

CPFP (Child Pays For Parent)

深入了解 Child Pays For Parent 機制,如何透過子交易提升父交易的確認優先級。

10 分鐘

什麼是 CPFP?

Child Pays For Parent(CPFP)是一種手續費提升技術,允許交易接收者透過創建一個高手續費的子交易, 來加速低手續費父交易的確認。這對於無法使用 RBF 的情況特別有用。

CPFP vs RBF

RBF

  • • 發送者操作
  • • 替換原始交易
  • • 需要 RBF 信號
  • • 更省費用

CPFP

  • • 接收者操作
  • • 創建新交易
  • • 無需特殊信號
  • • 需要額外費用

運作原理

祖先費率計算

礦工在選擇交易時,會計算整個交易「包」的平均費率,而不是單個交易的費率:

祖先費率 (Ancestor Fee Rate) = 祖先總費用 / 祖先總大小

例如:
父交易 (Parent):
  - 大小: 200 vB
  - 費用: 200 sats (1 sat/vB) ← 太低!

子交易 (Child):
  - 大小: 150 vB
  - 費用: 4,800 sats (32 sat/vB)

合併計算:
  - 總大小: 200 + 150 = 350 vB
  - 總費用: 200 + 4,800 = 5,000 sats
  - 有效費率: 5,000 / 350 ≈ 14.3 sat/vB

礦工會將父子交易一起打包,因為它們的組合費率夠高

礦工打包算法

interface MempoolTransaction {
  txid: string;
  fee: number;
  vsize: number;
  parents: string[];  // 未確認的父交易
}

interface TxPackage {
  transactions: MempoolTransaction[];
  totalFee: number;
  totalSize: number;
  effectiveRate: number;
}

// 計算交易包的有效費率
function calculatePackageRate(tx: MempoolTransaction, mempool: Map): TxPackage {
  const pkg: TxPackage = {
    transactions: [tx],
    totalFee: tx.fee,
    totalSize: tx.vsize,
    effectiveRate: 0,
  };

  // 遞歸添加所有未確認的祖先
  const addAncestors = (txid: string) => {
    const parent = mempool.get(txid);
    if (parent && !pkg.transactions.includes(parent)) {
      pkg.transactions.push(parent);
      pkg.totalFee += parent.fee;
      pkg.totalSize += parent.vsize;
      parent.parents.forEach(addAncestors);
    }
  };

  tx.parents.forEach(addAncestors);

  pkg.effectiveRate = pkg.totalFee / pkg.totalSize;
  return pkg;
}

// 礦工選擇交易
function selectTransactionsForBlock(
  mempool: Map,
  maxWeight: number
): MempoolTransaction[] {
  // 計算所有交易包的有效費率
  const packages = Array.from(mempool.values())
    .map(tx => calculatePackageRate(tx, mempool));

  // 按有效費率排序
  packages.sort((a, b) => b.effectiveRate - a.effectiveRate);

  // 貪心選擇
  const selected: MempoolTransaction[] = [];
  let totalWeight = 0;

  for (const pkg of packages) {
    if (totalWeight + pkg.totalSize * 4 <= maxWeight) {
      // 添加整個包(去重)
      for (const tx of pkg.transactions) {
        if (!selected.includes(tx)) {
          selected.push(tx);
          totalWeight += tx.vsize * 4;
        }
      }
    }
  }

  return selected;
}

費用計算

需要多少費用?

interface CpfpCalculation {
  parentTxid: string;
  parentSize: number;    // vBytes
  parentFee: number;     // sats
  childSize: number;     // vBytes
  targetRate: number;    // sat/vB
}

function calculateChildFee(params: CpfpCalculation): number {
  const { parentSize, parentFee, childSize, targetRate } = params;

  // 目標:組合費率達到 targetRate
  // (parentFee + childFee) / (parentSize + childSize) = targetRate
  // childFee = targetRate * (parentSize + childSize) - parentFee

  const totalSize = parentSize + childSize;
  const totalFeeNeeded = targetRate * totalSize;
  const childFee = totalFeeNeeded - parentFee;

  // 確保子交易費率也合理
  const childRate = childFee / childSize;

  return {
    childFee: Math.ceil(childFee),
    childRate: childRate.toFixed(2),
    effectiveRate: targetRate,
    additionalCost: Math.ceil(childFee) - (childSize * targetRate),
  };
}

// 使用範例
const result = calculateChildFee({
  parentTxid: 'abc123...',
  parentSize: 200,    // 父交易 200 vB
  parentFee: 200,     // 父交易只付了 200 sats (1 sat/vB)
  childSize: 150,     // 子交易 150 vB
  targetRate: 20,     // 目標 20 sat/vB
});

console.log(result);
// {
//   childFee: 6800,        // 子交易需要 6,800 sats
//   childRate: "45.33",    // 子交易費率 45.33 sat/vB
//   effectiveRate: 20,     // 組合費率 20 sat/vB
//   additionalCost: 3800   // 相比正常多付 3,800 sats
// }

成本分析: CPFP 會產生額外成本,因為你需要為父交易「補貼」費用。 如果可能,RBF 通常是更經濟的選擇。CPFP 主要用於接收者無法讓發送者使用 RBF 的情況。

CPFP Carve-Out

祖先限制問題

Bitcoin Core 對交易的祖先數量有限制(預設 25 個交易,101 kvB)。這可能阻止 CPFP:

問題場景(Lightning Network):

Alice 和 Bob 有一個 Lightning 通道
通道關閉交易有兩個輸出:
  - 輸出 0: 給 Alice
  - 輸出 1: 給 Bob

如果 Alice 創建了大量子交易(消耗祖先限制):
  Alice 輸出 → Child 1 → Child 2 → ... → Child 25

Bob 就無法使用 CPFP 提升關閉交易的費用!
(因為祖先限制已被 Alice 消耗)

Carve-Out 規則

CPFP Carve-Out(BIP-331 的前身)允許一個額外的小型子交易,即使已達到祖先限制:

Carve-Out 條件:
1. 子交易只有一個未確認的祖先
2. 子交易大小 ≤ 10,000 vBytes
3. 祖先數量超過限制最多 1 個

這允許 Lightning 的「第二方」總是可以 CPFP:

Alice 輸出 → 25 個子交易(達到限制)
Bob 輸出 → 1 個 CPFP 交易(carve-out 允許!)

實現示例

使用 Bitcoin CLI

# 1. 查看卡住的交易
bitcoin-cli getmempoolentry 

# 2. 查看輸出(找到你控制的輸出)
bitcoin-cli getrawtransaction  true | jq '.vout'

# 3. 創建子交易花費該輸出
bitcoin-cli createrawtransaction \
  '[{"txid":"","vout":1}]' \
  '{"":0.00099}'

# 4. 簽名
bitcoin-cli signrawtransactionwithwallet 

# 5. 廣播
bitcoin-cli sendrawtransaction 

# 或者使用錢包的 bumpfee(如果你是發送者)
bitcoin-cli bumpfee 

# 查看祖先資訊
bitcoin-cli getmempoolentry  | jq '{ancestorcount, ancestorsize, ancestorfees}'

程式化實現

interface CpfpParams {
  parentTxid: string;
  parentVout: number;
  parentValue: number;  // sats
  parentSize: number;   // vB
  parentFee: number;    // sats
  targetFeeRate: number;  // sat/vB
  destinationAddress: string;
}

async function createCpfpTransaction(params: CpfpParams): Promise {
  const {
    parentTxid,
    parentVout,
    parentValue,
    parentSize,
    parentFee,
    targetFeeRate,
    destinationAddress,
  } = params;

  // 估算子交易大小
  const estimatedChildSize = 110;  // P2WPKH 1-in-1-out

  // 計算需要的子交易費用
  const totalSize = parentSize + estimatedChildSize;
  const totalFeeNeeded = totalSize * targetFeeRate;
  const childFee = totalFeeNeeded - parentFee;

  // 確保費用合理
  if (childFee > parentValue * 0.5) {
    throw new Error('CPFP fee would consume too much value');
  }

  // 計算輸出金額
  const outputValue = parentValue - childFee;

  // 創建交易
  const tx = new Transaction();
  tx.addInput(parentTxid, parentVout);
  tx.addOutput(destinationAddress, outputValue);

  // 簽名並返回
  const signedTx = await signTransaction(tx);
  return signedTx.toHex();
}

// 使用示例
const cpfpTx = await createCpfpTransaction({
  parentTxid: 'abc123...',
  parentVout: 0,
  parentValue: 100000,  // 0.001 BTC
  parentSize: 200,
  parentFee: 200,  // 1 sat/vB (太低)
  targetFeeRate: 20,  // 目標 20 sat/vB
  destinationAddress: 'bc1q...',
});

console.log('CPFP transaction:', cpfpTx);

使用場景

Lightning Network

通道關閉交易可能因手續費過低而卡住。雙方都可以使用 CPFP 來加速確認, 這對時間敏感的 HTLC 超時特別重要。

交易所提款

交易所可能批量處理提款,使用低費率。用戶可以使用 CPFP 來加速自己的提款確認。

無 RBF 的交易

如果發送者沒有啟用 RBF,接收者可以使用 CPFP 來加速交易,無需發送者配合。

緊急情況

網路擁堵時,即使手續費估算正確的交易也可能延遲。CPFP 提供了一個補救措施。

最佳實踐

✓ 推薦做法

  • • 計算組合費率,不只是子交易費率
  • • 使用高效的子交易(小體積)
  • • 考慮使用 P2WPKH/P2TR 減少大小
  • • 優先考慮 RBF(如果可用)

⚠ 注意事項

  • • CPFP 有額外成本
  • • 注意祖先限制
  • • 確保有足夠的輸出價值
  • • 監控交易狀態

總結

  • 接收者工具:CPFP 讓接收者可以加速交易,無需發送者配合
  • 祖先費率:礦工按整個交易包的平均費率選擇交易
  • Carve-Out:特殊規則允許 Lightning 雙方都能使用 CPFP
  • 額外成本:需要為父交易補貼費用,比 RBF 更貴
已複製連結
已複製到剪貼簿