-
Notifications
You must be signed in to change notification settings - Fork 175
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
Improvements to wallet syncing and monitoring #359
Conversation
As of 8240655 I can report that I no longer have the problem of "need to do multiple restarts" from my ongoing mainnet testing. The change is explained in some detail in the commit message. (1) save the wallet indices at the end of a successful sync, as otherwise a change in the index will not be persisted unless a transaction happens (meaning on restart, you have to go back to the previous, unsynced index). @kristapsk if you have a chance to test, let me know if this commit fixes sync for you on whatever big wallet you have around. @undeath This isn't much more than a curiosity at this point, but don't you think these lines are un-needed? |
https://github.com/JoinMarket-Org/joinmarket-clientserver/pull/359/files#diff-79627d21bc41aff521fe45af1ee3968aR560 breaks wallet-tool's history method and probably other read-only stuff, raises |
@kristapsk yep i saw it earlier today also. Fix is in the next commit. Basically, some wallet-tool methods are "noscan" and that's important so you can access the data without trying to sync the wallet (like So I removed the 'read-only' flag from runs of wallet-tool on the methods 'display' and similar (like 'showutxos') that must sync/scan the wallet/blockchain. I judge there's no meaningful loss in security; this is not a long-running process like the maker or taker. You're still reading the secrets into memory, so there's no point blocking an update to the wallet file itself. |
There is big downside with removing read-only flag - now you can't run them while yield generator is running, because of wallet locks. So, it requires to shutdown yg, just to view history or list addresses (let's say, you want to send additional funds to your yg wallet) or do anything else with a specific wallet. |
Ah gotcha. Will figure it out tomorrow then. |
OK I'll just remove that index-saving code, it won't help anyway in normal conditions, it would only rarely make things more efficient, and I agree it's better not to screw up the locking function vs allowing read-only query. |
Those are an emergency fallback in case the wallet has been uncleanly closed (eg because of a crash). Removing those could cause jm to not recognise already used addresses, re-using them instead (and failing to display funds in there). Removing those would mean the user has no way to instruct jm to scan addresses beyond the wallet-saved index. |
I am running this all the time and didn't got any "restart Bitcoin Core..." messages until today. Only thing different is that I deposited some funds into external address of a wallet. But I think I have done it before (like in a last month or so) too, but don't remember having that message. In any case, clearly an improvement, although if depositing funds can cause it, will not be ok for #336. |
Well that's a disappointment. Clearly the intention was to prevent this; I'll try to reproduce, but pretty sure this was exactly the scenario I tested before (and indeed, both in testing and real world use I am not seeing this), so I don't know what causes it. If you can provide any more info on the circumstances it may help. I'll get back on working on this whole attempted syncing revamp today, or this week, at least I'll try to make progress ... Edit: hmm I see you mention #336 independently of #328 so I guess you mean, a deposit while JM is running, which is distinct I guess, from a deposit between runs. Maybe I didn't test that. Well, I am going to progress with earlier plans to address #336 anyway, so we'll have to wait to see if those plans actually solve this problem. |
I was depositing while yg is running and then got error with wallet-tool, IIRC. Will be mosly offline for about a week now, will be able to do more testing from my side next week. |
So I've spent a day or more reviewing and analysing the syncing code as-is, and I've come to the following conclusions:
So, the result of the review and discussion is that I believe I made an error in not promoting the The approach behind fast sync: We work on the assumption that all addresses that were ever used in the wallet label
Notice how this leverages two basic assumptions - no "foreign" usage of the JM HD wallet's specific label, and the wallet branches are not used beyond batch size * num iterations - to make a very simple algorithm. With perhaps a bump to the latter (batch size maybe 200 should be fine), this should cover every situation where the wallet is created on one Core instance and then progressively used. About imports: About the detailed/non-fast sync: The basic principle here is not to assume anything; it is specifically designed to address the needs of a recovery operation of a wallet on a new Core instance, where there is no wallet jmdat file and thus no JM HD wallet index, and there are no imports. It also does not assume that there are no usages of addresses beyond the gap limit, nor does it assume (or, let's say, use the assumption) that there are no usages of addresses at that label that are "foreign" to the JM HD wallet. This set of assumptions, or rather non-assumptions both makes it slow and also makes it hard to reason about and unreliable. One example of that is what @kristapsk found above: when he deposited to a new address, it created a situation where the set of "gap addresses" (the gap_limit addresses on each branch beyond the currently set index) was bumped forwards and then included new, un-imported addresses, causing the triggering of this line, which shuts down after doing address imports, specifically because it does not 100% know that the newly imported addresses are unused (in fact, that assumption is nearly safe, so one could argue for changing this), and if they are used, then a rescan is needed. The more general problematic symptom, which existed before 1e4e63c , was that restarts were needed after every transaction in the wallet. This was a very similar but not identical situation to the above: new transactions caused new imports and bumped the index, but the imports triggered did not include the whole of the gap addresses beyond that current index, and so this triggered a quit even earlier, here. In case it wasn't clear, the only difference between these two situations was that the "deposit" scenario didn't bump the index, whereas a transaction did. This is just a subset of the complexity here. It's important to note that not only is the second algorithm more complex, but that because it makes fewer assumptions it actually can often fail where the first algorithm succeeds, as well as being slower. Proposed changes: Make
Then also: rename the current default sync mode to "recovery" mode, as that will be its primary use case. All of the above is about sync, not about wallet monitoring which should be addressed separately. Ping @undeath @adlai @chris-belcher @AlexCato just in case you have thoughts on this. |
I approve of all these changes and would be happy to see them. I guess most users are unaware of --fast and barely read any documentation. I've lately forgot --fast sometimes, and boy that does take forever on a wallet that has seen some use. So it's a very userfriendly change to make --fast the default; also renaming the other one to recovery is good. |
1e4e63c
to
4837805
Compare
This was force-pushed today. There is already here a major refactoring, and I am increasingly confident that it's a very useful change. Since it's very big, here's a summary:
Avoiding getting lost in detail by listing more, but next steps:
None of these should be particularly hard at all, but they'll take some days. I'll also need to rebase of course. I expect this to be done within a week, probably. Feedback would be appreciated, especially if you can test after I've fixed the tests (dubious value to test it now). |
Syncing: The above commit adds the "default to fast sync" as previously discussed. Otherwise, the syncing methods are largely unchanged (except that you don't have to call them directly in user-level scripts; the I should also add that these changes have not addressed recently discovered problems with regard to imports, but they provide a route to doing so - we can add periodically woken up calls to do imports in small batches (not exactly a beautiful thing, but we seem to have no choice given what is effectively a bug in Core for slow HDs). |
53a217a
to
f2a49bc
Compare
I have removed this from WIP status because I think a natural end point has been reached that achieves these basic goals (not entirely what I set out, but a very significant chunk of improvement):
There are other minor things, notably the Qt Wallet tab properly respecting expansion states, and a few small refactorings. What has not been done is to cache importing, but I believe this will be much easier with the WalletService architecture.
What has been tested: TODO: keep testing as many functions as possible. I will test payjoin (although it runs in functional tests), and I will keep running from Maker and Taker on mainnet. So far I have run yieldgenerators and seen transactions go through, but it needs quite a bit more. So I would very much appreciate people running this in various ways, especially on mainnet. Since it's a broad change it needs a fair bit, there will doubtless be one or two more bugs, but I expect them to be minor at this point. (Will squash at end but left commits for now in case it's easier to read) |
8f594f0
to
c5d562d
Compare
This looks like a significant improvement over the kind of syncing done right now, thanks for this! I plan on reviewing and testing this code in the near future. When I start jm I see a bunch of "saw tx on network" messages with this code, which is a little confusing. |
Thanks.
Yes you're right. I haven't got round to it, it's just an artifact of setting up the monitoring loop by "caching" the current set of returns from |
@chris-belcher @AlexCato thanks. @kristapsk - It's been a while, have you checked again and specifically were you running dad8bcc ? |
Yes I was running that commit. |
@chris-belcher I think you misread :) I wasn't asking you that, only @kristapsk specifically - and that, because what he described on IRC at the time led to me to suspect that a code divergence may have caused the crash he experienced. For your case, I don't find it surprising that there may be such an error considering I haven't re-tested manual recovery since the latest changes, so I'll just repro and fix it today, most likely. |
So 3a60c67 should fix that. It came from me moving code around while refactoring. Now it behaves as before: if there is no restart callback specified, it defaults to command line printout. A reminder that |
With that new commit it correctly recovered a mainnet wallet from seed phrase. Edit: also just tested by using sendpayment.py with my own yield-gens on regtest. It seems to all work correctly, including only announcing confirmed funds. |
@AdamISZ , no, was busy with other stuff and now I'm travelling this week, so cannot promise anything in coming days. |
@kristapsk understood; thanks for letting me know. |
@kristapsk fwiw tested |
Introduces WalletService object which is in control of blockchain and wallet access. The service manages a single transaction monitoring loop, instead of multiple, and allows updates to the wallet from external sources to be handled in real time, so that both Qt and other apps (yg) can respond to deposits or withdrawals automatically. The refactoring also controls access to both wallet and blockchain so that client apps (Taker, Maker) will not need to be changed for future new versions e.g. client-side filtering. Also updates and improves Wallet Tab behaviour in Qt (memory of expansion state). Additionally, blockchain sync is now --fast by default, with the former default of detailed sync being renamed --recoversync.
68bf872
to
c654de0
Compare
c654de0 Wallet and blockchain refactoring (AdamISZ)
In refactor for #359 it was noted that the wallet monitoring loop in Qt updated the status bar every 5 seconds, overwriting any existing status updates. This fixes that UI bug so that the wallet synced successfully (or unsucessfully) message is only shown at start up or if there is a change of status (i.e. the wallet monitoring loop stops working).
Idea of this PR was prompted by some related problems.
See #328 - there seems to be some flaw in full sync at least (and fast also perhaps) involving not recognising/registering new addresses to the wallet such that restarts almost always involve retrying the sync when that shouldn't be necessary.
Not obviously related, but #336 for example is a simple failure at UI level where wallet does not dynamically update the GUI; similar but more fundamental, a deposit into the wallet during operation is not recognized until restart.
I think all these should be fixed, and it makes sense to do it as one "project". I'd like to achieve these things:
--fast
sync of assuming "normal" conditions and make it always work, first time, then - for the restarting-on-new-Core-wallet case, we can still keep the more clunky fallback.usage)
The first pushed commit here is something fairly minor, but part of the clean up: removed duplicated
import_new_addresses
functions and replaced them with an atomically in-wallet call, so that we can "guarantee" that all addresses used during JM operation have been imported.