Skip to content

Commit fdf3ab3

Browse files
Merge #7056: refactor: extract CActiveMasternodeManager from LLMQContext (1/n, preliminary refactoring)
0114f58 fix: guard `quorumBaseBlockIndexCache` (Kittywhiskers Van Gogh) 2c6cbc9 refactor: use `gsl::not_null` in `CQuorumManager` wherever possible (Kittywhiskers Van Gogh) 8f8078f refactor: initialize `CJWalletManager` after `ActiveContext` (Kittywhiskers Van Gogh) dac4769 refactor: move `CDKGSessionManager` to `{Active,Observer}Context` (Kittywhiskers Van Gogh) 9c61900 refactor: create stub class for watch-only mode context (Kittywhiskers Van Gogh) b9e20f4 refactor: introduce `MakePeerManager()` helper for test setup (Kittywhiskers Van Gogh) 6b811c2 refactor: make `CDKGSessionManager` a plugable obj for `CQuorumManager` (Kittywhiskers Van Gogh) 5d54cfe refactor: couple listener registration with instantiation (Kittywhiskers Van Gogh) 263dd67 refactor: drop remaining `gArgs` usage in LLMQ code (Kittywhiskers Van Gogh) 3f41401 refactor: move `GetEnabledQuorumVvecSyncEntries()` invocation to init (Kittywhiskers Van Gogh) 16459c5 refactor: drop `QuorumDataRecoveryEnabled()` (Kittywhiskers Van Gogh) 7f32d39 refactor: drop `IsWatchQuorumsEnabled()` (Kittywhiskers Van Gogh) Pull request description: ## Additional Information * Dependency for #7062 * As mentioned in [bitcoin#25862](bitcoin#25862), code in `libbitcoin_kernel` should not interact with `ArgsManager` and currently, Dash-specific chainstate validation relies on it to query flags like `-watchquorums` and `-llmq-data-recovery`. They have been refactored to be taken as constructor arguments in the style of [bitcoin#23280](bitcoin#23280) and passed from the context to the constructor of the underlying managers. Similar changes have been extended to remaining `gArgs` usage. * When debugging dependent PRs, it was found that there was a potential race condition as the creation of the signer was done by one entity (`ActiveContext`) but activation was done by the parent entity (e.g. `CChainLocksHandler`). Further complicating the relationship is the introduction of a network entity (e.g. `NetInstantSend`) which could cause potential lifecycle issues. To simpilfy this, the entity that is responsible for creation of the signer is also responsible for registration of the signer. The functions have also been renamed to follow the convention in `CSigSharesManager` to `{Unr,R}egisterAsRecoveredSigsListener()` as it more descriptive as opposed to `Start`/`Stop()`, which is associated with spawning worker entities. * `CDKGSessionManager` is a dormant entity if the node is not in watch-only mode or masternode mode ([source](https://github.com/dashpay/dash/blob/bac6bfadffe6fcf323e5e0208c8619e1e68401fe/src/llmq/dkgsessionmgr.cpp#L46-L49)), to allow moving them to contexts that are mode-specific (in order to keep `LLMQContext` limited to only chainstate validation logic), it is now a connectable entity in the style of [dash#5980](#5980) (a5be37c). * Conversely, we now have ready access to `ChainstateManager` when constructing `CMNHFManager` so we can partially revert the change introduced in [dash#6078](#6078) (208b1c0). * As subsequent PRs will change the ctor arguments for `PeerManager` multiple times, a helper has been added in the form of `MakePeerManager()` to contain the changes to the helper. * Currently, `CJWalletManager` is initialised if `CActiveMasternodeManager` is _not_ initialised. This is fine _until_ we move `CActiveMasternodeManager` into `ActiveContext` as `ActiveContext` is initialised after `CJWalletManager` and cannot be moved upward due to hard dependencies. As there's no reason that `CJWalletManager` needs to be initialised early, we can move it down instead. ## Breaking Changes None expected. ## 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)_ Top commit has no ACKs. Tree-SHA512: d4597f24f918f2b7bc3468111acce004d3df83b2229afd658bb2b4df319369f337cc3a7ae27ed8159ea36265f8f7ad12cba91299d2b156e75b13c62ebdeedc19
2 parents 6458199 + 0114f58 commit fdf3ab3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+463
-283
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ BITCOIN_CORE_H = \
285285
llmq/snapshot.h \
286286
llmq/types.h \
287287
llmq/utils.h \
288+
llmq/observer/context.h \
288289
logging.h \
289290
logging/timer.h \
290291
mapport.h \
@@ -553,6 +554,7 @@ libbitcoin_node_a_SOURCES = \
553554
llmq/signing_shares.cpp \
554555
llmq/snapshot.cpp \
555556
llmq/utils.cpp \
557+
llmq/observer/context.cpp \
556558
mapport.cpp \
557559
masternode/active/context.cpp \
558560
masternode/active/notificationinterface.cpp \

