-
Notifications
You must be signed in to change notification settings - Fork 64
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
Save transactions in database #1180
Conversation
I think list_missing_txids may fetch a too big batch of txids. I was thinking maybe it is better to loop over list_txids: https://github.com/wizardsardine/liana/blob/master/src/database/mod.rs#L148 from current time to genesis block timestamp, and for unconfirmed transactions use the coins(&[Status::Unconfirmed], ...) |
Perhaps yes, although in that case, we should probably also do the same for the |
I'll change |
I used a loop to get the missing txids using |
Sorry If I was unclear, my point was to fetch missing txids and store transactions by batch in order to not keep a whole set in memory. In fact, i am thinking that we do not need to paginate txids to do that, just fetch 20 txids from the coins table where the txid is not in the txid field of the table transactions, fetch their raw tx with bitcoind then store them in transactions table and repeat until no txids are fund. |
Ah I see, yep that makes sense, will change it. |
I couldn't quite do it like this in the end as there's a chance we won't be able to retrieve the transaction from bitcoind, and so the loop might have continued forever. Instead, I get all missing txids in one query still, but then retrieve chunks of transactions at a time so that we don't store them all in memory at once. As the transactions are larger than txids, and we already store the same order of coins in memory as there are txids, I felt it was fine to do it this way. |
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.
I think we should do something closer to what we do for the backend and its poller:
- Have the coins table's txid row reference a transaction in the transactions table (thereby introducing a constraint that a transaction must exist in database for any coin);
- When inserting new coins to the database, first insert the corresponding transaction.
Of course this means you need access to transactions at the time of the migration. I'm still thinking about ways to reduce ugliness of doing that.
Perhaps we could add a migration step in |
Alright, so here is how i think we should proceed:
At the expense of making the code less encapsulated and a bit harder to follow, this gives us two nice robustness properties:
I've implemented this on this branch: https://github.com/darosior/liana/commits/pr_1180. Feel free to take anything from there, of course. |
Thanks for the updated approach and code. I wonder whether for such migrations that need to query the DB (to get the txids in the present case), we should first migrate the DB to the most recent version, then query the DB, and then apply the final migration. Although I don't think it would cause any problems in the present case, the DB query used in the current code base may not always be compatible with the user's DB version. Perhaps this could be done by passing the bitcoind connection to |
I think we should strive to make migrations atomics: your database is either fully compatible with the previous version or the next version. For instance with what you suggest a user could use Liana version N+1 with a database created with Liana version N, apply the first migration, for whatever reason encounter an error a crash or just stop the application before applying the second migration, and be stuck on a database which can neither be used by Liana version N nor by Liana version N+1. If the existing query methods on the SQLite connection struct were not appropriate to an old database we could just write a custom one for this purpose.
I precisely tried to avoid entangling the Bitcoin and Database modules. |
Sorry, I wasn't clear in my description. I didn't mean that the migration from DB versions 4 to 5 would be split in two separate steps. Each migration from one DB version to the following would still be atomic. So the function But I agree that keeping in mind the potential need to modify DB queries for previous DB versions should be sufficient. Indeed, that could still be required using my approach if version N - 1 is different. I'll proceed using your code and start adding it into this PR. |
Does bitcoind's watchonly wallet keep transactions that are no longer in the best chain or were never confirmed and are no longer in the mempool? |
Yes. |
I've now updated it to use foreign key constraints from the coins to transactions tables and to retrieve transactions as part of the migration. |
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.
Just a few comments as i read through the diff, which looks good.
I've written a unit to specifically exercise the migration from v4 to v5, including the failure case: darosior@c9c82f2. It only trips on the last check which compares the transactions from DB with the transactions created in the test because i think your |
The failing test may be due to the spend_txid having multiple different block infos, whereas |
I could add a corresponding assertion to |
Ah, good catch. Fixing it now. |
This is a slightly modified version of darosior's commit: d826f9f
I think I've now made all the requested changes. |
Tested migrating from v4.0, v5.0 and v6.0 using the migration functional test. |
Tested by upgrading a mainnet wallet. No issue. |
ACK 3953a0b |
re-ACK bf1e90e |
Thanks for the review and additional commits 😃 |
Thanks for bearing through the many iterations!
…-------- Original Message --------
On 8/2/24 12:25 PM, Michael Mallan wrote:
Thanks for the review and additional commits 😃
—
Reply to this email directly, [view it on GitHub](#1180 (comment)), or [unsubscribe](https://github.com/notifications/unsubscribe-auth/AFLK3F5P2U6R7WUMV4XJMJTZPNNA5AVCNFSM6AAAAABKSKEGOOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENRVGA3DGMZYHE).
You are receiving this because you modified the open/close state.Message ID: ***@***.***>
|
341f940 func test: prevent disconnects when using mocktime (Michael Mallan) b630d46 func test: wait for block heights to match (Michael Mallan) ada89c5 doc: update with electrum info (Michael Mallan) 177dfc4 lib: expose BDK's electrum client (Michael Mallan) 72c6314 ci: add electrs to func tests (jp1ac4) 371e31e func test: allow to run using electrs backend (jp1ac4) a85d488 func test: allow for different bitcoin backends (jp1ac4) 1b04b29 func test: fix min rbf feerate (jp1ac4) c7ee862 bitcoin: add electrum backend (jp1ac4) c4c2424 bitcoin: expose MempoolEntryFees (jp1ac4) 5011ad9 bitcoin: return spent block height & time separately (jp1ac4) 689442c bitcoin: allow to store UTXO deriv index (jp1ac4) 4c02b0d bitcoin: use mut ref for start_rescan (Michael Mallan) 69259c1 poller: sync wallet before checking updates (jp1ac4) 89e004d bitcoin: add sync_wallet method to interface (jp1ac4) 34b9a49 config: add general bitcoin backend option (jp1ac4) e267f66 descriptors: allow to get underlying public key (jp1ac4) Pull request description: This is to add the Electrum backend as part of #56 (comment). This requires the database to be running version 5 following #1180. The migration from a previous DB version must be done using bitcoind. Thereafter, the daemon can be run using an Electrum backend by replacing the `[bitcoind_config]` section in the daemon.toml config file with: ``` [electrum_config] addr = "127.0.0.1:50001" # adjust IP:port as required ``` Remaining tasks: - [x] Include ancestors and descendants when getting a transaction's `MempoolEntry` - [ ] Additional sanity checks, e.g. check Electrum version - [x] Check if logic regarding ongoing rescan needs to be adjusted - [x] Add Electrum backend to functional tests - [x] Add Electrum backend to CI pipline functional tests - [ ] Add unit tests - [x] Update README & other docs ACKs for top commit: darosior: re-ACK 341f940 Tree-SHA512: dbbb375123cc5c566f5c8535d002ac4491b4be5ab2766845b5b7ab51d19e7e85eafc0097235e1ebc5c5a049bd2222ab5582264314e46c77b5fff8027da31b803
This is the first step of #56 (comment).
The poller will now save transactions in our own database. These transactions are selected based on the deposit and spend transactions of coins. Only the txid and transaction itself are saved, with the corresponding block height and time taken from the coins table.
In a couple of follow-up commits, I've replaced some RPC calls to bitcoind with DB queries.