Open rafal-ch opened 4 weeks ago
This issue will be delivered in at least 2 PRs:
How to achieve pt. 1:
main_db
- the current oneindex_db
- the new, indexation DBUSER|ASSET|AMOUNT
, and value is going to be a key from the main_db
USER|ASSET
prefix, getting all coins in sorted orderutxo_id
). This suffix will also be used to quickly exclude coins.Example DB structure:
main_db |
key: utxo_id | amount | block_created | tx_created_idx | asset_id | owner |
---|---|---|---|---|---|---|
X1 | 1 | 3 | 12 | BTC | Alice | |
X2 | 100 | 3 | 10 | BTC | Alice | |
X3 | 10 | 3 | 11 | BTC | Alice | |
Y1 | 54321 | 4 | 101 | LCK | Bob | |
Y2 | 12345 | 4 | 100 | LCK | Bob | |
X4 | 20 | 3 | 14 | ETH | Alice |
Corresponding index_db , assuming that the coins were added in the order presented above: |
key[^1] | value |
---|---|---|
Alice-BTC-0000000000000001-X1 | empty | |
Alice-BTC-000000000000000a-X3 | empty | |
Alice-BTC-0000000000000064-X2 | empty | |
Alice-ETH-0000000000000014-X4 | empty | |
Bob-LCK-0000000000003039-Y2 | empty | |
Bob-LCK-000000000000d431-Y1 | empty |
[^1]: key
is a concatenation of owner
, asset_id
, big-endian encoded amount, utxo_id
(for conflict avoidance and coin exclusion)
How to achieve pt. 2:
Remarks:
Questions:
The PoC implementation of the above is available here: https://github.com/rafal-ch/coins_to_spend_poc
Current flow:
coinsToSpend()
arrives at the GraphQL APIoff_chain
DB is queried for "owned coin ids"
OwnedCoins
storageon_chain
DB (coins_iter()
)
Coins
storagebase_asset_id
, the above is repeated for "messages":
off_chain
DB is queried for "owned message ids"
OwnedMessageIds
storageon_chain
DB (messages_iter()
)
Messages
storagerandom_improve()
algo is used to select coins
largest_first()
algorithmNew flow:
AvailableCoinsManager
Messages
and Coins
storage
AvailableCoinsManager
will update the internal state in the off_chain
DB indexation cacheCoins
and OwnedCoins
are kept in synccoinsToSpend()
arrives at the GraphQL APIAvailableCoinsManager
for quick answer based on the internal state
The source of this issue is https://github.com/FuelLabs/fuel-core/issues/623.
Initially, the idea was to remove all complex queries from
fuel-core
and make it part of the indexer's responsibility. But the SDK is deeply integrated with these basic queries, that we need to support them onfuel-core
. For that, we need to optimize the following query by aggregating some information in the off-chain worker or adding new indexes to the database:coins_to_spend
query is very complex and requiresn^2
operations wheren
is the number of coins and messages. The algorithm itself can use additional indexes from RocksDB to solve the issue with dust coins and works fast.Extracted from the https://github.com/FuelLabs/fuel-core/issues/1965, which initially covered optimizations for 3 different areas: balances, coins to spend, dry run.