-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Decouple peer-processing-logic from block-connection-logic #8865
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
void InitPeerLogic(CConnman& connman) { | ||
if (mapPeerLogics.count(&connman)) | ||
return; | ||
mapPeerLogics.emplace(std::make_pair(&connman, std::unique_ptr<PeerLogicValidation>(new PeerLogicValidation(&connman)))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: don't make_pair with emplace, just use the components directly.
} | ||
} | ||
}; | ||
std::map<CConnman*, std::unique_ptr<PeerLogicValidation> > mapPeerLogics; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a ptr for the index feels kinda icky. Since a reference is passed and stored anyway, let's add an Id to CConnman instead. It'll be helpful in other places too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I feel like that is a layer violation? If CConnman is a low-level network socket/connection manager, it should have little knowledge of the fact that there is something hooked up above it to listen to validation callbacks and do things with them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I meant: add a GetID() to CConnman, which would return a const value set during construction. That would allow maps to be created which refer to specific connman instances without tying them to a pointer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we're overengineering? Are we ever really gonna have more than one CConnman? Maybe something without even a map is simpler?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm hoping to be able to hook up 2 CConnmans to eachother in the future for testing against eachother, yes. I've gone to significant efforts to remove the "stuff a static global somewhere" practice from much of the net code, please don't start reintroducing.
A pointer is fine here if you'd prefer to keep it simple, we can adapt later if needed.
} | ||
} | ||
if (it != mapBlockSource.end()) | ||
mapBlockSource.erase(it); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, were these not erased before in the invalid case?
Concept ACK and quick code-review ACK other than the nits. I'd like to spend some time testing, though. |
No? I think after this patch set the only place mapBlockSource is erased from is this line. On October 3, 2016 8:26:53 PM EDT, Cory Fields notifications@github.com wrote:
|
I was just pointing out that this looks to be a memleak bugfix :) |
I dont believe it is actually any (much?) different than it used to be. Maybe it will be deleted more often on reorgs now, I didnt investigate fully. In any case, its pretty hard to DoS since you only add to the map after AcceptBlock succeeds (ie the block is syntactically valid/connects/has valid PoW) |
Switched g_connman to be a shared_ptr instead of a unique_ptr, which I think should neatly address all the outstanding nits. |
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.
7366465
to
8cbd3c2
Compare
Backed out the shared_ptr change, I misunderstood @theuni's comments, just fixed the make_pair nit and left everything else as-is: it should be easier to clean up things like class design once everything is split out. |
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.
8cbd3c2
to
a9aec5c
Compare
Restructured the code after discussion on IRC with @theuni...now the CValidationInterface subclass is defined in main.h (requires an extra include, but we can drop that when we move all the stuff to another file) and init.cpp itself does the object initialization and keeps the CValidationInterface around. |
utACK a9aec5c |
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)
connman->ForEachNode([nNewHeight, nBlockEstimate, &vHashes](CNode* pnode) { | ||
if (nNewHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) { | ||
connman->ForEachNode([nNewHeight, &vHashes](CNode* pnode) { | ||
if (nNewHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 0)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If pnode->nStartingHeight is -1, we just haven't completed the version handshake, no? Shouldn't we always refuse to relay in that case?
Or am I not seeing some other way this can happen?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, probably, though that would be a behavior change whereas this PR shouldnt have any :p.
@@ -50,6 +48,8 @@ class CValidationInterface { | |||
struct CMainSignals { | |||
/** Notifies listeners of updated block chain tip */ | |||
boost::signals2::signal<void (const CBlockIndex *, const CBlockIndex *, bool fInitialDownload)> UpdatedBlockTip; | |||
/** A posInBlock value for SyncTransaction which indicates the transaction was conflicted, disconnected, or not in a block */ | |||
static const int SYNC_TRANSACTION_NOT_IN_BLOCK = -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine for now, but I think we ultimately want these split up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, I think medium-term we need to think hard about what goes in what signaling interface (we have two already that are highly duplicative, I have some thoughts but we should discuss)
post-merge utACK. |
} | ||
// 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)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic of this line is confusing now... If pnode->nStartingHeight = -1 then don't do (if nNewHeight > -1) but instead do (if nNewHeight > 0)?! It hardly makes any difference, it will return true, therefore simply do if (nNewHeight > pnode->nStartingHeight - 2000) without any need for the ? operator.
Anyway, why make it always true and not make use of the nBlocksEstimate as was previously done?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in #8958
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See the earlier commit: "Remove duplicate nBlocksEstimate cmp (we already checked IsIBD())".
Posthummus utACK. |
InitialBlockDownload upstream changes Cherry-picked from the following upstream PRs: - bitcoin/bitcoin#7208 - bitcoin/bitcoin#8007 - bitcoin/bitcoin#9053 - Excluding second commit (requires bitcoin/bitcoin#8865) - bitcoin/bitcoin#10388
InitialBlockDownload upstream changes Cherry-picked from the following upstream PRs: - bitcoin/bitcoin#7208 - bitcoin/bitcoin#8007 - bitcoin/bitcoin#9053 - Excluding second commit (requires bitcoin/bitcoin#8865) - bitcoin/bitcoin#10388
InitialBlockDownload upstream changes Cherry-picked from the following upstream PRs: - bitcoin/bitcoin#7208 - bitcoin/bitcoin#8007 - bitcoin/bitcoin#9053 - Excluding second commit (requires bitcoin/bitcoin#8865) - bitcoin/bitcoin#10388
…n logic 94cc49f Move nTimeBestReceived updating into net processing code (Matt Corallo) d2029cd Move all calls to CheckBlockIndex out of net-processing logic (random-zebra) 44b2f68 Remove network state wipe from UnloadBlockIndex. (Matt Corallo) 0b9b4e2 Move MarkBlockAsReceived out of ProcessNewBlock (random-zebra) b093584 Move FlushStateToDisk call out of ProcessMessages::TX into ATMP (Matt Corallo) 5c4e7c6 Use BlockChecked signal to send reject messages from mapBlockSource (Matt Corallo) 14af52a Always call UpdatedBlockTip, even if blocks were only disconnected (Matt Corallo) 3982e0e Remove CConnman parameter from ProcessNewBlock/ActivateBestChain (Matt Corallo) 48ee837 [Refactoring] Set connman best height in UpdatedBlockTip (random-zebra) 3137b55 Use CValidationInterface from chain logic to notify peer logic (random-zebra) 69ef798 Move net-processing logic definitions together in main.h (Matt Corallo) cc51897 Remove duplicate nBlocksEstimate cmp (we already checked IsIBD()) (Matt Corallo) 625acdd [Cleanup] Remove unused signals/functions in validation interface (random-zebra) ab94b70 Make validationinterface.UpdatedBlockTip more verbose (Matt Corallo) Pull request description: Backports bitcoin#8865 and bitcoin#8969, in preparation for the long-awaited net_processing/validation split. ACKs for top commit: Fuzzbawls: ACK 94cc49f furszy: Looking good, ACK 94cc49f and merging.. Tree-SHA512: 5e17f9f018d1d1898bce77baefa0b614aaa59b883fbca3f851603208ed93d3a66141cd54f6faaa0bfbef24a6dbefcb16a55dc260f27d2c5ecd4c3f8297fd4e76
This is part of a series of about 20 commits which split main.cpp into two - peer processing logic and blockchain/mempool/UTXO logic. Most of them arent much more intrusive than these, at least until there are large blocks of code moving.
This set focuses primarily on using CValidationinterface to handle peer-processing-logic updates when connecting/disconnecting blocks.
I haven't significantly tested this as my normal test machine is largely unavailable atm, but most of the changes here are pretty straight-forward.