src/chainlock/chainlock.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,6 @@ CChainLocksHandler::~CChainLocksHandler()
6363

6464
void CChainLocksHandler::Start(const llmq::CInstantSendManager& isman)
6565
{
66-
if (auto signer = m_signer.load(std::memory_order_acquire); signer) {
67-
signer->Start();
68-
}
6966
scheduler->scheduleEvery(
7067
[&]() {
7168
auto signer = m_signer.load(std::memory_order_acquire);
@@ -83,9 +80,6 @@ void CChainLocksHandler::Start(const llmq::CInstantSendManager& isman)
8380
void CChainLocksHandler::Stop()
8481
{
8582
scheduler->stop();
86-
if (auto signer = m_signer.load(std::memory_order_acquire); signer) {
87-
signer->Stop();
88-
}
8983
}
9084

9185
bool CChainLocksHandler::AlreadyHave(const CInv& inv) const

src/chainlock/signing.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ ChainLockSigner::ChainLockSigner(CChainState& chainstate, ChainLockSignerParent&
3030

3131
ChainLockSigner::~ChainLockSigner() = default;
3232

33-
void ChainLockSigner::Start()
33+
void ChainLockSigner::RegisterRecoveryInterface()
3434
{
3535
m_sigman.RegisterRecoveredSigsListener(this);
3636
}
3737

38-
void ChainLockSigner::Stop()
38+
void ChainLockSigner::UnregisterRecoveryInterface()
3939
{
4040
m_sigman.UnregisterRecoveredSigsListener(this);
4141
}

src/chainlock/signing.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ class ChainLockSigner final : public llmq::CRecoveredSigsListener
7070
llmq::CSigSharesManager& shareman, CSporkManager& sporkman, const CMasternodeSync& mn_sync);
7171
~ChainLockSigner();
7272

73-
void Start();
74-
void Stop();
73+
void RegisterRecoveryInterface();
74+
void UnregisterRecoveryInterface();
7575

7676
void EraseFromBlockHashTxidMap(const uint256& hash)
7777
EXCLUSIVE_LOCKS_REQUIRED(!cs_signer);

src/dsnotificationinterface.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con
7878

7979
m_llmq_ctx->isman->UpdatedBlockTip(pindexNew);
8080
m_llmq_ctx->clhandler->UpdatedBlockTip(*m_llmq_ctx->isman);
81-
m_llmq_ctx->qdkgsman->UpdatedBlockTip(pindexNew, fInitialDownload);
8281
m_llmq_ctx->qman->UpdatedBlockTip(pindexNew, m_connman, fInitialDownload);
8382

8483
if (m_govman.IsValid()) {

src/init.cpp

Lines changed: 55 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,9 @@
9494
#include <instantsend/net_instantsend.h>
9595
#include <llmq/context.h>
9696
#include <llmq/dkgsessionmgr.h>
97-
#include <llmq/options.h>
9897
#include <llmq/net_signing.h>
98+
#include <llmq/options.h>
99+
#include <llmq/observer/context.h>
99100
#include <masternode/active/context.h>
100101
#include <masternode/active/notificationinterface.h>
101102
#include <masternode/meta.h>
@@ -258,9 +259,6 @@ void Interrupt(NodeContext& node)
258259
if (node.peerman) {
259260
node.peerman->InterruptHandlers();
260261
}
261-
if (node.llmq_ctx) {
262-
node.llmq_ctx->Interrupt();
263-
}
264262
InterruptMapPort();
265263
if (node.connman)
266264
node.connman->Interrupt();
@@ -350,6 +348,10 @@ void PrepareShutdown(NodeContext& node)
350348
// CValidationInterface callbacks, flush them...
351349
GetMainSignals().FlushBackgroundCallbacks();
352350

351+
if (node.observer_ctx) {
352+
UnregisterValidationInterface(node.observer_ctx.get());
353+
}
354+
353355
if (g_active_notification_interface) {
354356
UnregisterValidationInterface(g_active_notification_interface.get());
355357
g_active_notification_interface.reset();
@@ -366,6 +368,7 @@ void PrepareShutdown(NodeContext& node)
366368

367369
// After all scheduled tasks have been flushed, destroy pointers
368370
// and reset all to nullptr.
371+
node.observer_ctx.reset();
369372
node.active_ctx.reset();
370373
node.mn_sync.reset();
371374
node.sporkman.reset();
@@ -1409,9 +1412,8 @@ bool AppInitParameterInteraction(const ArgsManager& args)
14091412
}
14101413

14111414
try {
1412-
const bool fRecoveryEnabled{llmq::QuorumDataRecoveryEnabled()};
1413-
const bool fQuorumVvecRequestsEnabled{llmq::GetEnabledQuorumVvecSyncEntries().size() > 0};
1414-
if (!fRecoveryEnabled && fQuorumVvecRequestsEnabled) {
1415+
const bool fQuorumVvecRequestsEnabled{llmq::GetEnabledQuorumVvecSyncEntries(args).size() > 0};
1416+
if (!args.GetBoolArg("-llmq-data-recovery", llmq::DEFAULT_ENABLE_QUORUM_DATA_RECOVERY) && fQuorumVvecRequestsEnabled) {
14151417
InitWarning(Untranslated("-llmq-qvvec-sync set but recovery is disabled due to -llmq-data-recovery=0"));
14161418
}
14171419
} catch (const std::invalid_argument& e) {
@@ -1956,6 +1958,9 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
19561958
fReindex = args.GetBoolArg("-reindex", false);
19571959
bool fReindexChainState = args.GetBoolArg("-reindex-chainstate", false);
19581960

1961+
const bool quorums_recovery = args.GetBoolArg("-llmq-data-recovery", llmq::DEFAULT_ENABLE_QUORUM_DATA_RECOVERY);
1962+
const bool quorums_watch = args.GetBoolArg("-watchquorums", llmq::DEFAULT_WATCH_QUORUMS);
1963+
19591964
// cache size calculations
19601965
CacheSizes cache_sizes = CalculateCacheSizes(args, g_enabled_filter_types.size());
19611966

@@ -2023,13 +2028,27 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
20232028
args.GetBoolArg("-spentindex", DEFAULT_SPENTINDEX),
20242029
args.GetBoolArg("-timestampindex", DEFAULT_TIMESTAMPINDEX),
20252030
chainparams.GetConsensus(),
2031+
llmq::GetEnabledQuorumVvecSyncEntries(args),
20262032
fReindexChainState,
20272033
cache_sizes.block_tree_db,
20282034
cache_sizes.coins_db,
20292035
cache_sizes.coins,
20302036
/*block_tree_db_in_memory=*/false,
20312037
/*coins_db_in_memory=*/false,
20322038
/*dash_dbs_in_memory=*/false,
2039+
quorums_recovery,
2040+
quorums_watch,
2041+
/*bls_threads=*/[&args]() -> int8_t {
2042+
int8_t threads = args.GetIntArg("-parbls", llmq::DEFAULT_BLSCHECK_THREADS);
2043+
if (threads <= 0) {
2044+
// -parbls=0 means autodetect (number of cores - 1 validator threads)
2045+
// -parbls=-n means "leave n cores free" (number of cores - n - 1 validator threads)
2046+
threads += GetNumCores();
2047+
}
2048+
// Subtract 1 because the main thread counts towards the par threads
2049+
return std::clamp<int8_t>(threads - 1, 0, llmq::MAX_BLSCHECK_THREADS);
2050+
}(),
2051+
args.GetIntArg("-maxrecsigsage", llmq::DEFAULT_MAX_RECOVERED_SIGS_AGE),
20332052
/*shutdown_requested=*/ShutdownRequested,
20342053
/*coins_error_cb=*/[]() {
20352054
uiInterface.ThreadSafeMessageBox(
@@ -2175,45 +2194,56 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
21752194
assert(!node.dstxman);
21762195
node.dstxman = std::make_unique<CDSTXManager>();
21772196

2178-
assert(!node.cj_walletman);
2179-
if (!node.mn_activeman) {
2180-
node.cj_walletman = CJWalletManager::make(chainman, *node.dmnman, *node.mn_metaman, *node.mempool, *node.mn_sync,
2181-
*node.llmq_ctx->isman, !ignores_incoming_txs);
2182-
}
2183-
if (node.cj_walletman) {
2184-
RegisterValidationInterface(node.cj_walletman.get());
2185-
}
2186-
21872197
assert(!node.peerman);
21882198
node.peerman = PeerManager::make(chainparams, *node.connman, *node.addrman, node.banman.get(), *node.dstxman,
21892199
chainman, *node.mempool, *node.mn_metaman, *node.mn_sync,
2190-
*node.govman, *node.sporkman, node.mn_activeman.get(), node.dmnman,
2191-
node.active_ctx, node.cj_walletman.get(), node.llmq_ctx, ignores_incoming_txs);
2200+
*node.govman, *node.sporkman, node.mn_activeman.get(), node.active_ctx, node.dmnman,
2201+
node.cj_walletman, node.llmq_ctx, node.observer_ctx, ignores_incoming_txs);
21922202
RegisterValidationInterface(node.peerman.get());
21932203

21942204
g_ds_notification_interface = std::make_unique<CDSNotificationInterface>(
21952205
*node.connman, *node.dstxman, *node.mn_sync, *node.govman, chainman, node.dmnman, node.llmq_ctx
21962206
);
21972207
RegisterValidationInterface(g_ds_notification_interface.get());
21982208

2199-
// ********************************************************* Step 7c: Setup masternode mode
2209+
// ********************************************************* Step 7c: Setup masternode mode or watch-only mode
22002210
assert(!node.active_ctx);
22012211
assert(!g_active_notification_interface);
2212+
assert(!node.observer_ctx);
2213+
22022214
node.peerman->AddExtraHandler(std::make_unique<NetInstantSend>(node.peerman.get(), *node.llmq_ctx->isman, *node.llmq_ctx->qman, chainman.ActiveChainstate()));
22032215
node.peerman->AddExtraHandler(std::make_unique<NetSigning>(node.peerman.get(), *node.llmq_ctx->sigman));
2204-
if (node.mn_activeman) {
2205-
std::unique_ptr<CCoinJoinServer> cj_server = std::make_unique<CCoinJoinServer>(node.peerman.get(), chainman, *node.connman, *node.dmnman, *node.dstxman, *node.mn_metaman, *node.mempool, *node.mn_activeman, *node.mn_sync, *node.llmq_ctx->isman);
22062216

2207-
node.active_ctx = std::make_unique<ActiveContext>(chainman, *node.connman, *node.dmnman, *node.govman,
2217+
const util::DbWrapperParams dash_db_params{.path = args.GetDataDirNet(), .memory = false, .wipe = (fReindex || fReindexChainState)};
2218+
if (node.mn_activeman) {
2219+
auto cj_server = std::make_unique<CCoinJoinServer>(node.peerman.get(), chainman, *node.connman, *node.dmnman, *node.dstxman, *node.mn_metaman,
2220+
*node.mempool, *node.mn_activeman, *node.mn_sync, *node.llmq_ctx->isman);
2221+
node.active_ctx = std::make_unique<ActiveContext>(*cj_server, *node.connman, *node.dmnman, *node.govman, chainman, *node.mn_metaman,
22082222
*node.mnhf_manager, *node.sporkman, *node.mempool, *node.llmq_ctx, *node.peerman,
2209-
*node.mn_activeman, *node.mn_sync, *cj_server);
2223+
*node.mn_activeman, *node.mn_sync, dash_db_params, quorums_watch);
22102224
node.peerman->AddExtraHandler(std::move(cj_server));
22112225
g_active_notification_interface = std::make_unique<ActiveNotificationInterface>(*node.active_ctx, *node.mn_activeman);
22122226
RegisterValidationInterface(g_active_notification_interface.get());
2227+
} else if (quorums_watch) {
2228+
node.observer_ctx = std::make_unique<llmq::ObserverContext>(*node.llmq_ctx->bls_worker, *node.dmnman, *node.mn_metaman, *node.llmq_ctx->dkg_debugman,
2229+
*node.llmq_ctx->quorum_block_processor, *node.llmq_ctx->qman, *node.llmq_ctx->qsnapman, chainman,
2230+
*node.sporkman, dash_db_params);
2231+
RegisterValidationInterface(node.observer_ctx.get());
22132232
}
22142233

22152234
// ********************************************************* Step 7d: Setup other Dash services
22162235

2236+
assert(!node.cj_walletman);
2237+
if (!node.active_ctx) {
2238+
// Can return nullptr if built without wallet support, must check before use
2239+
node.cj_walletman = CJWalletManager::make(chainman, *node.dmnman, *node.mn_metaman, *node.mempool, *node.mn_sync,
2240+
*node.llmq_ctx->isman, !ignores_incoming_txs);
2241+
}
2242+
2243+
if (node.cj_walletman) {
2244+
RegisterValidationInterface(node.cj_walletman.get());
2245+
}
2246+
22172247
bool fLoadCacheFiles = !(fReindex || fReindexChainState) && (chainman.ActiveChain().Tip() != nullptr);
22182248

22192249
if (!node.netfulfilledman->LoadCache(fLoadCacheFiles)) {
@@ -2307,7 +2337,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
23072337

23082338
// ********************************************************* Step 10a: schedule Dash-specific tasks
23092339

2310-
node.llmq_ctx->Start(*node.peerman);
2340+
node.llmq_ctx->Start();
23112341
node.peerman->StartHandlers();
23122342
if (node.active_ctx) node.active_ctx->Start(*node.connman, *node.peerman);
23132343

@@ -2317,7 +2347,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
23172347
node.peerman->ScheduleHandlers(*node.scheduler);
23182348

23192349
if (node.mn_activeman) {
2320-
node.scheduler->scheduleEvery(std::bind(&llmq::CDKGSessionManager::CleanupOldContributions, std::ref(*node.llmq_ctx->qdkgsman)), std::chrono::hours{1});
2350+
node.scheduler->scheduleEvery(std::bind(&llmq::CDKGSessionManager::CleanupOldContributions, std::ref(*node.active_ctx->qdkgsman)), std::chrono::hours{1});
23212351
}
23222352

23232353
if (node.cj_walletman) {

src/instantsend/instantsend.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class CInstantSendManager final : public instantsend::InstantSendSignerParent
118118
}
119119
void DisconnectSigner() { m_signer.store(nullptr, std::memory_order_release); }
120120

121-
instantsend::InstantSendSigner* Signer() const { return m_signer.load(); }
121+
instantsend::InstantSendSigner* Signer() const { return m_signer.load(std::memory_order_acquire); }
122122

123123
private:
124124
void AddNonLockedTx(const CTransactionRef& tx, const CBlockIndex* pindexMined)

src/instantsend/net_instantsend.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,18 +72,10 @@ void NetInstantSend::Start()
7272
}
7373

7474
workThread = std::thread(&util::TraceThread, "isman", [this] { WorkThreadMain(); });
75-
76-
if (auto signer = m_is_manager.Signer(); signer) {
77-
signer->Start();
78-
}
7975
}
8076

8177
void NetInstantSend::Stop()
8278
{
83-
if (auto signer = m_is_manager.Signer(); signer) {
84-
signer->Stop();
85-
}
86-
8779
// make sure to call Interrupt() first
8880
if (!workInterrupt) {
8981
assert(false);

src/instantsend/signing.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,12 @@ InstantSendSigner::InstantSendSigner(CChainState& chainstate, llmq::CChainLocksH
4646

4747
InstantSendSigner::~InstantSendSigner() = default;
4848

49-
void InstantSendSigner::Start()
49+
void InstantSendSigner::RegisterRecoveryInterface()
5050
{
5151
m_sigman.RegisterRecoveredSigsListener(this);
5252
}
5353

54-
void InstantSendSigner::Stop()
54+
void InstantSendSigner::UnregisterRecoveryInterface()
5555
{
5656
m_sigman.UnregisterRecoveredSigsListener(this);
5757
}

src/instantsend/signing.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ class InstantSendSigner final : public llmq::CRecoveredSigsListener
8282
CTxMemPool& mempool, const CMasternodeSync& mn_sync);
8383
~InstantSendSigner();
8484

85-
void Start();
86-
void Stop();
85+
void RegisterRecoveryInterface();
86+
void UnregisterRecoveryInterface();
8787

8888
void ClearInputsFromQueue(const Uint256HashSet& ids) EXCLUSIVE_LOCKS_REQUIRED(!cs_input_requests);
8989

0 commit comments

Comments
 (0)