java-topology/whitepaper/outreach/zebra-0001.md
russell@unturf.com 6784cdf1cf feat: add 39 outreach docs (batches 6-8)
Batch 6 (9): dolibarr, jitsi-videobridge, zed, tryton, suricata,
  strawberry, zulip, zesarux, zephyr
Batch 7 (15): xonotic (4), xash3d (3), xenia, xtuple, zabbix (2),
  zathura, zebra, yabause, zephyr-0001
Batch 8 (15): woodpecker (2), wine (4), widelands (3), wesnoth (3),
  wekan (3)

Mix of CWE-407 and CWE-312.
2026-04-14 17:06:28 -04:00

3.5 KiB
Raw Blame History

Zebra (Zcash Foundation) — CWE-407 Disclosure Brief (zebra-0001)

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

Finding

One O(T×S) defect in Zebra ZIP-317 block template construction. has_direct_dependencies scans the entire Vec<SelectedMempoolTx> to check whether a candidate transaction's dependencies have been selected, producing O(T²) total work for deep dependency chains.

The Defect

zebra-0001 (PATCHED — LOW-MEDIUM): zebra-rpc/src/methods/types/get_block_template/zip317.rs:228

// In has_direct_dependencies() — fires per dependent tx evaluation:
fn has_direct_dependencies(
    candidate_tx_deps: Option<&HashSet<transaction::Hash>>,
    selected_txs: &Vec<SelectedMempoolTx>,
) -> bool {
    // ...
    for tx in selected_txs {           // O(S) per call
        if deps.contains(&tx.transaction.id.mined_id()) {
            num_available_deps += 1;
        }
        if num_available_deps == deps.len() {
            return true;
        }
    }
    false
}

selected_txs grows as transactions are added to the block template. Each dependent transaction evaluation scans the entire selected list. In a deep chain topology with T transactions, total work across a block template build reaches O(T²).

Complexity Proof

At T=1000 transactions in a chain dependency topology:

  • Defective: ~500,000 comparisons (O(T²/2))
  • Fixed: ~3,000 comparisons (O(T×D) where D=3 average deps)
  • ~167x op reduction at T=1000, pathological topology.

At typical mainnet conditions (shallow dependency chains), the practical speedup is smaller, but the worst case remains available to any mempool that constructs deep chains.

Impact

Zebra serves as a Zcash full node implementation by the Zcash Foundation. Block template construction runs once per block (~75 seconds on Zcash mainnet). While not a hot path in typical operation, miners constructing templates from mempools with deep transaction dependency chains (long unconfirmed spend chains) hit the quadratic path. The defect also exists in the low-fee transaction selection path, doubling the exposure.

The Fix

Maintain a HashSet<transaction::Hash> of selected transaction IDs alongside the Vec, reducing has_direct_dependencies to O(D) per check:

// Before
fn has_direct_dependencies(
    candidate_tx_deps: Option<&HashSet<transaction::Hash>>,
    selected_txs: &Vec<SelectedMempoolTx>,
) -> bool { /* O(S) scan */ }

// After
// CWE-407 fix: HashSet for O(D) dependency check instead of O(S) Vec scan.
fn has_direct_dependencies(
    candidate_tx_deps: Option<&HashSet<transaction::Hash>>,
    selected_tx_ids: &HashSet<transaction::Hash>,
) -> bool {
    deps.iter().all(|dep_id| selected_tx_ids.contains(dep_id))  // O(D)
}

Patch

Fix available: defects/zebra-0001/patch/zebra-0001-zip317-dep-check-hashset.patch

Single-file patch on zebra-rpc/src/methods/types/get_block_template/zip317.rs. Adds selected_tx_ids: HashSet parameter, replaces Vec scan with HashSet membership, inserts IDs incrementally.

What We Ask

A patch is ready for review.

  1. Confirm receipt and assign a GitHub issue reference (ZcashFoundation/zebra).
  2. Assess severity — quadratic in transaction chain depth during block template construction.
  3. Coordinate a disclosure date — we target 90 days from first contact.
  4. We will credit the Zcash Foundation / Zebra team in the public disclosure. Preferred acknowledgment format welcome.

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