Skip to content

Commit 05998da

Browse files
committed
Merge #8865: Decouple peer-processing-logic from block-connection-logic
a9aec5c Use BlockChecked signal to send reject messages from mapBlockSource (Matt Corallo) 7565e03 Remove SyncWithWallets wrapper function (Matt Corallo) 12ee1fe Always call UpdatedBlockTip, even if blocks were only disconnected (Matt Corallo) f5efa28 Remove CConnman parameter from ProcessNewBlock/ActivateBestChain (Matt Corallo) fef1010 Use CValidationInterface from chain logic to notify peer logic (Matt Corallo) aefcb7b Move net-processing logic definitions together in main.h (Matt Corallo) 0278fb5 Remove duplicate nBlocksEstimate cmp (we already checked IsIBD()) (Matt Corallo) 87e7d72 Make validationinterface.UpdatedBlockTip more verbose (Matt Corallo)
2 parents 23e03f8 + a9aec5c commit 05998da

11 files changed

+132
-104
lines changed

src/init.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ static const bool DEFAULT_DISABLE_SAFEMODE = false;
7272
static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
7373

7474
std::unique_ptr<CConnman> g_connman;
75+
std::unique_ptr<PeerLogicValidation> peerLogic;
7576

7677
#if ENABLE_ZMQ
7778
static CZMQNotificationInterface* pzmqNotificationInterface = NULL;
@@ -200,6 +201,8 @@ void Shutdown()
200201
pwalletMain->Flush(false);
201202
#endif
202203
MapPort(false);
204+
UnregisterValidationInterface(peerLogic.get());
205+
peerLogic.reset();
203206
g_connman.reset();
204207

205208
StopTorControl();
@@ -1102,6 +1105,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
11021105
g_connman = std::unique_ptr<CConnman>(new CConnman(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max())));
11031106
CConnman& connman = *g_connman;
11041107

1108+
peerLogic.reset(new PeerLogicValidation(&connman));
1109+
RegisterValidationInterface(peerLogic.get());
11051110
RegisterNodeSignals(GetNodeSignals());
11061111

11071112
// sanitize comments per BIP-0014, format user agent and check total size

src/main.cpp

Lines changed: 65 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,7 +1567,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
15671567
}
15681568
}
15691569

1570-
SyncWithWallets(tx, NULL);
1570+
GetMainSignals().SyncTransaction(tx, NULL, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK);
15711571

15721572
return true;
15731573
}
@@ -1882,17 +1882,6 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
18821882
}
18831883

18841884
void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) {
1885-
int nDoS = 0;
1886-
if (state.IsInvalid(nDoS)) {
1887-
std::map<uint256, NodeId>::iterator it = mapBlockSource.find(pindex->GetBlockHash());
1888-
if (it != mapBlockSource.end() && State(it->second)) {
1889-
assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
1890-
CBlockReject reject = {(unsigned char)state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), pindex->GetBlockHash()};
1891-
State(it->second)->rejects.push_back(reject);
1892-
if (nDoS > 0)
1893-
Misbehaving(it->second, nDoS);
1894-
}
1895-
}
18961885
if (!state.CorruptionPossible()) {
18971886
pindex->nStatus |= BLOCK_FAILED_VALID;
18981887
setDirtyBlockIndex.insert(pindex);
@@ -2800,7 +2789,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara
28002789
// Let wallets know transactions went from 1-confirmed to
28012790
// 0-confirmed or conflicted:
28022791
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
2803-
SyncWithWallets(tx, pindexDelete->pprev);
2792+
GetMainSignals().SyncTransaction(tx, pindexDelete->pprev, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK);
28042793
}
28052794
return true;
28062795
}
@@ -2839,7 +2828,6 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
28392828
InvalidBlockFound(pindexNew, state);
28402829
return error("ConnectTip(): ConnectBlock %s failed", pindexNew->GetBlockHash().ToString());
28412830
}
2842-
mapBlockSource.erase(pindexNew->GetBlockHash());
28432831
nTime3 = GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2;
28442832
LogPrint("bench", " - Connect total: %.2fms [%.2fs]\n", (nTime3 - nTime2) * 0.001, nTimeConnectTotal * 0.000001);
28452833
assert(view.Flush());
@@ -3038,7 +3026,7 @@ static void NotifyHeaderTip() {
30383026
* or an activated best chain. pblock is either NULL or a pointer to a block
30393027
* that is already loaded (to avoid loading it again from disk).
30403028
*/
3041-
bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, const CBlock *pblock, CConnman* connman) {
3029+
bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, const CBlock *pblock) {
30423030
CBlockIndex *pindexMostWork = NULL;
30433031
CBlockIndex *pindexNewTip = NULL;
30443032
std::vector<std::tuple<CTransaction,CBlockIndex*,int>> txChanged;
@@ -3053,7 +3041,6 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
30533041
const CBlockIndex *pindexFork;
30543042
std::list<CTransaction> txConflicted;
30553043
bool fInitialDownload;
3056-
int nNewHeight;
30573044
{
30583045
LOCK(cs_main);
30593046
CBlockIndex *pindexOldTip = chainActive.Tip();
@@ -3076,59 +3063,27 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
30763063
pindexNewTip = chainActive.Tip();
30773064
pindexFork = chainActive.FindFork(pindexOldTip);
30783065
fInitialDownload = IsInitialBlockDownload();
3079-
nNewHeight = chainActive.Height();
30803066
}
30813067
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
30823068

30833069
// Notifications/callbacks that can run without cs_main
3084-
if(connman)
3085-
connman->SetBestHeight(nNewHeight);
30863070

30873071
// throw all transactions though the signal-interface
30883072
// while _not_ holding the cs_main lock
30893073
BOOST_FOREACH(const CTransaction &tx, txConflicted)
30903074
{
3091-
SyncWithWallets(tx, pindexNewTip);
3075+
GetMainSignals().SyncTransaction(tx, pindexNewTip, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK);
30923076
}
30933077
// ... and about transactions that got confirmed:
30943078
for(unsigned int i = 0; i < txChanged.size(); i++)
3095-
SyncWithWallets(std::get<0>(txChanged[i]), std::get<1>(txChanged[i]), std::get<2>(txChanged[i]));
3079+
GetMainSignals().SyncTransaction(std::get<0>(txChanged[i]), std::get<1>(txChanged[i]), std::get<2>(txChanged[i]));
3080+
3081+
// Notify external listeners about the new tip.
3082+
GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload);
30963083

