Skip to content

Conversation

@Chand-ra
Copy link

Make the wallet/spend fuzz target stateful and extend coverage for several missing methods.

Chandra Pratap added 2 commits January 12, 2026 15:10
Update the `wallet_create_transaction` fuzz target to move the
transaction creation logic inside a `CallOneOf` block.

This refactoring is a structural preparation for stateful fuzzing,
allowing commits to easily add and interleave other wallet
operations within the same loop.
Move the `CCoinControl` parameter configuration inside the fuzzing
loop to allow mutation of settings between operations. Additionally,
introduce logic to randomly `Select` or `UnSelect` specific available
outpoints within `coin_control`.

This allows the fuzzer to simulate scenarios where a user manually
mandates specific inputs.
@DrahtBot
Copy link
Contributor

DrahtBot commented Jan 12, 2026

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Code Coverage & Benchmarks

For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/34264.

Reviews

See the guideline for information on the review process.
A summary of reviews will appear here.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #34032 (util: Add some more Unexpected and Expected methods by maflcko)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@DrahtBot
Copy link
Contributor

🚧 At least one of the CI tasks failed.
Task tidy: https://github.com/bitcoin/bitcoin/actions/runs/20924396327/job/60120935082
LLM reason (✨ experimental): CI failure due to clang-tidy errors in spend.cpp (unnecessary temporary object in emplace_back and unused-return-value).

Hints

Try to run the tests locally, according to the documentation. However, a CI failure may still
happen due to a number of reasons, for example:

  • Possibly due to a silent merge conflict (the changes in this pull request being
    incompatible with the current code in the target branch). If so, make sure to rebase on the latest
    commit of the target branch.

  • A sanitizer issue, which can only be found by compiling with the sanitizer and running the
    affected test.

  • An intermittent issue.

Leave a comment here, if you need help tracking down a confusing failure.

@brunoerg
Copy link
Contributor

From CI:

[515/729][5.2s] clang-tidy-21 -p=/home/admin/actions-runner/_work/_temp/build -quiet -load=/tidy-build/libbitcoin-tidy.so /home/admin/actions-runner/_work/_temp/src/test/fuzz/block_index_tree.cpp
1126 warnings generated.
+ echo '^^^ ⚠️ Failure generated from clang-tidy'
+ false

[516/729][8.1s] clang-tidy-21 -p=/home/admin/actions-runner/_work/_temp/build -quiet -load=/tidy-build/libbitcoin-tidy.so /home/admin/actions-runner/_work/_temp/src/wallet/test/fuzz/spend.cpp
/home/admin/actions-runner/_work/_temp/src/wallet/test/fuzz/spend.cpp:125:41: error: unnecessary temporary object created while calling emplace_back [modernize-use-emplace,-warnings-as-errors]
  125 |                     tx.vin.emplace_back(CTxIn(out));
      |                                         ^~~~~~   ~
/home/admin/actions-runner/_work/_temp/src/wallet/test/fuzz/spend.cpp:152:23: error: the value returned by this function should not be disregarded; neglecting it may lead to errors [bugprone-unused-return-value,-warnings-as-errors]
  152 |                 (void)FundTransaction(*fuzzed_wallet.wallet, tx, recipients, change_pos, lockUnspents, coin_control);
      |                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2392 warnings generated.

[517/729][3.6s] clang-tidy-21 -p=/home/admin/actions-runner/_work/_temp/build -quiet -load=/tidy-build/libbitcoin-tidy.so /home/admin/actions-runner/_work/_temp/src/qt/bitcoinaddressvalidator.cpp
^^^ ⚠️ Failure generated from clang-tidy
Command '['docker', 'exec', '88e904189f27a153218451cb9cc2cf6a3600de9821f8b631509e657c4e1d73df', '/home/admin/actions-runner/_work/_temp/ci/test/03_test_script.sh']' returned non-zero exit status 1.

Copy link
Contributor

@frankomosh frankomosh left a comment

Choose a reason for hiding this comment

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

I think that the variables int next_locktime and CAmount all_values become dead code after you’ve refactored?
Also some inline nits below.

int num_inputs = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, available_outpoints.size());
for (int i = 0; i < num_inputs; i++) {
auto out = PickValue(fuzzed_data_provider, available_outpoints);
tx.vin.emplace_back(CTxIn(out));
Copy link
Contributor

Choose a reason for hiding this comment

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

Could simplify to tx.vin.emplace_back(out)

if (fuzzed_data_provider.ConsumeBool()) change_pos = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
bool lockUnspents = fuzzed_data_provider.ConsumeBool();

(void)FundTransaction(*fuzzed_wallet.wallet, tx, recipients, change_pos, lockUnspents, coin_control);
Copy link
Contributor

Choose a reason for hiding this comment

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

Also, should FundTransaction have wallet lock protection i.e wrap it in LOCK(fuzzed_wallet.wallet -> cs_wallet), as has been done in ListCoins ?

Copy link
Author

@Chand-ra Chand-ra Jan 13, 2026

Choose a reason for hiding this comment

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

Not really, FundTransaction() doesn't require an exclusive lock unlike ListCoins() does.

tx.vin.emplace_back(CTxIn(out));
}
std::vector<CRecipient> recipients;
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 50) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I notice that this logic appears twice. Would it make sense to extract it into a lambda helper at the top of the function?

@Chand-ra
Copy link
Author

I think that the variables int next_locktime and CAmount all_values become dead code after you’ve refactored? Also some inline nits below.

I believe next_locktime and all_values are still necessary in the setup loop. next_locktime ensures that we generate unique TXIDs and all_values is used to enforce the MAX_MONEY cap so we don't overflow the wallet balance during setup.

Chandra Pratap added 2 commits January 13, 2026 16:08
Extend the target to cover `FundTransaction()`.
Extend the fuzz target to cover `ListCoins()`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants