upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp50
1 files changed, 47 insertions, 3 deletions
diff --git a/src/main.cpp b/src/main.cpp
index b147ddd..4bc9c4d 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -293,6 +293,43 @@ void AddOrphanTx(const CDataStream& vMsg)
293// grow this map until the node runs out of memory. Evict at random rather than 293// grow this map until the node runs out of memory. Evict at random rather than
294// in map order, so an attacker cannot keep its own orphans resident by 294// in map order, so an attacker cannot keep its own orphans resident by
295// choosing hashes that sort low. 295// choosing hashes that sort low.
296// Drop orphan blocks at random until we are back under the ceiling.
297//
298// Random rather than oldest-first, matching LimitOrphanTx below: there is no
299// arrival order recorded, and an attacker who knew the eviction rule could aim
300// at it. Dropping one costs nothing that matters -- if its parent ever shows
301// up, the block is requested again like any other.
302//
303// Both maps have to be kept in step, and the CBlock itself has to be deleted:
304// mapOrphanBlocks owns it.
305void LimitOrphanBlocks(unsigned int nMaxOrphans)
306{
307 while (mapOrphanBlocks.size() > nMaxOrphans)
308 {
309 uint256 randomhash;
310 for (int i = 0; i < 4; i++)
311 ((uint64*)&randomhash)[i] = GetRand(_UI64_MAX);
312 map<uint256, CBlock*>::iterator it = mapOrphanBlocks.lower_bound(randomhash);
313 if (it == mapOrphanBlocks.end())
314 it = mapOrphanBlocks.begin();
315
316 CBlock* pblock = it->second;
317 uint256 hashPrev = pblock->hashPrevBlock;
318
319 for (multimap<uint256, CBlock*>::iterator mi = mapOrphanBlocksByPrev.lower_bound(hashPrev);
320 mi != mapOrphanBlocksByPrev.upper_bound(hashPrev);)
321 {
322 if (mi->second == pblock)
323 mapOrphanBlocksByPrev.erase(mi++);
324 else
325 ++mi;
326 }
327
328 mapOrphanBlocks.erase(it);
329 delete pblock;
330 }
331}
332
296void LimitOrphanTx(unsigned int nMaxOrphans) 333void LimitOrphanTx(unsigned int nMaxOrphans)
297{ 334{
298 while (mapOrphanTransactions.size() > nMaxOrphans) 335 while (mapOrphanTransactions.size() > nMaxOrphans)
@@ -1468,9 +1505,16 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock)
1468 mapOrphanBlocks.insert(make_pair(hash, pblock)); 1505 mapOrphanBlocks.insert(make_pair(hash, pblock));
1469 mapOrphanBlocksByPrev.insert(make_pair(pblock->hashPrevBlock, pblock)); 1506 mapOrphanBlocksByPrev.insert(make_pair(pblock->hashPrevBlock, pblock));
1470 1507
1508 // Read what we need out of pblock before trimming: eviction picks at
1509 // random and is perfectly entitled to pick the block just inserted,
1510 // which would leave the GetOrphanRoot call below reading freed memory.
1511 uint256 hashOrphanRoot = GetOrphanRoot(pblock);
1512
1513 LimitOrphanBlocks(MAX_ORPHAN_BLOCKS);
1514
1471 // Ask this guy to fill in what we're missing 1515 // Ask this guy to fill in what we're missing
1472 if (pfrom) 1516 if (pfrom)
1473 pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), GetOrphanRoot(pblock)); 1517 pfrom->PushGetBlocks(pindexBest, hashOrphanRoot);
1474 return true; 1518 return true;
1475 } 1519 }
1476 1520
@@ -2047,7 +2091,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
2047 if (!fAskedForBlocks && !pfrom->fClient) 2091 if (!fAskedForBlocks && !pfrom->fClient)
2048 { 2092 {
2049 fAskedForBlocks = true; 2093 fAskedForBlocks = true;
2050 pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), uint256(0)); 2094 pfrom->PushGetBlocks(pindexBest, uint256(0));
2051 } 2095 }
2052 2096
2053 // Introduce ourselves and hand over the .btf peers that answered us. 2097 // Introduce ourselves and hand over the .btf peers that answered us.
@@ -2110,7 +2154,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
2110 if (!fAlreadyHave) 2154 if (!fAlreadyHave)
2111 pfrom->AskFor(inv); 2155 pfrom->AskFor(inv);
2112 else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) 2156 else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash))
2113 pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), GetOrphanRoot(mapOrphanBlocks[inv.hash])); 2157 pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));
2114 } 2158 }
2115 } 2159 }
2116 2160