handshake-org / hsd

Handshake Daemon & Full Node
Other
1.9k stars 273 forks source link

Wallet TX Count and time indexing #888

Open nodech opened 4 months ago

nodech commented 4 months ago

This is a port of the https://github.com/bcoin-org/bcoin/pull/605. It includes fixes mentioned in the PR.

This resolves CPU and memory exhaustion issues when requesting transaction history for a wallet with many transactions. Transactions are now also able to be queried by time based on median-time-past (MTP) based on chain data.

Backport:

Issues:

Related:

WDB Migration:

Minor changes

Wallet changes

Update wdb version to v3. Migration is handled by #889.

Wallet HTTP

Deprecated and removed:

Wallet HTTP Client

Deprecate and remove:

Examples
GET /wallet/:id/tx/history?after=<txid>&limit=50&reverse=false
GET /wallet/:id/tx/history?after=<txid>&limit=50&reverse=true

By using after=<txid> we can anchor pages so that results will not shift when new blocks and transactions arrive. With reverse=true we can change the order the transactions are returned as latest to genesis. The limit=<number> specifies the maximum number of transactions to return in the result.

GET /wallet/:id/tx/history?time=<median-time-past>&limit=50&reverse=false
GET /wallet/:id/tx/history?time=<median-time-past>&limit=50&reverse=true

The param time is in epoch seconds and indexed based on median-time-past (MTP) and date is ISO 8601 format. Because multiple transactions can share the same time, this can function as an initial query, and then switch to the above after format for the following pages.

GET /wallet/:id/tx/unconfirmed?after=<txid>&limit=50&reverse=false
GET /wallet/:id/tx/unconfirmed?after=<txid>&limit=50&reverse=true
GET /wallet/:id/tx/unconfirmed?time=<time-received>&limit=50&reverse=false

The same will apply to unconfirmed transactions. The time is in epoch seconds and indexed based on when the transaction was added to the wallet.

Wallet RPC

The following new methods have been added:

The following methods have been deprecated:

Wallet CLI (hsw-cli)

TXDB Change

TX Pagination

Pagination introduces sorted indexes in the database, that is consistently sorted thoroughout the tx history, whether it's confirmed or unconfirmed. It uses Count indexes to achieve the sorted behaviour. Note this is not strictly based on the tx creation. Instead confirmed transactions use: height + index in the block. Even if one tx was created before another, they will be sorted based on their position in the block and height. Time index for confirmed transactions is based on the "median time past". It ensures, that time increases monotonically with each block. They give us pointer to the Count index. There's also "next" page, which gives us next results based on the last hash of the previous response. This is another pointer to the Count index, indexed separately from time.

Count index

This can look like this, if we have 3 transactions in block 200100:

coveralls commented 4 months ago

Coverage Status

coverage: 69.806% (+1.2%) from 68.632% when pulling 0fda0181d3522b8cf660162bb028863d498e9446 on nodech:wallet-pagination into 0a4f24bdb0cc93b1d0236c77966085b305fe3d71 on handshake-org:master.

nodech commented 3 months ago

TODO