Fix issues introduced with asynchronous signal handling (#3369)

* Introduce SynchronousUpdatedBlockTip signal

This version of UpdatedBlockTip mirrors the asynchronous behavior that we
had before the introduction of asynchronous signal handling.

* Fix tab spacing in validationinterface.cpp

* Invoke CDeterministicMNManager::UpdatedBlockTip from validation thread

It must be invoked synchronously as otherwise things become inconsistent.

* Call CActiveMasternodeManager::Init with block index

pindexNew in UpdatedBlockTip is not necessarily the current tip, so we
shouldn't rely on it in Init(). This is due to the async nature of the
UpdatedBlockTip invocation.
This commit is contained in:
Alexander Block 2020-03-20 17:11:54 +01:00 committed by GitHub
parent b188c5c25e
commit 0fa2e14065
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 45 additions and 17 deletions

View File

@ -24,6 +24,7 @@
void CDSNotificationInterface::InitializeCurrentBlockTip()
{
LOCK(cs_main);
SynchronousUpdatedBlockTip(chainActive.Tip(), nullptr, IsInitialBlockDownload());
UpdatedBlockTip(chainActive.Tip(), nullptr, IsInitialBlockDownload());
}
@ -38,12 +39,18 @@ void CDSNotificationInterface::NotifyHeaderTip(const CBlockIndex *pindexNew, boo
masternodeSync.NotifyHeaderTip(pindexNew, fInitialDownload, connman);
}
void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
void CDSNotificationInterface::SynchronousUpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
{
if (pindexNew == pindexFork) // blocks were disconnected without any new ones
return;
deterministicMNManager->UpdatedBlockTip(pindexNew);
}
void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
{
if (pindexNew == pindexFork) // blocks were disconnected without any new ones
return;
masternodeSync.UpdatedBlockTip(pindexNew, fInitialDownload, connman);

View File

@ -20,6 +20,7 @@ protected:
// CValidationInterface
void AcceptedBlockHeader(const CBlockIndex *pindexNew) override;
void NotifyHeaderTip(const CBlockIndex *pindexNew, bool fInitialDownload) override;
void SynchronousUpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override;
void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override;
void TransactionAddedToMempool(const CTransactionRef& tx, int64_t nAcceptTime) override;
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex, const std::vector<CTransactionRef>& vtxConflicted) override;

View File

@ -829,7 +829,12 @@ void ThreadImport(std::vector<fs::path> vImportFiles)
if (fMasternodeMode) {
assert(activeMasternodeManager);
activeMasternodeManager->Init();
const CBlockIndex* pindexTip;
{
LOCK(cs_main);
pindexTip = chainActive.Tip();
}
activeMasternodeManager->Init(pindexTip);
}
#ifdef ENABLE_WALLET

View File

@ -59,13 +59,13 @@ std::string CActiveMasternodeManager::GetStatus() const
}
}
void CActiveMasternodeManager::Init()
void CActiveMasternodeManager::Init(const CBlockIndex* pindex)
{
LOCK(cs_main);
if (!fMasternodeMode) return;
if (!deterministicMNManager->IsDIP3Enforced()) return;
if (!deterministicMNManager->IsDIP3Enforced(pindex->nHeight)) return;
// Check that our local network configuration is correct
if (!fListen) {
@ -81,7 +81,7 @@ void CActiveMasternodeManager::Init()
return;
}
CDeterministicMNList mnList = deterministicMNManager->GetListAtChainTip();
CDeterministicMNList mnList = deterministicMNManager->GetListForBlock(pindex);
CDeterministicMNCPtr dmn = mnList.GetMNByOperatorKey(*activeMasternodeInfo.blsPubKeyOperator);
if (!dmn) {
@ -148,7 +148,7 @@ void CActiveMasternodeManager::UpdatedBlockTip(const CBlockIndex* pindexNew, con
activeMasternodeInfo.proTxHash = uint256();
activeMasternodeInfo.outpoint.SetNull();
// MN might have reappeared in same block with a new ProTx
Init();
Init(pindexNew);
return;
}
@ -160,7 +160,7 @@ void CActiveMasternodeManager::UpdatedBlockTip(const CBlockIndex* pindexNew, con
activeMasternodeInfo.proTxHash = uint256();
activeMasternodeInfo.outpoint.SetNull();
// MN might have reappeared in same block with a new ProTx
Init();
Init(pindexNew);
return;
}
@ -169,13 +169,13 @@ void CActiveMasternodeManager::UpdatedBlockTip(const CBlockIndex* pindexNew, con
state = MASTERNODE_PROTX_IP_CHANGED;
activeMasternodeInfo.proTxHash = uint256();
activeMasternodeInfo.outpoint.SetNull();
Init();
Init(pindexNew);
return;
}
} else {
// MN might have (re)appeared with a new ProTx or we've found some peers
// and figured out our local address
Init();
Init(pindexNew);
}
}

