Skip to content

audit: reaudit low fixes (tx.head RAM gate, in-flight bytes, pending FIFO, cut-through batch, tapscript weight) - #303

Merged
reardencode merged 6 commits into
masterfrom
audit/reaudit-lows-2
Aug 29, 2026
Merged

audit: reaudit low fixes (tx.head RAM gate, in-flight bytes, pending FIFO, cut-through batch, tapscript weight)#303
reardencode merged 6 commits into
masterfrom
audit/reaudit-lows-2

Conversation

@rearden-grok

@rearden-grok rearden-grok Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Five findings from the 2026-08-28 reaudit, one commit each:

  • N-L4 — tx.head rebuild workers sized at 1 GiB peak. The free-RAM gate still used 750 MiB while BDZ peel scratch + keys + g at the default 2²⁵ seal peaks around 1 GiB. Two workers on a 1.5 GiB-free host would oversubscribe. Gate and owner docs now match the peak (1.5 GiB → 1 worker; 2 GiB → 2).
  • L9 — in-flight byte meter follows live creates / outs occupancy. Same-txid overwrite saturating-added another 40-byte creates listing while the HashMap still held one slot, so iflight= could exceed live Arc bytes until the older pack pruned. Charge creates occupancy on vacant insert only; subtract only when remove_keys actually drops the map entry or the CreatePin.
  • L5 — pending-block eviction at the 128 cap is FIFO. stash_pending_block dropped pending.keys().next() (HashMap iteration order), so a burst could evict the body on the current header path. Insert order is tracked; the oldest hash is popped. Re-stash of the same hash keeps its place. Matches Q-60's pending FIFO.
  • N-L1 — Electrum cut-through spentness is one spent.idx batch per wave. Cake historicalMode=false walked idx + body once per eligible tx (up to 16384 serial reads on the serve thread). unspent_create_vouts_batch does one spent_range_batch plus one spent-body walk per create; get_output_spender_metas_at is that walk (not one 8-byte pread per vout). Serial unspent_create_vouts results unchanged.
  • L3 — tapscript empty-pubkey fail after BIP342 weight decrement. Core EvalChecksigTapscript subtracts VALIDATION_WEIGHT_PER_SIGOP for a non-empty sig, then rejects an empty pubkey. We rejected empty pubkey first, so a CHECKSIG that was also over the weight budget reported "empty pubkey" instead of "validation weight". Same reject either way; match Core's error class.

Tests

  • parse_rebuild_workers_and_1gib_cap / workers_for_free_ram_1gib_head_is_not_sh_1_5gib (store)
  • same_txid_overwrite_does_not_double_count_creates_bytes (query)
  • pending_blocks_insert_evicts_at_cap (net)
  • unspent_create_vouts_batch_matches_serial / get_output_spender_metas_at_one_walk (store); load_thin_cut_through_drops_spent_p2tr (query)
  • tapscript_empty_pubkey_reports_weight_when_budget_exhausted (consensus)

Each failed red before its fix. Targeted crate tests green locally; cargo fmt clean.

Made with Cursor

rbitcoin-grok and others added 6 commits August 28, 2026 20:23
BDZ peel scratch + keys + g at the default 2^25 seal peaks around
1 GiB per worker, but the free-RAM gate still used 750 MiB. Two
workers on a 1.5 GiB-free host would oversubscribe. Match the gate
(and owner docs) to the actual peak.

Co-authored-by: Cursor <cursoragent@cursor.com>
Same-txid overwrite saturating-added another 40-byte creates listing
while the HashMap still held one slot, so iflight= could exceed live
Arc bytes until the older pack pruned. Charge creates occupancy on
vacant insert only, and subtract only when remove_keys actually drops
the map entry (or the CreatePin).

Co-authored-by: Cursor <cursoragent@cursor.com>
stash_pending_block dropped pending.keys().next() — HashMap iteration
order — so a burst could evict the body on the current header path.
Track insert order and pop the oldest hash, matching Q-60's pending
FIFO. Re-stash of the same hash keeps its place.

Co-authored-by: Cursor <cursoragent@cursor.com>
Core EvalChecksigTapscript subtracts VALIDATION_WEIGHT_PER_SIGOP for a
non-empty sig, then rejects an empty pubkey. We rejected empty pubkey
first, so a CHECKSIG that was also over the weight budget reported
\"empty pubkey\" instead of \"validation weight\". Same reject either
way; match Core's error class.

Co-authored-by: Cursor <cursoragent@cursor.com>
Cake historicalMode=false walked spent.idx + spent.body once per
eligible tx (up to 16384 serial reads). One spent_range_batch plus
one spent-body walk per create, matching serial unspent_create_vouts.

Co-authored-by: Cursor <cursoragent@cursor.com>
PendingBlocks::insert and len were only reached from tests, so
-D warnings failed the non-test lib build. Tip-follow now inserts
through the wrapper; the cap pin uses keys().len().

Co-authored-by: Cursor <cursoragent@cursor.com>
@reardencode
reardencode merged commit 96541f8 into master Aug 29, 2026
13 checks passed
@rearden-grok
rearden-grok Bot deleted the audit/reaudit-lows-2 branch August 29, 2026 17:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant