Skip to content

confirm: cut write-thread CPU below the milestone - #870

Merged
reardencode merged 10 commits into
masterfrom
confirm/write-thread-cpu
Oct 2, 2026
Merged

reardencode merged 10 commits into
masterfrom
confirm/write-thread-cpu

Conversation

@rearden-grok

@rearden-grok rearden-grok Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Below the milestone the write thread is the confirm pole. Script jobs are already off, and each batch was still walking spend absolute offsets more than once, allocating a fresh structural scratch and create-height map, and reading the wire header back from the store for the tip event.

  • Collect spend absolute offsets once, after fill stamps the ranges, and reuse that list in structural validation. A missing in-range offset is still Corrupt before the tx.head insert.
  • Keep one structural scratch and one in-batch double-spend set on the write thread, cleared at each batch.
  • Look up create heights by foreign-key span when every block in the batch is contiguous. A gap, a null key, or an overlap still uses the map.
  • Send the already-validated wire header on the tip event.

Spentness order is unchanged: BIP30, absolute offsets, the same-batch overlay skip, the 8-byte spent-meta read, the in-batch double-spend set, coinbase maturity, BIP68, and subsidy. Class C still flushes pre-tip tables, then the confirmed set, then the tip seal. The load thread keeps its own double-spend set.

The fee-history, tip-burst, and compact-block commits only loosen deadlines that failed while the workspace suite was sharing the machine. The fee-history check now reads the new tip from the snapshot or the journal.

Test plan

  • cargo fmt --all -- --check
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo deny check
  • ./scripts/ast-grep.sh
  • cargo test --workspace --quiet
  • ./scripts/ci-os-smoke.sh
  • GitHub qc, test, windows, macos, coverage

The write phase looked up each spend abs in fill, again in
ensure_spend_abs_layouts, and a third time inside structural.
One spend_abs_jobs walk after fill is the Corrupt gate before
tx.head insert, and structural reuses those jobs.
Each write batch allocated a new spentness scratch, pending-spent
set, and create-height map. The write thread keeps one of each and
clears slots, the pending set, and heights at the start of the batch
so annotate and double-spend state cannot cross batches. The pending
check is one insert.
IBD create fks are one contiguous range per block. Binary search over
those spans replaces a HashMap insert per transaction on the write
thread. A gap, a null fk, or an overlap keeps the map so a missing fk
does not inherit a neighbor height.
The write thread re-read header.body for each connected block while
holding the confirmed-hash lock. Copy the wire headers before the
batch is consumed and put those on TipEvent. A count that does not
match the batch is Corrupt. Mempool relay stays gated on relay_enabled.

ensure_spend_abs_layouts is test-only. The non-test library was
carrying that walker after the write path stopped calling it.
Clippy's argument cap is 7. The write-thread entry keeps its call-site
arguments unbundled, matching the other confirm helpers.
Copying the wire headers before commit adds one arm to the write
loop, which was already at clippy's complexity cap. Same allowance
as the load thread.
A restart preload rewrites the snapshot and truncates the journal to its
header. The next connect appends one record. When the previous run already
journaled a record of that size, the two files stay the same length while
the new height is stored. The cross-surface check now reads that height.
Under a full workspace run the follower was still mid-burst when the 10s
wait ended (55 of 80). Forty-five seconds stays inside the 60s sync_blocks
interval.
The workspace run hit the 30s wall around the getblocktxn and orphan
steps while other tests were running. Neighboring multinode tests already
use a 60s wall.
changelog.d fragment for the single spend-abs walk, the reused structural
scratch, foreign-key span heights, and the validated wire header on the
tip event.

@rearden-grok rearden-grok Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the write-thread changes, the updated invariants, and the associated test changes against the repo's confirm pipeline and IO rules. No correctness or significant performance findings. The one-pass spend-absolute collection, span lookup fallback, per-batch scratch reset, and prevalidated wire-header forwarding are consistent with the described stage order. qc, test, windows, and macos are green; coverage and Rust CodeQL were still running when I reviewed.

@reardencode
reardencode merged commit aa2a935 into master Oct 2, 2026
18 checks passed
@rearden-grok
rearden-grok Bot deleted the confirm/write-thread-cpu branch October 4, 2026 16:06
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