If CreateCoins generates a coin that is already inside any of the results, AddInputs will throw a runtime error, which the fuzzing framework will detect as a failure when it is not. It is part of the class boundaries.
If CreateCoins generates a coin that is already inside any of the results, AddInputs will throw a runtime error, which the fuzzing framework will detect as a failure when it is not. It is part of the class boundaries.
Yes, that’s why it calls CreateCoins twice and with different “utxos pool”. Is there any risk yet?
No ok. The reason why this doesn’t fails is the test global increasing next_locktime which ensures that all UTXOs receive a different hash even when the fuzzer provided the same data for them.
So, nvm. A comment wouldn’t hurt but nothing serious.
in
src/wallet/test/fuzz/coinselection.cpp:111
in
d5282a45bdoutdated
121+ }
122123 auto result_srd = SelectCoinsSRD(group_pos, target, fast_random_context, MAX_STANDARD_TX_WEIGHT);
124- if (result_srd) result_srd->ComputeAndSetWaste(cost_of_change, cost_of_change, 0);
125+ if (result_srd) {
126+ result_srd->ComputeAndSetWaste(cost_of_change, cost_of_change, 0);
murchandamus
commented at 5:44 pm on June 1, 2023:
It’s not clear to me why the ComputeAndSetWaste() is called with these parameters. The first should be min_viable_change which should be bigger than change_fee but not really related to cost_of_change. I guess that’s fine for this test. It’s also not clear to me, though why the change_fee is set to 0 here. Wouldn’t it be better to have it derive from the current coin_params?
Not sure if it adds interesting test coverage here, but I could see some ComputeAndSetWaste() come to different conclusions occasionally when a fee is considered.
murchandamus
commented at 6:03 pm on June 1, 2023:
contributor
I’m pretty new to fuzz testing, so I am not sure whether we want to have all these additional calls for each selection result. It seems to me that if we wanted to test the behavior of SelectionResult, it might make more sense to separately fuzz that instead of fuzzing that in the context of running all the different coin selection algorithms, since it might lower the number of executions we get on fuzzing coin selection.
OTOH, it’s great to get fuzzing coverage for these codepaths.
Code changes look good to me.
Tentative ACKd5282a45bd452844dc815181825e3dd46133ac51, except that I’d be curious to hear what others think about expanding the responsibility of this fuzz target vs adding a second fuzz target for testing SelectionResult.
brunoerg force-pushed
on Jun 1, 2023
brunoerg
commented at 9:40 pm on June 1, 2023:
contributor
murchandamus
commented at 4:12 pm on June 13, 2023:
Nevermind that. I ran about 500k executions on the coinselection fuzz test and could not substantiate my concern.
murchandamus approved
murchandamus
commented at 4:18 pm on June 13, 2023:
contributor
ACK2d739a425c92e2dd409c45273e8e376d39ead1cc
My concern about the min_viable_change and change_fee causing issues did not substantiate after some light fuzzing. Since it does not seem to cause crashes, having independent values for the two parameters may be better. Thanks for adding more coverage.
DrahtBot added the label
Needs rebase
on Jun 23, 2023
brunoerg force-pushed
on Jun 26, 2023
brunoerg
commented at 8:20 pm on June 26, 2023:
contributor
Rebased
DrahtBot removed the label
Needs rebase
on Jun 26, 2023
fanquake requested review from murchandamus
on Jul 5, 2023
fanquake requested review from furszy
on Jul 5, 2023
murchandamus
commented at 2:59 pm on July 5, 2023:
contributor
reACKbd6315a2a75d2891a8d3476c492d6b53309b7296
in
src/wallet/test/fuzz/coinselection.cpp:128
in
df15464a9coutdated
Does it worth? BnB internally calls ComputeSetAndWaste which checks change. Any unexpected action regarding it would affect the assertion - assert(best_waste == result.GetWaste());.
I think that it worth. One of fuzzing goals is to assert expected behavior externally. Black-box style. So if the internal implementation changes by mistake (or if there is a way to by-pass the expected behavior that we aren’t aware of), the fuzzer catches it.
Also, the internal BnB ComputeSetAndWaste call checks that the final selection is within a certain range: target <= value < target + change cost. It is indirectly checking GetChange() result but I don’t think that we should rely on that. If change_cost is also 0, the GetChange result doesn’t really matter, the same code will be executed in both branches of the ComputeAndSetWaste function.
Should check the Merge outcome. e.g. the result target and weight need to be the sum of the two merged targets and weights. Moreover, if one result uses the effective value and the other one not, the use_effective field must be updated.
furszy
commented at 2:57 pm on July 24, 2023:
member
Left few comments. I think that we could go further in few places and check that the called functions are actually doing what they suppose to be doing.
For instance, all valid results must have a target below the sum of the selected inputs amounts. Also, waste on results with more difference between target and inputs sum should be greater than results with closer diff between target and inputs sum.
brunoerg force-pushed
on Aug 3, 2023
brunoerg
commented at 8:50 pm on August 3, 2023:
contributor
Could also check the resulting inputs size and the use_effective_fee field.
Also, we only use of the Merge function in the sources to combine a MANUAL selection with one of the automatic selections. We never combine two srd solutions.
Just changed it to not use two srd solutions and I created a function to “simulate” a manual selection. Also, added more asserts, including checking the input set.
in
src/wallet/test/fuzz/coinselection.cpp:131
in
da3b3b3deeoutdated
126+ utxos_set.insert(std::make_shared<COutput>(utxo));
127+ }
128+
129+ if (result_srd) result_srd->AddInputs(utxos_set, subtract_fee_outputs);
130+ if (result_knapsack) result_knapsack->AddInputs(utxos_set, subtract_fee_outputs);
131+ if (result_bnb) result_bnb->AddInputs(utxos_set, subtract_fee_outputs);
murchandamus
commented at 9:00 pm on August 14, 2023:
While we don’t broadcast transactions with outputs of that amount (except OP_RETURN maybe), if it doesn’t break anywhere, a target of 1 ṩ should maybe be legal for coin selection?
IIRC, Bitcoin Core permits 294 ṩ for P2WPKH outputs, so it should at least not be bigger than that.
I checked that 1ṩ may break assert(result_bnb->GetChange(coin_params.m_cost_of_change, CAmount{0}) == 0);
murchandamus
commented at 9:47 pm on August 14, 2023:
Ah, my bad, I thought this target referred to the sum of recipient outputs, but it’s actually recipient_sum + not_input_fees.
Is it possible that this then would need to be at least as large as the cost for the header + change output? 1000 ṩ might not be enough for every feerate then.
I got a crash after 130k attempts when I tried to lower the target to 1 ṩ. Gonna fuzz with the 1000 ṩ tonight, will revisit tomorrow.
brunoerg
commented at 5:54 pm on August 15, 2023:
contributor
@murchandamus I got a crash with 5000 as well, perhaps we should increase the value even more.
murchandamus
commented at 6:39 pm on August 15, 2023:
contributor
I don’t think that an absolute value will work. My guess is that the crash may be caused by m_cost_of_change being generated randomly independent from m_change_fee. Usually, cost_of_change cannot ever be smaller than m_change_fee, so if it happens to be smaller here, it may interfere with the change calculation?
I attempted to calculate cost_of_change instead from m_change_fee + input_size×LTFRE, leaving the fuzz input consumption unchanged. It made the test pass:
I’m about 2.1M runs in, and no issues so far. :smile:
brunoerg
commented at 9:00 pm on August 15, 2023:
contributor
I don’t think that an absolute value will work. My guess is that the crash may be caused by m_cost_of_change being generated randomly independent from m_change_fee. Usually, cost_of_change cannot ever be smaller than m_change_fee, so if it happens to be smaller here, it may interfere with the change calculation?
Bingo, I think so!
Also, in long_term_fee_rate.GetFee(58) why 58?
murchandamus
commented at 9:32 pm on August 15, 2023:
contributor
You could then also make the change_spend_size or change_input_size a random variable in the range 41…1000. Inputs cannot ever be smaller than 41 vB (32+4+4+1).
brunoerg force-pushed
on Aug 16, 2023
brunoerg
commented at 1:38 am on August 16, 2023:
contributor
Need to make next_locktime a global variable (or receive it as ref here).
This variable prevents CreateCoins from generating duplicated transaction hashes (look at AddCoin()). If the variable is reset on every CreateCoins call, as is now, could be the case where the same coins are created twice.
Which will cause a runtime_error in AddInputs() and Merge() calls (see SelectionResult::InsertInputs()).
furszy
commented at 4:01 pm on August 23, 2023:
member
Code review ACK5f0237f2
As an extra small nit, I would merge the GetInputSet and GetShuffledInputSet commits into one (ec82d1c3a523a9b28adf66f840e239f4adead37a, 4531ab1aee85a6801e0de00816b3764b8462771c) as they are basically doing the same. But, not a big deal if you don’t do it anyway.
DrahtBot requested review from murchandamus
on Aug 23, 2023
fuzz: coinselection, add coverage for `AddInputs`808618b8a2
fuzz: coinselection, add coverage for `GetShuffledInputVector`/`GetInputSet`f0244a8614
fuzz: coinselection, add coverage for `Merge`1e351e5db1
fuzz: coinselection, improve `ComputeAndSetWaste`
Instead of using `cost_of_change` for `min_viable_change`
and `change_cost`, and 0 for `change_fee`, use values from
`coin_params`. The previous values don't generate any effects
that is relevant for that context.
0df0438c60
fuzz: coinselection, compare `GetSelectedValue` with target
The valid results should have a target below the sum of
the selected inputs amounts. Also, it increases the
minimum value for target to make it more realistic.
b2eb558407
fuzz: coinselection, BnB should never produce change6d9b26d56a
fuzz: coinselection, fix `m_cost_of_change`
`m_cost_of_change` must not be generated randomly
independent from m_change_fee. This commit changes
it to set it up according to `wallet/spend`.
bf26f978ff
brunoerg force-pushed
on Aug 23, 2023
brunoerg
commented at 8:25 pm on August 23, 2023:
contributor
Force-pushed: changed to use DUST_RELAY_TX_FEE instead of hardcoding the value and squashed GetInputSet and GetShuffledInputSet commits.
furszy
commented at 8:36 pm on August 23, 2023:
member
re-ACKbf26f97
murchandamus
commented at 2:29 pm on August 24, 2023:
contributor
reACK with some minimal fuzzing bf26f978ffbe7e2fc681825de631600e24e5c93e
DrahtBot removed review request from murchandamus
on Aug 24, 2023
achow101
commented at 8:04 pm on August 24, 2023:
member
ACKbf26f978ffbe7e2fc681825de631600e24e5c93e
achow101 merged this
on Aug 24, 2023
achow101 closed this
on Aug 24, 2023
maflcko
commented at 5:59 am on August 25, 2023:
member
This is a metadata mirror of the GitHub repository
bitcoin/bitcoin.
This site is not affiliated with GitHub.
Content is generated from a GitHub metadata backup.
generated: 2025-06-03 09:12 UTC
This site is hosted by @0xB10C More mirrored repositories can be found on mirror.b10c.me