Track txids of new blocks and first-seen time of TXs in CChainLocksHandler
This commit is contained in:
parent
7945192ff6
commit
bd7edc8ae9
@ -71,9 +71,15 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con
|
||||
llmq::quorumDKGSessionManager->UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload);
|
||||
}
|
||||
|
||||
void CDSNotificationInterface::NewPoWValidBlock(const CBlockIndex* pindex, const std::shared_ptr<const CBlock>& block)
|
||||
{
|
||||
llmq::chainLocksHandler->NewPoWValidBlock(pindex, block);
|
||||
}
|
||||
|
||||
void CDSNotificationInterface::SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock)
|
||||
{
|
||||
llmq::quorumInstantSendManager->SyncTransaction(tx, pindex, posInBlock);
|
||||
llmq::chainLocksHandler->SyncTransaction(tx, pindex, posInBlock);
|
||||
instantsend.SyncTransaction(tx, pindex, posInBlock);
|
||||
CPrivateSend::SyncTransaction(tx, pindex, posInBlock);
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ protected:
|
||||
void AcceptedBlockHeader(const CBlockIndex *pindexNew) override;
|
||||
void NotifyHeaderTip(const CBlockIndex *pindexNew, bool fInitialDownload) override;
|
||||
void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override;
|
||||
void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& block) override;
|
||||
void SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock) override;
|
||||
void NotifyMasternodeListChanged(const CDeterministicMNList& newList) override;
|
||||
void NotifyChainLock(const CBlockIndex* pindex);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "net_processing.h"
|
||||
#include "scheduler.h"
|
||||
#include "spork.h"
|
||||
#include "txmempool.h"
|
||||
#include "validation.h"
|
||||
|
||||
namespace llmq
|
||||
@ -244,6 +245,51 @@ void CChainLocksHandler::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBl
|
||||
quorumSigningManager->AsyncSignIfMember(Params().GetConsensus().llmqChainLocks, requestId, msgHash);
|
||||
}
|
||||
|
||||
void CChainLocksHandler::NewPoWValidBlock(const CBlockIndex* pindex, const std::shared_ptr<const CBlock>& block)
|
||||
{
|
||||
LOCK(cs);
|
||||
if (blockTxs.count(pindex->GetBlockHash())) {
|
||||
// should actually not happen (blocks are only written once to disk and this is when NewPoWValidBlock is called)
|
||||
// but be extra safe here in case this behaviour changes.
|
||||
return;
|
||||
}
|
||||
|
||||
// We listen for NewPoWValidBlock so that we can collect all TX ids of all included TXs of newly received blocks
|
||||
// We need this information later when we try to sign a new tip, so that we can determine if all included TXs are
|
||||
// safe.
|
||||
|
||||
auto txs = std::make_shared<std::unordered_set<uint256, StaticSaltedHasher>>();
|
||||
for (const auto& tx : block->vtx) {
|
||||
if (tx->nVersion == 3) {
|
||||
if (tx->nType == TRANSACTION_COINBASE ||
|
||||
tx->nType == TRANSACTION_QUORUM_COMMITMENT) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
txs->emplace(tx->GetHash());
|
||||
}
|
||||
blockTxs[pindex->GetBlockHash()] = txs;
|
||||
|
||||
int64_t curTime = GetAdjustedTime();
|
||||
for (auto& tx : block->vtx) {
|
||||
txFirstSeenTime.emplace(tx->GetHash(), curTime);
|
||||
}
|
||||
}
|
||||
|
||||
void CChainLocksHandler::SyncTransaction(const CTransaction& tx, const CBlockIndex* pindex, int posInBlock)
|
||||
{
|
||||
if (tx.nVersion == 3) {
|
||||
if (tx.nType == TRANSACTION_COINBASE ||
|
||||
tx.nType == TRANSACTION_QUORUM_COMMITMENT) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LOCK(cs);
|
||||
int64_t curTime = GetAdjustedTime();
|
||||
txFirstSeenTime.emplace(tx.GetHash(), curTime);
|
||||
}
|
||||
|
||||
// WARNING: cs_main and cs should not be held!
|
||||
void CChainLocksHandler::EnforceBestChainLock()
|
||||
{
|
||||
@ -420,7 +466,9 @@ void CChainLocksHandler::Cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
LOCK2(cs_main, cs);
|
||||
// need mempool.cs due to GetTransaction calls
|
||||
LOCK2(cs_main, mempool.cs);
|
||||
LOCK(cs);
|
||||
|
||||
for (auto it = seenChainLocks.begin(); it != seenChainLocks.end(); ) {
|
||||
if (GetTimeMillis() - it->second >= CLEANUP_SEEN_TIMEOUT) {
|
||||
@ -430,6 +478,38 @@ void CChainLocksHandler::Cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = blockTxs.begin(); it != blockTxs.end(); ) {
|
||||
auto pindex = mapBlockIndex.at(it->first);
|
||||
if (InternalHasChainLock(pindex->nHeight, pindex->GetBlockHash())) {
|
||||
for (auto& txid : *it->second) {
|
||||
txFirstSeenTime.erase(txid);
|
||||
}
|
||||
it = blockTxs.erase(it);
|
||||
} else if (InternalHasConflictingChainLock(pindex->nHeight, pindex->GetBlockHash())) {
|
||||
it = blockTxs.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
for (auto it = txFirstSeenTime.begin(); it != txFirstSeenTime.end(); ) {
|
||||
CTransactionRef tx;
|
||||
uint256 hashBlock;
|
||||
if (!GetTransaction(it->first, tx, Params().GetConsensus(), hashBlock)) {
|
||||
// tx has vanished, probably due to conflicts
|
||||
it = txFirstSeenTime.erase(it);
|
||||
} else if (!hashBlock.IsNull()) {
|
||||
auto pindex = mapBlockIndex.at(hashBlock);
|
||||
if (chainActive.Tip()->GetAncestor(pindex->nHeight) == pindex && chainActive.Height() - pindex->nHeight >= 6) {
|
||||
// tx got confirmed >= 6 times, so we can stop keeping track of it
|
||||
it = txFirstSeenTime.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
lastCleanupTime = GetTimeMillis();
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "chainparams.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <unordered_set>
|
||||
|
||||
class CBlockIndex;
|
||||
class CScheduler;
|
||||
@ -61,6 +62,10 @@ private:
|
||||
uint256 lastSignedRequestId;
|
||||
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;
|
||||
std::unordered_map<uint256, int64_t> txFirstSeenTime;
|
||||
|
||||
std::map<uint256, int64_t> seenChainLocks;
|
||||
|
||||
int64_t lastCleanupTime{0};
|
||||
@ -79,6 +84,8 @@ public:
|
||||
void ProcessNewChainLock(NodeId from, const CChainLockSig& clsig, const uint256& hash);
|
||||
void AcceptedBlockHeader(const CBlockIndex* pindexNew);
|
||||
void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork);
|
||||
void NewPoWValidBlock(const CBlockIndex* pindex, const std::shared_ptr<const CBlock>& block);
|
||||
void SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock);
|
||||
void EnforceBestChainLock();
|
||||
virtual void HandleNewRecoveredSig(const CRecoveredSig& recoveredSig);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user