From 8bd3f3e6e5bfa6d9d3f324ff859ec7fd73c11671 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Thu, 9 May 2019 08:06:54 +0200 Subject: [PATCH 1/3] 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. --- src/llmq/quorums_chainlocks.cpp | 56 ++++++++++++++++++++++++++------- src/llmq/quorums_chainlocks.h | 5 ++- 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/src/llmq/quorums_chainlocks.cpp b/src/llmq/quorums_chainlocks.cpp index 0c6e5e431d04..364d430c241f 100644 --- a/src/llmq/quorums_chainlocks.cpp +++ b/src/llmq/quorums_chainlocks.cpp @@ -301,18 +301,7 @@ void CChainLocksHandler::TrySignChainTip() break; } - decltype(blockTxs.begin()->second) txids; - { - LOCK(cs); - auto it = blockTxs.find(pindexWalk->GetBlockHash()); - if (it == blockTxs.end()) { - // this should actually not happen as NewPoWValidBlock should have been called before - LogPrint("chainlocks", "CChainLocksHandler::%s -- blockTxs for %s not found\n", __func__, - pindexWalk->GetBlockHash().ToString()); - return; - } - txids = it->second; - } + auto txids = GetBlockTxs(pindexWalk->GetBlockHash()); for (auto& txid : *txids) { int64_t txAge = 0; @@ -382,6 +371,49 @@ void CChainLocksHandler::SyncTransaction(const CTransaction& tx, const CBlockInd } } +CChainLocksHandler::BlockTxs::mapped_type CChainLocksHandler::GetBlockTxs(const uint256& blockHash) +{ + AssertLockNotHeld(cs); + AssertLockNotHeld(cs_main); + + CChainLocksHandler::BlockTxs::mapped_type ret; + + { + LOCK(cs); + auto it = blockTxs.find(blockHash); + if (it != blockTxs.end()) { + ret = it->second; + } + } + if (!ret) { + // This should only happen when freshly started. + // If running for some time, SyncTransaction should have been called before which fills blockTxs. + LogPrint("chainlocks", "CChainLocksHandler::%s -- blockTxs for %s not found. Trying ReadBlockFromDisk\n", __func__, + blockHash.ToString()); + + { + LOCK(cs_main); + auto pindex = mapBlockIndex.at(blockHash); + CBlock block; + if (!ReadBlockFromDisk(block, pindex, Params().GetConsensus())) { + return nullptr; + } + + ret = std::make_shared>(); + for (auto& tx : block.vtx) { + if (tx->IsCoinBase() || tx->vin.empty()) { + continue; + } + ret->emplace(tx->GetHash()); + } + } + + LOCK(cs); + blockTxs.emplace(blockHash, ret); + } + return ret; +} + bool CChainLocksHandler::IsTxSafeForMining(const uint256& txid) { if (!sporkManager.IsSporkActive(SPORK_3_INSTANTSEND_BLOCK_FILTERING)) { diff --git a/src/llmq/quorums_chainlocks.h b/src/llmq/quorums_chainlocks.h index e057a25242f3..98378f7a1447 100644 --- a/src/llmq/quorums_chainlocks.h +++ b/src/llmq/quorums_chainlocks.h @@ -68,7 +68,8 @@ class CChainLocksHandler : public CRecoveredSigsListener uint256 lastSignedMsgHash; // We keep track of txids from recently received blocks so that we can check if all TXs got ixlocked - std::unordered_map>> blockTxs; + typedef std::unordered_map>> BlockTxs; + BlockTxs blockTxs; std::unordered_map txFirstSeenTime; std::map seenChainLocks; @@ -107,6 +108,8 @@ class CChainLocksHandler : public CRecoveredSigsListener void DoInvalidateBlock(const CBlockIndex* pindex, bool activateBestChain); + BlockTxs::mapped_type GetBlockTxs(const uint256& blockHash); + void Cleanup(); }; From eafaa1c1667f556fb455197ab28bf2e3ab7e9586 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Thu, 9 May 2019 08:13:36 +0200 Subject: [PATCH 2/3] Also update txFirstSeenTime --- src/llmq/quorums_chainlocks.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/llmq/quorums_chainlocks.cpp b/src/llmq/quorums_chainlocks.cpp index 364d430c241f..45f12a58a5a0 100644 --- a/src/llmq/quorums_chainlocks.cpp +++ b/src/llmq/quorums_chainlocks.cpp @@ -391,6 +391,7 @@ CChainLocksHandler::BlockTxs::mapped_type CChainLocksHandler::GetBlockTxs(const LogPrint("chainlocks", "CChainLocksHandler::%s -- blockTxs for %s not found. Trying ReadBlockFromDisk\n", __func__, blockHash.ToString()); + uint32_t blockTime; { LOCK(cs_main); auto pindex = mapBlockIndex.at(blockHash); @@ -406,10 +407,15 @@ CChainLocksHandler::BlockTxs::mapped_type CChainLocksHandler::GetBlockTxs(const } ret->emplace(tx->GetHash()); } + + blockTime = block.nTime; } LOCK(cs); blockTxs.emplace(blockHash, ret); + for (auto& txid : *ret) { + txFirstSeenTime.emplace(txid, blockTime); + } } return ret; } From d1c513b0e235e08eaf52ac63a46bbb642ba50801 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Fri, 10 May 2019 11:25:41 +0200 Subject: [PATCH 3/3] Properly handle txids == nullptr --- src/llmq/quorums_chainlocks.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/llmq/quorums_chainlocks.cpp b/src/llmq/quorums_chainlocks.cpp index 45f12a58a5a0..0cba352672fd 100644 --- a/src/llmq/quorums_chainlocks.cpp +++ b/src/llmq/quorums_chainlocks.cpp @@ -302,6 +302,10 @@ void CChainLocksHandler::TrySignChainTip() } auto txids = GetBlockTxs(pindexWalk->GetBlockHash()); + if (!txids) { + pindexWalk = pindexWalk->pprev; + continue; + } for (auto& txid : *txids) { int64_t txAge = 0;