I ran into this writing a regression test for the smart ’estimate fees’ code.
CreateTransaction does not deal well with wallets that have lots of small-value inputs and just a couple of high-value inputs.
In pseudo-code, with default settings CreateTransaction does this:
0loop:
1 Select enough inputs to pay (amount+0 fees).
2 Maybe add a change output.
3 Create and sign transaction.
4 IF transaction is small and high priority: DONE.
5 IF enough fees are paid: DONE
6 ELSE:
7 go back to top of loop, re-selecting inputs to pay (amount+fees needed)
The bug is that if you have a lot of small-value inputs, you get a ‘ratchet’ effect where (say) 10 inputs are selected, they don’t add up to enough to pay fees, so 11 inputs are selected, but adding another input makes the fees even higher so 12 inputs are needed. That continues until SelectCoins either runs out of inputs OR it randomly decides to select a large coin.
The bug bothering me is when it eventually selects a large coin it will create a very small transaction that pays a much-larger-than-necessary fee-per-kilobyte.
Here is debug.log output from the smartfee CreateTransaction code (instrumented with extra LogPrint statements):
02014-04-22 16:59:56 Estimated fee rate: 0.09375 BTC/kB; size 374, need 3506250 satoshis
12014-04-22 16:59:56 Estimated fee rate: 0.09375 BTC/kB; size 962, need 9018750 satoshis
22014-04-22 16:59:56 Estimated fee rate: 0.09375 BTC/kB; size 1700, need 15937500 satoshis
32014-04-22 16:59:56 Estimated fee rate: 0.09375 BTC/kB; size 2586, need 24243750 satoshis
42014-04-22 16:59:56 Estimated fee rate: 0.09375 BTC/kB; size 3615, need 33890625 satoshis
52014-04-22 16:59:56 Estimated fee rate: 0.09375 BTC/kB; size 4942, need 46331250 satoshis
62014-04-22 16:59:56 Estimated fee rate: 0.09375 BTC/kB; size 6568, need 61575000 satoshis
72014-04-22 16:59:56 CommitTransaction:
8CTransaction(hash=10c367c2c1, ver=1, vin.size=1, vout.size=2, nLockTime=0)
9 CTxIn(COutPoint(036acfae76, 1), scriptSig=304402207b0c1bdadc92c9b7)
10 CTxOut(nValue=2.48612500, scriptPubKey=OP_DUP OP_HASH160 c808df63821d)
11 CTxOut(nValue=0.01000000, scriptPubKey=OP_DUP OP_HASH160 05fe160591a6)
So CreateTransaction ends up creating a ~250-byte transaction that pays as much as a 6,500 byte transaction: about 25 times as much as necessary (and that had me pulling my hair out, trying to figure out why my regression test sanity-check code was randomly failing).
We don’t see this as much in our existing code, because the wallet code rounds up transaction sizes to the next 1,000-byte multiple. That is really just hiding the problem, though.
I’m still thinking about how to test and fix this.