Skip to content

Commit 6698131

Browse files
committed
Merge d104aa0 into merged_master (Bitcoin PR #17951)
2 parents b6dc1e0 + d104aa0 commit 6698131

File tree

2 files changed

+69
-25
lines changed

2 files changed

+69
-25
lines changed

src/net_processing.cpp

Lines changed: 68 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,14 @@ namespace {
148148
std::unique_ptr<CRollingBloomFilter> recentRejects GUARDED_BY(cs_main);
149149
uint256 hashRecentRejectsChainTip GUARDED_BY(cs_main);
150150

151+
/*
152+
* Filter for transactions that have been recently confirmed.
153+
* We use this to avoid requesting transactions that have already been
154+
* confirnmed.
155+
*/
156+
RecursiveMutex g_cs_recent_confirmed_transactions;
157+
std::unique_ptr<CRollingBloomFilter> g_recent_confirmed_transactions GUARDED_BY(g_cs_recent_confirmed_transactions);
158+
151159
/** Blocks that are in flight, and that are in the queue to be downloaded. */
152160
struct QueuedBlock {
153161
uint256 hash;
@@ -1116,6 +1124,16 @@ PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn, BanMan* banman, CS
11161124
// Initialize global variables that cannot be constructed at startup.
11171125
recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
11181126

1127+
// Blocks don't typically have more than 4000 transactions, so this should
1128+
// be at least six blocks (~1 hr) worth of transactions that we can store.
1129+
// If the number of transactions appearing in a block goes up, or if we are
1130+
// seeing getdata requests more than an hour after initial announcement, we
1131+
// can increase this number.
1132+
// The false positive rate of 1/1M should come out to less than 1
1133+
// transaction per day that would be inadvertently ignored (which is the
1134+
// same probability that we have in the reject filter).
1135+
g_recent_confirmed_transactions.reset(new CRollingBloomFilter(24000, 0.000001));
1136+
11191137
const Consensus::Params& consensusParams = Params().GetConsensus();
11201138
// Stale tip checking and peer eviction are on two different timers, but we
11211139
// don't want them to get out of sync due to drift in the scheduler, so we
@@ -1129,36 +1147,59 @@ PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn, BanMan* banman, CS
11291147
* Evict orphan txn pool entries (EraseOrphanTx) based on a newly connected
11301148
* block. Also save the time of the last tip update.
11311149
*/
1132-
void PeerLogicValidation::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex, const std::vector<CTransactionRef>& vtxConflicted) {
1133-
LOCK(g_cs_orphans);
1150+
void PeerLogicValidation::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex, const std::vector<CTransactionRef>& vtxConflicted)
1151+
{
1152+
{
1153+
LOCK(g_cs_orphans);
11341154

1135-
std::vector<uint256> vOrphanErase;
1155+
std::vector<uint256> vOrphanErase;
11361156

1137-
for (const CTransactionRef& ptx : pblock->vtx) {
1138-
const CTransaction& tx = *ptx;
1157+
for (const CTransactionRef& ptx : pblock->vtx) {
1158+
const CTransaction& tx = *ptx;
11391159

1140-
// Which orphan pool entries must we evict?
1141-
for (const auto& txin : tx.vin) {
1142-
auto itByPrev = mapOrphanTransactionsByPrev.find(txin.prevout);
1143-
if (itByPrev == mapOrphanTransactionsByPrev.end()) continue;
1144-
for (auto mi = itByPrev->second.begin(); mi != itByPrev->second.end(); ++mi) {
1145-
const CTransaction& orphanTx = *(*mi)->second.tx;
1146-
const uint256& orphanHash = orphanTx.GetHash();
1147-
vOrphanErase.push_back(orphanHash);
1160+
// Which orphan pool entries must we evict?
1161+
for (const auto& txin : tx.vin) {
1162+
auto itByPrev = mapOrphanTransactionsByPrev.find(txin.prevout);
1163+
if (itByPrev == mapOrphanTransactionsByPrev.end()) continue;
1164+
for (auto mi = itByPrev->second.begin(); mi != itByPrev->second.end(); ++mi) {
1165+
const CTransaction& orphanTx = *(*mi)->second.tx;
1166+
const uint256& orphanHash = orphanTx.GetHash();
1167+
vOrphanErase.push_back(orphanHash);
1168+
}
11481169
}
11491170
}
1150-
}
11511171

1152-
// Erase orphan transactions included or precluded by this block
1153-
if (vOrphanErase.size()) {
1154-
int nErased = 0;
1155-
for (const uint256& orphanHash : vOrphanErase) {
1156-
nErased += EraseOrphanTx(orphanHash);
1172+
// Erase orphan transactions included or precluded by this block
1173+
if (vOrphanErase.size()) {
1174+
int nErased = 0;
1175+
for (const uint256& orphanHash : vOrphanErase) {
1176+
nErased += EraseOrphanTx(orphanHash);
1177+
}
1178+
LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx included or conflicted by block\n", nErased);
1179+
}
1180+
1181+
g_last_tip_update = GetTime();
1182+
}
1183+
{
1184+
LOCK(g_cs_recent_confirmed_transactions);
1185+
for (const auto ptx : pblock->vtx) {
1186+
g_recent_confirmed_transactions->insert(ptx->GetHash());
11571187
}
1158-
LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx included or conflicted by block\n", nErased);
11591188
}
1189+
}
11601190

1161-
g_last_tip_update = GetTime();
1191+
void PeerLogicValidation::BlockDisconnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex* pindex)
1192+
{
1193+
// To avoid relay problems with transactions that were previously
1194+
// confirmed, clear our filter of recently confirmed transactions whenever
1195+
// there's a reorg.
1196+
// This means that in a 1-block reorg (where 1 block is disconnected and
1197+
// then another block reconnected), our filter will drop to having only one
1198+
// block's worth of transactions in it, but that should be fine, since
1199+
// presumably the most common case of relaying a confirmed transaction
1200+
// should be just after a new block containing it is found.
1201+
LOCK(g_cs_recent_confirmed_transactions);
1202+
g_recent_confirmed_transactions->reset();
11621203
}
11631204

11641205
// All of the following cache a recent block, and are protected by cs_most_recent_block
@@ -1311,12 +1352,14 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
13111352
LOCK(g_cs_orphans);
13121353
if (mapOrphanTransactions.count(inv.hash)) return true;
13131354
}
1314-
const CCoinsViewCache& coins_cache = ::ChainstateActive().CoinsTip();
1355+
1356+
{
1357+
LOCK(g_cs_recent_confirmed_transactions);
1358+
if (g_recent_confirmed_transactions->contains(inv.hash)) return true;
1359+
}
13151360

13161361
return recentRejects->contains(inv.hash) ||
1317-
mempool.exists(inv.hash) ||
1318-
coins_cache.HaveCoinInCache(COutPoint(inv.hash, 0)) || // Best effort: only try output 0 and 1
1319-
coins_cache.HaveCoinInCache(COutPoint(inv.hash, 1));
1362+
mempool.exists(inv.hash);
13201363
}
13211364
case MSG_BLOCK:
13221365
case MSG_WITNESS_BLOCK:

src/net_processing.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class PeerLogicValidation final : public CValidationInterface, public NetEventsI
3333
* Overridden from CValidationInterface.
3434
*/
3535
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected, const std::vector<CTransactionRef>& vtxConflicted) override;
36+
void BlockDisconnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex* pindex) override;
3637
/**
3738
* Overridden from CValidationInterface.
3839
*/

0 commit comments

Comments
 (0)