mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-21 07:39:08 +01:00
Merge #8865: Decouple peer-processing-logic from block-connection-logic
a9aec5cUse BlockChecked signal to send reject messages from mapBlockSource (Matt Corallo)7565e03Remove SyncWithWallets wrapper function (Matt Corallo)12ee1feAlways call UpdatedBlockTip, even if blocks were only disconnected (Matt Corallo)f5efa28Remove CConnman parameter from ProcessNewBlock/ActivateBestChain (Matt Corallo)fef1010Use CValidationInterface from chain logic to notify peer logic (Matt Corallo)aefcb7bMove net-processing logic definitions together in main.h (Matt Corallo)0278fb5Remove duplicate nBlocksEstimate cmp (we already checked IsIBD()) (Matt Corallo)87e7d72Make validationinterface.UpdatedBlockTip more verbose (Matt Corallo)
This commit is contained in:
122
src/main.cpp
122
src/main.cpp
@@ -1567,7 +1567,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
|
||||
}
|
||||
}
|
||||
|
||||
SyncWithWallets(tx, NULL);
|
||||
GetMainSignals().SyncTransaction(tx, NULL, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1882,17 +1882,6 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
|
||||
}
|
||||
|
||||
void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) {
|
||||
int nDoS = 0;
|
||||
if (state.IsInvalid(nDoS)) {
|
||||
std::map<uint256, NodeId>::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);
|
||||
@@ -2800,7 +2789,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara
|
||||
// Let wallets know transactions went from 1-confirmed to
|
||||
// 0-confirmed or conflicted:
|
||||
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
|
||||
SyncWithWallets(tx, pindexDelete->pprev);
|
||||
GetMainSignals().SyncTransaction(tx, pindexDelete->pprev, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -2839,7 +2828,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());
|
||||
@@ -3038,7 +3026,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;
|
||||
std::vector<std::tuple<CTransaction,CBlockIndex*,int>> txChanged;
|
||||
@@ -3053,7 +3041,6 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
|
||||
const CBlockIndex *pindexFork;
|
||||
std::list<CTransaction> txConflicted;
|
||||
bool fInitialDownload;
|
||||
int nNewHeight;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
CBlockIndex *pindexOldTip = chainActive.Tip();
|
||||
@@ -3076,59 +3063,27 @@ 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(nNewHeight);
|
||||
|
||||
// throw all transactions though the signal-interface
|
||||
// while _not_ holding the cs_main lock
|
||||
BOOST_FOREACH(const CTransaction &tx, txConflicted)
|
||||
{
|
||||
SyncWithWallets(tx, pindexNewTip);
|
||||
GetMainSignals().SyncTransaction(tx, pindexNewTip, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK);
|
||||
}
|
||||
// ... and about transactions that got confirmed:
|
||||
for(unsigned int i = 0; i < txChanged.size(); i++)
|
||||
SyncWithWallets(std::get<0>(txChanged[i]), std::get<1>(txChanged[i]), std::get<2>(txChanged[i]));
|
||||
GetMainSignals().SyncTransaction(std::get<0>(txChanged[i]), std::get<1>(txChanged[i]), std::get<2>(txChanged[i]));
|
||||
|
||||
// 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<uint256> 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());
|
||||
@@ -3787,7 +3742,7 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha
|
||||
return true;
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -3809,7 +3764,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__);
|
||||
|
||||
return true;
|
||||
@@ -4742,6 +4697,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<uint256> 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<uint256, NodeId>::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
|
||||
@@ -5845,7 +5853,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||
pfrom->PushMessage(NetMsgType::GETDATA, invs);
|
||||
} else {
|
||||
CValidationState state;
|
||||
ProcessNewBlock(state, chainparams, pfrom, &block, false, NULL, &connman);
|
||||
ProcessNewBlock(state, chainparams, pfrom, &block, false, NULL);
|
||||
int nDoS;
|
||||
if (state.IsInvalid(nDoS)) {
|
||||
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,
|
||||
// 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
|
||||
|
||||
Reference in New Issue
Block a user