Skip to content

Commit f22fb22

Browse files
committed
refactor: separate masternode mode logic into dedicated manager class
1 parent 544791d commit f22fb22

File tree

6 files changed

+235
-133
lines changed

6 files changed

+235
-133
lines changed

src/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ BITCOIN_CORE_H = \
233233
instantsend/db.h \
234234
instantsend/instantsend.h \
235235
instantsend/lock.h \
236+
instantsend/signing.h \
236237
key.h \
237238
key_io.h \
238239
limitedmap.h \

src/instantsend/instantsend.cpp

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include <bls/bls_batchverifier.h>
2121
#include <instantsend/lock.h>
22+
#include <instantsend/signing.h>
2223
#include <llmq/chainlocks.h>
2324
#include <llmq/commitment.h>
2425
#include <llmq/quorums.h>
@@ -51,11 +52,12 @@ CInstantSendManager::CInstantSendManager(CChainLocksHandler& _clhandler, CChainS
5152
m_chainstate{chainstate},
5253
qman{_qman},
5354
sigman{_sigman},
54-
shareman{_shareman},
5555
spork_manager{sporkman},
5656
mempool{_mempool},
5757
m_mn_sync{mn_sync},
58-
m_is_masternode{is_masternode}
58+
m_signer{is_masternode ? std::make_unique<instantsend::InstantSendSigner>(chainstate, _clhandler, *this, _sigman,
59+
_shareman, _qman, sporkman, _mempool, mn_sync)
60+
: nullptr}
5961
{
6062
workInterrupt.reset();
6163
}
@@ -71,12 +73,16 @@ void CInstantSendManager::Start(PeerManager& peerman)
7173

7274
workThread = std::thread(&util::TraceThread, "isman", [this, &peerman] { WorkThreadMain(peerman); });
7375

74-
sigman.RegisterRecoveredSigsListener(this);
76+
if (m_signer) {
77+
sigman.RegisterRecoveredSigsListener(m_signer.get());
78+
}
7579
}
7680

