#36068 fuzz: reuse one fuzzed wallet across inputs

full analysis

https://github.com/bitcoin/bitcoin/pull/36068 · brunoerg · +146/-17 in 4 files, 2 commits · labels: Fuzzing

Goal

  • Speed up wallet fuzz testing by reusing a single wallet instance across inputs
  • Avoid repeated overhead from descriptor imports, BIP32 derivations, and database setups

This pull request optimizes fuzzing of wallet operations by reusing a single FuzzedWallet instance across fuzz inputs rather than reconstructing it each iteration. It introduces CWallet::ClearInMemoryTxStateForTest() to reset transaction and spend maps in memory, and caches derived destinations in FuzzedWallet.

Problem: Rebuilding FuzzedWallet for every fuzz input incurs heavy repeated overhead from importing eight descriptors, BIP32 derivations, and database transactions, slowing fuzz iterations down significantly.

Category: Test infrastructure (#10 of 45)

P3 · speedup

  • P3 because a 4x to 6x speedup meaningfully increases fuzz testing throughput
  • Accelerates test coverage rate for wallet transaction creation

A 4x to 6x speedup on fuzz execution meaningfully increases fuzz testing throughput and test coverage rate for wallet transaction creation. It is a solid optimization for test infrastructure, though deferrable.

Membership: Modifies shared fuzz utility src/test/fuzz/util/wallet.h and the spend fuzz target src/wallet/test/fuzz/spend.cpp.

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

Category: Wallet (#71 of 84)

P4 · cleanup

  • P4 because it only adds an internal test-only helper to wipe in-memory state
  • Has no impact on production wallet behavior or user-facing functionality

From a wallet maintenance perspective, this only introduces an internal test-only helper function to wipe in-memory maps, with no impact on real wallet operation or user-facing behavior.

Membership: Touches src/wallet/wallet.h and src/wallet/wallet.cpp by adding CWallet::ClearInMemoryTxStateForTest().

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

Reviewability: Ready

  • Ready to review
  • Clean patch, passing CI, and initial review questions answered

The patch is small, CI is passing, mergeable clean, and feedback from the initial review has been addressed.

Author status: active

Resolved concerns:

  • jeanpablojp noted that DescriptorScriptPubKeyMan next_index drift across inputs causes successive iterations to derive different change addresses; author clarified the bound assertions and documentation.
  • jeanpablojp questioned the order of clearing mapWallet relative to containers referencing it; author noted safe order in the test helper.

Agreement: Strong

  • Approach approval confirming a roughly 4x fuzz execution speedup (jeanpablojp)
  • Concerns about index drift and container clearing order were addressed (jeanpablojp)

Approach ACK from jeanpablojp confirming a 4x fuzz speedup.

jeanpablojp verified the performance improvement on local corpus runs and gave an Approach ACK with only minor questions that the author addressed.

  • jeanpablojp: 'Approach ACK. Ran the qa-assets corpus on master and on this head, the speedup reproduces, around 4x here.'

Review verdicts (DrahtBot): 0

Files

144 lines under test/bench/ci.

  • src/test/fuzz/util/wallet.h +118/-12
  • src/wallet/test/fuzz/spend.cpp +9/-5
  • src/wallet/wallet.cpp +11/-0
  • src/wallet/wallet.h +8/-0

Card

This PR refactors FuzzedWallet to initialize once in fuzz target initialization and reset in-memory state per input rather than re-importing descriptors and re-deriving keys every time. It adds a test-only CWallet::ClearInMemoryTxStateForTest() method and precomputes destination pools. Reviewers confirmed a 4x to 6x speedup on the qa-assets corpus. It has an Approach ACK and is ready for merge review.

Data

dossier JSON · extract JSON · model openrouter/google/gemini-3.8-flash, generated 2026-09-17T16:22, confidence high, input hash 8034d053b58a0301