#36318 validation: Ensure Invalid ValidationState has result

ReviewabilityReviewsAgreementSize
#36318 optout21 validation: Ensure Invalid ValidationState has resultReady0Crickets18 + 9 tests
  • Ensure invalid validation states always carry a concrete failure result and non-empty reason
  • Prevent ambiguous validation outcomes in downstream callers like P2P logic and the kernel C API
  • Ready for review
  • Nothing known that would invalidate a review now
  • No review verdicts recorded
  • No substantive reviews or objections yet
  • Neutral context provided noting where the defaulted result originated (hodlinator)
  • 18 lines added or modified outside tests
  • 9 lines added or modified in tests
  • 11 lines removed in total
  • 10 files, 4 commits
Kernel (libbitcoinkernel)#13 of 18
P3 · bug fix
  • P3 because it updates the kernel C API to report inconclusive validation rather than an unset result
  • Improves error reporting clarity at the kernel boundary for external consumers
Validation#31 of 53
P3 · bug fix
  • P3 because invalid validation states can no longer be left unset or missing a reason
  • Prevents ambiguous failure results across consensus callers and peer punishment logic
Reviewability: ReadyStalePaused
Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets
Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs.
Size: lines added or modified outside tests, then in tests; greener = smaller.

Goal

Enforces that invalid `ValidationState` instances always have a concrete failure `Result` enum and a non-empty `reject_reason`. Adds `BlockValidationResult::BLOCK_INCONCLUSIVE` across consensus validation, net processing, and the kernel C API to represent tests where block validity cannot be evaluated, replacing an unset result in `TestBlockValidity`.

Problem: Callers could construct an invalid `ValidationState` with an unset result enum or an empty reject reason string, leaving downstream consumers like P2P punishment logic and the kernel C API with ambiguous state. Specifically, `TestBlockValidity` used an unset result when a block did not connect to the active chain tip.

Evidence of importance:

  • Commit message (ee04f82075): 'A violating usage in `TestBlockValidity` is being changed: instead of the default `BLOCK_RESULT_UNSET`, it now uses `BLOCK_INCONCLUSIVE`.'
  • PR description notes that PR #31981 moved a check into `TestBlockValidity` that introduced a `BlockValidationState` with an unset result, which was noted in review on #35570.

Risk of a mistake: medium (validation, p2p). A faulty validation result invariant or misclassification could trigger debug assertions or improperly punish or fail to penalize P2P peers.

Reviewability

Ready

Nothing known that would invalidate a review now.

Waiting on (from the thread read):

Agreement

Crickets

no substantive comment either way

Thread notes: Initial read. No objections or reviews yet; hodlinator provided context pointing to a previous discussion. / Initial record. No substantive reviews or objections yet.

Objections, suggestions, and questions: none recorded.

Participants:

  • hodlinator (member, neutral, 1 statements 2026-09-23 to 2026-09-23): noted origin of the defaulted result enum and suggested pinging ryanofsky

Files

15 lines under test/bench/ci.

  • src/consensus/validation.h +6/-3
  • src/test/fuzz/txdownloadman.cpp +3/-3
  • src/test/txdownload_tests.cpp +3/-3
  • src/bitcoin-chainstate.cpp +3/-0
  • src/kernel/bitcoinkernel_wrapper.h +2/-1
  • src/net_processing.cpp +3/-0
  • src/test/kernel/test_kernel.cpp +3/-0
  • src/kernel/bitcoinkernel.cpp +2/-0
  • src/validation.cpp +1/-1
  • src/kernel/bitcoinkernel.h +1/-0

Card

The short text the ranking pass compares across PRs.

validation: Ensure Invalid ValidationState has result enforces that all invalid validation states specify both an explicit failure enum and a non-empty reject reason. It introduces `BLOCK_INCONCLUSIVE` to represent checks whose validity could not be resolved (e.g., when a block does not connect to the current chain tip in `TestBlockValidity`) and updates the kernel C API and net processing accordingly. This addresses an unset result introduced in PR #31981 and adds an `Assume` invariant to prevent incomplete validation error states.

Data

dossier JSON · extract JSON · model ledger, generated 2026-09-24T02:49, confidence high, input hash 8fea2f41a31601fa
thread read through 2026-09-23 (3 statements), head 22cf9d54b3
Discussion read under schema 1 rules: suggestions and questions may be missing, and an objection may combine several harms (schema history).
labels: Validation

Categories

Kernel (libbitcoinkernel)

P3 · bug fix

Extends the kernel C API to report the new inconclusive block validation state rather than exposing an ambiguous unset result. Error reporting at the kernel library boundary is directly improved, though the change is a straightforward extension of internal validation semantics.

Membership: Touches src/kernel/bitcoinkernel.h and src/kernel/bitcoinkernel.cpp to add BLOCK_INCONCLUSIVE to the kernel C API result reporting.

Factors: security/stability 1, bug 1, performance 0, user value 0, leverage 1

Validation

P3 · bug fix

Enforces that invalid ValidationState instances cannot be left in an unset or empty state, preventing ambiguous results in callers like TestBlockValidity. This strengthens validation invariants and retires a hazard for downstream validation state consumers.

Membership: Labeled Validation; changes ValidationState invariant enforcement in src/consensus/validation.h and updates TestBlockValidity in src/validation.cpp.

Factors: security/stability 1, bug 1, performance 0, user value 0, leverage 1