-
Notifications
You must be signed in to change notification settings - Fork 232
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make kaspawallet store the utxos sorted by amount #1924
Make kaspawallet store the utxos sorted by amount #1924
Conversation
… utxos are spent first - making it less likely a compound will be required
49b32ef
to
8370138
Compare
Codecov Report
@@ Coverage Diff @@
## master #1924 +/- ##
==========================================
- Coverage 61.60% 61.35% -0.26%
==========================================
Files 627 631 +4
Lines 29502 29610 +108
==========================================
- Hits 18176 18166 -10
- Misses 8751 8865 +114
- Partials 2575 2579 +4
Continue to review full report at Codecov.
|
Note that this approach also has some negative effect, since also a medium-size send will use the largest UTXO, while it could of merged a few small UTXOs with out passing the mempool/block limit |
As a simple compromise, perhaps we should first start by accumulating the smallest UTXOs, and only if passing the limit, go to the largest UTXOs. Although I'm sure that with a bit more thinking we can come up with some better greedy approximation algo. |
I'll push back, saying that it is in the interest of the sender to use as little UTXOs as possible, since: Thus I'm not convinced what you presented as a downside is indeed a downside (it might be a downside for the network, I'd say a minor one, but not for the user). |
Anyway, the main thing this PR does is make sure the utxos are sorted, from which end do we pick them can be discussed and decided upon later down the road. |
func (s *server) insertUTXO(utxo *walletUTXO) { | ||
s.utxosSortedByAmount = append(s.utxosSortedByAmount, utxo) | ||
// bubble up the new UTXO to keep the UTXOs sorted by value | ||
index := len(s.utxosSortedByAmount) - 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be a binary search
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can also use sort.Search
, like in findTransactionIndex
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I think it's more readable to use code such as func (tobf *TransactionsOrderedByFeeRate) Push
, and maybe even more efficient
@@ -244,13 +256,14 @@ func (s *server) refreshExistingUTXOs() error { | |||
return err | |||
} | |||
|
|||
s.utxos = make(map[externalapi.DomainOutpoint]*walletUTXO, len(getUTXOsByAddressesResponse.Entries)) | |||
s.utxosSortedByAmount = make([]*walletUTXO, 0, len(getUTXOsByAddressesResponse.Entries)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Binary search above is especially important here since it will reduce the overall insertion cost from n^2 to nlogn
func (s *server) insertUTXO(utxo *walletUTXO) { | ||
s.utxosSortedByAmount = append(s.utxosSortedByAmount, utxo) | ||
// bubble up the new UTXO to keep the UTXOs sorted by value | ||
index := len(s.utxosSortedByAmount) - 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can also use sort.Search
, like in findTransactionIndex
func (s *server) insertUTXO(utxo *walletUTXO) { | ||
s.utxosSortedByAmount = append(s.utxosSortedByAmount, utxo) | ||
// bubble up the new UTXO to keep the UTXOs sorted by value | ||
index := len(s.utxosSortedByAmount) - 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I think it's more readable to use code such as func (tobf *TransactionsOrderedByFeeRate) Push
, and maybe even more efficient
d1ead01
to
5a0b056
Compare
5a0b056
to
4926054
Compare
(replacing collectUTXOs methods)
4926054
to
c1fdc7c
Compare
@@ -9,7 +9,7 @@ type GetBalanceByAddressRequestMessage struct { | |||
|
|||
// Command returns the protocol command string for the message | |||
func (msg *GetBalanceByAddressRequestMessage) Command() MessageCommand { | |||
return CmdGetBalanceByAddressRequestMessage | |||
return CmdGetBalancesByAddressesRequestMessage |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
was this file suppose to change?
@@ -30,7 +30,7 @@ type GetBalanceByAddressResponseMessage struct { | |||
|
|||
// Command returns the protocol command string for the message | |||
func (msg *GetBalanceByAddressResponseMessage) Command() MessageCommand { | |||
return CmdGetBalanceByAddressResponseMessage | |||
return CmdGetBalancesByAddressesResponseMessage |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here, seems like a mistake and it should remain CmdGetBalanceByAddressResponseMessage
* Report progress percentage when downloading headers in IBD. * Extract reporting logic to a separate type. * Report progress for IBD missing block bodies.
…aspanet#1937) * Split ApplyPruningPointProof to multiple small database transactions. * Increase the timeout duration in TestIBDWithPruning. * Increase the timeout duration in simple-sync. * Explain that if ApplyPruningPointProof fails, the database must be discarded.
* Drop support for p2p v3 * Remove redundant aliases * Remove redundant condition
…aspanet#1945) * Use a time format without ":" to support all file systems * go fmt
Co-authored-by: stasatdaglabs <39559713+stasatdaglabs@users.noreply.github.com>
} | ||
|
||
getUTXOsByAddressesResponse, err := s.rpcClient.GetUTXOsByAddresses(addressSet.strings()) | ||
sort.Slice(utxos, func(i, j int) bool { return utxos[i].UTXOEntry.Amount() > utxos[j].UTXOEntry.Amount() }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it's better to test it on testnet first with a very big wallet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
n log n
should be fine any way
This is a preliminary PR for #1922 .
I'm sending this as a separate PR, since it will immidiately help, even without the compound feature, which might take some time to implement properly.
This changes kaspawallet daemon to always keeps a sorted list of UTXOs.
Thus, on average, less UTXOs would be needed for any created transaction, making it less likely that a too-big transaction would be created.
Note this does incur some performance hit, especially for large wallets, but profiling showed it's probably negligible.