# Context (Current Flow on Master)
In the transaction creation process, in order to select which coins the new transaction will spend, we first obtain all the available coins known by the wallet, which means walking-through the wallet txes map, gathering the ones that fulfill certain spendability requirements in a vector.
This coins vector is then provided to the Coin Selection process, which first checks if the user has manually selected any input (which could be internal, aka known by the wallet, or external), and if it does, it fetches them by searching each of them inside the wallet and/or inside the Coin Control external tx data.
Then, after finding the pre-selected-inputs and gathering them in a vector, the Coin Selection process walks-through the entire available coins vector once more just to erase coins that are in both vectors. So the Coin Selection process doesn’t pick them twice (duplicate inputs inside the same transaction).
# Process Workflow Changes
Now, a new method, FetchCoins
will be responsible for:
- Lookup the user pre-selected-inputs (which can be internal or external).
- And, fetch the available coins in the wallet (excluding the already fetched ones).
Which will occur prior to the Coin Selection process. Which allows us to never include the pre-selected-inputs inside the available coins vector in the first place, as well as doing other nice improvements (written below).
So, Coin Selection can perform its main responsibility without mixing it with having to fetch internal/external coins nor any slow and unneeded duplicate coins verification.
# Summarizing the Improvements:
-
If any pre-selected-input lookup fail, the process will return the error right away. (before, the wallet was fetching all the wallet available coins, walking through the entire txes map, and then failing for an invalid pre-selected-input inside SelectCoins)
-
The pre-selected-inputs lookup failure causes are properly described on the return error. (before, we were returning an “Insufficient Funds” error for everything, even if the failure was due a not solvable external input)
-
Faster Coin Selection: no longer need to “remove the pre-set inputs from the available coins vector so that Coin Selection doesn’t pick them” (which meant to loop-over the entire available coins vector at Coin Selection time, erasing duplicate coins that were pre-selected).
Now, the available coins vector, which is built after the pre-selected-inputs fetching, doesn’t include the already selected inputs in the first place.
-
Faster transaction creation for transactions that only use manually selected inputs.
We now will return early, as soon as we finish fetching the pre-selected-inputs and not perform the resources expensive calculation of walking-through the entire wallet txes map to obtain the available coins (coins that we will not use).
Added a new bench (f6d0bb2) measuring the transaction creation process, for a wallet with ~250k UTXO, only using the pre-selected-inputs inside coin control. Setting m_allow_other_inputs=false
to disallow the wallet to include coins automatically.
Result on this PR (tip f6d0bb2d):
ns/op | op/s | err% | total | benchmark |
---|---|---|---|---|
1,048,675.00 | 953.58 | 0.3% | 0.06 | WalletCreateTransaction |
vs
Result on master (tip 4a4289e2):
ns/op | op/s | err% | total | benchmark |
---|---|---|---|---|
96,373,458.20 | 10.38 | 0.2% | 5.30 | WalletCreateTransaction |
The benchmark took to run in master: 96.37 milliseconds, while in this PR: 1 millisecond 🚀 .