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);
|
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)
|
void CDSNotificationInterface::SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock)
|
||||||
{
|
{
|
||||||
llmq::quorumInstantSendManager->SyncTransaction(tx, pindex, posInBlock);
|
llmq::quorumInstantSendManager->SyncTransaction(tx, pindex, posInBlock);
|
||||||
|
llmq::chainLocksHandler->SyncTransaction(tx, pindex, posInBlock);
|
||||||
instantsend.SyncTransaction(tx, pindex, posInBlock);
|
instantsend.SyncTransaction(tx, pindex, posInBlock);
|
||||||
CPrivateSend::SyncTransaction(tx, pindex, posInBlock);
|
CPrivateSend::SyncTransaction(tx, pindex, posInBlock);
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ protected:
|
|||||||
void AcceptedBlockHeader(const CBlockIndex *pindexNew) override;
|
void AcceptedBlockHeader(const CBlockIndex *pindexNew) override;
|
||||||
void NotifyHeaderTip(const CBlockIndex *pindexNew, bool fInitialDownload) override;
|
void NotifyHeaderTip(const CBlockIndex *pindexNew, bool fInitialDownload) override;
|
||||||
void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, 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 SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock) override;
|
||||||
void NotifyMasternodeListChanged(const CDeterministicMNList& newList) override;
|
void NotifyMasternodeListChanged(const CDeterministicMNList& newList) override;
|
||||||
void NotifyChainLock(const CBlockIndex* pindex);
|
void NotifyChainLock(const CBlockIndex* pindex);
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "net_processing.h"
|
#include "net_processing.h"
|
||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
#include "spork.h"
|
#include "spork.h"
|
||||||
|
#include "txmempool.h"
|
||||||
#include "validation.h"
|
#include "validation.h"
|
||||||
|
|
||||||
namespace llmq
|
namespace llmq
|
||||||
@ -244,6 +245,51 @@ void CChainLocksHandler::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBl
|
|||||||
quorumSigningManager->AsyncSignIfMember(Params().GetConsensus().llmqChainLocks, requestId, msgHash);
|
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!
|
// WARNING: cs_main and cs should not be held!
|
||||||
void CChainLocksHandler::EnforceBestChainLock()
|
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(); ) {
|
for (auto it = seenChainLocks.begin(); it != seenChainLocks.end(); ) {
|
||||||
if (GetTimeMillis() - it->second >= CLEANUP_SEEN_TIMEOUT) {
|
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();
|
lastCleanupTime = GetTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "chainparams.h"
|
#include "chainparams.h"
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
class CBlockIndex;
|
class CBlockIndex;
|
||||||
class CScheduler;
|
class CScheduler;
|
||||||
@ -61,6 +62,10 @@ private:
|
|||||||
uint256 lastSignedRequestId;
|
uint256 lastSignedRequestId;
|
||||||
uint256 lastSignedMsgHash;
|
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;
|
std::map<uint256, int64_t> seenChainLocks;
|
||||||
|
|
||||||
int64_t lastCleanupTime{0};
|
int64_t lastCleanupTime{0};
|
||||||
@ -79,6 +84,8 @@ public:
|
|||||||
void ProcessNewChainLock(NodeId from, const CChainLockSig& clsig, const uint256& hash);
|
void ProcessNewChainLock(NodeId from, const CChainLockSig& clsig, const uint256& hash);
|
||||||
void AcceptedBlockHeader(const CBlockIndex* pindexNew);
|
void AcceptedBlockHeader(const CBlockIndex* pindexNew);
|
||||||
void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork);
|
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();
|
void EnforceBestChainLock();
|
||||||
virtual void HandleNewRecoveredSig(const CRecoveredSig& recoveredSig);
|
virtual void HandleNewRecoveredSig(const CRecoveredSig& recoveredSig);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user