View File

@ -52,7 +52,7 @@ private:
public:
virtual void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload);
void Init();
void Init(const CBlockIndex* pindex);
std::string GetStateString() const;
std::string GetStatus() const;

View File

@ -2887,6 +2887,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
// Notifications/callbacks that can run without cs_main
// Notify external listeners about the new tip.
GetMainSignals().SynchronousUpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload);
GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload);
// Always notify the UI if a new block tip was connected
@ -3009,6 +3010,7 @@ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, C
}
InvalidChainFound(pindex);
GetMainSignals().SynchronousUpdatedBlockTip(chainActive.Tip(), nullptr, IsInitialBlockDownload());
GetMainSignals().UpdatedBlockTip(chainActive.Tip(), nullptr, IsInitialBlockDownload());
uiInterface.NotifyBlockTip(IsInitialBlockDownload(), pindex->pprev);
return true;

View File

@ -19,6 +19,7 @@
struct MainSignalsInstance {
boost::signals2::signal<void (const CBlockIndex *, const CBlockIndex *, bool fInitialDownload)> UpdatedBlockTip;
boost::signals2::signal<void (const CBlockIndex *, const CBlockIndex *, bool fInitialDownload)> SynchronousUpdatedBlockTip;
boost::signals2::signal<void (const CTransactionRef &, int64_t)> TransactionAddedToMempool;
boost::signals2::signal<void (const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::vector<CTransactionRef>&)> BlockConnected;
boost::signals2::signal<void (const std::shared_ptr<const CBlock> &, const CBlockIndex* pindexDisconnected)> BlockDisconnected;
@ -78,6 +79,7 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.m_internals->AcceptedBlockHeader.connect(boost::bind(&CValidationInterface::AcceptedBlockHeader, pwalletIn, _1));
g_signals.m_internals->NotifyHeaderTip.connect(boost::bind(&CValidationInterface::NotifyHeaderTip, pwalletIn, _1, _2));
g_signals.m_internals->UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3));
g_signals.m_internals->SynchronousUpdatedBlockTip.connect(boost::bind(&CValidationInterface::SynchronousUpdatedBlockTip, pwalletIn, _1, _2, _3));
g_signals.m_internals->TransactionAddedToMempool.connect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1, _2));
g_signals.m_internals->BlockConnected.connect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3));
g_signals.m_internals->BlockDisconnected.connect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1, _2));
@ -107,6 +109,7 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.m_internals->BlockDisconnected.disconnect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1, _2));
g_signals.m_internals->TransactionRemovedFromMempool.disconnect(boost::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, _1));
g_signals.m_internals->UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3));
g_signals.m_internals->SynchronousUpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::SynchronousUpdatedBlockTip, pwalletIn, _1, _2, _3));
g_signals.m_internals->NewPoWValidBlock.disconnect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2));
g_signals.m_internals->NotifyHeaderTip.disconnect(boost::bind(&CValidationInterface::NotifyHeaderTip, pwalletIn, _1, _2));
g_signals.m_internals->AcceptedBlockHeader.disconnect(boost::bind(&CValidationInterface::AcceptedBlockHeader, pwalletIn, _1));
@ -131,6 +134,7 @@ void UnregisterAllValidationInterfaces() {
g_signals.m_internals->BlockDisconnected.disconnect_all_slots();
g_signals.m_internals->TransactionRemovedFromMempool.disconnect_all_slots();
g_signals.m_internals->UpdatedBlockTip.disconnect_all_slots();
g_signals.m_internals->SynchronousUpdatedBlockTip.disconnect_all_slots();
g_signals.m_internals->NewPoWValidBlock.disconnect_all_slots();
g_signals.m_internals->NotifyHeaderTip.disconnect_all_slots();
g_signals.m_internals->AcceptedBlockHeader.disconnect_all_slots();
@ -158,6 +162,10 @@ void CMainSignals::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockInd
});
}
void CMainSignals::SynchronousUpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {
m_internals->SynchronousUpdatedBlockTip(pindexNew, pindexFork, fInitialDownload);
}
void CMainSignals::TransactionAddedToMempool(const CTransactionRef &ptx, int64_t nAcceptTime) {
m_internals->m_schedulerClient.AddToProcessQueue([ptx, nAcceptTime, this] {
m_internals->TransactionAddedToMempool(ptx, nAcceptTime);
@ -205,29 +213,29 @@ void CMainSignals::AcceptedBlockHeader(const CBlockIndex *pindexNew) {
}
void CMainSignals::NotifyHeaderTip(const CBlockIndex *pindexNew, bool fInitialDownload) {
m_internals->NotifyHeaderTip(pindexNew, fInitialDownload);
m_internals->NotifyHeaderTip(pindexNew, fInitialDownload);
}
void CMainSignals::NotifyTransactionLock(const CTransaction &tx, const llmq::CInstantSendLock& islock) {
m_internals->NotifyTransactionLock(tx, islock);
m_internals->NotifyTransactionLock(tx, islock);
}
void CMainSignals::NotifyChainLock(const CBlockIndex* pindex, const llmq::CChainLockSig& clsig) {
m_internals->NotifyChainLock(pindex, clsig);
m_internals->NotifyChainLock(pindex, clsig);
}
void CMainSignals::NotifyGovernanceVote(const CGovernanceVote &vote) {
m_internals->NotifyGovernanceVote(vote);
m_internals->NotifyGovernanceVote(vote);
}
void CMainSignals::NotifyGovernanceObject(const CGovernanceObject &object) {
m_internals->NotifyGovernanceObject(object);
m_internals->NotifyGovernanceObject(object);
}
void CMainSignals::NotifyInstantSendDoubleSpendAttempt(const CTransaction &currentTx, const CTransaction &previousTx) {
m_internals->NotifyInstantSendDoubleSpendAttempt(currentTx, previousTx);
m_internals->NotifyInstantSendDoubleSpendAttempt(currentTx, previousTx);
}
void CMainSignals::NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff) {
m_internals->NotifyMasternodeListChanged(undo, oldMNList, diff);
m_internals->NotifyMasternodeListChanged(undo, oldMNList, diff);
}

View File

@ -61,6 +61,10 @@ protected:
* Called on a background thread.
*/
virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {}
/**
* Same as UpdatedBlockTip, but called from the caller's thread
*/
virtual void SynchronousUpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {}
/**
* Notifies listeners of a transaction having been added to mempool.
*
@ -155,6 +159,7 @@ public:
void AcceptedBlockHeader(const CBlockIndex *pindexNew);
void NotifyHeaderTip(const CBlockIndex *pindexNew, bool fInitialDownload);
void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload);
void SynchronousUpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload);
void TransactionAddedToMempool(const CTransactionRef &, int64_t);
void BlockConnected(const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>> &);
void BlockDisconnected(const std::shared_ptr<const CBlock> &, const CBlockIndex* pindexDisconnected);