Changeset View
Changeset View
Standalone View
Standalone View
src/net_processing.cpp
Show First 20 Lines • Show All 1,244 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
void static ProcessGetBlockData(const Config &config, CNode *pfrom, | void static ProcessGetBlockData(const Config &config, CNode *pfrom, | ||||
const CInv &inv, CConnman *connman, | const CInv &inv, CConnman *connman, | ||||
const std::atomic<bool> &interruptMsgProc) { | const std::atomic<bool> &interruptMsgProc) { | ||||
const Consensus::Params &consensusParams = | const Consensus::Params &consensusParams = | ||||
config.GetChainParams().GetConsensus(); | config.GetChainParams().GetConsensus(); | ||||
LOCK(cs_main); | |||||
bool send = false; | bool send = false; | ||||
std::shared_ptr<const CBlock> a_recent_block; | std::shared_ptr<const CBlock> a_recent_block; | ||||
std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block; | std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block; | ||||
{ | { | ||||
LOCK(cs_most_recent_block); | LOCK(cs_most_recent_block); | ||||
a_recent_block = most_recent_block; | a_recent_block = most_recent_block; | ||||
a_recent_compact_block = most_recent_compact_block; | a_recent_compact_block = most_recent_compact_block; | ||||
} | } | ||||
bool need_activate_chain = false; | |||||
{ | { | ||||
LOCK(cs_main); | |||||
BlockMap::iterator mi = mapBlockIndex.find(inv.hash); | BlockMap::iterator mi = mapBlockIndex.find(inv.hash); | ||||
if (mi != mapBlockIndex.end()) { | if (mi != mapBlockIndex.end()) { | ||||
if (mi->second->nChainTx && | if (mi->second->nChainTx && | ||||
!mi->second->IsValid(BlockValidity::SCRIPTS) && | !mi->second->IsValid(BlockValidity::SCRIPTS) && | ||||
mi->second->IsValid(BlockValidity::TREE)) { | mi->second->IsValid(BlockValidity::TREE)) { | ||||
// If we have the block and all of its parents, but have | // If we have the block and all of its parents, but have | ||||
// not yet validated it, we might be in the middle of | // not yet validated it, we might be in the middle of | ||||
// connecting it (ie in the unlock of cs_main before | // connecting it (ie in the unlock of cs_main before | ||||
// ActivateBestChain but after AcceptBlock). In this | // ActivateBestChain but after AcceptBlock). In this | ||||
// case, we need to run ActivateBestChain prior to | // case, we need to run ActivateBestChain prior to | ||||
// checking the relay conditions below. | // checking the relay conditions below. | ||||
CValidationState dummy; | need_activate_chain = true; | ||||
ActivateBestChain(config, dummy, a_recent_block); | |||||
} | } | ||||
} | } | ||||
} // release cs_main before calling ActivateBestChain | |||||
if (need_activate_chain) { | |||||
CValidationState dummy; | |||||
ActivateBestChain(config, dummy, a_recent_block); | |||||
} | } | ||||
LOCK(cs_main); | |||||
BlockMap::iterator mi = mapBlockIndex.find(inv.hash); | BlockMap::iterator mi = mapBlockIndex.find(inv.hash); | ||||
if (mi != mapBlockIndex.end()) { | if (mi != mapBlockIndex.end()) { | ||||
send = BlockRequestAllowed(mi->second, consensusParams); | send = BlockRequestAllowed(mi->second, consensusParams); | ||||
if (!send) { | if (!send) { | ||||
LogPrint(BCLog::NET, | LogPrint(BCLog::NET, | ||||
"%s: ignoring request from peer=%i for old " | "%s: ignoring request from peer=%i for old " | ||||
"block that isn't in the main chain\n", | "block that isn't in the main chain\n", | ||||
__func__, pfrom->GetId()); | __func__, pfrom->GetId()); | ||||
▲ Show 20 Lines • Show All 120 Lines • ▼ Show 20 Lines | if (send && (mi->second->nStatus.hasData())) { | ||||
pfrom->hashContinue.SetNull(); | pfrom->hashContinue.SetNull(); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
static void ProcessGetData(const Config &config, CNode *pfrom, | static void ProcessGetData(const Config &config, CNode *pfrom, | ||||
CConnman *connman, | CConnman *connman, | ||||
const std::atomic<bool> &interruptMsgProc) { | const std::atomic<bool> &interruptMsgProc) { | ||||
AssertLockNotHeld(cs_main); | |||||
std::deque<CInv>::iterator it = pfrom->vRecvGetData.begin(); | std::deque<CInv>::iterator it = pfrom->vRecvGetData.begin(); | ||||
std::vector<CInv> vNotFound; | std::vector<CInv> vNotFound; | ||||
const CNetMsgMaker msgMaker(pfrom->GetSendVersion()); | const CNetMsgMaker msgMaker(pfrom->GetSendVersion()); | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
while (it != pfrom->vRecvGetData.end() && it->type == MSG_TX) { | while (it != pfrom->vRecvGetData.end() && it->type == MSG_TX) { | ||||
if (interruptMsgProc) { | if (interruptMsgProc) { | ||||
Show All 30 Lines | const CNetMsgMaker msgMaker(pfrom->GetSendVersion()); | ||||
} | } | ||||
if (!push) { | if (!push) { | ||||
vNotFound.push_back(inv); | vNotFound.push_back(inv); | ||||
} | } | ||||
// Track requests for our stuff. | // Track requests for our stuff. | ||||
GetMainSignals().Inventory(inv.hash); | GetMainSignals().Inventory(inv.hash); | ||||
} | } | ||||
} // release cs_main | |||||
if (it != pfrom->vRecvGetData.end()) { | if (it != pfrom->vRecvGetData.end()) { | ||||
const CInv &inv = *it; | const CInv &inv = *it; | ||||
it++; | it++; | ||||
if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || | if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || | ||||
inv.type == MSG_CMPCT_BLOCK) { | inv.type == MSG_CMPCT_BLOCK) { | ||||
ProcessGetBlockData(config, pfrom, inv, connman, | ProcessGetBlockData(config, pfrom, inv, connman, interruptMsgProc); | ||||
interruptMsgProc); | |||||
} | } | ||||
} | } | ||||
} // release cs_main | |||||
pfrom->vRecvGetData.erase(pfrom->vRecvGetData.begin(), it); | pfrom->vRecvGetData.erase(pfrom->vRecvGetData.begin(), it); | ||||
if (!vNotFound.empty()) { | if (!vNotFound.empty()) { | ||||
// Let the peer know that we didn't find what it asked for, so it | // Let the peer know that we didn't find what it asked for, so it | ||||
// doesn't have to wait around forever. Currently only SPV clients | // doesn't have to wait around forever. Currently only SPV clients | ||||
// actually care about this message: it's needed when they are | // actually care about this message: it's needed when they are | ||||
// recursively walking the dependencies of relevant unconfirmed | // recursively walking the dependencies of relevant unconfirmed | ||||
▲ Show 20 Lines • Show All 892 Lines • ▼ Show 20 Lines | else if (strCommand == NetMsgType::GETBLOCKTXN) { | ||||
// actually receive all the data read from disk over the network. | // actually receive all the data read from disk over the network. | ||||
LogPrint(BCLog::NET, | LogPrint(BCLog::NET, | ||||
"Peer %d sent us a getblocktxn for a block > %i deep", | "Peer %d sent us a getblocktxn for a block > %i deep", | ||||
pfrom->GetId(), MAX_BLOCKTXN_DEPTH); | pfrom->GetId(), MAX_BLOCKTXN_DEPTH); | ||||
CInv inv; | CInv inv; | ||||
inv.type = MSG_BLOCK; | inv.type = MSG_BLOCK; | ||||
inv.hash = req.blockhash; | inv.hash = req.blockhash; | ||||
pfrom->vRecvGetData.push_back(inv); | pfrom->vRecvGetData.push_back(inv); | ||||
ProcessGetData(config, pfrom, connman, interruptMsgProc); | // The message processing loop will go around again (without | ||||
// pausing) and we'll respond then (without cs_main) | |||||
return true; | return true; | ||||
} | } | ||||
CBlock block; | CBlock block; | ||||
bool ret = ReadBlockFromDisk(block, it->second, config); | bool ret = ReadBlockFromDisk(block, it->second, config); | ||||
assert(ret); | assert(ret); | ||||
SendBlockTransactions(block, req, pfrom, connman); | SendBlockTransactions(block, req, pfrom, connman); | ||||
▲ Show 20 Lines • Show All 1,963 Lines • Show Last 20 Lines |