From a3c8cb20dfd4bf04505a8860bd11db71b221a29c Mon Sep 17 00:00:00 2001
From: Oleg Girko
Date: Fri, 28 Jul 2017 15:10:10 +0100
Subject: [PATCH] Backport Bitcoin PR#8865: Decouple peer-processing-logic from
block-connection-logic (#1556)
* Make validationinterface.UpdatedBlockTip more verbose
In anticipation of making all the callbacks out of block processing
flow through it. Note that vHashes will always have something in it
since pindexFork != pindexNewTip.
* Remove duplicate nBlocksEstimate cmp (we already checked IsIBD())
* Remove CConnman parameter from ProcessNewBlock/ActivateBestChain
* Remove SyncWithWallets wrapper function
* Move net-processing logic definitions together in main.h
* Use CValidationInterface from chain logic to notify peer logic
This adds a new CValidationInterface subclass, defined in main.h,
to receive notifications of UpdatedBlockTip and use that to push
blocks to peers, instead of doing it directly from
ActivateBestChain.
* Always call UpdatedBlockTip, even if blocks were only disconnected
* Use BlockChecked signal to send reject messages from mapBlockSource
---
src/init.cpp | 5 ++
src/main.cpp | 121 ++++++++++++++-------------
src/main.h | 72 +++++++++-------
src/miner.cpp | 6 +-
src/rpc/blockchain.cpp | 4 +-
src/rpc/mining.cpp | 4 +-
src/test/miner_tests.cpp | 2 +-
src/test/test_dash.cpp | 2 +-
src/validationinterface.cpp | 8 +-
src/validationinterface.h | 6 +-
src/zmq/zmqnotificationinterface.cpp | 7 +-
src/zmq/zmqnotificationinterface.h | 2 +-
12 files changed, 133 insertions(+), 106 deletions(-)
diff --git a/src/init.cpp b/src/init.cpp
index c2cf50e929986..e577e538d9e6b 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -99,6 +99,7 @@ static const bool DEFAULT_DISABLE_SAFEMODE = false;
static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
std::unique_ptr g_connman;
+std::unique_ptr peerLogic;
#if ENABLE_ZMQ
static CZMQNotificationInterface* pzmqNotificationInterface = NULL;
@@ -228,6 +229,8 @@ void PrepareShutdown()
#endif
GenerateBitcoins(false, 0, Params(), *g_connman);
MapPort(false);
+ UnregisterValidationInterface(peerLogic.get());
+ peerLogic.reset();
g_connman.reset();
// STORE DATA CACHES INTO SERIALIZED DAT FILES
@@ -1316,6 +1319,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
g_connman = std::unique_ptr(new CConnman());
CConnman& connman = *g_connman;
+ peerLogic.reset(new PeerLogicValidation(&connman));
+ RegisterValidationInterface(peerLogic.get());
RegisterNodeSignals(GetNodeSignals());
// sanitize comments per BIP-0014, format user agent and check total size
diff --git a/src/main.cpp b/src/main.cpp
index 433b598b15f25..76adfcf4d3daa 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1540,7 +1540,8 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
}
}
- if(!fDryRun) SyncWithWallets(tx, NULL);
+ if(!fDryRun)
+ GetMainSignals().SyncTransaction(tx, NULL);
return true;
}
@@ -1966,17 +1967,6 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
}
void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) {
- int nDoS = 0;
- if (state.IsInvalid(nDoS)) {
- std::map::iterator it = mapBlockSource.find(pindex->GetBlockHash());
- if (it != mapBlockSource.end() && State(it->second)) {
- assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
- CBlockReject reject = {(unsigned char)state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), pindex->GetBlockHash()};
- State(it->second)->rejects.push_back(reject);
- if (nDoS > 0)
- Misbehaving(it->second, nDoS);
- }
- }
if (!state.CorruptionPossible()) {
pindex->nStatus |= BLOCK_FAILED_VALID;
setDirtyBlockIndex.insert(pindex);
@@ -3047,7 +3037,7 @@ bool static DisconnectTip(CValidationState& state, const Consensus::Params& cons
// Let wallets know transactions went from 1-confirmed to
// 0-confirmed or conflicted:
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
- SyncWithWallets(tx, NULL);
+ GetMainSignals().SyncTransaction(tx, NULL);
}
return true;
}
@@ -3086,7 +3076,6 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
InvalidBlockFound(pindexNew, state);
return error("ConnectTip(): ConnectBlock %s failed", pindexNew->GetBlockHash().ToString());
}
- mapBlockSource.erase(pindexNew->GetBlockHash());
nTime3 = GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2;
LogPrint("bench", " - Connect total: %.2fms [%.2fs]\n", (nTime3 - nTime2) * 0.001, nTimeConnectTotal * 0.000001);
assert(view.Flush());
@@ -3106,11 +3095,11 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
// Tell wallet about transactions that went from mempool
// to conflicted:
BOOST_FOREACH(const CTransaction &tx, txConflicted) {
- SyncWithWallets(tx, NULL);
+ GetMainSignals().SyncTransaction(tx, NULL);
}
// ... and about transactions that got confirmed:
BOOST_FOREACH(const CTransaction &tx, pblock->vtx) {
- SyncWithWallets(tx, pblock);
+ GetMainSignals().SyncTransaction(tx, pblock);
}
int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1;
@@ -3336,7 +3325,7 @@ static void NotifyHeaderTip() {
* or an activated best chain. pblock is either NULL or a pointer to a block
* that is already loaded (to avoid loading it again from disk).
*/
-bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, const CBlock *pblock, CConnman* connman) {
+bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, const CBlock *pblock) {
CBlockIndex *pindexMostWork = NULL;
CBlockIndex *pindexNewTip = NULL;
do {
@@ -3346,7 +3335,6 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
const CBlockIndex *pindexFork;
bool fInitialDownload;
- int nNewHeight;
{
LOCK(cs_main);
CBlockIndex *pindexOldTip = chainActive.Tip();
@@ -3369,49 +3357,17 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
pindexNewTip = chainActive.Tip();
pindexFork = chainActive.FindFork(pindexOldTip);
fInitialDownload = IsInitialBlockDownload();
- nNewHeight = chainActive.Height();
}
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
// Notifications/callbacks that can run without cs_main
- if(connman)
- connman->SetBestHeight(chainActive.Height());
+
+ // Notify external listeners about the new tip.
+ GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload);
// Always notify the UI if a new block tip was connected
if (pindexFork != pindexNewTip) {
uiInterface.NotifyBlockTip(fInitialDownload, pindexNewTip);
-
- if (!fInitialDownload) {
- // Find the hashes of all blocks that weren't previously in the best chain.
- std::vector vHashes;
- CBlockIndex *pindexToAnnounce = pindexNewTip;
- while (pindexToAnnounce != pindexFork) {
- vHashes.push_back(pindexToAnnounce->GetBlockHash());
- pindexToAnnounce = pindexToAnnounce->pprev;
- if (vHashes.size() == MAX_BLOCKS_TO_ANNOUNCE) {
- // Limit announcements in case of a huge reorganization.
- // Rely on the peer's synchronization mechanism in that case.
- break;
- }
- }
- // Relay inventory, but don't relay old inventory during initial block download.
- int nBlockEstimate = 0;
- if (fCheckpointsEnabled)
- nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints());
- if(connman) {
- connman->ForEachNode([nNewHeight, nBlockEstimate, &vHashes](CNode* pnode) {
- if (nNewHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) {
- BOOST_REVERSE_FOREACH(const uint256& hash, vHashes) {
- pnode->PushBlockHash(hash);
- }
- }
- });
- }
- // Notify external listeners about the new tip.
- if (!vHashes.empty()) {
- GetMainSignals().UpdatedBlockTip(pindexNewTip);
- }
- }
}
} while (pindexNewTip != pindexMostWork);
CheckBlockIndex(chainparams.GetConsensus());
@@ -4003,7 +3959,7 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned
}
-bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, CConnman* connman)
+bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp)
{
{
LOCK(cs_main);
@@ -4025,7 +3981,7 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, C
NotifyHeaderTip();
- if (!ActivateBestChain(state, chainparams, pblock, connman))
+ if (!ActivateBestChain(state, chainparams, pblock))
return error("%s: ActivateBestChain failed", __func__);
masternodeSync.IsBlockchainSynced(true);
@@ -4909,6 +4865,59 @@ std::string GetWarnings(const std::string& strFor)
+//////////////////////////////////////////////////////////////////////////////
+//
+// blockchain -> download logic notification
+//
+
+void PeerLogicValidation::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {
+ const int nNewHeight = pindexNew->nHeight;
+ connman->SetBestHeight(nNewHeight);
+
+ if (!fInitialDownload) {
+ // Find the hashes of all blocks that weren't previously in the best chain.
+ std::vector vHashes;
+ const CBlockIndex *pindexToAnnounce = pindexNew;
+ while (pindexToAnnounce != pindexFork) {
+ vHashes.push_back(pindexToAnnounce->GetBlockHash());
+ pindexToAnnounce = pindexToAnnounce->pprev;
+ if (vHashes.size() == MAX_BLOCKS_TO_ANNOUNCE) {
+ // Limit announcements in case of a huge reorganization.
+ // Rely on the peer's synchronization mechanism in that case.
+ break;
+ }
+ }
+ // Relay inventory, but don't relay old inventory during initial block download.
+ connman->ForEachNode([nNewHeight, &vHashes](CNode* pnode) {
+ if (nNewHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 0)) {
+ BOOST_REVERSE_FOREACH(const uint256& hash, vHashes) {
+ pnode->PushBlockHash(hash);
+ }
+ }
+ });
+ }
+}
+
+void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationState& state) {
+ LOCK(cs_main);
+
+ const uint256 hash(block.GetHash());
+ std::map::iterator it = mapBlockSource.find(hash);
+
+ int nDoS = 0;
+ if (state.IsInvalid(nDoS)) {
+ if (it != mapBlockSource.end() && State(it->second)) {
+ assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
+ CBlockReject reject = {(unsigned char)state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), hash};
+ State(it->second)->rejects.push_back(reject);
+ if (nDoS > 0)
+ Misbehaving(it->second, nDoS);
+ }
+ }
+ if (it != mapBlockSource.end())
+ mapBlockSource.erase(it);
+}
+
//////////////////////////////////////////////////////////////////////////////
//
// Messages
@@ -6107,7 +6116,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Such an unrequested block may still be processed, subject to the
// conditions in AcceptBlock().
bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload();
- ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL, &connman);
+ ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL);
int nDoS;
if (state.IsInvalid(nDoS)) {
assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
diff --git a/src/main.h b/src/main.h
index f9b0971068d81..04bc1c3f6a673 100644
--- a/src/main.h
+++ b/src/main.h
@@ -17,6 +17,7 @@
#include "net.h"
#include "script/script_error.h"
#include "sync.h"
+#include "validationinterface.h"
#include "versionbits.h"
#include "spentindex.h"
@@ -42,7 +43,6 @@ class CTxMemPool;
class CValidationInterface;
class CValidationState;
-struct CNodeStateStats;
struct LockPoints;
/** Default for accepting alerts from the P2P network. */
@@ -189,11 +189,6 @@ static const unsigned int DEFAULT_CHECKLEVEL = 3;
// Setting the target to > than 550MB will make it likely we can respect the target.
static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
-/** Register with a network node to receive its signals */
-void RegisterNodeSignals(CNodeSignals& nodeSignals);
-/** Unregister a network node */
-void UnregisterNodeSignals(CNodeSignals& nodeSignals);
-
/**
* Process an incoming block. This only returns after the best known valid
* block is made active. Note that it does not, however, guarantee that the
@@ -206,7 +201,7 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals);
* @param[out] dbp The already known disk position of pblock, or NULL if not yet stored.
* @return True if state.IsValid()
*/
-bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, CConnman* connman);
+bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp);
/** Check whether enough disk space is available for an incoming block */
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0);
/** Open a block file (blk?????.dat) */
@@ -223,15 +218,6 @@ bool InitBlockIndex(const CChainParams& chainparams);
bool LoadBlockIndex();
/** Unload database information */
void UnloadBlockIndex();
-/** Process protocol messages received from a given node */
-bool ProcessMessages(CNode* pfrom, CConnman& connman);
-/**
- * Send queued protocol messages to be sent to a give node.
- *
- * @param[in] pto The node which we are sending messages to.
- * @param[in] connman The connection manager for that node.
- */
-bool SendMessages(CNode* pto, CConnman& connman);
/** Run an instance of the script checking thread */
void ThreadScriptCheck();
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
@@ -247,7 +233,7 @@ std::string GetWarnings(const std::string& strFor);
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
bool GetTransaction(const uint256 &hash, CTransaction &tx, const Consensus::Params& params, uint256 &hashBlock, bool fAllowSlow = false);
/** Find the best known block, and make it the tip of the block chain */
-bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, const CBlock* pblock = NULL, CConnman* connman = NULL);
+bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, const CBlock* pblock = NULL);
double ConvertBitsToDouble(unsigned int nBits);
CAmount GetBlockSubsidy(int nBits, int nHeight, const Consensus::Params& consensusParams, bool fSuperblockPartOnly = false);
@@ -277,10 +263,6 @@ void UnlinkPrunedFiles(std::set& setFilesToPrune);
/** Create a new block index entry for a given block hash */
CBlockIndex * InsertBlockIndex(uint256 hash);
-/** Get statistics from node state */
-bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats);
-/** Increase a node's misbehavior score. */
-void Misbehaving(NodeId nodeid, int howmuch);
/** Flush all state, indexes and buffers to disk. */
void FlushStateToDisk();
/** Prune block files and flush state to disk. */
@@ -301,13 +283,6 @@ std::string FormatStateMessage(const CValidationState &state);
/** Get the BIP9 state for a given deployment at the current tip. */
ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::DeploymentPos pos);
-struct CNodeStateStats {
- int nMisbehavior;
- int nSyncHeight;
- int nCommonHeight;
- std::vector vHeightInFlight;
-};
-
struct CTimestampIndexIteratorKey {
unsigned int timestamp;
@@ -863,4 +838,45 @@ static const unsigned int REJECT_ALREADY_KNOWN = 0x101;
/** Transaction conflicts with a transaction already known */
static const unsigned int REJECT_CONFLICT = 0x102;
+// The following things handle network-processing logic
+// (and should be moved to a separate file)
+
+/** Register with a network node to receive its signals */
+void RegisterNodeSignals(CNodeSignals& nodeSignals);
+/** Unregister a network node */
+void UnregisterNodeSignals(CNodeSignals& nodeSignals);
+
+class PeerLogicValidation : public CValidationInterface {
+private:
+ CConnman* connman;
+
+public:
+ PeerLogicValidation(CConnman* connmanIn) : connman(connmanIn) {}
+
+ virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload);
+ virtual void BlockChecked(const CBlock& block, const CValidationState& state);
+};
+
+struct CNodeStateStats {
+ int nMisbehavior;
+ int nSyncHeight;
+ int nCommonHeight;
+ std::vector vHeightInFlight;
+};
+
+/** Get statistics from node state */
+bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats);
+/** Increase a node's misbehavior score. */
+void Misbehaving(NodeId nodeid, int howmuch);
+
+/** Process protocol messages received from a given node */
+bool ProcessMessages(CNode* pfrom, CConnman& connman);
+/**
+ * Send queued protocol messages to be sent to a give node.
+ *
+ * @param[in] pto The node which we are sending messages to.
+ * @param[in] connman The connection manager for that node.
+ */
+bool SendMessages(CNode* pto, CConnman& connman);
+
#endif // BITCOIN_MAIN_H
diff --git a/src/miner.cpp b/src/miner.cpp
index 468640467c82b..9dbc8c3f28262 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -376,7 +376,7 @@ void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned
// }
//}
-static bool ProcessBlockFound(const CBlock* pblock, const CChainParams& chainparams, CConnman* connman)
+static bool ProcessBlockFound(const CBlock* pblock, const CChainParams& chainparams)
{
LogPrintf("%s\n", pblock->ToString());
LogPrintf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue));
@@ -393,7 +393,7 @@ static bool ProcessBlockFound(const CBlock* pblock, const CChainParams& chainpar
// Process this block the same as if we had received it from another node
CValidationState state;
- if (!ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL, connman))
+ if (!ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL))
return error("ProcessBlockFound -- ProcessNewBlock() failed, block not accepted");
return true;
@@ -468,7 +468,7 @@ void static BitcoinMiner(const CChainParams& chainparams, CConnman& connman)
// Found a solution
SetThreadPriority(THREAD_PRIORITY_NORMAL);
LogPrintf("DashMiner:\n proof-of-work found\n hash: %s\n target: %s\n", hash.GetHex(), hashTarget.GetHex());
- ProcessBlockFound(pblock, chainparams, &connman);
+ ProcessBlockFound(pblock, chainparams);
SetThreadPriority(THREAD_PRIORITY_LOWEST);
coinbaseScript->KeepScript();
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 5a712a4e6ac7c..bafebb0d3cb64 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1007,7 +1007,7 @@ UniValue invalidateblock(const UniValue& params, bool fHelp)
}
if (state.IsValid()) {
- ActivateBestChain(state, Params(), NULL, g_connman.get());
+ ActivateBestChain(state, Params(), NULL);
}
if (!state.IsValid()) {
@@ -1046,7 +1046,7 @@ UniValue reconsiderblock(const UniValue& params, bool fHelp)
}
if (state.IsValid()) {
- ActivateBestChain(state, Params(), NULL, g_connman.get());
+ ActivateBestChain(state, Params(), NULL);
}
if (!state.IsValid()) {
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 53661d0bbaf53..d00c8366c98a0 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -178,7 +178,7 @@ UniValue generate(const UniValue& params, bool fHelp)
++pblock->nNonce;
}
CValidationState state;
- if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL, g_connman.get()))
+ if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL))
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
++nHeight;
blockHashes.push_back(pblock->GetHash().GetHex());
@@ -797,7 +797,7 @@ UniValue submitblock(const UniValue& params, bool fHelp)
CValidationState state;
submitblock_StateCatcher sc(block.GetHash());
RegisterValidationInterface(&sc);
- bool fAccepted = ProcessNewBlock(state, Params(), NULL, &block, true, NULL, g_connman.get());
+ bool fAccepted = ProcessNewBlock(state, Params(), NULL, &block, true, NULL);
UnregisterValidationInterface(&sc);
if (fBlockPresent)
{
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index b583215a93420..4ccde505cab5a 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -118,7 +118,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
pblock->nNonce = blockinfo[i].nonce;
CValidationState state;
- BOOST_CHECK(ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL, connman));
+ BOOST_CHECK(ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL));
BOOST_CHECK(state.IsValid());
pblock->hashPrevBlock = pblock->GetHash();
}
diff --git a/src/test/test_dash.cpp b/src/test/test_dash.cpp
index e52257934a248..af06f8485cf3b 100644
--- a/src/test/test_dash.cpp
+++ b/src/test/test_dash.cpp
@@ -136,7 +136,7 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector&
while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
CValidationState state;
- ProcessNewBlock(state, chainparams, NULL, &block, true, NULL, connman);
+ ProcessNewBlock(state, chainparams, NULL, &block, true, NULL);
CBlock result = block;
delete pblocktemplate;
diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp
index 1ae2705caa865..46454c8da141f 100644
--- a/src/validationinterface.cpp
+++ b/src/validationinterface.cpp
@@ -13,7 +13,7 @@ CMainSignals& GetMainSignals()
}
void RegisterValidationInterface(CValidationInterface* pwalletIn) {
- g_signals.UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1));
+ g_signals.UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3));
g_signals.SyncTransaction.connect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2));
g_signals.NotifyTransactionLock.connect(boost::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, _1));
g_signals.UpdatedTransaction.connect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1));
@@ -35,7 +35,7 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.UpdatedTransaction.disconnect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1));
g_signals.NotifyTransactionLock.disconnect(boost::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, _1));
g_signals.SyncTransaction.disconnect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2));
- g_signals.UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1));
+ g_signals.UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3));
}
void UnregisterAllValidationInterfaces() {
@@ -50,7 +50,3 @@ void UnregisterAllValidationInterfaces() {
g_signals.SyncTransaction.disconnect_all_slots();
g_signals.UpdatedBlockTip.disconnect_all_slots();
}
-
-void SyncWithWallets(const CTransaction &tx, const CBlock *pblock) {
- g_signals.SyncTransaction(tx, pblock);
-}
diff --git a/src/validationinterface.h b/src/validationinterface.h
index e20c3d61452a9..c373f515d1e48 100644
--- a/src/validationinterface.h
+++ b/src/validationinterface.h
@@ -27,12 +27,10 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn);
void UnregisterValidationInterface(CValidationInterface* pwalletIn);
/** Unregister all wallets from core */
void UnregisterAllValidationInterfaces();
-/** Push an updated transaction to all registered wallets */
-void SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL);
class CValidationInterface {
protected:
- virtual void UpdatedBlockTip(const CBlockIndex *pindex) {}
+ virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {}
virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock) {}
virtual void NotifyTransactionLock(const CTransaction &tx) {}
virtual void SetBestChain(const CBlockLocator &locator) {}
@@ -49,7 +47,7 @@ class CValidationInterface {
struct CMainSignals {
/** Notifies listeners of updated block chain tip */
- boost::signals2::signal UpdatedBlockTip;
+ boost::signals2::signal UpdatedBlockTip;
/** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */
boost::signals2::signal SyncTransaction;
/** Notifies listeners of an updated transaction lock without new data. */
diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp
index b99b4293080ae..a83085bfb848c 100644
--- a/src/zmq/zmqnotificationinterface.cpp
+++ b/src/zmq/zmqnotificationinterface.cpp
@@ -126,12 +126,15 @@ void CZMQNotificationInterface::Shutdown()
}
}
-void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindex)
+void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
{
+ if (fInitialDownload || pindexNew == pindexFork) // In IBD or blocks were disconnected without any new ones
+ return;
+
for (std::list::iterator i = notifiers.begin(); i!=notifiers.end(); )
{
CZMQAbstractNotifier *notifier = *i;
- if (notifier->NotifyBlock(pindex))
+ if (notifier->NotifyBlock(pindexNew))
{
i++;
}
diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h
index 11d4db83dd4b6..424d7c30e067e 100644
--- a/src/zmq/zmqnotificationinterface.h
+++ b/src/zmq/zmqnotificationinterface.h
@@ -25,7 +25,7 @@ class CZMQNotificationInterface : public CValidationInterface
// CValidationInterface
void SyncTransaction(const CTransaction &tx, const CBlock *pblock);
- void UpdatedBlockTip(const CBlockIndex *pindex);
+ void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload);
void NotifyTransactionLock(const CTransaction &tx);
private: