Skip to content

fix: stack review follow-ups for #120-#127 - #135

Draft
bronxyz wants to merge 7 commits into
perf/hot-path-optimizationsfrom
fix/stack-review-followups
Draft

fix: stack review follow-ups for #120-#127#135
bronxyz wants to merge 7 commits into
perf/hot-path-optimizationsfrom
fix/stack-review-followups

Conversation

@bronxyz

@bronxyz bronxyz commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

Stack 9/9 of the txpool in-flight tracker and observer-forwarder series.

Review findings deliberately not taken, with the reason:

Surface areas touched

  • Consensus protocol (primary / worker / network / state-sync)
  • Execution / EVM
  • JSON-RPC (eth_*, rayls_*, faucet)
  • Middleware (orchestrator / processor / bridge)
  • Infrastructure (types / storage / config / network-cli)
  • On-chain contracts (rayls-contracts/)
  • Operations (etc/, scripts, Docker, compose)
  • CI / build (.github/workflows/, Makefile)
  • Documentation only (doc/, in-crate READMEs, root docs)
  • Tests only

Breaking / compatibility

None. The gossip pin proves Vec<Bytes> and Vec<Vec<u8>> bcs-encode identically; a mark backup from another schema version is now discarded on restore instead of applied, which only affects a node-local file.

Test plan

  • Red-first tests for the four behavior changes: suspended_cert_count_follows_the_drain, arm_rejects_a_backup_from_another_schema_version, reconstruct_drops_a_parked_batch_whose_body_is_corrupt, worker_gossip_txn_payload_is_bcs_identical_to_vec_vec_u8.
  • make check clean; 534/534 tests in the touched crates (primary, evm, storage, worker, batch-builder, orchestrator); clippy warnings only in untouched files.

… releases

- the watch has no receiver (the proposer borrows the sender), so `send` failed and
  discarded every value: the backpressure brake read 0 forever
- `send_replace` stores unconditionally; publish from the pending manager on both
  suspension and drain so the count falls back to 0 once parents resolve
- drop the duplicate publish in the cert manager; `insert_pending` already owns it
- red test: suspend, drain, assert the watch reads 0

- addresses the PR #127 (perf/hot-path-optimizations) review blocker: proposer livelock on
  backpressure drain; the fix also covers the dead-watch case the review missed
- `MARK_BACKUP_VERSION` was written but never read on restore; bcs is positional, so a
  reshaped backup could decode into wrong marks instead of being refused
- `#[must_use]` on `SealMarks`/`ForwardMarks`: dropping the handle silently discards the
  capability the arm minted; one test was doing exactly that

- addresses the PR #120 (feature/txpool-in-flight-tracker-core) review: unchecked
  `MarkBackup::version` and the missing `#[must_use]` on the arm handles
…ting

- boot recovery already drops a parked ref with no `Batches` row; a corrupt row used the
  infallible decode and aborted the node on the same defensive path

- addresses the PR #123 (feature/txpool-ordering-and-proposer-hardening) review: infallible
  `decode` in `reconstruct_parked`
- `ok_or_eyre` takes a `Display` value, so the braces were emitted literally

- addresses the PR #125 (feature/txpool-in-flight-tracker-forwarding-affinity) review:
  `ok_or_eyre` literal at both `node_inner.rs` sites
- `elapsed_ms` was stamped after the quorum result had already arrived, so it logged
  the resolution overhead, never the wait; `AwaitingQuorum` now carries the spawn instant

- fix "becuase" in the max-batch-size error text

- addresses the PR #124 (feature/txpool-in-flight-tracker-builder-pipeline) review: `elapsed_ms`
  always ~0, plus the typo nit
- the `Vec<Bytes>` identity with `Vec<Vec<u8>>` was asserted only in a comment; the pin
  encodes both and cross-decodes the old bytes into the new variant

- addresses the PR #125 (feature/txpool-in-flight-tracker-forwarding-affinity) review: the
  `Vec<Bytes>` wire identity was comment-only
- the post-drain twin logs; the pre-drain snapshot swallowed the `JoinError`, leaving no
  trace when the node entered the drain with no backup

- note at `max_tx_lifetime` that reth applies it to the queued sub-pool only

- addresses the PR #121 (feature/txpool-reth-pool-maintenance) review: swallowed `JoinError`;
  the `max_tx_lifetime` note answers the same review's eviction concern, which misread the knob
@bronxyz
bronxyz force-pushed the fix/stack-review-followups branch from f653415 to 02563e4 Compare August 26, 2026 13:20
@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Claude finished @bronxyz's task in 3m 20s —— View job


  • Gather context and read CLAUDE.md
  • Examine PR diff against base branch
  • Review changed files in detail
  • Post comprehensive review feedback

PR Review: fix/stack-review-followups

Seven targeted follow-up fixes with red-first tests. The stale doc comment flagged in the previous review pass has been corrected. One prior suggestion remains outstanding; everything else is correct.


What changed since the last pass

The suspended_cert_count doc in consensus_bus.rs:376-377 was updated from "Published on each suspension, so a drained queue is reflected only at the next suspension." to "Published on each suspension and each drain, so the gate releases as soon as the queue empties." ✓


Findings

pending_cert_manager.rssend_replace + drain publish

publish_count() helper is clean. send_replace is the right primitive: the proposer reads via Sender::borrow() with no live receiver, so send was silently discarding every update. The drain publish at line 174 is the essential second half — without it the backpressure brake would remain stuck at the last-seen suspension count until a new cert arrived. ✓

