Good question.
It has been a while since I made this change, but if I remember correctly, my fixing the duplicate meaning of change_cost
broke this bench test due to the following:
Before my change, we would set change_cost
to 0
as a signal that a transaction does not require a change output. This would happen when a coin selection algorithm found a changeless solution and after creating the recipient outputs there would not be sufficient funds to make a viable change output. However, change_cost
will also be computed to be zero when effective_feerate
, long_term_feerate
, and discard_feerate
are zero.
IIRC, this lead to some unintuitive behavior in coin selection:
- One coin selection algorithm may propose a changeless input set with the two UTXOs 1000+3 BTC. Its waste score would be calculated to be 0, as both the
effective_feerate
and the long_term_feerate
are set to 0 and there is no excess.
- Another coin selection algorithm might propose a solution that should lead to a change output, e.g. two UTXOs 1000+1000 BTC. Because
change_cost
was computed to be 0, the transaction building would not create a change output, drop the excess 997 BTC to fees, and therefore assess the waste score to be 997 BTC of waste.
The changeless solution would be preferred, because of its waste score, and the bench would always succeed in finding a two input solution that uses exactly 1000+3 BTC in the inputs.
After my rewrite, change_cost
only contains the computed value and is no longer used as a signal on whether we have sufficient budget to create a change output.
- As before, the changeless solution would have a waste score of 0, as both the
effective_feerate
and the long_term_feerate
are set to 0 and there is no excess.
- However, the solution that creates change due to picking two UTXOs with 1000+1000 BTC, would now recognize that it has a ton of money left and that it should create a change output. Instead of dropping the excess 997 BTC to fees, it would create a change output of 997 BTC. Since the
effective_feerate
and discard_feerate
is 0, the change_cost
is 0. Because the effective_feerate
and long_term_feerate
are 0, the waste score on the inputs is also 0. Since effective_feerate
is 0, the fees for transaction header and recipient outputs are also 0. Therefore, the transaction with a change output now also gets a waste score of 0, correctly.
All of the proposed input sets get presented to ChooseSelectionResult(…)
which picks the lowest waste score, but all solutions are tied with the same waste score of zero. The tie-breaker is to prefer the input set with more inputs, but all solutions have two inputs and are tied on that as well. Finally, it picks the first element from the result vector. The bench test expects that 1003 BTC get selected, but when it selects 2000 BTC, the bench fails.
Therefore, I fixed the bench to not depend on using feerates that are do not appear in standard transactions and lead to quirky coin selection behavior, which required that I reduce the target to leave a money for fees. I would argue that we could probably do much better for a bench that tests coin selection in general.