30973084
// Always notify the UI if a new block tip was connected
30983085
if (pindexFork != pindexNewTip) {
30993086
uiInterface.NotifyBlockTip(fInitialDownload, pindexNewTip);
3100-
3101-
if (!fInitialDownload) {
3102-
// Find the hashes of all blocks that weren't previously in the best chain.
3103-
std::vector<uint256> vHashes;
3104-
CBlockIndex *pindexToAnnounce = pindexNewTip;
3105-
while (pindexToAnnounce != pindexFork) {
3106-
vHashes.push_back(pindexToAnnounce->GetBlockHash());
3107-
pindexToAnnounce = pindexToAnnounce->pprev;
3108-
if (vHashes.size() == MAX_BLOCKS_TO_ANNOUNCE) {
3109-
// Limit announcements in case of a huge reorganization.
3110-
// Rely on the peer's synchronization mechanism in that case.
3111-
break;
3112-
}
3113-
}
3114-
// Relay inventory, but don't relay old inventory during initial block download.
3115-
int nBlockEstimate = 0;
3116-
if (fCheckpointsEnabled)
3117-
nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints());
3118-
if(connman) {
3119-
connman->ForEachNode([nNewHeight, nBlockEstimate, &vHashes](CNode* pnode) {
3120-
if (nNewHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) {
3121-
BOOST_REVERSE_FOREACH(const uint256& hash, vHashes) {
3122-
pnode->PushBlockHash(hash);
3123-
}
3124-
}
3125-
});
3126-
}
3127-
// Notify external listeners about the new tip.
3128-
if (!vHashes.empty()) {
3129-
GetMainSignals().UpdatedBlockTip(pindexNewTip);
3130-
}
3131-
}
31323087
}
31333088
} while (pindexNewTip != pindexMostWork);
31343089
CheckBlockIndex(chainparams.GetConsensus());
@@ -3787,7 +3742,7 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha
37873742
return true;
37883743
}
37893744