The test suspended_cert_count_follows_the_drain covers both halves: suspension count matches after insert, falls to 0 after the first-round unlock. The Sender::borrow() read is correct here because send_replace writes unconditionally regardless of receiver state. ✓

cert_manager.rs — redundant publish removal

The outer send + metric-mirror pair in process_verified_certificates is gone; insert_pending now handles both via publish_count(). No duplication, no double-publish. ✓

in_flight/mod.rs — version check in consume_stash

Version check placed before role check — correct ordering. A schema-mismatched backup could decode into wrong mark types under BCS's positional encoding; rejecting wholesale before checking the role is the safe default. The log fields (discarded, saved_version, current_version) give an operator enough to diagnose a rolling-upgrade scenario. ✓

marks.rs#[must_use]

Both handles annotated with actionable messages. The backup.rs fix (let _fwd = loader.arm_forwarding(policy)) demonstrates the exact pattern this guards against, which makes the test self-documenting. ✓

batch_ordering_store.rstry_decode in reconstruct_parked

decode panics on corrupt bytes; try_decode returns Result. The match restructuring is clean: the Some(Ok), Some(Err), and None arms each have appropriate warn logs with consistent context fields. The Some(Err) arm correctly includes %e while None omits it — the asymmetry is right and expected. The test uses [0xff, 0xff, 0xff] as reliably undecodable BCS, which is valid since the length prefix would indicate a far-larger payload than the 3 bytes present. ✓

pipeline.rs / lib.rsAwaitingQuorum::started

Instant::now() is stamped inside start_building(), which is called by the select! loop immediately after spawning the build task. The gap between spawn and stamp is a few function-call stack frames — negligible against quorum latency. lib.rs now reads awaiting.state.started instead of re-stamping after the .await, which is the fix. Both Accumulating and BacklogDraining transitions stamp the instant correctly. ✓

message.rs — BCS wire-compatibility pin test

The test builds old_wire as [1u8, ...encode(&vecs)] and then asserts encode(&gossip) == old_wire, which implicitly verifies the variant index is 1. The round-trip decode confirms un-upgraded peers can still deserialize the new type.

Remaining nit from the prior review pass (not addressed): The implicit variant-index check could still become a named, enforced invariant:

assert_eq!(encode(&gossip)[0], 1, "WorkerGossip::Txn must remain bcs variant 1");

Without this, a future variant-order change shifts the index and the test would still pass because both sides of assert_eq!(encode(&gossip), old_wire) would shift together — the old_wire is constructed from the old format but the test would only catch drift if the lengths also changed. Worth adding, but non-blocking.

Fix this →

node_inner.rs — worker ID interpolation

Both call sites fixed. The unused use eyre::OptionExt import is also removed, which is correct since ok_or_else is on Option directly. ✓

core.rs — pre-drain JoinError

The let _ = spawn_blocking(...) pattern is gone; the JoinError (a thread-panic indicator) is now logged at error!. The comment "Best-effort: a panic here must not skip the drain" remains accurate — logging and continuing is the right behavior here since the drain must not be blocked. ✓

txn_pool.rsmax_tx_lifetime comment

The comment correctly scopes the knob to the queued sub-pool, explains why pending txs are never lifetime-evicted, and documents the intent (cap nonce-gapped stranding). ✓


Verdict

Approve. The doc-comment fix from the prior pass is in. The BCS variant-index explicit assert is still absent but is a documentation nit, not a correctness issue. All behavior changes are correctly tested and the logic is sound throughout.

@github-actions

Copy link
Copy Markdown
Contributor

Security Scan - Code

Severity: HIGH, CRITICAL

No vulnerabilities found

View scan results

Report Summary

┌─────────────────────────────────────────────┬────────────┬─────────────────┬───────────────────┐
│                   Target                    │    Type    │ Vulnerabilities │ Misconfigurations │
├─────────────────────────────────────────────┼────────────┼─────────────────┼───────────────────┤
│ Cargo.lock                                  │   cargo    │        0        │         -         │
├─────────────────────────────────────────────┼────────────┼─────────────────┼───────────────────┤
│ crates/testing/fuzz-targets/Cargo.lock      │   cargo    │        0        │         -         │
├─────────────────────────────────────────────┼────────────┼─────────────────┼───────────────────┤
│ crates/testing/fuzz-targets/fuzz/Cargo.lock │   cargo    │        0        │         -         │
├─────────────────────────────────────────────┼────────────┼─────────────────┼───────────────────┤
│ etc/state-sum/Cargo.lock                    │   cargo    │        0        │         -         │
├─────────────────────────────────────────────┼────────────┼─────────────────┼───────────────────┤
│ etc/tps/package-lock.json                   │    npm     │        0        │         -         │
├─────────────────────────────────────────────┼────────────┼─────────────────┼───────────────────┤
│ rayls-contracts/package-lock.json           │    npm     │        0        │         -         │
├─────────────────────────────────────────────┼────────────┼─────────────────┼───────────────────┤
│ etc/chaos-network/Dockerfile                │ dockerfile │        -        │         0         │
├─────────────────────────────────────────────┼────────────┼─────────────────┼───────────────────┤
│ etc/docker-network/Dockerfile               │ dockerfile │        -        │         0         │
├─────────────────────────────────────────────┼────────────┼─────────────────┼───────────────────┤
│ etc/docker-replay/Dockerfile                │ dockerfile │        -        │         0         │
└─────────────────────────────────────────────┴────────────┴─────────────────┴───────────────────┘
Legend:
- '-': Not scanned
- '0': Clean (no security findings detected)

@raylsnetwork raylsnetwork deleted a comment from github-actions Bot Aug 26, 2026
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