Skip to content

Commit

Permalink
Fall back to ReadBlockFromDisk when blockTxs is not filled yet (#2908)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
codablock committed May 10, 2019
1 parent 4dc5c0e commit 56f3119
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 12 deletions.
64 changes: 53 additions & 11 deletions src/llmq/quorums_chainlocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,17 +301,10 @@ 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());
if (!txids) {
pindexWalk = pindexWalk->pprev;
continue;
}

for (auto& txid : *txids) {
Expand Down Expand Up @@ -382,6 +375,55 @@ 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());

uint32_t blockTime;
{
LOCK(cs_main);
auto pindex = mapBlockIndex.at(blockHash);
CBlock block;
if (!ReadBlockFromDisk(block, pindex, Params().GetConsensus())) {
return nullptr;
}

ret = std::make_shared<std::unordered_set<uint256, StaticSaltedHasher>>();
for (auto& tx : block.vtx) {
if (tx->IsCoinBase() || tx->vin.empty()) {
continue;
}
ret->emplace(tx->GetHash());
}

blockTime = block.nTime;
}

LOCK(cs);
blockTxs.emplace(blockHash, ret);
for (auto& txid : *ret) {
txFirstSeenTime.emplace(txid, blockTime);
}
}
return ret;
}

bool CChainLocksHandler::IsTxSafeForMining(const uint256& txid)
{
if (!sporkManager.IsSporkActive(SPORK_3_INSTANTSEND_BLOCK_FILTERING)) {
Expand Down
5 changes: 4 additions & 1 deletion src/llmq/quorums_chainlocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<uint256, std::shared_ptr<std::unordered_set<uint256, StaticSaltedHasher>>> blockTxs;
typedef std::unordered_map<uint256, std::shared_ptr<std::unordered_set<uint256, StaticSaltedHasher>>> BlockTxs;
BlockTxs blockTxs;
std::unordered_map<uint256, int64_t> txFirstSeenTime;

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

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

BlockTxs::mapped_type GetBlockTxs(const uint256& blockHash);

void Cleanup();
};

Expand Down

0 comments on commit 56f3119

Please sign in to comment.