3790-
bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, CConnman* connman)
3745+
bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp)
37913746
{
37923747
{
37933748
LOCK(cs_main);
@@ -3809,7 +3764,7 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, C
38093764

38103765
NotifyHeaderTip();
38113766

3812-
if (!ActivateBestChain(state, chainparams, pblock, connman))
3767+
if (!ActivateBestChain(state, chainparams, pblock))
38133768
return error("%s: ActivateBestChain failed", __func__);
38143769

38153770
return true;
@@ -4742,6 +4697,59 @@ std::string GetWarnings(const std::string& strFor)
47424697

47434698

47444699

4700+
//////////////////////////////////////////////////////////////////////////////
4701+
//
4702+
// blockchain -> download logic notification
4703+
//
4704+
4705+
void PeerLogicValidation::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {
4706+
const int nNewHeight = pindexNew->nHeight;
4707+
connman->SetBestHeight(nNewHeight);
4708+
4709+
if (!fInitialDownload) {
4710+
// Find the hashes of all blocks that weren't previously in the best chain.
4711+
std::vector<uint256> vHashes;
4712+
const CBlockIndex *pindexToAnnounce = pindexNew;
4713+
while (pindexToAnnounce != pindexFork) {
4714+
vHashes.push_back(pindexToAnnounce->GetBlockHash());
4715+
pindexToAnnounce = pindexToAnnounce->pprev;
4716+
if (vHashes.size() == MAX_BLOCKS_TO_ANNOUNCE) {
4717+
// Limit announcements in case of a huge reorganization.
4718+
// Rely on the peer's synchronization mechanism in that case.
4719+
break;
4720+
}
4721+
}
4722+
// Relay inventory, but don't relay old inventory during initial block download.
4723+
connman->ForEachNode([nNewHeight, &vHashes](CNode* pnode) {
4724+
if (nNewHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 0)) {
4725+
BOOST_REVERSE_FOREACH(const uint256& hash, vHashes) {
4726+
pnode->PushBlockHash(hash);
4727+
}
4728+
}
4729+
});
4730+
}
4731+
}
4732+
4733+
void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationState& state) {
4734+
LOCK(cs_main);
4735+
4736+
const uint256 hash(block.GetHash());
4737+
std::map<uint256, NodeId>::iterator it = mapBlockSource.find(hash);
4738+
4739+
int nDoS = 0;
4740+
if (state.IsInvalid(nDoS)) {
4741+
if (it != mapBlockSource.end() && State(it->second)) {
4742+
assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
4743+
CBlockReject reject = {(unsigned char)state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), hash};
4744+
State(it->second)->rejects.push_back(reject);
4745+
if (nDoS > 0)
4746+
Misbehaving(it->second, nDoS);
4747+
}
4748+
}
4749+
if (it != mapBlockSource.end())
4750+
mapBlockSource.erase(it);
4751+
}
4752+
47454753
//////////////////////////////////////////////////////////////////////////////
47464754
//
47474755
// Messages
@@ -5845,7 +5853,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
58455853
pfrom->PushMessage(NetMsgType::GETDATA, invs);
58465854
} else {
58475855
CValidationState state;
5848-
ProcessNewBlock(state, chainparams, pfrom, &block, false, NULL, &connman);
5856+
ProcessNewBlock(state, chainparams, pfrom, &block, false, NULL);
58495857
int nDoS;
58505858
if (state.IsInvalid(nDoS)) {
58515859
assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
@@ -6021,7 +6029,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
60216029
// Such an unrequested block may still be processed, subject to the
60226030
// conditions in AcceptBlock().
60236031
bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload();
6024-
ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL, &connman);
6032+
ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL);
60256033
int nDoS;
60266034
if (state.IsInvalid(nDoS)) {
60276035
assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes

src/main.h

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "net.h"
1717
#include "script/script_error.h"
1818
#include "sync.h"
19+
#include "validationinterface.h"
1920
#include "versionbits.h"
2021

2122
#include <algorithm>
@@ -41,7 +42,6 @@ class CValidationInterface;
4142
class CValidationState;
4243

4344
struct PrecomputedTransactionData;
44-
struct CNodeStateStats;
4545
struct LockPoints;
4646

4747
/** Default for DEFAULT_WHITELISTRELAY. */
@@ -211,11 +211,6 @@ static const unsigned int DEFAULT_CHECKLEVEL = 3;
211211
// Setting the target to > than 550MB will make it likely we can respect the target.
212212
static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
213213

214-
/** Register with a network node to receive its signals */
215-
void RegisterNodeSignals(CNodeSignals& nodeSignals);
216-
/** Unregister a network node */
217-
void UnregisterNodeSignals(CNodeSignals& nodeSignals);
218-
219214
/**
220215
* Process an incoming block. This only returns after the best known valid
221216
* block is made active. Note that it does not, however, guarantee that the
@@ -228,7 +223,7 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals);
228223
* @param[out] dbp The already known disk position of pblock, or NULL if not yet stored.
229224
* @return True if state.IsValid()
230225
*/
231-
bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, CConnman* connman);
226+
bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp);
232227
/** Check whether enough disk space is available for an incoming block */
233228
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0);
234229
/** Open a block file (blk?????.dat) */
@@ -245,15 +240,6 @@ bool InitBlockIndex(const CChainParams& chainparams);
245240
bool LoadBlockIndex();
246241
/** Unload database information */
247242
void UnloadBlockIndex();
248-
/** Process protocol messages received from a given node */
249-
bool ProcessMessages(CNode* pfrom, CConnman& connman);
250-
/**
251-
* Send queued protocol messages to be sent to a give node.
252-
*
253-
* @param[in] pto The node which we are sending messages to.
254-
* @param[in] connman The connection manager for that node.
255-
*/
256-
bool SendMessages(CNode* pto, CConnman& connman);
257243
/** Run an instance of the script checking thread */
258244
void ThreadScriptCheck();
259245
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
@@ -269,7 +255,7 @@ std::string GetWarnings(const std::string& strFor);
269255
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
270256
bool GetTransaction(const uint256 &hash, CTransaction &tx, const Consensus::Params& params, uint256 &hashBlock, bool fAllowSlow = false);
271257
/** Find the best known block, and make it the tip of the block chain */
272-
bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, const CBlock* pblock = NULL, CConnman* connman = NULL);
258+
bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, const CBlock* pblock = NULL);
273259
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams);
274260

