refactor: remove ::vpwallets and related global variables#19101
refactor: remove ::vpwallets and related global variables#19101fanquake merged 1 commit intobitcoin:masterfrom
Conversation
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
Qt tests currently are currently using two NodeContext structs at the same time, one in interfaces::NodeImpl::m_context, and the other in BasicTestingSetup::m_node, and the tests have hacks transferring state between them. Fix this by getting rid of the NodeImpl::m_context struct and making it a pointer. This way a common BitcoinApplication object can be used for all qt tests, but they can still have their own testing setups. Non-test code is changing but non-test behavior is still the same as before. Benefit of this PR is to being able to remove the existing "std::move(test.m_node.connman)" and mempool hacks. Motivation for this PR is to let qt wallet tests continue working when the ::vpwallets global variable is removed bitcoin#19101 and not have to add even more complicated hacks exposing duplicate WalletContext and WalletClient instances in addition to the duplicate NodeContext instances and having to manipulate them in the test setup.
|
Rebased 197a403 -> 7272686 ( |
Qt tests currently are currently using two NodeContext structs at the same time, one in interfaces::NodeImpl::m_context, and the other in BasicTestingSetup::m_node, and the tests have hacks transferring state between them. Fix this by getting rid of the NodeImpl::m_context struct and making it a pointer. This way a common BitcoinApplication object can be used for all qt tests, but they can still have their own testing setups. Non-test code is changing but non-test behavior is still the same as before. Benefit of this PR is to being able to remove the existing "std::move(test.m_node.connman)" and mempool hacks. Motivation for this PR is to let qt wallet tests continue working when the ::vpwallets global variable is removed bitcoin#19101 and not have to add even more complicated hacks exposing duplicate WalletContext and WalletClient instances in addition to the duplicate NodeContext instances and having to manipulate them in the test setup.
|
Concept ACK, need to update commits in OP. |
src/qt/bitcoin.cpp
Outdated
|
|
||
| #ifdef ENABLE_WALLET | ||
| // Delete wallet controller here manually, instead of relying on Qt | ||
| // reference counting. This makes sure walletmodel m_handle_* notification |
There was a problem hiding this comment.
There was a problem hiding this comment.
re: #19101 (comment)
instead of relying on Qt reference counting.
What Qt reference counting?
Thanks, changed "reference counting" to "object tracking" and linked to https://doc.qt.io/qt-5/objecttrees.html
| // wallet implementations. It also avoids these notifications having to be | ||
| // handled while GUI objects are being destroyed, making GUI code less | ||
| // fragile as well. | ||
| delete m_wallet_controller; |
There was a problem hiding this comment.
Just noting that its not necessary to check for WalletModel::isWalletEnabled()), delete nullptr is safe.
src/wallet/context.h
Outdated
| struct WalletContext { | ||
| interfaces::Chain* chain{nullptr}; | ||
| ArgsManager* args{nullptr}; | ||
| RecursiveMutex wallets_mutex; |
There was a problem hiding this comment.
It seems this can be a Mutex, just a suggestion for follow-up.
There was a problem hiding this comment.
re: #19101 (comment)
It seems this can be a
Mutex, just a suggestion for follow-up.
Thanks went ahead and made the change here. It's not an immediately obvious change because the mutex is held while calling wallet_load_fns callbacks, but looking at the callbacks registered in GUI code it seems like these will never change the list of wallets so it seems good change to get rid of the recursive mutex now to prevent more complexity in the future
There was a problem hiding this comment.
I also tested Mutex and built it with TSAN, LGTM
ryanofsky
left a comment
There was a problem hiding this comment.
Thanks for review! Made some updates based on comments.
Updated 4be544c -> eb389b3 (pr/novp.24 -> pr/novp.25, compare) with review tweaks
src/qt/bitcoin.cpp
Outdated
|
|
||
| #ifdef ENABLE_WALLET | ||
| // Delete wallet controller here manually, instead of relying on Qt | ||
| // reference counting. This makes sure walletmodel m_handle_* notification |
There was a problem hiding this comment.
re: #19101 (comment)
instead of relying on Qt reference counting.
What Qt reference counting?
Thanks, changed "reference counting" to "object tracking" and linked to https://doc.qt.io/qt-5/objecttrees.html
src/wallet/context.h
Outdated
| struct WalletContext { | ||
| interfaces::Chain* chain{nullptr}; | ||
| ArgsManager* args{nullptr}; | ||
| RecursiveMutex wallets_mutex; |
There was a problem hiding this comment.
re: #19101 (comment)
It seems this can be a
Mutex, just a suggestion for follow-up.
Thanks went ahead and made the change here. It's not an immediately obvious change because the mutex is held while calling wallet_load_fns callbacks, but looking at the callbacks registered in GUI code it seems like these will never change the list of wallets so it seems good change to get rid of the recursive mutex now to prevent more complexity in the future
|
@ryanofsky I find your PR good. It's easier to follow for me than the code in master branch. Concept ACK. I can see that #15638 of yours added I had a look where the functions from WalletContext& context = *node.walletClient().context();
AddWallet(context, wallet);
WalletModel walletModel(interfaces::MakeWallet(context, wallet), clientModel, platformStyle.get());
RemoveWallet(context, wallet, std::nullopt);to: WalletClient& walletClient = *node.walletClient();
walletClient.AddWallet(wallet);
// WalletModel walletModel(interfaces::MakeWallet(context, wallet), clientModel, platformStyle.get()); // not sure here
walletClient.RemoveWallet(wallet, std::nullopt);I don't really know if it is possible at all, I would just love to hear your opinion on this. |
|
You could merge I think I'm not understanding the advantages of the specific Qt apptest change you mentioned. Qt test code does access internals of many layers because some checks are easier to do at the GUI layer, other are easier to do at the wallet layer, etc. I think it's important for this to be possible, but in general the interfaces should be designed more to hide internals than expose them. As for wallet load code it's true it is only called in one place. Probably it is missing some test coverage. I would like to move more wallet loading code from |
I certainly do not suggest to make code worse from modularity point of view. I wrote my comment to understand better how/why you implemented this PR as you did. Thank you for the explanation. Also I did not write the comment to suggest any modifications to this PR but to understand what would happen if instead of I spent several hours trying to get familiar with various wallet classes and it still feels like I only scratched the surface, so that's why your insights here may be very valuable to other reviewers as well. |
|
Thanks for asking these questions! I'm very happy to answer them, and I hope I didn't give the impression that I was disagreeing with anything. I was trying to answer "Is it necessary to have the context struct?" and say I don't think it's necessary, but I do think it's good because I think it's more lightweight than |
src/qt/test/wallettests.cpp
Outdated
| WalletContext& context = *node.walletClient().context(); | ||
| AddWallet(context, wallet); | ||
| WalletModel walletModel(interfaces::MakeWallet(context, wallet), clientModel, platformStyle.get()); | ||
| RemoveWallet(context, wallet, std::nullopt); |
There was a problem hiding this comment.
(This snippet is exactly the same as in src/qt/test/addressbooktests.cpp but I must say I rather double checked with my editor's text search.)
There was a problem hiding this comment.
re: #19101 (comment)
(This snippet is exactly the same as in
src/qt/test/addressbooktests.cppbut I must say I rather double checked with my editor's text search.)
Duplication is good to note, but it precedes this PR, and I think trying to simplify or dedup here would be more invasive and make more sense as a separate change. (This PR is just adding function parameters. Trying to replace the actual function calls would be a bigger change.)
There was a problem hiding this comment.
Yes, that was just an observation. I agree that it is better to address that in another PR if at all.
| return HandleLoadWallet(std::move(fn)); | ||
| return HandleLoadWallet(m_context, std::move(fn)); | ||
| } | ||
| WalletContext* context() override { return &m_context; } |
There was a problem hiding this comment.
Would it be possible to pass WalletContext via constructor to WalletClientImpl? It seems that in that case, this function may not be necessary and a test can still create WalletClientImpl.
There was a problem hiding this comment.
re: #19101 (comment)
Would it be possible to pass
WalletContextvia constructor toWalletClientImpl? It seems that in that case, this function may not be necessary and a test can still createWalletClientImpl.
I think that could work but it seems a little better to me if instead of passing around WalletClient / WalletContext pairs, that if tests are already using WalletClient interfaces, they prefer using them, and only access the internal context as a fallback so they are less tied to implementation details. I think having a context method does a good job of encouraging using the external interface while making internal access still possible.
There was a problem hiding this comment.
Thanks for review! Responded and implemented some of the suggestions
Rebased eb389b3 -> 6ef719f (pr/novp.25 -> pr/novp.26, compare) on top of bitcoin-core/gui#360, with review suggestions
Rebased 6ef719f -> df609b1 (pr/novp.26 -> pr/novp.27, compare) due to conflict with #21866
| return HandleLoadWallet(std::move(fn)); | ||
| return HandleLoadWallet(m_context, std::move(fn)); | ||
| } | ||
| WalletContext* context() override { return &m_context; } |
There was a problem hiding this comment.
re: #19101 (comment)
Would it be possible to pass
WalletContextvia constructor toWalletClientImpl? It seems that in that case, this function may not be necessary and a test can still createWalletClientImpl.
I think that could work but it seems a little better to me if instead of passing around WalletClient / WalletContext pairs, that if tests are already using WalletClient interfaces, they prefer using them, and only access the internal context as a fallback so they are less tied to implementation details. I think having a context method does a good job of encouraging using the external interface while making internal access still possible.
src/qt/test/wallettests.cpp
Outdated
| WalletContext& context = *node.walletClient().context(); | ||
| AddWallet(context, wallet); | ||
| WalletModel walletModel(interfaces::MakeWallet(context, wallet), clientModel, platformStyle.get()); | ||
| RemoveWallet(context, wallet, std::nullopt); |
There was a problem hiding this comment.
re: #19101 (comment)
(This snippet is exactly the same as in
src/qt/test/addressbooktests.cppbut I must say I rather double checked with my editor's text search.)
Duplication is good to note, but it precedes this PR, and I think trying to simplify or dedup here would be more invasive and make more sense as a separate change. (This PR is just adding function parameters. Trying to replace the actual function calls would be a bigger change.)
|
Base PR bitcoin-core/gui#360 is now merged so this PR doesn't have any dependencies Rebased df609b1 -> 6e6a7e1 ( |
There was a problem hiding this comment.
Code review ACK 6e6a7e1
Thanks Russ for your continued great work!
Move global wallet variables to WalletContext struct
|
Rebased 6e6a7e1 -> 62a09a3 ( |
|
ACK 62a09a3 |
|
@kiminuo maybe you'll want to follow up here given some of the comments up thread? |
Yes, will do. Thanks for the notification. |
| // Schedule periodic wallet flushes and tx rebroadcasts | ||
| if (args.GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET)) { | ||
| scheduler.scheduleEvery(MaybeCompactWalletDB, std::chrono::milliseconds{500}); | ||
| if (context.args->GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET)) { |
There was a problem hiding this comment.
Previously this was an Assert, now it is UB. Obviously doesn't matter, but I wanted to point out the difference.
Get rid of global wallet list variables by moving them to WalletContext struct
cs_walletsis nowWalletContext::wallet_mutexvpwalletsis nowWalletContext::walletsg_load_wallet_fnsis nowWalletContext::wallet_load_fns