7781
void CInstantSendManager::Stop()
7882
{
79-
sigman.UnregisterRecoveredSigsListener(this);
83+
if (m_signer) {
84+
sigman.UnregisterRecoveredSigsListener(m_signer.get());
85+
}
8086

8187
// make sure to call InterruptWorkerThread() first
8288
if (!workInterrupt) {
@@ -337,10 +343,10 @@ void CInstantSendManager::ProcessInstantSendLock(NodeId from, PeerManager& peerm
337343
{
338344
LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s, islock=%s: processing islock, peer=%d\n", __func__,
339345
islock->txid.ToString(), hash.ToString(), from);
340-
{
341-
LOCK(cs_creating);
342-
creatingInstantSendLocks.erase(islock->GetRequestId());
343-
txToCreatingInstantSendLocks.erase(islock->txid);
346+
if (m_signer) {
347+
LOCK(m_signer->cs_creating);
348+
m_signer->creatingInstantSendLocks.erase(islock->GetRequestId());
349+
m_signer->txToCreatingInstantSendLocks.erase(islock->txid);
344350
}
345351
if (db.KnownInstantSendLock(hash)) {
346352
return;
@@ -411,7 +417,7 @@ void CInstantSendManager::ProcessInstantSendLock(NodeId from, PeerManager& peerm
411417
// bump mempool counter to make sure newly locked txes are picked up by getblocktemplate
412418
mempool.AddTransactionsUpdated(1);
413419
} else {
414-
peerman.AskPeersForTransaction(islock->txid, m_is_masternode);
420+
peerman.AskPeersForTransaction(islock->txid, /*is_masternode=*/m_signer != nullptr);
415421
}
416422
}
417423

@@ -440,7 +446,9 @@ void CInstantSendManager::TransactionAddedToMempool(PeerManager& peerman, const
440446
}
441447

442448
if (islock == nullptr) {
443-
ProcessTx(*tx, false, Params().GetConsensus());
449+
if (m_signer) {
450+
m_signer->ProcessTx(*tx, false, Params().GetConsensus());
451+
}
444452
// TX is not locked, so make sure it is tracked
445453
AddNonLockedTx(tx, nullptr);
446454
} else {
@@ -479,7 +487,9 @@ void CInstantSendManager::BlockConnected(const std::shared_ptr<const CBlock>& pb
479487
}
480488

481489
if (!IsLocked(tx->GetHash()) && !has_chainlock) {
482-
ProcessTx(*tx, true, Params().GetConsensus());
490+
if (m_signer) {
491+
m_signer->ProcessTx(*tx, true, Params().GetConsensus());
492+
}
483493
// TX is not locked, so make sure it is tracked
484494
AddNonLockedTx(tx, pindex);
485495
} else {
@@ -582,19 +592,22 @@ void CInstantSendManager::RemoveNonLockedTx(const uint256& txid, bool retryChild
582592
void CInstantSendManager::RemoveConflictedTx(const CTransaction& tx)
583593
{
584594
RemoveNonLockedTx(tx.GetHash(), false);
595+
if (!m_signer) return;
585596

586-
LOCK(cs_inputReqests);
597+
LOCK(m_signer->cs_inputReqests);
587598
for (const auto& in : tx.vin) {
588599
auto inputRequestId = ::SerializeHash(std::make_pair(INPUTLOCK_REQUESTID_PREFIX, in));
589-
inputRequestIds.erase(inputRequestId);
600+
m_signer->inputRequestIds.erase(inputRequestId);
590601
}
591602
}
592603

593604
void CInstantSendManager::TruncateRecoveredSigsForInputs(const llmq::CInstantSendLock& islock)
594605
{
606+
if (!m_signer) return;
607+
595608
for (const auto& in : islock.inputs) {
596609
auto inputRequestId = ::SerializeHash(std::make_pair(INPUTLOCK_REQUESTID_PREFIX, in));
597-
WITH_LOCK(cs_inputReqests, inputRequestIds.erase(inputRequestId));
610+
WITH_LOCK(m_signer->cs_inputReqests, m_signer->inputRequestIds.erase(inputRequestId));
598611
sigman.TruncateRecoveredSig(Params().GetConsensus().llmqTypeDIP0024InstantSend, inputRequestId);
599612
}
600613
}
@@ -693,7 +706,7 @@ void CInstantSendManager::RemoveMempoolConflictsForLock(PeerManager& peerman, co
693706
for (const auto& p : toDelete) {
694707
RemoveConflictedTx(*p.second);
695708
}
696-
peerman.AskPeersForTransaction(islock.txid, m_is_masternode);
709+
peerman.AskPeersForTransaction(islock.txid, /*is_masternode=*/m_signer != nullptr);
697710
}
698711
}
699712

@@ -898,7 +911,9 @@ void CInstantSendManager::WorkThreadMain(PeerManager& peerman)
898911
{
899912
while (!workInterrupt) {
900913
bool fMoreWork = ProcessPendingInstantSendLocks(peerman);
901-
ProcessPendingRetryLockTxs();
914+
if (m_signer) {
915+
m_signer->ProcessPendingRetryLockTxs();
916+
}
902917

903918
if (!fMoreWork && !workInterrupt.sleep_for(std::chrono::milliseconds(100))) {
904919
return;

src/instantsend/instantsend.h

Lines changed: 25 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,18 @@ class CMasternodeSync;
3030
class CSporkManager;
3131
class PeerManager;
3232

33+
namespace instantsend {
34+
class InstantSendSigner;
35+
} // namespace instantsend
36+
3337
namespace llmq
3438
{
3539
class CChainLocksHandler;
3640
class CQuorumManager;
3741
class CSigningManager;
3842
class CSigSharesManager;
3943

40-
class CInstantSendManager : public CRecoveredSigsListener
44+
class CInstantSendManager
4145
{
4246
private:
4347
instantsend::CInstantSendDb db;
@@ -46,35 +50,15 @@ class CInstantSendManager : public CRecoveredSigsListener
4650
CChainState& m_chainstate;
4751
CQuorumManager& qman;
4852
CSigningManager& sigman;
49-
CSigSharesManager& shareman;
5053
CSporkManager& spork_manager;
5154
CTxMemPool& mempool;
5255
const CMasternodeSync& m_mn_sync;
5356

54-
const bool m_is_masternode;
57+
std::unique_ptr<instantsend::InstantSendSigner> m_signer{nullptr};
5558

5659
std::thread workThread;
5760
CThreadInterrupt workInterrupt;
5861

59-
mutable Mutex cs_inputReqests;
60-
61-
/**
62-
* Request ids of inputs that we signed. Used to determine if a recovered signature belongs to an
63-
* in-progress input lock.
64-
*/
65-
std::unordered_set<uint256, StaticSaltedHasher> inputRequestIds GUARDED_BY(cs_inputReqests);
66-
67-
mutable Mutex cs_creating;
68-
69-
/**
70-
* These are the islocks that are currently in the middle of being created. Entries are created when we observed
71-
* recovered signatures for all inputs of a TX. At the same time, we initiate signing of our sigshare for the islock.
72-
* When the recovered sig for the islock later arrives, we can finish the islock and propagate it.
73-
*/
74-
std::unordered_map<uint256, CInstantSendLock, StaticSaltedHasher> creatingInstantSendLocks GUARDED_BY(cs_creating);
75-
// maps from txid to the in-progress islock
76-
std::unordered_map<uint256, CInstantSendLock*, StaticSaltedHasher> txToCreatingInstantSendLocks GUARDED_BY(cs_creating);
77-
7862
mutable Mutex cs_pendingLocks;
7963
// Incoming and not verified yet
8064
std::unordered_map<uint256, std::pair<NodeId, CInstantSendLockPtr>, StaticSaltedHasher> pendingInstantSendLocks GUARDED_BY(cs_pendingLocks);
@@ -111,69 +95,52 @@ class CInstantSendManager : public CRecoveredSigsListener
11195
void InterruptWorkerThread() { workInterrupt(); };
11296

11397
private:
114-
void ProcessTx(const CTransaction& tx, bool fRetroactive, const Consensus::Params& params)
115-
EXCLUSIVE_LOCKS_REQUIRED(!cs_creating, !cs_inputReqests);
116-
bool CheckCanLock(const CTransaction& tx, bool printDebug, const Consensus::Params& params) const;
117-
bool CheckCanLock(const COutPoint& outpoint, bool printDebug, const uint256& txHash,
118-
const Consensus::Params& params) const;
119-
120-
void HandleNewInputLockRecoveredSig(const CRecoveredSig& recoveredSig, const uint256& txid)
121-
EXCLUSIVE_LOCKS_REQUIRED(!cs_creating);
122-
void HandleNewInstantSendLockRecoveredSig(const CRecoveredSig& recoveredSig)
123-
EXCLUSIVE_LOCKS_REQUIRED(!cs_creating, !cs_pendingLocks);
124-
125-
bool TrySignInputLocks(const CTransaction& tx, bool allowResigning, Consensus::LLMQType llmqType,
126-
const Consensus::Params& params) EXCLUSIVE_LOCKS_REQUIRED(!cs_inputReqests);
127-
void TrySignInstantSendLock(const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(!cs_creating);
128-
12998
PeerMsgRet ProcessMessageInstantSendLock(const CNode& pfrom, PeerManager& peerman, const CInstantSendLockPtr& islock);
13099
bool ProcessPendingInstantSendLocks(PeerManager& peerman)
131-
EXCLUSIVE_LOCKS_REQUIRED(!cs_creating, !cs_inputReqests, !cs_nonLocked, !cs_pendingLocks, !cs_pendingRetry);
100+
EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingLocks, !cs_pendingRetry);
132101

133102
std::unordered_set<uint256, StaticSaltedHasher> ProcessPendingInstantSendLocks(
134103
const Consensus::LLMQParams& llmq_params, PeerManager& peerman, int signOffset,
135104
const std::unordered_map<uint256, std::pair<NodeId, CInstantSendLockPtr>, StaticSaltedHasher>& pend, bool ban)
136-
EXCLUSIVE_LOCKS_REQUIRED(!cs_creating, !cs_inputReqests, !cs_nonLocked, !cs_pendingLocks, !cs_pendingRetry);
105+
EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingLocks, !cs_pendingRetry);
137106
void ProcessInstantSendLock(NodeId from, PeerManager& peerman, const uint256& hash, const CInstantSendLockPtr& islock)
138-
EXCLUSIVE_LOCKS_REQUIRED(!cs_creating, !cs_inputReqests, !cs_nonLocked, !cs_pendingLocks, !cs_pendingRetry);
107+
EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingLocks, !cs_pendingRetry);
139108

140109
void AddNonLockedTx(const CTransactionRef& tx, const CBlockIndex* pindexMined)
141110
EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingLocks);
142111
void RemoveNonLockedTx(const uint256& txid, bool retryChildren)
143112
EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingRetry);
144113
void RemoveConflictedTx(const CTransaction& tx)
145-
EXCLUSIVE_LOCKS_REQUIRED(!cs_inputReqests, !cs_nonLocked, !cs_pendingRetry);
146-
void TruncateRecoveredSigsForInputs(const CInstantSendLock& islock)
147-
EXCLUSIVE_LOCKS_REQUIRED(!cs_inputReqests);
114+
EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingRetry);
115+
void TruncateRecoveredSigsForInputs(const CInstantSendLock& islock);
148116

149117
void RemoveMempoolConflictsForLock(PeerManager& peerman, const uint256& hash, const CInstantSendLock& islock)
150-
EXCLUSIVE_LOCKS_REQUIRED(!cs_inputReqests, !cs_nonLocked, !cs_pendingRetry);
118+
EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingRetry);
151119
void ResolveBlockConflicts(const uint256& islockHash, const CInstantSendLock& islock)
152-
EXCLUSIVE_LOCKS_REQUIRED(!cs_inputReqests, !cs_nonLocked, !cs_pendingLocks, !cs_pendingRetry);
153-
void ProcessPendingRetryLockTxs()
154-
EXCLUSIVE_LOCKS_REQUIRED(!cs_creating, !cs_inputReqests, !cs_nonLocked, !cs_pendingRetry);
120+
EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingLocks, !cs_pendingRetry);
155121

156122
void WorkThreadMain(PeerManager& peerman)
157-
EXCLUSIVE_LOCKS_REQUIRED(!cs_creating, !cs_inputReqests, !cs_nonLocked, !cs_pendingLocks, !cs_pendingRetry);
123+
NO_THREAD_SAFETY_ANALYSIS;
124+
// Needed as compiler cannot differentiate between negative capability against member and against
125+
// member accessed through reference.
126+
// TODO: Remove this, it's terrible.
127+
// EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingLocks, !cs_pendingRetry);
158128

159129
void HandleFullyConfirmedBlock(const CBlockIndex* pindex)
160-
EXCLUSIVE_LOCKS_REQUIRED(!cs_inputReqests, !cs_nonLocked, !cs_pendingRetry);
130+
EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingRetry);
161131

162132
public:
163133
bool IsLocked(const uint256& txHash) const;
164134
bool IsWaitingForTx(const uint256& txHash) const EXCLUSIVE_LOCKS_REQUIRED(!cs_pendingLocks);
165135
CInstantSendLockPtr GetConflictingLock(const CTransaction& tx) const;
166136

167-
[[nodiscard]] MessageProcessingResult HandleNewRecoveredSig(const CRecoveredSig& recoveredSig) override
168-
EXCLUSIVE_LOCKS_REQUIRED(!cs_creating, !cs_inputReqests, !cs_pendingLocks);
169-
170137
PeerMsgRet ProcessMessage(const CNode& pfrom, PeerManager& peerman, std::string_view msg_type, CDataStream& vRecv);
171138

172139
void TransactionAddedToMempool(PeerManager& peerman, const CTransactionRef& tx)
173-
EXCLUSIVE_LOCKS_REQUIRED(!cs_creating, !cs_inputReqests, !cs_nonLocked, !cs_pendingLocks, !cs_pendingRetry);
140+
EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingLocks, !cs_pendingRetry);
174141
void TransactionRemovedFromMempool(const CTransactionRef& tx);
175142
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex)
176-
EXCLUSIVE_LOCKS_REQUIRED(!cs_creating, !cs_inputReqests, !cs_nonLocked, !cs_pendingLocks, !cs_pendingRetry);
143+
EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingLocks, !cs_pendingRetry);
177144
void BlockDisconnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexDisconnected);
178145

