java-topology/whitepaper/outreach/bcoin.md
russell@unturf.com 9a78d1afbe feat: add 15 outreach docs (15 defects) for 1-patch projects
0ad (4), aranym, ardour, argo-cd, aria2, azahar, bcoin, bind9,
btcpayserver (3), bullet3. Mix of CWE-407 and CWE-312.
2026-04-14 14:33:17 -04:00

2.5 KiB
Raw Blame History

bcoin — CWE-407 Disclosure Brief (bcoin-0001)

2026-04-13 · Patch available — awaiting upstream merge

Finding

One O(H*T) defect in bcoin's RPC layer. gettxoutproof calls block.hasTX(hash) per requested hash, where hasTX does an O(T) linear scan over block transactions. Fix: build a BufferSet for O(1) membership testing.

The Defect

bcoin-0001 (PATCHED — MEDIUM): lib/node/rpc.js:1032

// In RPC.getTxOutProof():
for (const hash of hashes) {
    if (!block.hasTX(hash)) {
        throw new RPCError(errs.VERIFY_ERROR,
            'Block does not contain all txids.');
    }
}

hashes contains H transaction hashes the caller wants a Merkle proof for. block.hasTX(hash) performs an O(T) linear scan over all T transactions in the block. Total cost: O(H*T). For a full Bitcoin block with T=3000 transactions and H=100 requested proofs, this performs 300,000 buffer comparisons.

Complexity Proof

At H=100 requested hashes, T=3000 transactions per block:

  • Defective: 100 × 3000 = 300,000 buffer comparisons
  • Fixed: T=3000 set construction + 100 O(1) lookups = ~3,100 operations
  • ~97× op reduction.

Impact

bcoin is a full Bitcoin node implementation in JavaScript. gettxoutproof is an RPC endpoint used by wallets, block explorers, and SPV verification tools. Large blocks (post-SegWit) routinely contain 3000+ transactions. High-frequency RPC callers requesting multiple proofs per block hit the quadratic path repeatedly.

The Fix

Build a BufferSet from block transactions for O(1) membership testing:

// Before
for (const hash of hashes) {
    if (!block.hasTX(hash)) { ... }
}

// After
// CWE-407 fix: BufferSet for O(1) membership instead of O(T) hasTX scan.
const txSet = new BufferSet();
for (const tx of block.txs)
    txSet.add(tx.hash());

for (const hash of hashes) {
    if (!txSet.has(hash)) { ... }
}

Patch

Fix available: defects/bcoin/patch/bcoin-0001-rpc-gettxoutproof-linear-scan.patch

Single-file patch on lib/node/rpc.js. Adds BufferSet construction before the validation loop.

What We Ask

A patch is ready for review.

  1. Confirm receipt and assign a GitHub issue reference (bcoin-org/bcoin).
  2. Assess severity — fires on every gettxoutproof RPC call with multiple hashes.
  3. Coordinate a disclosure date — we target 90 days from first contact.
  4. We will credit the bcoin team in the public disclosure. Preferred acknowledgment format welcome.

Contact: see cover email. This brief is confidential until coordinated disclosure.