Skip to content

Commit 56f3119

Browse files
authored
Fall back to ReadBlockFromDisk when blockTxs is not filled yet (#2908)
* Fall back to ReadBlockFromDisk when blockTxs is not filled yet This handles the case where a MN is freshly started and SyncTransaction was not been called for older transactions/blocks. * Also update txFirstSeenTime * Properly handle txids == nullptr
1 parent 4dc5c0e commit 56f3119

File tree

2 files changed

+57
-12
lines changed

2 files changed

+57
-12
lines changed

src/llmq/quorums_chainlocks.cpp

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -301,17 +301,10 @@ void CChainLocksHandler::TrySignChainTip()
301301
break;
302302
}
303303

304-
decltype(blockTxs.begin()->second) txids;
305-
{
306-
LOCK(cs);
307-
auto it = blockTxs.find(pindexWalk->GetBlockHash());
308-
if (it == blockTxs.end()) {
309-
// this should actually not happen as NewPoWValidBlock should have been called before
310-
LogPrint("chainlocks", "CChainLocksHandler::%s -- blockTxs for %s not found\n", __func__,
311-
pindexWalk->GetBlockHash().ToString());
312-
return;
313-
}
314-
txids = it->second;
304+
auto txids = GetBlockTxs(pindexWalk->GetBlockHash());
305+
if (!txids) {
306+
pindexWalk = pindexWalk->pprev;
307+
continue;
315308
}
316309

317310
for (auto& txid : *txids) {
@@ -382,6 +375,55 @@ void CChainLocksHandler::SyncTransaction(const CTransaction& tx, const CBlockInd
382375
}
383376
}
384377

378+
CChainLocksHandler::BlockTxs::mapped_type CChainLocksHandler::GetBlockTxs(const uint256& blockHash)
379+
{
380+
AssertLockNotHeld(cs);
381+
AssertLockNotHeld(cs_main);
382+
383+
CChainLocksHandler::BlockTxs::mapped_type ret;
384+
385+
{
386+
LOCK(cs);
387+
auto it = blockTxs.find(blockHash);
388+
if (it != blockTxs.end()) {
389+
ret = it->second;
390+
}
391+
}
392+
if (!ret) {
393+
// This should only happen when freshly started.
394+
// If running for some time, SyncTransaction should have been called before which fills blockTxs.
395+
LogPrint("chainlocks", "CChainLocksHandler::%s -- blockTxs for %s not found. Trying ReadBlockFromDisk\n", __func__,
396+
blockHash.ToString());
397+
398+
uint32_t blockTime;
399+
{
400+
LOCK(cs_main);
401+
auto pindex = mapBlockIndex.at(blockHash);
402+
CBlock block;
403+
if (!ReadBlockFromDisk(block, pindex, Params().GetConsensus())) {
404+
return nullptr;
405+
}
406+
407+
ret = std::make_shared<std::unordered_set<uint256, StaticSaltedHasher>>();
408+
for (auto& tx : block.vtx) {
409+
if (tx->IsCoinBase() || tx->vin.empty()) {
410+
continue;
411+
}
412+
ret->emplace(tx->GetHash());
413+
}
414+
415+
blockTime = block.nTime;
416+
}
417+
418+
LOCK(cs);
419+
blockTxs.emplace(blockHash, ret);
420+
for (auto& txid : *ret) {
421+
txFirstSeenTime.emplace(txid, blockTime);
422+
}
423+
}
424+
return ret;
425+
}
426+
385427
bool CChainLocksHandler::IsTxSafeForMining(const uint256& txid)
386428
{
387429
if (!sporkManager.IsSporkActive(SPORK_3_INSTANTSEND_BLOCK_FILTERING)) {

src/llmq/quorums_chainlocks.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ class CChainLocksHandler : public CRecoveredSigsListener
6868
uint256 lastSignedMsgHash;
6969

7070
// We keep track of txids from recently received blocks so that we can check if all TXs got ixlocked
71-
std::unordered_map<uint256, std::shared_ptr<std::unordered_set<uint256, StaticSaltedHasher>>> blockTxs;
71+
typedef std::unordered_map<uint256, std::shared_ptr<std::unordered_set<uint256, StaticSaltedHasher>>> BlockTxs;
72+
BlockTxs blockTxs;
7273
std::unordered_map<uint256, int64_t> txFirstSeenTime;
7374

7475
std::map<uint256, int64_t> seenChainLocks;
@@ -107,6 +108,8 @@ class CChainLocksHandler : public CRecoveredSigsListener
107108

108109
void DoInvalidateBlock(const CBlockIndex* pindex, bool activateBestChain);
109110

111+
BlockTxs::mapped_type GetBlockTxs(const uint256& blockHash);
112+
110113
void Cleanup();
111114
};
112115

0 commit comments

Comments
 (0)