179146
bool AlreadyHave(const CInv& inv) const EXCLUSIVE_LOCKS_REQUIRED(!cs_pendingLocks);
@@ -182,9 +149,9 @@ class CInstantSendManager : public CRecoveredSigsListener
182149
CInstantSendLockPtr GetInstantSendLockByTxid(const uint256& txid) const;
183150

184151
void NotifyChainLock(const CBlockIndex* pindexChainLock)
185-
EXCLUSIVE_LOCKS_REQUIRED(!cs_inputReqests, !cs_nonLocked, !cs_pendingRetry);
152+
EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingRetry);
186153
void UpdatedBlockTip(const CBlockIndex* pindexNew)
187-
EXCLUSIVE_LOCKS_REQUIRED(!cs_inputReqests, !cs_nonLocked, !cs_pendingRetry);
154+
EXCLUSIVE_LOCKS_REQUIRED(!cs_nonLocked, !cs_pendingRetry);
188155

189156
void RemoveConflictingLock(const uint256& islockHash, const CInstantSendLock& islock);
190157

@@ -196,8 +163,9 @@ class CInstantSendManager : public CRecoveredSigsListener
196163
* transactions in mempool, but should sign txes included in a block. This
197164
* allows ChainLocks to continue even while this spork is disabled.
198165
*/
199-
bool IsInstantSendMempoolSigningEnabled() const;
200166
bool RejectConflictingBlocks() const;
167+
168+
friend class ::instantsend::InstantSendSigner;
201169
};
202170
} // namespace llmq
203171

0 commit comments

Comments
 (0)