aboutsummaryrefslogtreecommitdiff
path: root/src/net_processing.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/net_processing.cpp')
-rw-r--r--src/net_processing.cpp77
1 files changed, 64 insertions, 13 deletions
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 747167264b..e10694ed18 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -50,6 +50,7 @@ struct IteratorComparator
};
struct COrphanTx {
+ // When modifying, adapt the copy of this definition in tests/DoS_tests.
CTransaction tx;
NodeId fromPeer;
int64_t nTimeExpire;
@@ -1517,7 +1518,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
CBlock block;
- assert(ReadBlockFromDisk(block, it->second, chainparams.GetConsensus()));
+ bool ret = ReadBlockFromDisk(block, it->second, chainparams.GetConsensus());
+ assert(ret);
BlockTransactions resp(req);
for (size_t i = 0; i < req.indexes.size(); i++) {
@@ -1594,8 +1596,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
deque<COutPoint> vWorkQueue;
vector<uint256> vEraseQueue;
- CTransaction tx;
- vRecv >> tx;
+ CTransaction tx(deserialize, vRecv);
CInv inv(MSG_TX, tx.GetHash());
pfrom->AddInventoryKnown(inv);
@@ -1781,6 +1782,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
}
+ // Keep a CBlock for "optimistic" compactblock reconstructions (see
+ // below)
+ std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
+ bool fBlockReconstructed = false;
+
LOCK(cs_main);
// If AcceptBlockHeader returned true, it set pindex
assert(pindex);
@@ -1869,6 +1875,23 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
req.blockhash = pindex->GetBlockHash();
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETBLOCKTXN, req));
}
+ } else {
+ // This block is either already in flight from a different
+ // peer, or this peer has too many blocks outstanding to
+ // download from.
+ // Optimistically try to reconstruct anyway since we might be
+ // able to without any round trips.
+ PartiallyDownloadedBlock tempBlock(&mempool);
+ ReadStatus status = tempBlock.InitData(cmpctblock);
+ if (status != READ_STATUS_OK) {
+ // TODO: don't ignore failures
+ return true;
+ }
+ std::vector<CTransactionRef> dummy;
+ status = tempBlock.FillBlock(*pblock, dummy);
+ if (status == READ_STATUS_OK) {
+ fBlockReconstructed = true;
+ }
}
} else {
if (fAlreadyInFlight) {
@@ -1888,6 +1911,29 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
return ProcessMessage(pfrom, NetMsgType::HEADERS, vHeadersMsg, nTimeReceived, chainparams, connman);
}
}
+
+ if (fBlockReconstructed) {
+ // If we got here, we were able to optimistically reconstruct a
+ // block that is in flight from some other peer.
+ {
+ LOCK(cs_main);
+ mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom->GetId(), false));
+ }
+ bool fNewBlock = false;
+ ProcessNewBlock(chainparams, pblock, true, &fNewBlock);
+ if (fNewBlock)
+ pfrom->nLastBlockTime = GetTime();
+
+ LOCK(cs_main); // hold cs_main for CBlockIndex::IsValid()
+ if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS)) {
+ // Clear download state for this block, which is in
+ // process from some other peer. We do this after calling
+ // ProcessNewBlock so that a malleated cmpctblock announcement
+ // can't be used to interfere with block relay.
+ MarkBlockAsReceived(pblock->GetHash());
+ }
+ }
+
}
else if (strCommand == NetMsgType::BLOCKTXN && !fImporting && !fReindex) // Ignore blocks received while importing
@@ -1895,7 +1941,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
BlockTransactions resp;
vRecv >> resp;
- CBlock block;
+ std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
bool fBlockRead = false;
{
LOCK(cs_main);
@@ -1908,7 +1954,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
PartiallyDownloadedBlock& partialBlock = *it->second.second->partialBlock;
- ReadStatus status = partialBlock.FillBlock(block, resp.txn);
+ ReadStatus status = partialBlock.FillBlock(*pblock, resp.txn);
if (status == READ_STATUS_INVALID) {
MarkBlockAsReceived(resp.blockhash); // Reset in-flight state in case of whitelist
Misbehaving(pfrom->GetId(), 100);
@@ -1951,7 +1997,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
bool fNewBlock = false;
// Since we requested this block (it was in mapBlocksInFlight), force it to be processed,
// even if it would not be a candidate for new tip (missing previous block, chain not long enough, etc)
- ProcessNewBlock(chainparams, &block, true, NULL, &fNewBlock);
+ ProcessNewBlock(chainparams, pblock, true, &fNewBlock);
if (fNewBlock)
pfrom->nLastBlockTime = GetTime();
}
@@ -2112,17 +2158,17 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
else if (strCommand == NetMsgType::BLOCK && !fImporting && !fReindex) // Ignore blocks received while importing
{
- CBlock block;
- vRecv >> block;
+ std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
+ vRecv >> *pblock;
- LogPrint("net", "received block %s peer=%d\n", block.GetHash().ToString(), pfrom->id);
+ LogPrint("net", "received block %s peer=%d\n", pblock->GetHash().ToString(), pfrom->id);
// Process all blocks from whitelisted peers, even if not requested,
// unless we're still syncing with the network.
// Such an unrequested block may still be processed, subject to the
// conditions in AcceptBlock().
bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload();
- const uint256 hash(block.GetHash());
+ const uint256 hash(pblock->GetHash());
{
LOCK(cs_main);
// Also always process if we requested the block explicitly, as we may
@@ -2133,7 +2179,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
mapBlockSource.emplace(hash, std::make_pair(pfrom->GetId(), true));
}
bool fNewBlock = false;
- ProcessNewBlock(chainparams, &block, forceProcessing, NULL, &fNewBlock);
+ ProcessNewBlock(chainparams, pblock, forceProcessing, &fNewBlock);
if (fNewBlock)
pfrom->nLastBlockTime = GetTime();
}
@@ -2730,7 +2776,8 @@ bool SendMessages(CNode* pto, CConnman& connman)
vHeaders.front().GetHash().ToString(), pto->id);
//TODO: Shouldn't need to reload block from disk, but requires refactor
CBlock block;
- assert(ReadBlockFromDisk(block, pBestIndex, consensusParams));
+ bool ret = ReadBlockFromDisk(block, pBestIndex, consensusParams);
+ assert(ret);
CBlockHeaderAndShortTxIDs cmpctblock(block, state.fWantsCmpctWitness);
int nSendFlags = state.fWantsCmpctWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
connman.PushMessage(pto, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
@@ -2995,8 +3042,12 @@ bool SendMessages(CNode* pto, CConnman& connman)
CAmount currentFilter = mempool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK();
int64_t timeNow = GetTimeMicros();
if (timeNow > pto->nextSendTimeFeeFilter) {
- static FeeFilterRounder filterRounder(::minRelayTxFee);
+ static CFeeRate default_feerate(DEFAULT_MIN_RELAY_TX_FEE);
+ static FeeFilterRounder filterRounder(default_feerate);
CAmount filterToSend = filterRounder.round(currentFilter);
+ // If we don't allow free transactions, then we always have a fee filter of at least minRelayTxFee
+ if (GetArg("-limitfreerelay", DEFAULT_LIMITFREERELAY) <= 0)
+ filterToSend = std::max(filterToSend, ::minRelayTxFee.GetFeePerK());
if (filterToSend != pto->lastSentFeeFilter) {
connman.PushMessage(pto, msgMaker.Make(NetMsgType::FEEFILTER, filterToSend));
pto->lastSentFeeFilter = filterToSend;