Skip to content

Commit 74c1b28

Browse files
committed
refactor: separate masternode mode logic into dedicated manager class
1 parent f469c46 commit 74c1b28

File tree

6 files changed

+212
-120
lines changed

6 files changed

+212
-120
lines changed

src/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ BITCOIN_CORE_H = \
152152
chain.h \
153153
chainlock/chainlock.h \
154154
chainlock/clsig.h \
155+
chainlock/signing.h \
155156
chainparams.h \
156157
chainparamsbase.h \
157158
chainparamsseeds.h \

src/chainlock/chainlock.cpp

Lines changed: 62 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <validation.h>
1717
#include <validationinterface.h>
1818

19+
#include <chainlock/signing.h>
1920
#include <instantsend/instantsend.h>
2021
#include <llmq/quorums.h>
2122
#include <masternode/sync.h>
@@ -34,17 +35,18 @@ namespace llmq {
3435
CChainLocksHandler::CChainLocksHandler(CChainState& chainstate, CQuorumManager& _qman, CSigningManager& _sigman,
3536
CSigSharesManager& _shareman, CSporkManager& sporkman, CTxMemPool& _mempool,
3637
const CMasternodeSync& mn_sync, bool is_masternode) :
37-
m_chainstate(chainstate),
38-
qman(_qman),
39-
sigman(_sigman),
40-
shareman(_shareman),
41-
spork_manager(sporkman),
42-
mempool(_mempool),
43-
m_mn_sync(mn_sync),
44-
m_is_masternode{is_masternode},
45-
scheduler(std::make_unique<CScheduler>()),
46-
scheduler_thread(
47-
std::make_unique<std::thread>(std::thread(util::TraceThread, "cl-schdlr", [&] { scheduler->serviceQueue(); })))
38+
m_chainstate{chainstate},
39+
qman{_qman},
40+
sigman{_sigman},
41+
spork_manager{sporkman},
42+
mempool{_mempool},
43+
m_mn_sync{mn_sync},
44+
scheduler{std::make_unique<CScheduler>()},
45+
scheduler_thread{
46+
std::make_unique<std::thread>(std::thread(util::TraceThread, "cl-schdlr", [&] { scheduler->serviceQueue(); }))},
47+
m_signer{is_masternode
48+
? std::make_unique<chainlock::ChainLockSigner>(chainstate, *this, _sigman, _shareman, sporkman, mn_sync)
49+
: nullptr}
4850
{
4951
}
5052

@@ -56,19 +58,26 @@ CChainLocksHandler::~CChainLocksHandler()
5658

5759
void CChainLocksHandler::Start(const llmq::CInstantSendManager& isman)
5860
{
59-
sigman.RegisterRecoveredSigsListener(this);
61+
if (m_signer) {
62+
sigman.RegisterRecoveredSigsListener(m_signer.get());
63+
}
6064
scheduler->scheduleEvery([&]() {
6165
CheckActiveState();
6266
EnforceBestChainLock();
67+
Cleanup();
6368
// regularly retry signing the current chaintip as it might have failed before due to missing islocks
64-
TrySignChainTip(isman);
69+
if (m_signer) {
70+
m_signer->TrySignChainTip(isman);
71+
}
6572
}, std::chrono::seconds{5});
6673
}
6774

6875
void CChainLocksHandler::Stop()
6976
{
7077
scheduler->stop();
71-
sigman.UnregisterRecoveredSigsListener(this);
78+
if (m_signer) {
79+
sigman.UnregisterRecoveredSigsListener(m_signer.get());
80+
}
7281
}
7382

7483
bool CChainLocksHandler::AlreadyHave(const CInv& inv) const
@@ -195,7 +204,10 @@ void CChainLocksHandler::UpdatedBlockTip(const llmq::CInstantSendManager& isman)
195204
scheduler->scheduleFromNow([&]() {
196205
CheckActiveState();
197206
EnforceBestChainLock();
198-
TrySignChainTip(isman);
207+
Cleanup();
208+
if (m_signer) {
209+
m_signer->TrySignChainTip(isman);
210+
}
199211
tryLockChainTipScheduled = false;
200212
}, std::chrono::seconds{0});
201213
}
@@ -234,36 +246,40 @@ void CChainLocksHandler::BlockConnected(const std::shared_ptr<const CBlock>& pbl
234246
}
235247

