#26022 Add util::ResultPtr class

ReviewabilityReviewsAgreementSize
#26022 ryanofsky Add util::ResultPtr classReview #25665 first0Mild596 + 246 tests
  • Simplifies error-handling wrappers for pointers by removing the need for double dereferencing
  • Prevents bugs where error checks mistakenly evaluate to true even when the returned pointer is null
  • No review verdicts recorded
  • Unaddressed objection: possible inverted boolean condition in wallet interfaces, no author reply (l0rinc)
  • 596 lines added or modified outside tests
  • 246 lines added or modified in tests
  • 199 lines removed in total
  • 19 files, 10 commits
Utilities (logging, arguments, libraries)#37 of 59
P3 · cleanup
  • P3 because it provides a safer and cleaner result-handling pattern for pointer types across the codebase
  • Reduces subtle null-pointer checking pitfalls without altering user-facing behavior
  • Ranking pass: Moved down: pure error-handling ergonomics rank below correctness and performance work here, but kept ahead of its dependent #25722.
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

Introduces `util::ResultPtr`, a wrapper around `util::Result` tailored for pointer types like `std::unique_ptr`. It enables single dereferencing (`*res` and `res->member`) and adjusts boolean evaluation to check that the result succeeded and the underlying pointer is non-null. Call sites returning unique pointers in `LoadAddrman` and the wallet loader interfaces are converted to use the new type.

Problem: Wrapping pointers in `util::Result` requires awkward double-dereferencing (`**res` or `(*res)->member`) to access pointed-to members. Moreover, evaluating a `util::Result` in a boolean context returns true whenever an error is absent, even if the wrapped pointer is null, which risks misleading checks and null-pointer bugs (#26004).

Evidence of importance:

  • Addresses issue #26004 ('util::Result has confusing interface for std::*_ptr T')
  • Author description: 'Instead of needing to be deferenced twice with **result or (*result)->member, it only needs to be dereferenced once with *result or result->member. Also when it is used in a boolean context, instead of evaluating to true when there is no error and the pointer is null, it evaluates to false so it is straightforward to determine whether the result points to something.'

Scope: The branch includes the commit stack of base PR #25665 (+842/-199 across 19 files); only the top two commits specifically introduce and apply `util::ResultPtr`.

Risk of a mistake: low (wallet, other). A bug in pointer validity checks or dereferencing logic could cause wallet load or addrman initialization failures during startup.

Changed since the previous assessment: Rebased on top of updated base PR #25665, incorporating CI compiler flag adjustments (`-Wno-error=maybe-uninitialized`) and memory usage tests from the underlying stack.

Reviewability

Ready · Review #25665 first

Stacked on #25665; the base PR's changes are included in this diff.

Waiting on (from the thread read):

  • author: response to l0rinc's question regarding whether boolean check is inverted 2026-07-23

Agreement

Mild

objection that needs an answer has none yet (l0rinc)

Thread notes: Added rebase announcements by the author; l0rinc's objection regarding the boolean check remains open.

Objections, suggestions, and questions:

ReviewerTypeHarm, request, or questionStatusMust beAuthor repliedQuote
l0rinc (member)objection, correctnessinverted boolean condition in src/wallet/interfaces.cppopenansweredno2026-07-23: 'isn't this inverted?'

Participants:

  • l0rinc (member, objection, 1 statements 2026-07-23 to 2026-07-23): asked whether a boolean check in src/wallet/interfaces.cpp was inverted

Dependencies

Depends on: #25665

Based on (shares commits with): #25665

Base for: #25722

Files

263 lines under test/bench/ci.

  • src/util/result.h +398/-63
  • src/test/result_tests.cpp +239/-11
  • src/node/chainstate.cpp +56/-39
  • src/util/messages.h +52/-0
  • src/init.cpp +24/-21
  • src/util/messages.cpp +32/-0
  • src/wallet/interfaces.cpp +9/-20
  • src/node/chainstate.h +6/-22
  • src/kernel/bitcoinkernel.cpp +7/-7
  • src/test/util/setup_common.cpp +4/-4
  • src/interfaces/wallet.h +3/-3
  • src/qt/walletcontroller.cpp +3/-3
  • src/wallet/wallet.cpp +2/-2
  • ci/test/00_setup_env_win64.sh +2/-1
  • ci/test/00_setup_env_native_previous_releases.sh +1/-1
  • src/addrdb.cpp +1/-1
  • src/addrdb.h +1/-1
  • src/kernel/CMakeLists.txt +1/-0
  • src/util/CMakeLists.txt +1/-0

Card

The short text the ranking pass compares across PRs.

Introduces `util::ResultPtr`, a wrapper around `util::Result` for pointer-like types such as `std::unique_ptr`. It enables single dereference syntax (`*res`, `res->member`) and ensures contextual boolean checks evaluate to false if an error occurred or if the pointer is null. This addresses the confusing interface and null-pointer risks reported in #26004, updating call sites in `LoadAddrman` and wallet loader interfaces. Depends on base PR #25665.

Data

dossier JSON · extract JSON · model ledger, generated 2026-11-01T01:16, confidence high, input hash 951a248d0c264939
thread read through 2026-07-23 (6 statements), head 2d0915656c
labels: none · draft

Categories

Utilities (logging, arguments, libraries)

P3 · cleanup (ranking pass: Moved down: pure error-handling ergonomics rank below correctness and performance work here, but kept ahead of its dependent #25722.)

Provides a safer, cleaner error-and-result pattern for pointer types across the codebase. It addresses issue #26004 where `util::Result` wrapping pointers required awkward double-dereferencing (`**res`) and avoided misleading boolean checks where null pointers evaluated to true.

Membership: Adds `util::ResultPtr` in src/util/result.h to improve result types handling pointers.

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