Store orphan blocks in serialized form
This commit is contained in:
parent
dc64c3c374
commit
da0fecffa7
1 changed files with 41 additions and 17 deletions
58
src/main.cpp
58
src/main.cpp
|
@ -56,8 +56,13 @@ int64_t CTransaction::nMinRelayTxFee = 10000;
|
||||||
|
|
||||||
static CMedianFilter<int> cPeerBlockCounts(8, 0); // Amount of blocks that other nodes claim to have
|
static CMedianFilter<int> cPeerBlockCounts(8, 0); // Amount of blocks that other nodes claim to have
|
||||||
|
|
||||||
map<uint256, CBlock*> mapOrphanBlocks;
|
struct COrphanBlock {
|
||||||
multimap<uint256, CBlock*> mapOrphanBlocksByPrev;
|
uint256 hashBlock;
|
||||||
|
uint256 hashPrev;
|
||||||
|
vector<unsigned char> vchBlock;
|
||||||
|
};
|
||||||
|
map<uint256, COrphanBlock*> mapOrphanBlocks;
|
||||||
|
multimap<uint256, COrphanBlock*> mapOrphanBlocksByPrev;
|
||||||
|
|
||||||
map<uint256, CTransaction> mapOrphanTransactions;
|
map<uint256, CTransaction> mapOrphanTransactions;
|
||||||
map<uint256, set<uint256> > mapOrphanTransactionsByPrev;
|
map<uint256, set<uint256> > mapOrphanTransactionsByPrev;
|
||||||
|
@ -985,12 +990,19 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 static GetOrphanRoot(const CBlockHeader* pblock)
|
uint256 static GetOrphanRoot(const uint256& hash)
|
||||||
{
|
{
|
||||||
|
map<uint256, COrphanBlock*>::iterator it = mapOrphanBlocks.find(hash);
|
||||||
|
if (it == mapOrphanBlocks.end())
|
||||||
|
return hash;
|
||||||
|
|
||||||
// Work back to the first block in the orphan chain
|
// Work back to the first block in the orphan chain
|
||||||
while (mapOrphanBlocks.count(pblock->hashPrevBlock))
|
do {
|
||||||
pblock = mapOrphanBlocks[pblock->hashPrevBlock];
|
map<uint256, COrphanBlock*>::iterator it2 = mapOrphanBlocks.find(it->second->hashPrev);
|
||||||
return pblock->GetHash();
|
if (it2 == mapOrphanBlocks.end())
|
||||||
|
return it->first;
|
||||||
|
it = it2;
|
||||||
|
} while(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t GetBlockValue(int nHeight, int64_t nFees)
|
int64_t GetBlockValue(int nHeight, int64_t nFees)
|
||||||
|
@ -2277,12 +2289,19 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
|
||||||
|
|
||||||
// Accept orphans as long as there is a node to request its parents from
|
// Accept orphans as long as there is a node to request its parents from
|
||||||
if (pfrom) {
|
if (pfrom) {
|
||||||
CBlock* pblock2 = new CBlock(*pblock);
|
COrphanBlock* pblock2 = new COrphanBlock();
|
||||||
|
{
|
||||||
|
CDataStream ss(SER_DISK, CLIENT_VERSION);
|
||||||
|
ss << *pblock;
|
||||||
|
pblock2->vchBlock = std::vector<unsigned char>(ss.begin(), ss.end());
|
||||||
|
}
|
||||||
|
pblock2->hashBlock = hash;
|
||||||
|
pblock2->hashPrev = pblock->hashPrevBlock;
|
||||||
mapOrphanBlocks.insert(make_pair(hash, pblock2));
|
mapOrphanBlocks.insert(make_pair(hash, pblock2));
|
||||||
mapOrphanBlocksByPrev.insert(make_pair(pblock2->hashPrevBlock, pblock2));
|
mapOrphanBlocksByPrev.insert(make_pair(pblock2->hashPrev, pblock2));
|
||||||
|
|
||||||
// Ask this guy to fill in what we're missing
|
// Ask this guy to fill in what we're missing
|
||||||
PushGetBlocks(pfrom, chainActive.Tip(), GetOrphanRoot(pblock2));
|
PushGetBlocks(pfrom, chainActive.Tip(), GetOrphanRoot(hash));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2297,17 +2316,22 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
|
||||||
for (unsigned int i = 0; i < vWorkQueue.size(); i++)
|
for (unsigned int i = 0; i < vWorkQueue.size(); i++)
|
||||||
{
|
{
|
||||||
uint256 hashPrev = vWorkQueue[i];
|
uint256 hashPrev = vWorkQueue[i];
|
||||||
for (multimap<uint256, CBlock*>::iterator mi = mapOrphanBlocksByPrev.lower_bound(hashPrev);
|
for (multimap<uint256, COrphanBlock*>::iterator mi = mapOrphanBlocksByPrev.lower_bound(hashPrev);
|
||||||
mi != mapOrphanBlocksByPrev.upper_bound(hashPrev);
|
mi != mapOrphanBlocksByPrev.upper_bound(hashPrev);
|
||||||
++mi)
|
++mi)
|
||||||
{
|
{
|
||||||
CBlock* pblockOrphan = (*mi).second;
|
CBlock block;
|
||||||
|
{
|
||||||
|
CDataStream ss(mi->second->vchBlock, SER_DISK, CLIENT_VERSION);
|
||||||
|
ss >> block;
|
||||||
|
}
|
||||||
|
block.BuildMerkleTree();
|
||||||
// Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan resolution (that is, feeding people an invalid block based on LegitBlockX in order to get anyone relaying LegitBlockX banned)
|
// Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan resolution (that is, feeding people an invalid block based on LegitBlockX in order to get anyone relaying LegitBlockX banned)
|
||||||
CValidationState stateDummy;
|
CValidationState stateDummy;
|
||||||
if (AcceptBlock(*pblockOrphan, stateDummy))
|
if (AcceptBlock(block, stateDummy))
|
||||||
vWorkQueue.push_back(pblockOrphan->GetHash());
|
vWorkQueue.push_back(mi->second->hashBlock);
|
||||||
mapOrphanBlocks.erase(pblockOrphan->GetHash());
|
mapOrphanBlocks.erase(mi->second->hashBlock);
|
||||||
delete pblockOrphan;
|
delete mi->second;
|
||||||
}
|
}
|
||||||
mapOrphanBlocksByPrev.erase(hashPrev);
|
mapOrphanBlocksByPrev.erase(hashPrev);
|
||||||
}
|
}
|
||||||
|
@ -3331,7 +3355,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||||
if (!fImporting && !fReindex)
|
if (!fImporting && !fReindex)
|
||||||
pfrom->AskFor(inv);
|
pfrom->AskFor(inv);
|
||||||
} else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) {
|
} else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) {
|
||||||
PushGetBlocks(pfrom, chainActive.Tip(), GetOrphanRoot(mapOrphanBlocks[inv.hash]));
|
PushGetBlocks(pfrom, chainActive.Tip(), GetOrphanRoot(inv.hash));
|
||||||
} else if (nInv == nLastBlock) {
|
} else if (nInv == nLastBlock) {
|
||||||
// In case we are on a very long side-chain, it is possible that we already have
|
// In case we are on a very long side-chain, it is possible that we already have
|
||||||
// the last block in an inv bundle sent in response to getblocks. Try to detect
|
// the last block in an inv bundle sent in response to getblocks. Try to detect
|
||||||
|
@ -4119,7 +4143,7 @@ public:
|
||||||
mapBlockIndex.clear();
|
mapBlockIndex.clear();
|
||||||
|
|
||||||
// orphan blocks
|
// orphan blocks
|
||||||
std::map<uint256, CBlock*>::iterator it2 = mapOrphanBlocks.begin();
|
std::map<uint256, COrphanBlock*>::iterator it2 = mapOrphanBlocks.begin();
|
||||||
for (; it2 != mapOrphanBlocks.end(); it2++)
|
for (; it2 != mapOrphanBlocks.end(); it2++)
|
||||||
delete (*it2).second;
|
delete (*it2).second;
|
||||||
mapOrphanBlocks.clear();
|
mapOrphanBlocks.clear();
|
||||||
|
|
Loading…
Reference in a new issue