236248
// We listen for BlockConnected so that we can collect all TX ids of all included TXs of newly received blocks
237-
// We need this information later when we try to sign a new tip, so that we can determine if all included TXs are
238-
// safe.
239-
240-
LOCK(cs);
241-
242-
auto it = blockTxs.find(pindex->GetBlockHash());
243-
if (it == blockTxs.end()) {
244-
// we must create this entry even if there are no lockable transactions in the block, so that TrySignChainTip
245-
// later knows about this block
246-
it = blockTxs.emplace(pindex->GetBlockHash(), std::make_shared<std::unordered_set<uint256, StaticSaltedHasher>>()).first;
247-
}
248-
auto& txids = *it->second;
249-
250249
int64_t curTime = GetTime<std::chrono::seconds>().count();
251-
252-
for (const auto& tx : pblock->vtx) {
253-
if (tx->IsCoinBase() || tx->vin.empty()) {
254-
continue;
250+
{
251+
LOCK(cs);
252+
for (const auto& tx : pblock->vtx) {
253+
if (!tx->IsCoinBase() && !tx->vin.empty()) {
254+
txFirstSeenTime.emplace(tx->GetHash(), curTime);
255+
}
255256
}
256-
257-
txids.emplace(tx->GetHash());
258-
txFirstSeenTime.emplace(tx->GetHash(), curTime);
259257
}
260258

259+
// We need this information later when we try to sign a new tip, so that we can determine if all included TXs are safe.
260+
if (m_signer) {
261+
LOCK(m_signer->cs_signer);
262+
auto it = m_signer->blockTxs.find(pindex->GetBlockHash());
263+
if (it == m_signer->blockTxs.end()) {
264+
// We must create this entry even if there are no lockable transactions in the block, so that TrySignChainTip
265+
// later knows about this block
266+
it = m_signer->blockTxs.emplace(pindex->GetBlockHash(), std::make_shared<std::unordered_set<uint256, StaticSaltedHasher>>()).first;
267+
}
268+
auto& txids = *it->second;
269+
for (const auto& tx : pblock->vtx) {
270+
if (!tx->IsCoinBase() && !tx->vin.empty()) {
271+
txids.emplace(tx->GetHash());
272+
}
273+
}
274+
}
261275
}
262276

263277
void CChainLocksHandler::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock, gsl::not_null<const CBlockIndex*> pindexDisconnected)
264278
{
265-
LOCK(cs);
266-
blockTxs.erase(pindexDisconnected->GetBlockHash());
279+
if (m_signer) {
280+
LOCK(m_signer->cs_signer);
281+
m_signer->blockTxs.erase(pindexDisconnected->GetBlockHash());
282+
}
267283
}
268284

269285
bool CChainLocksHandler::IsTxSafeForMining(const uint256& txid) const
@@ -428,15 +444,18 @@ void CChainLocksHandler::Cleanup()
428444
}
429445
}
430446