275261
/**
@@ -296,10 +282,6 @@ void UnlinkPrunedFiles(std::set<int>& setFilesToPrune);
296282

297283
/** Create a new block index entry for a given block hash */
298284
CBlockIndex * InsertBlockIndex(uint256 hash);
299-
/** Get statistics from node state */
300-
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats);
301-
/** Increase a node's misbehavior score. */
302-
void Misbehaving(NodeId nodeid, int howmuch);
303285
/** Flush all state, indexes and buffers to disk. */
304286
void FlushStateToDisk();
305287
/** Prune block files and flush state to disk. */
@@ -315,13 +297,6 @@ std::string FormatStateMessage(const CValidationState &state);
315297
/** Get the BIP9 state for a given deployment at the current tip. */
316298
ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::DeploymentPos pos);
317299

318-
struct CNodeStateStats {
319-
int nMisbehavior;
320-
int nSyncHeight;
321-
int nCommonHeight;
322-
std::vector<int> vHeightInFlight;
323-
};
324-
325300

326301

327302
/**
@@ -553,4 +528,45 @@ static const unsigned int REJECT_ALREADY_KNOWN = 0x101;
553528
/** Transaction conflicts with a transaction already known */
554529
static const unsigned int REJECT_CONFLICT = 0x102;
555530

531+
// The following things handle network-processing logic
532+
// (and should be moved to a separate file)
533+
534+
/** Register with a network node to receive its signals */
535+
void RegisterNodeSignals(CNodeSignals& nodeSignals);
536+
/** Unregister a network node */
537+
void UnregisterNodeSignals(CNodeSignals& nodeSignals);
538+
539+
class PeerLogicValidation : public CValidationInterface {
540+
private:
541+
CConnman* connman;
542+
543+
public:
544+
PeerLogicValidation(CConnman* connmanIn) : connman(connmanIn) {}
545+
546+
virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload);
547+
virtual void BlockChecked(const CBlock& block, const CValidationState& state);
548+
};
549+
550+
struct CNodeStateStats {
551+
int nMisbehavior;
552+
int nSyncHeight;
553+
int nCommonHeight;
554+
std::vector<int> vHeightInFlight;
555+
};
556+
557+
/** Get statistics from node state */
558+
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats);
559+
/** Increase a node's misbehavior score. */
560+
void Misbehaving(NodeId nodeid, int howmuch);
561+
562+
/** Process protocol messages received from a given node */
563+
bool ProcessMessages(CNode* pfrom, CConnman& connman);
564+
/**
565+
* Send queued protocol messages to be sent to a give node.
566+
*
567+
* @param[in] pto The node which we are sending messages to.
568+
* @param[in] connman The connection manager for that node.
569+
*/
570+
bool SendMessages(CNode* pto, CConnman& connman);
571+
556572
#endif // BITCOIN_MAIN_H

src/rpc/blockchain.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,7 +1317,7 @@ UniValue invalidateblock(const UniValue& params, bool fHelp)
13171317
}
13181318

13191319
if (state.IsValid()) {
1320-
ActivateBestChain(state, Params(), NULL, g_connman.get());
1320+
ActivateBestChain(state, Params(), NULL);
13211321
}
13221322

13231323
if (!state.IsValid()) {
@@ -1355,7 +1355,7 @@ UniValue reconsiderblock(const UniValue& params, bool fHelp)
13551355
}
13561356

13571357
CValidationState state;
1358-
ActivateBestChain(state, Params(), NULL, g_connman.get());
1358+
ActivateBestChain(state, Params(), NULL);
13591359

13601360
if (!state.IsValid()) {
13611361
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());

0 commit comments

Comments
 (0)