Skip to content

Commit e742b7b

Browse files
committed
refactor: remove need for mutual access to private members
1 parent 74c1b28 commit e742b7b

File tree

4 files changed

+103
-76
lines changed

4 files changed

+103
-76
lines changed

src/chainlock/chainlock.cpp

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,23 @@ CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMe
3232
using node::GetTransaction;
3333

3434
namespace llmq {
35+
namespace {
36+
static constexpr int64_t CLEANUP_INTERVAL{1000 * 30};
37+
static constexpr int64_t CLEANUP_SEEN_TIMEOUT{24 * 60 * 60 * 1000};
38+
//! How long to wait for islocks until we consider a block with non-islocked TXs to be safe to sign
39+
static constexpr int64_t WAIT_FOR_ISLOCK_TIMEOUT{10 * 60};
40+
} // anonymous namespace
41+
42+
bool AreChainLocksEnabled(const CSporkManager& sporkman)
43+
{
44+
return sporkman.IsSporkActive(SPORK_19_CHAINLOCKS_ENABLED);
45+
}
46+
3547
CChainLocksHandler::CChainLocksHandler(CChainState& chainstate, CQuorumManager& _qman, CSigningManager& _sigman,
3648
CSigSharesManager& _shareman, CSporkManager& sporkman, CTxMemPool& _mempool,
3749
const CMasternodeSync& mn_sync, bool is_masternode) :
3850
m_chainstate{chainstate},
3951
qman{_qman},
40-
sigman{_sigman},
4152
spork_manager{sporkman},
4253
mempool{_mempool},
4354
m_mn_sync{mn_sync},
@@ -59,7 +70,7 @@ CChainLocksHandler::~CChainLocksHandler()
5970
void CChainLocksHandler::Start(const llmq::CInstantSendManager& isman)
6071
{
6172
if (m_signer) {
62-
sigman.RegisterRecoveredSigsListener(m_signer.get());
73+
m_signer->Start();
6374
}
6475
scheduler->scheduleEvery([&]() {
6576
CheckActiveState();
@@ -76,7 +87,7 @@ void CChainLocksHandler::Stop()
7687
{
7788
scheduler->stop();
7889
if (m_signer) {
79-
sigman.UnregisterRecoveredSigsListener(m_signer.get());
90+
m_signer->Stop();
8091
}
8192
}
8293

@@ -105,6 +116,15 @@ chainlock::ChainLockSig CChainLocksHandler::GetBestChainLock() const
105116
return bestChainLock;
106117
}
107118

119+
void CChainLocksHandler::UpdateTxFirstSeenMap(const std::unordered_set<uint256, StaticSaltedHasher>& tx, const int64_t& time)
120+
{
121+
AssertLockNotHeld(cs);
122+
LOCK(cs);
123+
for (const auto& txid : tx) {
124+
txFirstSeenTime.emplace(txid, time);
125+
}
126+
}
127+
108128
MessageProcessingResult CChainLocksHandler::ProcessNewChainLock(const NodeId from, const chainlock::ChainLockSig& clsig,
109129
const uint256& hash)
110130
{
@@ -258,30 +278,24 @@ void CChainLocksHandler::BlockConnected(const std::shared_ptr<const CBlock>& pbl
258278

259279
// We need this information later when we try to sign a new tip, so that we can determine if all included TXs are safe.
260280
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-
}
281+
m_signer->UpdateBlockHashTxidMap(pindex->GetBlockHash(), pblock->vtx);
274282
}
275283
}
276284

277285
void CChainLocksHandler::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock, gsl::not_null<const CBlockIndex*> pindexDisconnected)
278286
{
279287
if (m_signer) {
280-
LOCK(m_signer->cs_signer);
281-
m_signer->blockTxs.erase(pindexDisconnected->GetBlockHash());
288+
m_signer->EraseFromBlockHashTxidMap(pindexDisconnected->GetBlockHash());
282289
}
283290
}
284291

292+
int32_t CChainLocksHandler::GetBestChainLockHeight() const
293+
{
294+
AssertLockNotHeld(cs);
295+
LOCK(cs);
296+
return bestChainLock.getHeight();
297+
}
298+
285299
bool CChainLocksHandler::IsTxSafeForMining(const uint256& txid) const
286300
{
287301
int64_t txAge = 0;
@@ -309,7 +323,7 @@ void CChainLocksHandler::EnforceBestChainLock()
309323
{
310324
LOCK(cs);
311325

312-
if (!isEnabled) {
326+
if (!IsEnabled()) {
313327
return;
314328
}
315329

@@ -371,7 +385,7 @@ bool CChainLocksHandler::InternalHasChainLock(int nHeight, const uint256& blockH
371385
{
372386
AssertLockHeld(cs);
373387

374-
if (!isEnabled) {
388+
if (!IsEnabled()) {
375389
return false;
376390
}
377391

@@ -401,7 +415,7 @@ bool CChainLocksHandler::InternalHasConflictingChainLock(int nHeight, const uint
401415
{
402416
AssertLockHeld(cs);
403417

404-
if (!isEnabled) {
418+
if (!IsEnabled()) {
405419
return false;
406420
}
407421

@@ -474,9 +488,4 @@ void CChainLocksHandler::Cleanup()
474488
}
475489
}
476490
}
477-
478-
bool AreChainLocksEnabled(const CSporkManager& sporkman)
479-
{
480-
return sporkman.IsSporkActive(SPORK_19_CHAINLOCKS_ENABLED);
481-
}
482491
} // namespace llmq

src/chainlock/chainlock.h

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,9 @@ enum class VerifyRecSigStatus;
4040

4141
class CChainLocksHandler
4242
{
43-
static constexpr int64_t CLEANUP_INTERVAL = 1000 * 30;
44-
static constexpr int64_t CLEANUP_SEEN_TIMEOUT = 24 * 60 * 60 * 1000;
45-
46-
// how long to wait for islocks until we consider a block with non-islocked TXs to be safe to sign
47-
static constexpr int64_t WAIT_FOR_ISLOCK_TIMEOUT = 10 * 60;
48-
4943
private:
5044
CChainState& m_chainstate;
5145
CQuorumManager& qman;
52-
CSigningManager& sigman;
5346
CSporkManager& spork_manager;
5447
CTxMemPool& mempool;
5548
const CMasternodeSync& m_mn_sync;
@@ -87,6 +80,8 @@ class CChainLocksHandler
8780
bool AlreadyHave(const CInv& inv) const EXCLUSIVE_LOCKS_REQUIRED(!cs);
8881
bool GetChainLockByHash(const uint256& hash, chainlock::ChainLockSig& ret) const EXCLUSIVE_LOCKS_REQUIRED(!cs);
8982
chainlock::ChainLockSig GetBestChainLock() const EXCLUSIVE_LOCKS_REQUIRED(!cs);
83+
void UpdateTxFirstSeenMap(const std::unordered_set<uint256, StaticSaltedHasher>& tx, const int64_t& time)
84+
EXCLUSIVE_LOCKS_REQUIRED(!cs);
9085

9186
[[nodiscard]] MessageProcessingResult ProcessNewChainLock(NodeId from, const chainlock::ChainLockSig& clsig,
9287
const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(!cs);
@@ -103,16 +98,16 @@ class CChainLocksHandler
10398
bool HasConflictingChainLock(int nHeight, const uint256& blockHash) const EXCLUSIVE_LOCKS_REQUIRED(!cs);
10499
VerifyRecSigStatus VerifyChainLock(const chainlock::ChainLockSig& clsig) const;
105100

101+
[[nodiscard]] int32_t GetBestChainLockHeight() const EXCLUSIVE_LOCKS_REQUIRED(!cs);
106102
bool IsTxSafeForMining(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(!cs);
103+
[[nodiscard]] bool IsEnabled() const { return isEnabled; }
107104

108105
private:
109106
// these require locks to be held already
110107
bool InternalHasChainLock(int nHeight, const uint256& blockHash) const EXCLUSIVE_LOCKS_REQUIRED(cs);
111108
bool InternalHasConflictingChainLock(int nHeight, const uint256& blockHash) const EXCLUSIVE_LOCKS_REQUIRED(cs);
112109

113110
void Cleanup() EXCLUSIVE_LOCKS_REQUIRED(!cs);
114-
115-
friend class ::chainlock::ChainLockSigner;
116111
};
117112

118113
bool AreChainLocksEnabled(const CSporkManager& sporkman);

src/chainlock/signing.cpp

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,23 @@ ChainLockSigner::ChainLockSigner(CChainState& chainstate, llmq::CChainLocksHandl
3030

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

33+
void ChainLockSigner::Start()
34+
{
35+
m_sigman.RegisterRecoveredSigsListener(this);
36+
}
37+
38+
void ChainLockSigner::Stop()
39+
{
40+
m_sigman.UnregisterRecoveredSigsListener(this);
41+
}
42+
3343
void ChainLockSigner::TrySignChainTip(const llmq::CInstantSendManager& isman)
3444
{
3545
if (!m_mn_sync.IsBlockchainSynced()) {
3646
return;
3747
}
3848

39-
if (!m_clhandler.isEnabled) {
49+
if (!m_clhandler.IsEnabled()) {
4050
return;
4151
}
4252

@@ -57,23 +67,23 @@ void ChainLockSigner::TrySignChainTip(const llmq::CInstantSendManager& isman)
5767
// Later, we'll add the multiple attempts process.
5868

5969
{
60-
LOCK2(m_clhandler.cs, cs_signer);
70+
LOCK(cs_signer);
6171

6272
if (pindex->nHeight == lastSignedHeight) {
6373
// already signed this one
6474
return;
6575
}
76+
}
6677

67-
if (m_clhandler.bestChainLock.getHeight() >= pindex->nHeight) {
68-
// already got the same CLSIG or a better one
69-
return;
70-
}
78+
if (m_clhandler.GetBestChainLockHeight() >= pindex->nHeight) {
79+
// already got the same CLSIG or a better one
80+
return;
81+
}
7182

72-
if (m_clhandler.InternalHasConflictingChainLock(pindex->nHeight, pindex->GetBlockHash())) {
73-
// don't sign if another conflicting CLSIG is already present. EnforceBestChainLock will later enforce
74-
// the correct chain.
75-
return;
76-
}
83+
if (m_clhandler.HasConflictingChainLock(pindex->nHeight, pindex->GetBlockHash())) {
84+
// don't sign if another conflicting CLSIG is already present. EnforceBestChainLock will later enforce
85+
// the correct chain.
86+
return;
7787
}
7888

7989
LogPrint(BCLog::CHAINLOCKS, "%s -- trying to sign %s, height=%d\n", __func__, pindex->GetBlockHash().ToString(), pindex->nHeight);
@@ -104,18 +114,9 @@ void ChainLockSigner::TrySignChainTip(const llmq::CInstantSendManager& isman)
104114
}
105115

106116
for (const auto& txid : *txids) {
107-
int64_t txAge = 0;
108-
{
109-
LOCK(m_clhandler.cs);
110-
auto it = m_clhandler.txFirstSeenTime.find(txid);
111-
if (it != m_clhandler.txFirstSeenTime.end()) {
112-
txAge = GetTime<std::chrono::seconds>().count() - it->second;
113-
}
114-
}
115-
116-
if (txAge < m_clhandler.WAIT_FOR_ISLOCK_TIMEOUT && !isman.IsLocked(txid)) {
117-
LogPrint(BCLog::CHAINLOCKS, "%s -- not signing block %s due to TX %s not being islocked and not old enough. age=%d\n", __func__,
118-
pindexWalk->GetBlockHash().ToString(), txid.ToString(), txAge);
117+
if (!m_clhandler.IsTxSafeForMining(txid) && !isman.IsLocked(txid)) {
118+
LogPrint(BCLog::CHAINLOCKS, "%s -- not signing block %s due to TX %s not being islocked and not old enough.\n", __func__,
119+
pindexWalk->GetBlockHash().ToString(), txid.ToString());
119120
return;
120121
}
121122
}
@@ -127,12 +128,9 @@ void ChainLockSigner::TrySignChainTip(const llmq::CInstantSendManager& isman)
127128
uint256 requestId = ::SerializeHash(std::make_pair(CLSIG_REQUESTID_PREFIX, pindex->nHeight));
128129
uint256 msgHash = pindex->GetBlockHash();
129130

130-
{
131-
LOCK(m_clhandler.cs);
132-
if (m_clhandler.bestChainLock.getHeight() >= pindex->nHeight) {
133-
// might have happened while we didn't hold cs
134-
return;
135-
}
131+
if (m_clhandler.GetBestChainLockHeight() >= pindex->nHeight) {
132+
// might have happened while we didn't hold cs
133+
return;
136134
}
137135
{
138136
LOCK(cs_signer);
@@ -144,10 +142,34 @@ void ChainLockSigner::TrySignChainTip(const llmq::CInstantSendManager& isman)
144142
m_sigman.AsyncSignIfMember(Params().GetConsensus().llmqTypeChainLocks, m_shareman, requestId, msgHash);
145143
}
146144

145+
void ChainLockSigner::EraseFromBlockHashTxidMap(const uint256& hash)
146+
{
147+
AssertLockNotHeld(cs_signer);
148+
LOCK(cs_signer);
149+
blockTxs.erase(hash);
150+
}
151+
152+
void ChainLockSigner::UpdateBlockHashTxidMap(const uint256& hash, const std::vector<CTransactionRef>& vtx)
153+
{
154+
AssertLockNotHeld(cs_signer);
155+
LOCK(cs_signer);
156+
auto it = blockTxs.find(hash);
157+
if (it == blockTxs.end()) {
158+
// We must create this entry even if there are no lockable transactions in the block, so that TrySignChainTip
159+
// later knows about this block
160+
it = blockTxs.emplace(hash, std::make_shared<std::unordered_set<uint256, StaticSaltedHasher>>()).first;
161+
}
162+
auto& txids = *it->second;
163+
for (const auto& tx : vtx) {
164+
if (!tx->IsCoinBase() && !tx->vin.empty()) {
165+
txids.emplace(tx->GetHash());
166+
}
167+
}
168+
}
169+
147170
ChainLockSigner::BlockTxs::mapped_type ChainLockSigner::GetBlockTxs(const uint256& blockHash)
148171
{
149172
AssertLockNotHeld(cs_signer);
150-
AssertLockNotHeld(m_clhandler.cs);
151173
AssertLockNotHeld(::cs_main);
152174

153175
ChainLockSigner::BlockTxs::mapped_type ret;
@@ -188,31 +210,26 @@ ChainLockSigner::BlockTxs::mapped_type ChainLockSigner::GetBlockTxs(const uint25
188210
LOCK(cs_signer);
189211
blockTxs.emplace(blockHash, ret);
190212
}
191-
{
192-
LOCK(m_clhandler.cs);
193-
for (const auto& txid : *ret) {
194-
m_clhandler.txFirstSeenTime.emplace(txid, blockTime);
195-
}
196-
}
213+
m_clhandler.UpdateTxFirstSeenMap(*ret, blockTime);
197214
}
198215
return ret;
199216
}
200217

201218
MessageProcessingResult ChainLockSigner::HandleNewRecoveredSig(const llmq::CRecoveredSig& recoveredSig)
202219
{
203-
if (!m_clhandler.isEnabled) {
220+
if (!m_clhandler.IsEnabled()) {
204221
return {};
205222
}
206223

207224
ChainLockSig clsig;
208225
{
209-
LOCK2(m_clhandler.cs, cs_signer);
226+
LOCK(cs_signer);
210227

211228
if (recoveredSig.getId() != lastSignedRequestId || recoveredSig.getMsgHash() != lastSignedMsgHash) {
212229
// this is not what we signed, so lets not create a CLSIG for it
213230
return {};
214231
}
215-
if (m_clhandler.bestChainLock.getHeight() >= lastSignedHeight) {
232+
if (m_clhandler.GetBestChainLockHeight() >= lastSignedHeight) {
216233
// already got the same or a better CLSIG through the CLSIG message
217234
return {};
218235
}

src/chainlock/signing.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ class ChainLockSigner : public llmq::CRecoveredSigsListener
4949
llmq::CSigSharesManager& shareman, CSporkManager& sporkman, const CMasternodeSync& mn_sync);
5050
~ChainLockSigner();
5151

52+
void Start();
53+
void Stop();
54+
55+
void EraseFromBlockHashTxidMap(const uint256& hash)
56+
EXCLUSIVE_LOCKS_REQUIRED(!cs_signer);
57+
void UpdateBlockHashTxidMap(const uint256& hash, const std::vector<CTransactionRef>& vtx)
58+
EXCLUSIVE_LOCKS_REQUIRED(!cs_signer);
59+
5260
void TrySignChainTip(const llmq::CInstantSendManager& isman)
5361
EXCLUSIVE_LOCKS_REQUIRED(!cs_signer);
5462
[[nodiscard]] MessageProcessingResult HandleNewRecoveredSig(const llmq::CRecoveredSig& recoveredSig) override
@@ -60,8 +68,6 @@ class ChainLockSigner : public llmq::CRecoveredSigsListener
6068
private:
6169
[[nodiscard]] BlockTxs::mapped_type GetBlockTxs(const uint256& blockHash)
6270
EXCLUSIVE_LOCKS_REQUIRED(!cs_signer);
63-
64-
friend class ::llmq::CChainLocksHandler;
6571
};
6672
} // namespace chainlock
6773

0 commit comments

Comments
 (0)