Changeset View
Changeset View
Standalone View
Standalone View
src/net_processing.cpp
Show First 20 Lines • Show All 1,345 Lines • ▼ Show 20 Lines | if (!vNotFound.empty()) { | ||||
// about (and store and rebroadcast and risk analyze) the dependencies | // about (and store and rebroadcast and risk analyze) the dependencies | ||||
// of transactions relevant to them, without having to download the | // of transactions relevant to them, without having to download the | ||||
// entire memory pool. | // entire memory pool. | ||||
connman.PushMessage(pfrom, | connman.PushMessage(pfrom, | ||||
msgMaker.Make(NetMsgType::NOTFOUND, vNotFound)); | msgMaker.Make(NetMsgType::NOTFOUND, vNotFound)); | ||||
} | } | ||||
} | } | ||||
uint32_t GetFetchFlags(CNode *pfrom, const CBlockIndex *pprev, | |||||
const Consensus::Params &chainparams) { | |||||
uint32_t nFetchFlags = 0; | |||||
return nFetchFlags; | |||||
} | |||||
inline static void SendBlockTransactions(const CBlock &block, | inline static void SendBlockTransactions(const CBlock &block, | ||||
const BlockTransactionsRequest &req, | const BlockTransactionsRequest &req, | ||||
CNode *pfrom, CConnman &connman) { | CNode *pfrom, CConnman &connman) { | ||||
BlockTransactions resp(req); | BlockTransactions resp(req); | ||||
for (size_t i = 0; i < req.indices.size(); i++) { | for (size_t i = 0; i < req.indices.size(); i++) { | ||||
if (req.indices[i] >= block.vtx.size()) { | if (req.indices[i] >= block.vtx.size()) { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
Misbehaving(pfrom, 100, "out-of-bound-tx-index"); | Misbehaving(pfrom, 100, "out-of-bound-tx-index"); | ||||
▲ Show 20 Lines • Show All 395 Lines • ▼ Show 20 Lines | else if (strCommand == NetMsgType::INV) { | ||||
// mode if whitelistrelay is true | // mode if whitelistrelay is true | ||||
if (pfrom->fWhitelisted && | if (pfrom->fWhitelisted && | ||||
gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)) { | gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)) { | ||||
fBlocksOnly = false; | fBlocksOnly = false; | ||||
} | } | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
uint32_t nFetchFlags = | |||||
GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus()); | |||||
std::vector<CInv> vToFetch; | std::vector<CInv> vToFetch; | ||||
for (size_t nInv = 0; nInv < vInv.size(); nInv++) { | for (size_t nInv = 0; nInv < vInv.size(); nInv++) { | ||||
CInv &inv = vInv[nInv]; | CInv &inv = vInv[nInv]; | ||||
if (interruptMsgProc) { | if (interruptMsgProc) { | ||||
return true; | return true; | ||||
} | } | ||||
bool fAlreadyHave = AlreadyHave(inv); | bool fAlreadyHave = AlreadyHave(inv); | ||||
LogPrint(BCLog::NET, "got inv: %s %s peer=%d\n", inv.ToString(), | LogPrint(BCLog::NET, "got inv: %s %s peer=%d\n", inv.ToString(), | ||||
fAlreadyHave ? "have" : "new", pfrom->id); | fAlreadyHave ? "have" : "new", pfrom->id); | ||||
if (inv.type == MSG_TX) { | |||||
inv.type |= nFetchFlags; | |||||
} | |||||
if (inv.type == MSG_BLOCK) { | if (inv.type == MSG_BLOCK) { | ||||
UpdateBlockAvailability(pfrom->GetId(), inv.hash); | UpdateBlockAvailability(pfrom->GetId(), inv.hash); | ||||
if (!fAlreadyHave && !fImporting && !fReindex && | if (!fAlreadyHave && !fImporting && !fReindex && | ||||
!mapBlocksInFlight.count(inv.hash)) { | !mapBlocksInFlight.count(inv.hash)) { | ||||
// We used to request the full block here, but since | // We used to request the full block here, but since | ||||
// headers-announcements are now the primary method of | // headers-announcements are now the primary method of | ||||
// announcement on the network, and since, in the case that | // announcement on the network, and since, in the case that | ||||
// a node fell back to inv we probably have a reorg which we | // a node fell back to inv we probably have a reorg which we | ||||
▲ Show 20 Lines • Show All 356 Lines • ▼ Show 20 Lines | else if (strCommand == NetMsgType::TX) { | ||||
bool fRejectedParents = false; | bool fRejectedParents = false; | ||||
for (const CTxIn &txin : tx.vin) { | for (const CTxIn &txin : tx.vin) { | ||||
if (recentRejects->contains(txin.prevout.GetTxId())) { | if (recentRejects->contains(txin.prevout.GetTxId())) { | ||||
fRejectedParents = true; | fRejectedParents = true; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (!fRejectedParents) { | if (!fRejectedParents) { | ||||
uint32_t nFetchFlags = GetFetchFlags( | |||||
pfrom, chainActive.Tip(), chainparams.GetConsensus()); | |||||
for (const CTxIn &txin : tx.vin) { | for (const CTxIn &txin : tx.vin) { | ||||
CInv _inv(MSG_TX | nFetchFlags, txin.prevout.GetTxId()); | // FIXME: MSG_TX should use a TxHash, not a TxId. | ||||
CInv _inv(MSG_TX, txin.prevout.GetTxId()); | |||||
pfrom->AddInventoryKnown(_inv); | pfrom->AddInventoryKnown(_inv); | ||||
if (!AlreadyHave(_inv)) { | if (!AlreadyHave(_inv)) { | ||||
pfrom->AskFor(_inv); | pfrom->AskFor(_inv); | ||||
} | } | ||||
} | } | ||||
AddOrphanTx(ptx, pfrom->GetId()); | AddOrphanTx(ptx, pfrom->GetId()); | ||||
// DoS prevention: do not allow mapOrphanTransactions to grow | // DoS prevention: do not allow mapOrphanTransactions to grow | ||||
▲ Show 20 Lines • Show All 153 Lines • ▼ Show 20 Lines | else if (strCommand == NetMsgType::CMPCTBLOCK && !fImporting && !fReindex) { | ||||
chainActive.Tip()->nChainWork || // We know something better | chainActive.Tip()->nChainWork || // We know something better | ||||
pindex->nTx != 0) { | pindex->nTx != 0) { | ||||
// We had this block at some point, but pruned it | // We had this block at some point, but pruned it | ||||
if (fAlreadyInFlight) { | if (fAlreadyInFlight) { | ||||
// We requested this block for some reason, but our mempool | // We requested this block for some reason, but our mempool | ||||
// will probably be useless so we just grab the block via | // will probably be useless so we just grab the block via | ||||
// normal getdata. | // normal getdata. | ||||
std::vector<CInv> vInv(1); | std::vector<CInv> vInv(1); | ||||
vInv[0] = CInv( | vInv[0] = CInv(MSG_BLOCK, cmpctblock.header.GetHash()); | ||||
MSG_BLOCK | GetFetchFlags(pfrom, pindex->pprev, | |||||
chainparams.GetConsensus()), | |||||
cmpctblock.header.GetHash()); | |||||
connman.PushMessage( | connman.PushMessage( | ||||
pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv)); | pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv)); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
// If we're not close to tip yet, give up and let parallel block | // If we're not close to tip yet, give up and let parallel block | ||||
// fetch work its magic. | // fetch work its magic. | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | else if (strCommand == NetMsgType::CMPCTBLOCK && !fImporting && !fReindex) { | ||||
Misbehaving(pfrom, 100, "invalid-cmpctblk"); | Misbehaving(pfrom, 100, "invalid-cmpctblk"); | ||||
LogPrintf("Peer %d sent us invalid compact block\n", | LogPrintf("Peer %d sent us invalid compact block\n", | ||||
pfrom->id); | pfrom->id); | ||||
return true; | return true; | ||||
} else if (status == READ_STATUS_FAILED) { | } else if (status == READ_STATUS_FAILED) { | ||||
// Duplicate txindices, the block is now in-flight, so | // Duplicate txindices, the block is now in-flight, so | ||||
// just request it. | // just request it. | ||||
std::vector<CInv> vInv(1); | std::vector<CInv> vInv(1); | ||||
vInv[0] = | vInv[0] = CInv(MSG_BLOCK, cmpctblock.header.GetHash()); | ||||
CInv(MSG_BLOCK | | |||||
GetFetchFlags(pfrom, pindex->pprev, | |||||
chainparams.GetConsensus()), | |||||
cmpctblock.header.GetHash()); | |||||
connman.PushMessage( | connman.PushMessage( | ||||
pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv)); | pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv)); | ||||
return true; | return true; | ||||
} | } | ||||
BlockTransactionsRequest req; | BlockTransactionsRequest req; | ||||
for (size_t i = 0; i < cmpctblock.BlockTxCount(); i++) { | for (size_t i = 0; i < cmpctblock.BlockTxCount(); i++) { | ||||
if (!partialBlock.IsTxAvailable(i)) { | if (!partialBlock.IsTxAvailable(i)) { | ||||
Show All 31 Lines | else if (strCommand == NetMsgType::CMPCTBLOCK && !fImporting && !fReindex) { | ||||
} | } | ||||
} | } | ||||
} else { | } else { | ||||
if (fAlreadyInFlight) { | if (fAlreadyInFlight) { | ||||
// We requested this block, but its far into the future, so | // We requested this block, but its far into the future, so | ||||
// our mempool will probably be useless - request the block | // our mempool will probably be useless - request the block | ||||
// normally. | // normally. | ||||
std::vector<CInv> vInv(1); | std::vector<CInv> vInv(1); | ||||
vInv[0] = CInv( | vInv[0] = CInv(MSG_BLOCK, cmpctblock.header.GetHash()); | ||||
MSG_BLOCK | GetFetchFlags(pfrom, pindex->pprev, | |||||
chainparams.GetConsensus()), | |||||
cmpctblock.header.GetHash()); | |||||
connman.PushMessage( | connman.PushMessage( | ||||
pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv)); | pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv)); | ||||
return true; | return true; | ||||
} else { | } else { | ||||
// If this was an announce-cmpctblock, we want the same | // If this was an announce-cmpctblock, we want the same | ||||
// treatment as a header message. Dirty hack to process as | // treatment as a header message. Dirty hack to process as | ||||
// if it were just a headers message (TODO: move message | // if it were just a headers message (TODO: move message | ||||
// handling into their own functions) | // handling into their own functions) | ||||
▲ Show 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | else if (strCommand == NetMsgType::BLOCKTXN && !fImporting && | ||||
Misbehaving(pfrom, 100, "invalid-cmpctblk-txns"); | Misbehaving(pfrom, 100, "invalid-cmpctblk-txns"); | ||||
LogPrintf("Peer %d sent us invalid compact block/non-matching " | LogPrintf("Peer %d sent us invalid compact block/non-matching " | ||||
"block transactions\n", | "block transactions\n", | ||||
pfrom->id); | pfrom->id); | ||||
return true; | return true; | ||||
} else if (status == READ_STATUS_FAILED) { | } else if (status == READ_STATUS_FAILED) { | ||||
// Might have collided, fall back to getdata now :( | // Might have collided, fall back to getdata now :( | ||||
std::vector<CInv> invs; | std::vector<CInv> invs; | ||||
invs.push_back( | invs.push_back(CInv(MSG_BLOCK, resp.blockhash)); | ||||
CInv(MSG_BLOCK | GetFetchFlags(pfrom, chainActive.Tip(), | |||||
chainparams.GetConsensus()), | |||||
resp.blockhash)); | |||||
connman.PushMessage(pfrom, | connman.PushMessage(pfrom, | ||||
msgMaker.Make(NetMsgType::GETDATA, invs)); | msgMaker.Make(NetMsgType::GETDATA, invs)); | ||||
} else { | } else { | ||||
// Block is either okay, or possibly we received | // Block is either okay, or possibly we received | ||||
// READ_STATUS_CHECKBLOCK_FAILED. | // READ_STATUS_CHECKBLOCK_FAILED. | ||||
// Note that CheckBlock can only fail for one of a few reasons: | // Note that CheckBlock can only fail for one of a few reasons: | ||||
// 1. bad-proof-of-work (impossible here, because we've already | // 1. bad-proof-of-work (impossible here, because we've already | ||||
// accepted the header) | // accepted the header) | ||||
▲ Show 20 Lines • Show All 191 Lines • ▼ Show 20 Lines | else if (strCommand == NetMsgType::HEADERS && !fImporting && !fReindex) { | ||||
// Download as much as possible, from earliest to latest. | // Download as much as possible, from earliest to latest. | ||||
for (const CBlockIndex *pindex : | for (const CBlockIndex *pindex : | ||||
boost::adaptors::reverse(vToFetch)) { | boost::adaptors::reverse(vToFetch)) { | ||||
if (nodestate->nBlocksInFlight >= | if (nodestate->nBlocksInFlight >= | ||||
MAX_BLOCKS_IN_TRANSIT_PER_PEER) { | MAX_BLOCKS_IN_TRANSIT_PER_PEER) { | ||||
// Can't download any more from this peer | // Can't download any more from this peer | ||||
break; | break; | ||||
} | } | ||||
uint32_t nFetchFlags = GetFetchFlags( | vGetData.push_back( | ||||
pfrom, pindex->pprev, chainparams.GetConsensus()); | CInv(MSG_BLOCK, pindex->GetBlockHash())); | ||||
vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, | |||||
pindex->GetBlockHash())); | |||||
MarkBlockAsInFlight(config, pfrom->GetId(), | MarkBlockAsInFlight(config, pfrom->GetId(), | ||||
pindex->GetBlockHash(), | pindex->GetBlockHash(), | ||||
chainparams.GetConsensus(), pindex); | chainparams.GetConsensus(), pindex); | ||||
LogPrint(BCLog::NET, | LogPrint(BCLog::NET, | ||||
"Requesting block %s from peer=%d\n", | "Requesting block %s from peer=%d\n", | ||||
pindex->GetBlockHash().ToString(), pfrom->id); | pindex->GetBlockHash().ToString(), pfrom->id); | ||||
} | } | ||||
if (vGetData.size() > 1) { | if (vGetData.size() > 1) { | ||||
▲ Show 20 Lines • Show All 958 Lines • ▼ Show 20 Lines | if (!pto->fClient && (fFetch || !IsInitialBlockDownload()) && | ||||
state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { | state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { | ||||
std::vector<const CBlockIndex *> vToDownload; | std::vector<const CBlockIndex *> vToDownload; | ||||
NodeId staller = -1; | NodeId staller = -1; | ||||
FindNextBlocksToDownload(pto->GetId(), | FindNextBlocksToDownload(pto->GetId(), | ||||
MAX_BLOCKS_IN_TRANSIT_PER_PEER - | MAX_BLOCKS_IN_TRANSIT_PER_PEER - | ||||
state.nBlocksInFlight, | state.nBlocksInFlight, | ||||
vToDownload, staller, consensusParams); | vToDownload, staller, consensusParams); | ||||
for (const CBlockIndex *pindex : vToDownload) { | for (const CBlockIndex *pindex : vToDownload) { | ||||
uint32_t nFetchFlags = | vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash())); | ||||
GetFetchFlags(pto, pindex->pprev, consensusParams); | |||||
vGetData.push_back( | |||||
CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash())); | |||||
MarkBlockAsInFlight(config, pto->GetId(), pindex->GetBlockHash(), | MarkBlockAsInFlight(config, pto->GetId(), pindex->GetBlockHash(), | ||||
consensusParams, pindex); | consensusParams, pindex); | ||||
LogPrint(BCLog::NET, "Requesting block %s (%d) peer=%d\n", | LogPrint(BCLog::NET, "Requesting block %s (%d) peer=%d\n", | ||||
pindex->GetBlockHash().ToString(), pindex->nHeight, | pindex->GetBlockHash().ToString(), pindex->nHeight, | ||||
pto->id); | pto->id); | ||||
} | } | ||||
if (state.nBlocksInFlight == 0 && staller != -1) { | if (state.nBlocksInFlight == 0 && staller != -1) { | ||||
if (State(staller)->nStallingSince == 0) { | if (State(staller)->nStallingSince == 0) { | ||||
▲ Show 20 Lines • Show All 90 Lines • Show Last 20 Lines |