431-
LOCK(cs);
432-
for (const auto& tx : CleanupSigner()) {
433-
for (const auto& txid : *tx) {
434-
txFirstSeenTime.erase(txid);
447+
if (m_signer) {
448+
const auto cleanup_txes{m_signer->Cleanup()};
449+
LOCK(cs);
450+
for (const auto& tx : cleanup_txes) {
451+
for (const auto& txid : *tx) {
452+
txFirstSeenTime.erase(txid);
453+
}
435454
}
436455
}
437456

438-
// need mempool.cs due to GetTransaction calls
439-
LOCK2(::cs_main, mempool.cs);
457+
LOCK(::cs_main);
458+
LOCK2(mempool.cs, cs); // need mempool.cs due to GetTransaction calls
440459
for (auto it = txFirstSeenTime.begin(); it != txFirstSeenTime.end(); ) {
441460
uint256 hashBlock;
442461
if (auto tx = GetTransaction(nullptr, &mempool, it->first, Params().GetConsensus(), hashBlock); !tx) {

src/chainlock/chainlock.h

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,8 @@
77

88
#include <chainlock/clsig.h>
99

10-
#include <crypto/common.h> // For ReadLE64
11-
#include <llmq/signing.h>
12-
#include <net.h> // For NodeId
13-
#include <net_types.h>
1410
#include <primitives/transaction.h>
11+
#include <protocol.h>
1512
#include <saltedhasher.h>
1613
#include <sync.h>
1714

@@ -28,15 +25,20 @@ class CMasternodeSync;
2825
class CScheduler;
2926
class CSporkManager;
3027
class CTxMemPool;
28+
namespace chainlock {
29+
class ChainLockSigner;
30+
} // namespace chainlock
3131

32-
namespace llmq
33-
{
32+
using NodeId = int64_t;
33+
34+
namespace llmq {
3435
class CInstantSendManager;
36+
class CQuorumManager;
3537
class CSigningManager;
3638
class CSigSharesManager;
3739
enum class VerifyRecSigStatus;
3840

39-
class CChainLocksHandler : public CRecoveredSigsListener
41+
class CChainLocksHandler
4042
{
4143
static constexpr int64_t CLEANUP_INTERVAL = 1000 * 30;
4244
static constexpr int64_t CLEANUP_SEEN_TIMEOUT = 24 * 60 * 60 * 1000;
@@ -48,14 +50,14 @@ class CChainLocksHandler : public CRecoveredSigsListener
4850
CChainState& m_chainstate;
4951
CQuorumManager& qman;
5052
CSigningManager& sigman;
51-
CSigSharesManager& shareman;
5253
CSporkManager& spork_manager;
5354
CTxMemPool& mempool;
5455
const CMasternodeSync& m_mn_sync;
55-
56-
const bool m_is_masternode;
5756
std::unique_ptr<CScheduler> scheduler;
5857
std::unique_ptr<std::thread> scheduler_thread;
58+
59+
std::unique_ptr<chainlock::ChainLockSigner> m_signer{nullptr};
60+
5961
mutable Mutex cs;
6062
std::atomic<bool> tryLockChainTipScheduled{false};
6163
std::atomic<bool> isEnabled{false};
@@ -67,17 +69,6 @@ class CChainLocksHandler : public CRecoveredSigsListener
6769
const CBlockIndex* bestChainLockBlockIndex GUARDED_BY(cs) {nullptr};
6870
const CBlockIndex* lastNotifyChainLockBlockIndex GUARDED_BY(cs) {nullptr};
6971

70-
int32_t lastSignedHeight GUARDED_BY(cs) {-1};
71-
uint256 lastSignedRequestId GUARDED_BY(cs);
72-
uint256 lastSignedMsgHash GUARDED_BY(cs);
73-
74-
// We keep track of txids from recently received blocks so that we can check if all TXs got islocked
75-
struct BlockHasher
76-
{
77-
size_t operator()(const uint256& hash) const { return ReadLE64(hash.begin()); }
78-
};
79-
using BlockTxs = std::unordered_map<uint256, std::shared_ptr<std::unordered_set<uint256, StaticSaltedHasher>>, BlockHasher>;
80-
BlockTxs blockTxs GUARDED_BY(cs);
8172
std::unordered_map<uint256, int64_t, StaticSaltedHasher> txFirstSeenTime GUARDED_BY(cs);
8273

8374
std::map<uint256, int64_t> seenChainLocks GUARDED_BY(cs);
@@ -106,10 +97,7 @@ class CChainLocksHandler : public CRecoveredSigsListener
10697
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, gsl::not_null<const CBlockIndex*> pindex) EXCLUSIVE_LOCKS_REQUIRED(!cs);
10798
void BlockDisconnected(const std::shared_ptr<const CBlock>& pblock, gsl::not_null<const CBlockIndex*> pindexDisconnected) EXCLUSIVE_LOCKS_REQUIRED(!cs);
10899
void CheckActiveState() EXCLUSIVE_LOCKS_REQUIRED(!cs);
109-
void TrySignChainTip(const llmq::CInstantSendManager& isman) EXCLUSIVE_LOCKS_REQUIRED(!cs);
110100
void EnforceBestChainLock() EXCLUSIVE_LOCKS_REQUIRED(!cs);
111-
[[nodiscard]] MessageProcessingResult HandleNewRecoveredSig(const CRecoveredSig& recoveredSig) override
112-
EXCLUSIVE_LOCKS_REQUIRED(!cs);
113101

114102
bool HasChainLock(int nHeight, const uint256& blockHash) const EXCLUSIVE_LOCKS_REQUIRED(!cs);
115103
bool HasConflictingChainLock(int nHeight, const uint256& blockHash) const EXCLUSIVE_LOCKS_REQUIRED(!cs);
@@ -122,11 +110,9 @@ class CChainLocksHandler : public CRecoveredSigsListener
122110
bool InternalHasChainLock(int nHeight, const uint256& blockHash) const EXCLUSIVE_LOCKS_REQUIRED(cs);
123111
bool InternalHasConflictingChainLock(int nHeight, const uint256& blockHash) const EXCLUSIVE_LOCKS_REQUIRED(cs);
124112

125-
BlockTxs::mapped_type GetBlockTxs(const uint256& blockHash) EXCLUSIVE_LOCKS_REQUIRED(!cs);
126-
127113
void Cleanup() EXCLUSIVE_LOCKS_REQUIRED(!cs);
128-
std::vector<std::shared_ptr<std::unordered_set<uint256, StaticSaltedHasher>>> CleanupSigner()
129-
EXCLUSIVE_LOCKS_REQUIRED(cs);
114+
115+
friend class ::chainlock::ChainLockSigner;
130116
};
131117

132118
bool AreChainLocksEnabled(const CSporkManager& sporkman);

0 commit comments

Comments
 (0)