-
Notifications
You must be signed in to change notification settings - Fork 1.2k
refactor: rearrange database initialization, trim globals use in net and net processing, move CheckSpecialTx into CSpecialTxProcessor #5966
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
Conversation
src/coinjoin/client.cpp
Outdated
| PeerMsgRet CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, CDataStream& vRecv) | ||
| { | ||
| assert(::mmetaman->IsValid()); | ||
| assert(m_mn_metaman.IsValid()); |
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.
600 lines up and down is not an easy thing to review :(
That one "refactor: remove CMasternodeMetaMan global, move to NodeContext" alone is worth a PR for itself only
|
This pull request has conflicts, please rebase. |
Same failure on develop https://gitlab.com/dashpay/dash/-/jobs/6483372677 |
knst
left a comment
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.
these commits are ACK:
- init: move CActiveMasternodeManager construction before PeerManager
- refactor: trim globals use in net processing functions
- refactor: const the pointer of type const CActiveMasternodeManager
- refactor: move CheckSpecialTx into CSpecialTxProcessor
To other commits I have a comments or haven't carefully reviewed yet
|
|
||
| PeerMsgRet CMNAuth::ProcessMessage(CNode& peer, CConnman& connman, const CDeterministicMNList& tip_mn_list, std::string_view msg_type, CDataStream& vRecv) | ||
| { | ||
| assert(::mmetaman->IsValid()); |
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.
what happen if mmetaman is not initialized yet and we will ignore this message? is it fatal?
I feel like this assert is a little bit too much. also if message is not MNAUTH - it's not even need any processing
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.
Database initialization (setting IsValid() to true) is done (source) before networking starts (source). If there is a database problem that didn't get caught earlier on, starting networking threads and read-writing values could result in an inconsistent state. This is a problem regardless of which database and therefore, should fast-fail if it happens.
CMNAuth::ProcessMessage is only called by PeerManagerImpl::ProcessMessages (source), there aren't any other threads or entities that can call it, making a state where peerman exists but mn_metaman doesn't improbable.
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.
let's add doxygen here to require mn_metamann be non nullptr here:
Line 56 in e210cb7
| static PeerMsgRet ProcessMessage(CNode& peer, CConnman& connman, CMasternodeMetaMan& mn_metaman, const CActiveMasternodeManager* const mn_activeman, |
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.
We're already passing CMasternodeMetaMan as a reference here, there's no opportunity for it to be a nullptr.
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.
sorry, I mean mn_metaman to be valid due to assert(mn_metaman.IsValid());. That can't be nullptr indeed, but it can be invalid
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.
Resolved in latest push (comment added in header)
src/txmempool.cpp
Outdated
| vTxHashes.clear(); | ||
|
|
||
| if (::deterministicMNManager) { | ||
| removeUncheckedProTx(it->GetTx()); |
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.
what if deterministicMNManager will be nullptr when tx is added, but won't be nullptr when tx is removed -- will it work correctly?
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.
That would be highly problematic as that shows us that in the order of (de)initialization has been messed with, which is highly unlikely in init and the constructors in setup_common, meaning, at worst, it's a faulty test where the values of globals are being manually manipulated.
The refactoring of CTxMemPool split up from the rest of CDeterministicMNManager deglobalization was done for ease of review, eventually, we use the pointer set with ConnectManagers instead of using globals directly (source), making any modifications explicit.
src/llmq/chainlocks.cpp
Outdated
| CChainLocksHandler::CChainLocksHandler(CChainState& chainstate, CConnman& _connman, CQuorumManager& _qman, | ||
| CSigningManager& _sigman, CSigSharesManager& _shareman, CSporkManager& sporkman, | ||
| CTxMemPool& _mempool) : | ||
| CTxMemPool& _mempool, const CMasternodeSync& mn_sync) : |
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.
why that? add const - ok, why changing order here?
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.
Because we place const args after non-const args, see LLMQContext, CJContext and CDSNotificationInterface for examples.
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.
there's no clear agreement about order of const/non-const argument in methods, but this one is the closest:
For consistency and friendliness to code generation tools, interface method input and inout parameters should be ordered first and output parameters should come last.
https://github.com/dashpay/dash/blob/e210cb734e16e0ecef9601251fe0e074ed86827e/doc/developer-notes.md
I would say that const argument are better to go first rather than being after non-const, thoughts?
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.
If we're talking about arguments that can be clearly understood as inputs/outputs, then I agree.
Though we have this middle ground with references to managers that are read-write (non-const) or read-only (const), some references are used to access functions that seem to do only read-only things even when behind the scenes they are read-write (like CDeterministicMNManager::GetListAtTip(), which is non-const).
Plus, sometimes we use const for unique_ptr refs, where we are only consting the container ref but intend to do read-write activities with the underlying type. It starts becoming less clear.
Maybe it can examined at some point but I think current convention is inoffensive, not particularly misleading.
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.
sometimes we use const for unique_ptr refs
indeed, but all const unique_ptr are just temporary workarounds until circular dependencies are broken
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.
IMO as long as they're there in the reasonable future, they need to be considered.
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.
so, still, is there any reason why you moved const argument from the beginning to the end? If there's anything uses not the best code style that's not a reason to spread it over codebase.
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 the placement here is fine. I think it only needs to be enforced that "out params" are at the end. Ordering of const and non-const in or inout params, is not important.
src/txmempool.cpp
Outdated
| // fully checked by AcceptToMemoryPool() at this point, so we just assume that | ||
| // everything is fine here. | ||
| if (::deterministicMNManager) { | ||
| if (m_dmnman) { |
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.
should we assert here then?
see #5966 (comment)
I think we should not let transactions to be added or removed from mempool if that's not fully initialized yet.
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.
Not necessary, the value of m_dmnman is assert'ed before being set (source). If in the middle of operation, a manager is gone, there are bigger problems.
CTxMemPool can actually operate without m_dmnman so long as you don't require ProTx logic (and this is the case with some unit tests), so we don't need to make it a compulsion.
|
PR has been split between refactors in preparation for deglobalization and deglobalization, the latter is now available at #5980 |
The order in which they're loaded is dictated by the order in which they
are initialized. This also lets us get rid of that fast-fail because
governance db was always going to load before mncache db and replace it
with an assert.
Also, rename UpdateCachesAndClean to CheckAndRemove in CGovernanceManager
as CheckAndRemove is already an existing alias to UpdateCachesAndClean and
CheckAndRemove is associated with similar functionality in
C{NetFulfilledRequest, Spork}Manager
knst
left a comment
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.
utACK
UdjinM6
left a comment
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.
utACK
PastaPastaPasta
left a comment
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.
utACK 191b3de
…er, CMasternode{MetaMan, Sync} to NodeContext
a5be37c refactor: remove CDeterministicMNManager global, move to NodeContext (Kittywhiskers Van Gogh)
cf90cf2 refactor: remove CMasternodeMetaMan global, move to NodeContext (Kittywhiskers Van Gogh)
81b1247 refactor: remove CActiveMasternodeManager global, move to NodeContext (Kittywhiskers Van Gogh)
c99fb42 refactor: remove CMasternodeSync global, move to NodeContext (Kittywhiskers Van Gogh)
a247a63 refactor: make CTxMemPool ProTx paths conditional on CDeterministicMNManager presence (Kittywhiskers Van Gogh)
Pull request description:
## Additional Information
* Depends on #5966
* `CTxMemPool`'s ProTx logic took the presence of `CDeterministicMNManager` for granted. To account for `CTxMemPool` instances that aren't seeded with the pointer to the manager (usually because the unit test doesn't call for them), refactoring was done to make ProTx code paths conditional on the manager pointer being set to something.
* Setting the manager pointer is done through `CTxMemPool::Init()`, to avoid having to pass another `std::unique_ptr` const-ref and also because `CTxMemPool` can _technically_ work without the manager if ProTx logic is not needed (and `CTxMemPool::existsProviderTxConflict()` isn't called)
* `CTxMemPool::Init()` doesn't allow overwriting a not-`nullptr` manager pointer. If that is desired, then `CTxMemPool::Reset()` should be called first. This was done to avoid unintentional double-initialization/overwriting.
## Breaking Changes
None. Changes are limited to refactoring.
## Checklist:
- [x] I have performed a self-review of my own code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have added or updated relevant unit/integration/functional/e2e tests
- [x] I have made corresponding changes to the documentation **(note: N/A)**
- [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_
ACKs for top commit:
PastaPastaPasta:
utACK a5be37c
Tree-SHA512: 8dc7ada6597a265b7753603bca6a43b69cfe3b0d330bae98c3e27b6aa24cd3cdff80f6939bb39ffc00902b76b6b145667f0b7ac98a17fe8255d6fd143088a98c
Additional Information
Dependency for refactor: move C{ActiveMasternode, DeterministicMN}Manager, CMasternode{MetaMan, Sync} to NodeContext #5980
CActiveMasternodeManagerconstruction is moved upwards (beforePeerManagerconstruction) to avoid having to pass it as astd::unique_ptrconst-ref. Shouldn't have any effect since initialization is done inThreadImport.CConnman::SetNetworkActivewill require a pointer toCMasternodeSyncin order to callCMasternodeSync::Reset(). As it is no longer available as a global, it will need to be manually called through for the effect to happen as theCConnmanconstructor will simply pass anullptrwhen callingSetNetworkActive, bypassing theReset()call.CMasternodeSyncis appropriately passed through in RPC (setnetworkactive) and interfaces.CheckSpecialTxwas moved intoCSpecialTxProcessorto avoid having to exposeCDeterministicMNManagertoMemPoolAccept(though it has been exposed toCChainstateHelperthrough a helper,CChainState::ChainHelper()that was introduced in this PR).CDeterministicMNManager, will also be accessingCChainstateHelper.Concerns
Some tests seem to sporadically fail (fail as part of a suite but succeed when run individually, no changes in this PR should worsen resource contention) but attempting to reproduce them reliably hasn't succeeded so far.It appears the sporadic failure is shown in
p2p_node_network_limited.pyduring TSan runs (see failed run for commit f95ffa7 that then succeeded in a second attempt versus a similar failed run for e210cb7 that also succeeded on second try). Similar behaviour has not been observed ondevelop(as of this writing is 27c0813).Breaking changes
CMasternodeSync::Reset()will not be called on everyCConnmanentity instantiated. Behaviour changes as a result of that are not substantiated. Protocol, networking or interface changes are not expected, changes are primarily refactoring.Checklist:
Go over all the following points, and put an
xin all the boxes that apply.