Rename CClaimTrieCache to CClaimTrieUpdateBuffer #156

Closed
kaykurokawa wants to merge 276 commits from cclaimtriecache_change into master
7 changed files with 382 additions and 156 deletions
Showing only changes of commit 50d78cfdba - Show all commits

View file

@ -6,6 +6,21 @@
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
std::vector<unsigned char> heightToVch(int n)
{
std::vector<unsigned char> vchHeight;
vchHeight.resize(8);
vchHeight[0] = 0;
vchHeight[1] = 0;
vchHeight[2] = 0;
vchHeight[3] = 0;
vchHeight[4] = n >> 24;
vchHeight[5] = n >> 16;
vchHeight[6] = n >> 8;
vchHeight[7] = n;
return vchHeight;
}
uint256 CClaimValue::GetHash() const uint256 CClaimValue::GetHash() const
{ {
CHash256 txHasher; CHash256 txHasher;
@ -396,31 +411,50 @@ std::vector<namedNodeType> CClaimTrie::flattenTrie() const
return nodes; return nodes;
} }
bool CClaimTrie::getInfoForName(const std::string& name, CClaimValue& claim) const const CClaimTrieNode* CClaimTrie::getNodeForName(const std::string& name) const
{ {
const CClaimTrieNode* current = &root; const CClaimTrieNode* current = &root;
for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname) for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname)
{ {
nodeMapType::const_iterator itchildren = current->children.find(*itname); nodeMapType::const_iterator itchildren = current->children.find(*itname);
if (itchildren == current->children.end()) if (itchildren == current->children.end())
return false; return NULL;
current = itchildren->second; current = itchildren->second;
} }
return current->getBestClaim(claim); return current;
} }
bool CClaimTrie::checkConsistency() bool CClaimTrie::getInfoForName(const std::string& name, CClaimValue& claim) const
{
const CClaimTrieNode* current = getNodeForName(name);
if (current)
return current->getBestClaim(claim);
return false;
}
bool CClaimTrie::getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const
{
const CClaimTrieNode* current = getNodeForName(name);
if (current)
{
lastTakeoverHeight = current->nHeightOfLastTakeover;
return true;
}
return false;
}
bool CClaimTrie::checkConsistency() const
{ {
if (empty()) if (empty())
return true; return true;
return recursiveCheckConsistency(&root); return recursiveCheckConsistency(&root);
} }
bool CClaimTrie::recursiveCheckConsistency(CClaimTrieNode* node) bool CClaimTrie::recursiveCheckConsistency(const CClaimTrieNode* node) const
{ {
std::vector<unsigned char> vchToHash; std::vector<unsigned char> vchToHash;
for (nodeMapType::iterator it = node->children.begin(); it != node->children.end(); ++it) for (nodeMapType::const_iterator it = node->children.begin(); it != node->children.end(); ++it)
{ {
if (recursiveCheckConsistency(it->second)) if (recursiveCheckConsistency(it->second))
{ {
@ -438,6 +472,8 @@ bool CClaimTrie::recursiveCheckConsistency(CClaimTrieNode* node)
{ {
uint256 claimHash = claim.GetHash(); uint256 claimHash = claim.GetHash();
vchToHash.insert(vchToHash.end(), claimHash.begin(), claimHash.end()); vchToHash.insert(vchToHash.end(), claimHash.begin(), claimHash.end());
std::vector<unsigned char> heightToHash = heightToVch(node->nHeightOfLastTakeover);
vchToHash.insert(vchToHash.end(), heightToHash.begin(), heightToHash.end());
} }
CHash256 hasher; CHash256 hasher;
@ -598,19 +634,21 @@ bool CClaimTrie::getSupportQueueNameRow(const std::string& name, std::vector<CSu
return db.Read(std::make_pair(SUPPORT_QUEUE_NAME_ROW, name), row); return db.Read(std::make_pair(SUPPORT_QUEUE_NAME_ROW, name), row);
} }
bool CClaimTrie::update(nodeCacheType& cache, hashMapType& hashes, const uint256& hashBlockIn, claimQueueType& queueCache, claimQueueNamesType& queueNameCache, claimQueueType& expirationQueueCache, int nNewHeight, supportMapType& supportCache, supportQueueType& supportQueueCache, supportQueueNamesType& supportQueueNameCache) bool CClaimTrie::update(nodeCacheType& cache, hashMapType& hashes, std::map<std::string, int>& takeoverHeights, const uint256& hashBlockIn, claimQueueType& queueCache, claimQueueNamesType& queueNameCache, claimQueueType& expirationQueueCache, int nNewHeight, supportMapType& supportCache, supportQueueType& supportQueueCache, supportQueueNamesType& supportQueueNameCache)
{ {
bool success = true;
for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache) for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache)
{ {
success = updateName(itcache->first, itcache->second); if (!updateName(itcache->first, itcache->second))
if (!success)
return false; return false;
} }
for (hashMapType::iterator ithash = hashes.begin(); ithash != hashes.end(); ++ithash) for (hashMapType::iterator ithash = hashes.begin(); ithash != hashes.end(); ++ithash)
{ {
success = updateHash(ithash->first, ithash->second); if (!updateHash(ithash->first, ithash->second))
if (!success) return false;
}
for (std::map<std::string, int>::iterator itheight = takeoverHeights.begin(); itheight != takeoverHeights.end(); ++itheight)
{
if (!updateTakeoverHeight(itheight->first, itheight->second))
return false; return false;
} }
for (claimQueueType::iterator itQueueCacheRow = queueCache.begin(); itQueueCacheRow != queueCache.end(); ++itQueueCacheRow) for (claimQueueType::iterator itQueueCacheRow = queueCache.begin(); itQueueCacheRow != queueCache.end(); ++itQueueCacheRow)
@ -728,6 +766,22 @@ bool CClaimTrie::updateHash(const std::string& name, uint256& hash)
return true; return true;
} }
bool CClaimTrie::updateTakeoverHeight(const std::string& name, int nTakeoverHeight)
{
CClaimTrieNode* current = &root;
for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname)
{
nodeMapType::iterator itchild = current->children.find(*itname);
if (itchild == current->children.end())
return false;
current = itchild->second;
}
assert(current != NULL);
current->nHeightOfLastTakeover = nTakeoverHeight;
markNodeDirty(name, current);
return true;
}
void CClaimTrie::BatchWriteNode(CLevelDBBatch& batch, const std::string& name, const CClaimTrieNode* pNode) const void CClaimTrie::BatchWriteNode(CLevelDBBatch& batch, const std::string& name, const CClaimTrieNode* pNode) const
{ {
uint32_t num_claims = 0; uint32_t num_claims = 0;
@ -962,6 +1016,10 @@ bool CClaimTrieCache::recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent, std:
{ {
uint256 claimHash = claim.GetHash(); uint256 claimHash = claim.GetHash();
vchToHash.insert(vchToHash.end(), claimHash.begin(), claimHash.end()); vchToHash.insert(vchToHash.end(), claimHash.begin(), claimHash.end());
int nHeightOfLastTakeover;
assert(getLastTakeoverForName(sPos, nHeightOfLastTakeover));
std::vector<unsigned char> heightToHash = heightToVch(nHeightOfLastTakeover);
vchToHash.insert(vchToHash.end(), heightToHash.begin(), heightToHash.end());
} }
CHash256 hasher; CHash256 hasher;
@ -1002,7 +1060,7 @@ bool CClaimTrieCache::empty() const
return base->empty() && cache.empty(); return base->empty() && cache.empty();
} }
bool CClaimTrieCache::insertClaimIntoTrie(const std::string name, CClaimValue claim) const bool CClaimTrieCache::insertClaimIntoTrie(const std::string name, CClaimValue claim, bool fCheckTakeover) const
{ {
assert(base); assert(base);
CClaimTrieNode* currentNode = &(base->root); CClaimTrieNode* currentNode = &(base->root);
@ -1092,11 +1150,13 @@ bool CClaimTrieCache::insertClaimIntoTrie(const std::string name, CClaimValue cl
dirtyHashes.insert(sub); dirtyHashes.insert(sub);
} }
dirtyHashes.insert(name); dirtyHashes.insert(name);
if (fCheckTakeover)
namesToCheckForTakeover.insert(name);
} }
return true; return true;
} }
bool CClaimTrieCache::removeClaimFromTrie(const std::string name, uint256 txhash, uint32_t nOut, int& nValidAtHeight) const bool CClaimTrieCache::removeClaimFromTrie(const std::string name, uint256 txhash, uint32_t nOut, int& nValidAtHeight, bool fCheckTakeover) const
{ {
assert(base); assert(base);
CClaimTrieNode* currentNode = &(base->root); CClaimTrieNode* currentNode = &(base->root);
@ -1176,6 +1236,8 @@ bool CClaimTrieCache::removeClaimFromTrie(const std::string name, uint256 txhash
dirtyHashes.insert(sub); dirtyHashes.insert(sub);
} }
dirtyHashes.insert(name); dirtyHashes.insert(name);
if (fCheckTakeover)
namesToCheckForTakeover.insert(name);
} }
CClaimTrieNode* rootNode = &(base->root); CClaimTrieNode* rootNode = &(base->root);
cachedNode = cache.find(""); cachedNode = cache.find("");
@ -1302,20 +1364,22 @@ bool CClaimTrieCache::addClaim(const std::string name, uint256 txhash, uint32_t
{ {
LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nAmount: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, txhash.GetHex(), nOut, nAmount, nHeight, nCurrentHeight); LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nAmount: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, txhash.GetHex(), nOut, nAmount, nHeight, nCurrentHeight);
assert(nHeight == nCurrentHeight); assert(nHeight == nCurrentHeight);
return addClaimToQueues(name, txhash, nOut, nAmount, nHeight, nHeight + getDelayForName(name)); CClaimValue claim(txhash, nOut, nAmount, nHeight, nHeight + getDelayForName(name));
return addClaimToQueues(name, claim);
} }
bool CClaimTrieCache::addClaim(const std::string name, uint256 txhash, uint32_t nOut, CAmount nAmount, int nHeight, uint256 prevTxhash, uint32_t nPrevOut) const bool CClaimTrieCache::addClaim(const std::string name, uint256 txhash, uint32_t nOut, CAmount nAmount, int nHeight, uint256 prevTxhash, uint32_t nPrevOut) const
{ {
LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nAmount: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, txhash.GetHex(), nOut, nAmount, nHeight, nCurrentHeight); LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nAmount: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, txhash.GetHex(), nOut, nAmount, nHeight, nCurrentHeight);
assert(nHeight == nCurrentHeight); assert(nHeight == nCurrentHeight);
CClaimValue claim; CClaimValue currentClaim;
if (base->getInfoForName(name, claim)) if (base->getInfoForName(name, currentClaim))
{ {
if (claim.txhash == prevTxhash && claim.nOut == nPrevOut) if (currentClaim.txhash == prevTxhash && currentClaim.nOut == nPrevOut)
{ {
LogPrintf("%s: This is an update to a best claim. Previous claim txhash: %s, nOut: %d\n", __func__, prevTxhash.GetHex(), nPrevOut); LogPrintf("%s: This is an update to a best claim. Previous claim txhash: %s, nOut: %d\n", __func__, prevTxhash.GetHex(), nPrevOut);
return addClaimToQueues(name, txhash, nOut, nAmount, nHeight, nHeight); CClaimValue newClaim(txhash, nOut, nAmount, nHeight, nHeight, prevTxhash, nPrevOut);
return addClaimToQueues(name, newClaim);
} }
} }
return addClaim(name, txhash, nOut, nAmount, nHeight); return addClaim(name, txhash, nOut, nAmount, nHeight);
@ -1324,25 +1388,24 @@ bool CClaimTrieCache::addClaim(const std::string name, uint256 txhash, uint32_t
bool CClaimTrieCache::undoSpendClaim(const std::string name, uint256 txhash, uint32_t nOut, CAmount nAmount, int nHeight, int nValidAtHeight) const bool CClaimTrieCache::undoSpendClaim(const std::string name, uint256 txhash, uint32_t nOut, CAmount nAmount, int nHeight, int nValidAtHeight) const
{ {
LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nAmount: %d, nHeight: %d, nValidAtHeight: %d, nCurrentHeight: %d\n", __func__, name, txhash.GetHex(), nOut, nAmount, nHeight, nValidAtHeight, nCurrentHeight); LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nAmount: %d, nHeight: %d, nValidAtHeight: %d, nCurrentHeight: %d\n", __func__, name, txhash.GetHex(), nOut, nAmount, nHeight, nValidAtHeight, nCurrentHeight);
CClaimValue claim(txhash, nOut, nAmount, nHeight, nValidAtHeight);
if (nValidAtHeight < nCurrentHeight) if (nValidAtHeight < nCurrentHeight)
{ {
CClaimValue claim(txhash, nOut, nAmount, nHeight, nValidAtHeight);
claimQueueEntryType entry(name, claim); claimQueueEntryType entry(name, claim);
addToExpirationQueue(entry); addToExpirationQueue(entry);
return insertClaimIntoTrie(name, claim); return insertClaimIntoTrie(name, claim, false);
} }
else else
{ {
return addClaimToQueues(name, txhash, nOut, nAmount, nHeight, nValidAtHeight); return addClaimToQueues(name, claim);
} }
} }
bool CClaimTrieCache::addClaimToQueues(const std::string name, uint256 txhash, uint32_t nOut, CAmount nAmount, int nHeight, int nValidAtHeight) const bool CClaimTrieCache::addClaimToQueues(const std::string name, CClaimValue& claim) const
{ {
LogPrintf("%s: nValidAtHeight: %d\n", __func__, nValidAtHeight); LogPrintf("%s: nValidAtHeight: %d\n", __func__, claim.nValidAtHeight);
CClaimValue claim(txhash, nOut, nAmount, nHeight, nValidAtHeight);
claimQueueEntryType entry(name, claim); claimQueueEntryType entry(name, claim);
claimQueueType::iterator itQueueRow = getQueueCacheRow(nValidAtHeight, true); claimQueueType::iterator itQueueRow = getQueueCacheRow(claim.nValidAtHeight, true);
claimQueueNamesType::iterator itQueueNameRow = getQueueCacheNameRow(name, true); claimQueueNamesType::iterator itQueueNameRow = getQueueCacheNameRow(name, true);
itQueueRow->second.push_back(entry); itQueueRow->second.push_back(entry);
itQueueNameRow->second.push_back(claim); itQueueNameRow->second.push_back(claim);
@ -1395,21 +1458,21 @@ bool CClaimTrieCache::removeClaimFromQueue(const std::string name, uint256 txhas
bool CClaimTrieCache::undoAddClaim(const std::string name, uint256 txhash, uint32_t nOut, int nHeight) const bool CClaimTrieCache::undoAddClaim(const std::string name, uint256 txhash, uint32_t nOut, int nHeight) const
{ {
int throwaway; int throwaway;
return removeClaim(name, txhash, nOut, nHeight, throwaway); return removeClaim(name, txhash, nOut, nHeight, throwaway, false);
} }
bool CClaimTrieCache::spendClaim(const std::string name, uint256 txhash, uint32_t nOut, int nHeight, int& nValidAtHeight) const bool CClaimTrieCache::spendClaim(const std::string name, uint256 txhash, uint32_t nOut, int nHeight, int& nValidAtHeight) const
{ {
return removeClaim(name, txhash, nOut, nHeight, nValidAtHeight); return removeClaim(name, txhash, nOut, nHeight, nValidAtHeight, true);
} }
bool CClaimTrieCache::removeClaim(const std::string name, uint256 txhash, uint32_t nOut, int nHeight, int& nValidAtHeight) const bool CClaimTrieCache::removeClaim(const std::string name, uint256 txhash, uint32_t nOut, int nHeight, int& nValidAtHeight, bool fCheckTakeover) const
{ {
LogPrintf("%s: name: %s, txhash: %s, nOut: %s, nHeight: %s, nCurrentHeight: %s\n", __func__, name, txhash.GetHex(), nOut, nHeight, nCurrentHeight); LogPrintf("%s: name: %s, txhash: %s, nOut: %s, nHeight: %s, nCurrentHeight: %s\n", __func__, name, txhash.GetHex(), nOut, nHeight, nCurrentHeight);
bool removed = false; bool removed = false;
if (removeClaimFromQueue(name, txhash, nOut, nValidAtHeight)) if (removeClaimFromQueue(name, txhash, nOut, nValidAtHeight))
removed = true; removed = true;
if (removed == false && removeClaimFromTrie(name, txhash, nOut, nValidAtHeight)) if (removed == false && removeClaimFromTrie(name, txhash, nOut, nValidAtHeight, fCheckTakeover))
removed = true; removed = true;
if (removed == true) if (removed == true)
removeFromExpirationQueue(name, txhash, nOut, nHeight); removeFromExpirationQueue(name, txhash, nOut, nHeight);
@ -1464,7 +1527,7 @@ claimQueueType::iterator CClaimTrieCache::getExpirationQueueCacheRow(int nHeight
return itQueueRow; return itQueueRow;
} }
bool CClaimTrieCache::reorderTrieNode(const std::string name) const bool CClaimTrieCache::reorderTrieNode(const std::string name, bool fCheckTakeover) const
{ {
assert(base); assert(base);
nodeCacheType::iterator cachedNode; nodeCacheType::iterator cachedNode;
@ -1521,6 +1584,8 @@ bool CClaimTrieCache::reorderTrieNode(const std::string name) const
dirtyHashes.insert(sub); dirtyHashes.insert(sub);
} }
dirtyHashes.insert(name); dirtyHashes.insert(name);
if (fCheckTakeover)
namesToCheckForTakeover.insert(name);
} }
return true; return true;
} }
@ -1540,7 +1605,7 @@ bool CClaimTrieCache::getSupportsForName(const std::string name, supportMapEntry
} }
} }
bool CClaimTrieCache::insertSupportIntoMap(const std::string name, CSupportValue support) const bool CClaimTrieCache::insertSupportIntoMap(const std::string name, CSupportValue support, bool fCheckTakeover) const
{ {
supportMapType::iterator cachedNode; supportMapType::iterator cachedNode;
// If this node is already in the cache, use that // If this node is already in the cache, use that
@ -1557,10 +1622,10 @@ bool CClaimTrieCache::insertSupportIntoMap(const std::string name, CSupportValue
} }
cachedNode->second.push_back(support); cachedNode->second.push_back(support);
// See if this changed the biggest bid // See if this changed the biggest bid
return reorderTrieNode(name); return reorderTrieNode(name, fCheckTakeover);
} }
bool CClaimTrieCache::removeSupportFromMap(const std::string name, uint256 txhash, uint32_t nOut, uint256 supportedTxhash, uint32_t supportednOut, int nHeight, int& nValidAtHeight) const bool CClaimTrieCache::removeSupportFromMap(const std::string name, uint256 txhash, uint32_t nOut, uint256 supportedTxhash, uint32_t supportednOut, int nHeight, int& nValidAtHeight, bool fCheckTakeover) const
{ {
supportMapType::iterator cachedNode; supportMapType::iterator cachedNode;
cachedNode = supportCache.find(name); cachedNode = supportCache.find(name);
@ -1589,7 +1654,7 @@ bool CClaimTrieCache::removeSupportFromMap(const std::string name, uint256 txhas
if (itSupport != cachedNode->second.end()) if (itSupport != cachedNode->second.end())
{ {
cachedNode->second.erase(itSupport); cachedNode->second.erase(itSupport);
return reorderTrieNode(name); return reorderTrieNode(name, fCheckTakeover);
} }
else else
{ {
@ -1715,7 +1780,7 @@ bool CClaimTrieCache::undoSpendSupport(const std::string name, uint256 txhash, u
{ {
CSupportValue support(txhash, nOut, supportedTxhash, supportednOut, nAmount, nHeight, nValidAtHeight); CSupportValue support(txhash, nOut, supportedTxhash, supportednOut, nAmount, nHeight, nValidAtHeight);
supportQueueEntryType entry(name, support); supportQueueEntryType entry(name, support);
return insertSupportIntoMap(name, support); return insertSupportIntoMap(name, support, false);
} }
else else
{ {
@ -1723,12 +1788,12 @@ bool CClaimTrieCache::undoSpendSupport(const std::string name, uint256 txhash, u
} }
} }
bool CClaimTrieCache::removeSupport(const std::string name, uint256 txhash, uint32_t nOut, uint256 supportedTxhash, uint32_t supportednOut, int nHeight, int& nValidAtHeight) const bool CClaimTrieCache::removeSupport(const std::string name, uint256 txhash, uint32_t nOut, uint256 supportedTxhash, uint32_t supportednOut, int nHeight, int& nValidAtHeight, bool fCheckTakeover) const
{ {
bool removed = false; bool removed = false;
if (removeSupportFromQueue(name, txhash, nOut, supportedTxhash, supportednOut, nValidAtHeight)) if (removeSupportFromQueue(name, txhash, nOut, supportedTxhash, supportednOut, nValidAtHeight))
removed = true; removed = true;
if (removed == false && removeSupportFromMap(name, txhash, nOut, supportedTxhash, supportednOut, nHeight, nValidAtHeight)) if (removed == false && removeSupportFromMap(name, txhash, nOut, supportedTxhash, supportednOut, nHeight, nValidAtHeight, fCheckTakeover))
removed = true; removed = true;
return removed; return removed;
} }
@ -1737,16 +1802,16 @@ bool CClaimTrieCache::undoAddSupport(const std::string name, uint256 txhash, uin
{ {
LogPrintf("%s: name: %s, txhash: %s, nOut: %d, supportedTxhash: %s, supportednOut: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, txhash.GetHex(), nOut, supportedTxhash.GetHex(), supportednOut, nHeight, nCurrentHeight); LogPrintf("%s: name: %s, txhash: %s, nOut: %d, supportedTxhash: %s, supportednOut: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, txhash.GetHex(), nOut, supportedTxhash.GetHex(), supportednOut, nHeight, nCurrentHeight);
int throwaway; int throwaway;
return removeSupport(name, txhash, nOut, supportedTxhash, supportednOut, nHeight, throwaway); return removeSupport(name, txhash, nOut, supportedTxhash, supportednOut, nHeight, throwaway, false);
} }
bool CClaimTrieCache::spendSupport(const std::string name, uint256 txhash, uint32_t nOut, uint256 supportedTxhash, uint32_t supportednOut, int nHeight, int& nValidAtHeight) const bool CClaimTrieCache::spendSupport(const std::string name, uint256 txhash, uint32_t nOut, uint256 supportedTxhash, uint32_t supportednOut, int nHeight, int& nValidAtHeight) const
{ {
LogPrintf("%s: name: %s, txhash: %s, nOut: %d, supportedTxhash: %s, supportednOut: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, txhash.GetHex(), nOut, supportedTxhash.GetHex(), supportednOut, nHeight, nCurrentHeight); LogPrintf("%s: name: %s, txhash: %s, nOut: %d, supportedTxhash: %s, supportednOut: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, txhash.GetHex(), nOut, supportedTxhash.GetHex(), supportednOut, nHeight, nCurrentHeight);
return removeSupport(name, txhash, nOut, supportedTxhash, supportednOut, nHeight, nValidAtHeight); return removeSupport(name, txhash, nOut, supportedTxhash, supportednOut, nHeight, nValidAtHeight, true);
} }
bool CClaimTrieCache::incrementBlock(claimQueueRowType& insertUndo, claimQueueRowType& expireUndo, supportQueueRowType& insertSupportUndo) const bool CClaimTrieCache::incrementBlock(claimQueueRowType& insertUndo, claimQueueRowType& expireUndo, supportQueueRowType& insertSupportUndo, std::vector<std::pair<std::string, int> >& takeoverHeightUndo) const
{ {
LogPrintf("%s: nCurrentHeight (before increment): %d\n", __func__, nCurrentHeight); LogPrintf("%s: nCurrentHeight (before increment): %d\n", __func__, nCurrentHeight);
claimQueueType::iterator itQueueRow = getQueueCacheRow(nCurrentHeight, false); claimQueueType::iterator itQueueRow = getQueueCacheRow(nCurrentHeight, false);
@ -1784,7 +1849,7 @@ bool CClaimTrieCache::incrementBlock(claimQueueRowType& insertUndo, claimQueueRo
LogPrintf("No claims found for that name\n"); LogPrintf("No claims found for that name\n");
} }
} }
insertClaimIntoTrie(itEntry->first, itEntry->second); insertClaimIntoTrie(itEntry->first, itEntry->second, true);
insertUndo.push_back(*itEntry); insertUndo.push_back(*itEntry);
} }
itQueueRow->second.clear(); itQueueRow->second.clear();
@ -1795,7 +1860,7 @@ bool CClaimTrieCache::incrementBlock(claimQueueRowType& insertUndo, claimQueueRo
for (claimQueueRowType::iterator itEntry = itExpirationRow->second.begin(); itEntry != itExpirationRow->second.end(); ++itEntry) for (claimQueueRowType::iterator itEntry = itExpirationRow->second.begin(); itEntry != itExpirationRow->second.end(); ++itEntry)
{ {
int nValidAtHeight; int nValidAtHeight;
assert(removeClaimFromTrie(itEntry->first, itEntry->second.txhash, itEntry->second.nOut, nValidAtHeight)); assert(removeClaimFromTrie(itEntry->first, itEntry->second.txhash, itEntry->second.nOut, nValidAtHeight, true));
expireUndo.push_back(*itEntry); expireUndo.push_back(*itEntry);
} }
itExpirationRow->second.clear(); itExpirationRow->second.clear();
@ -1835,65 +1900,252 @@ bool CClaimTrieCache::incrementBlock(claimQueueRowType& insertUndo, claimQueueRo
LogPrintf("No support found for that name\n"); LogPrintf("No support found for that name\n");
} }
} }
insertSupportIntoMap(itSupport->first, itSupport->second); insertSupportIntoMap(itSupport->first, itSupport->second, true);
insertSupportUndo.push_back(*itSupport); insertSupportUndo.push_back(*itSupport);
} }
itSupportRow->second.clear(); itSupportRow->second.clear();
} }
// check each potentially taken over name to see if a takeover occurred.
// if it did, then check the claim and support insertion queues for
// the names that have been taken over, immediately insert all claim and
// supports for those names, and stick them in the insertUndo or
// insertSupportUndo vectors, with the nValidAtHeight they had prior to
// this block
// Run through all names that have been taken over
for (std::set<std::string>::iterator itNamesToCheck = namesToCheckForTakeover.begin(); itNamesToCheck != namesToCheckForTakeover.end(); ++itNamesToCheck)
{
// Check if a takeover has occurred
nodeCacheType::iterator itCachedNode = cache.find(*itNamesToCheck);
// many possibilities
// if this node is new, don't put it into the undo -- there will be nothing to restore, after all
// if all of this node's claims were deleted, it should be put into the undo -- there could be
// claims in the queue for that name and the takeover height should be the current height
// if the node is not in the cache, or getbestclaim fails, that means all of its claims were
// deleted
// if base->getInfoForName returns false, that means it's new and shouldn't go into the undo
// if both exist, and the current best claim is not the same as or the parent to the new best
// claim, then ownership has changed and the current height of last takeover should go into
// the queue
CClaimValue claimInCache;
CClaimValue claimInTrie;
bool haveClaimInCache;
bool haveClaimInTrie;
if (itCachedNode == cache.end())
{
haveClaimInCache = false;
}
else
{
haveClaimInCache = itCachedNode->second->getBestClaim(claimInCache);
}
haveClaimInTrie = base->getInfoForName(*itNamesToCheck, claimInTrie);
bool takeoverHappened = false;
if (!haveClaimInTrie)
{
takeoverHappened = true;
}
else if (!haveClaimInCache)
{
takeoverHappened = true;
}
else if (claimInCache != claimInTrie)
{
if (!claimInCache.fIsUpdate || claimInCache.updateToTxhash != claimInTrie.txhash || claimInCache.updateToNOut != claimInTrie.nOut)
{
takeoverHappened = true;
}
}
if (takeoverHappened && !base->fConstantDelay)
{
// Get all claims in the queue for that name
claimQueueNamesType::iterator itQueueNameRow = getQueueCacheNameRow(*itNamesToCheck, false);
if (itQueueNameRow != claimQueueNameCache.end())
{
for (std::vector<CClaimValue>::iterator itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName)
{
// Pull those claims out of the height-based queue
claimQueueType::iterator itQueueRow = getQueueCacheRow(itQueueName->nValidAtHeight, false);
if (itQueueRow != claimQueueCache.end())
{
claimQueueRowType::iterator itQueue;
for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue)
{
if (*itNamesToCheck == itQueue->first && itQueue->second == *itQueueName)
{
break;
}
}
if (itQueue != itQueueRow->second.end())
{
// Insert them into the queue undo with their previous nValidAtHeight
insertUndo.push_back(*itQueue);
// Insert them into the name trie with the new nValidAtHeight
itQueue->second.nValidAtHeight = nCurrentHeight;
insertClaimIntoTrie(itQueue->first, itQueue->second, false);
// Delete them from the height-based queue
itQueueRow->second.erase(itQueue);
}
else
{
// here be problems
}
}
else
{
// here be problems
}
}
// remove all claims from the queue for that name
itQueueNameRow->second.clear();
}
//
// Then, get all supports in the queue for that name
supportQueueNamesType::iterator itSupportQueueNameRow = getSupportQueueCacheNameRow(*itNamesToCheck, false);
if (itSupportQueueNameRow != supportQueueNameCache.end())
{
for (std::vector<CSupportValue>::iterator itSupportQueueName = itSupportQueueNameRow->second.begin(); itSupportQueueName != itSupportQueueNameRow->second.end(); ++itSupportQueueName)
{
// Pull those supports out of the height-based queue
supportQueueType::iterator itSupportQueueRow = getSupportQueueCacheRow(itSupportQueueName->nValidAtHeight, false);
if (itSupportQueueRow != supportQueueCache.end())
{
supportQueueRowType::iterator itSupportQueue;
for (itSupportQueue = itSupportQueueRow->second.begin(); itSupportQueue != itSupportQueueRow->second.end(); ++itSupportQueue)
{
if (*itNamesToCheck == itSupportQueue->first && itSupportQueue->second == *itSupportQueueName)
{
break;
}
}
if (itSupportQueue != itSupportQueueRow->second.end())
{
// Insert them into the support queue undo with the previous nValidAtHeight
insertSupportUndo.push_back(*itSupportQueue);
// Insert them into the support map with the new nValidAtHeight
itSupportQueue->second.nValidAtHeight = nCurrentHeight;
insertSupportIntoMap(itSupportQueue->first, itSupportQueue->second, false);
// Delete them from the height-based queue
itSupportQueueRow->second.erase(itSupportQueue);
}
else
{
// here be problems
}
}
else
{
// here be problems
}
}
// remove all supports from the queue for that name
itSupportQueueNameRow->second.clear();
}
}
if (takeoverHappened)
{
// save the old last height so that it can be restored if the block is undone
if (haveClaimInTrie)
{
int nHeightOfLastTakeover;
assert(getLastTakeoverForName(*itNamesToCheck, nHeightOfLastTakeover));
takeoverHeightUndo.push_back(std::make_pair(*itNamesToCheck, nHeightOfLastTakeover));
}
itCachedNode = cache.find(*itNamesToCheck);
if (itCachedNode != cache.end())
{
cacheTakeoverHeights[*itNamesToCheck] = nCurrentHeight;
}
}
}
namesToCheckForTakeover.clear();
nCurrentHeight++; nCurrentHeight++;
return true; return true;
} }
bool CClaimTrieCache::decrementBlock(claimQueueRowType& insertUndo, claimQueueRowType& expireUndo, supportQueueRowType& insertSupportUndo) const bool CClaimTrieCache::decrementBlock(claimQueueRowType& insertUndo, claimQueueRowType& expireUndo, supportQueueRowType& insertSupportUndo, std::vector<std::pair<std::string, int> >& takeoverHeightUndo) const
{ {
LogPrintf("%s: nCurrentHeight (before decrement): %d\n", __func__, nCurrentHeight); LogPrintf("%s: nCurrentHeight (before decrement): %d\n", __func__, nCurrentHeight);
nCurrentHeight--; nCurrentHeight--;
if (insertUndo.begin() != insertUndo.end())
{
claimQueueType::iterator itQueueRow = getQueueCacheRow(nCurrentHeight, true);
for (claimQueueRowType::iterator itInsertUndo = insertUndo.begin(); itInsertUndo != insertUndo.end(); ++itInsertUndo) for (claimQueueRowType::iterator itInsertUndo = insertUndo.begin(); itInsertUndo != insertUndo.end(); ++itInsertUndo)
{ {
claimQueueType::iterator itQueueRow = getQueueCacheRow(itInsertUndo->second.nValidAtHeight, true);
int nValidHeightInTrie; int nValidHeightInTrie;
assert(removeClaimFromTrie(itInsertUndo->first, itInsertUndo->second.txhash, itInsertUndo->second.nOut, nValidHeightInTrie)); assert(removeClaimFromTrie(itInsertUndo->first, itInsertUndo->second.txhash, itInsertUndo->second.nOut, nValidHeightInTrie, false));
assert(nValidHeightInTrie == itInsertUndo->second.nValidAtHeight);
claimQueueNamesType::iterator itQueueNameRow = getQueueCacheNameRow(itInsertUndo->first, true); claimQueueNamesType::iterator itQueueNameRow = getQueueCacheNameRow(itInsertUndo->first, true);
itQueueRow->second.push_back(*itInsertUndo); itQueueRow->second.push_back(*itInsertUndo);
itQueueNameRow->second.push_back(itInsertUndo->second); itQueueNameRow->second.push_back(itInsertUndo->second);
} }
}
if (expireUndo.begin() != expireUndo.end()) if (expireUndo.begin() != expireUndo.end())
{ {
claimQueueType::iterator itExpireRow = getExpirationQueueCacheRow(nCurrentHeight, true); claimQueueType::iterator itExpireRow = getExpirationQueueCacheRow(nCurrentHeight, true);
for (claimQueueRowType::iterator itExpireUndo = expireUndo.begin(); itExpireUndo != expireUndo.end(); ++itExpireUndo) for (claimQueueRowType::iterator itExpireUndo = expireUndo.begin(); itExpireUndo != expireUndo.end(); ++itExpireUndo)
{ {
insertClaimIntoTrie(itExpireUndo->first, itExpireUndo->second); insertClaimIntoTrie(itExpireUndo->first, itExpireUndo->second, false);
itExpireRow->second.push_back(*itExpireUndo); itExpireRow->second.push_back(*itExpireUndo);
} }
} }
if (insertSupportUndo.begin() != insertSupportUndo.end())
{
supportQueueType::iterator itSupportRow = getSupportQueueCacheRow(nCurrentHeight, true);
for (supportQueueRowType::iterator itSupportUndo = insertSupportUndo.begin(); itSupportUndo != insertSupportUndo.end(); ++itSupportUndo) for (supportQueueRowType::iterator itSupportUndo = insertSupportUndo.begin(); itSupportUndo != insertSupportUndo.end(); ++itSupportUndo)
{ {
supportQueueType::iterator itSupportRow = getSupportQueueCacheRow(itSupportUndo->second.nValidAtHeight, true);
int nValidHeightInMap; int nValidHeightInMap;
assert(removeSupportFromMap(itSupportUndo->first, itSupportUndo->second.txhash, itSupportUndo->second.nOut, itSupportUndo->second.supportTxhash, itSupportUndo->second.supportnOut, itSupportUndo->second.nHeight, nValidHeightInMap)); assert(removeSupportFromMap(itSupportUndo->first, itSupportUndo->second.txhash, itSupportUndo->second.nOut, itSupportUndo->second.supportTxhash, itSupportUndo->second.supportnOut, itSupportUndo->second.nHeight, nValidHeightInMap, false));
assert(nValidHeightInMap == itSupportUndo->second.nValidAtHeight);
supportQueueNamesType::iterator itSupportNameRow = getSupportQueueCacheNameRow(itSupportUndo->first, true); supportQueueNamesType::iterator itSupportNameRow = getSupportQueueCacheNameRow(itSupportUndo->first, true);
itSupportRow->second.push_back(*itSupportUndo); itSupportRow->second.push_back(*itSupportUndo);
itSupportNameRow->second.push_back(itSupportUndo->second); itSupportNameRow->second.push_back(itSupportUndo->second);
} }
for (std::vector<std::pair<std::string, int> >::iterator itTakeoverHeightUndo = takeoverHeightUndo.begin(); itTakeoverHeightUndo != takeoverHeightUndo.end(); ++itTakeoverHeightUndo)
{
cacheTakeoverHeights[itTakeoverHeightUndo->first] = itTakeoverHeightUndo->second;
} }
return true; return true;
} }
bool CClaimTrieCache::getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const
{
std::map<std::string, int>::iterator itHeights = cacheTakeoverHeights.find(name);
if (itHeights == cacheTakeoverHeights.end())
{
if (base->getLastTakeoverForName(name, lastTakeoverHeight))
{
return true;
}
else
{
if (fRequireTakeoverHeights)
{
return false;
}
else
{
lastTakeoverHeight = 0;
return true;
}
}
}
lastTakeoverHeight = itHeights->second;
return true;
}
int CClaimTrieCache::getDelayForName(const std::string name) const int CClaimTrieCache::getDelayForName(const std::string name) const
{ {
if (base->fConstantDelay) if (base->fConstantDelay)
{ {
return base->nConstantDelayHeight; return base->nConstantDelayHeight;
} }
else
{
int nHeightOfLastTakeover;
if (getLastTakeoverForName(name, nHeightOfLastTakeover))
{
return nHeightOfLastTakeover >> base->nProportionalDelayBits;
}
else
{
return 0; return 0;
} }
}
}
uint256 CClaimTrieCache::getBestBlock() uint256 CClaimTrieCache::getBestBlock()
{ {
@ -1923,6 +2175,8 @@ bool CClaimTrieCache::clear() const
supportCache.clear(); supportCache.clear();
supportQueueCache.clear(); supportQueueCache.clear();
supportQueueNameCache.clear(); supportQueueNameCache.clear();
namesToCheckForTakeover.clear();
cacheTakeoverHeights.clear();
return true; return true;
} }
@ -1930,7 +2184,7 @@ bool CClaimTrieCache::flush()
{ {
if (dirty()) if (dirty())
getMerkleHash(); getMerkleHash();
bool success = base->update(cache, cacheHashes, getBestBlock(), claimQueueCache, claimQueueNameCache, expirationQueueCache, nCurrentHeight, supportCache, supportQueueCache, supportQueueNameCache); bool success = base->update(cache, cacheHashes, cacheTakeoverHeights, getBestBlock(), claimQueueCache, claimQueueNameCache, expirationQueueCache, nCurrentHeight, supportCache, supportQueueCache, supportQueueNameCache);
if (success) if (success)
{ {
success = clear(); success = clear();

View file

@ -57,56 +57,7 @@ public:
uint256 GetHash() const; uint256 GetHash() const;
unsigned int GetSerializeSize(int nType, int nVersion) const ADD_SERIALIZE_METHODS;
{
unsigned int nSize = 0;
nSize += ::GetSerializeSize(txhash, nType, nVersion);
nSize += ::GetSerializeSize(nOut, nType, nVersion);
nSize += ::GetSerializeSize(nAmount, nType, nVersion);
nSize += ::GetSerializeSize(nHeight, nType, nVersion);
nSize += ::GetSerializeSize(nValidAtHeight, nType, nVersion);
nSize += ::GetSerializeSize(fIsUpdate, nType, nVersion);
if (fIsUpdate)
{
nSize += ::GetSerializeSize(updateToTxhash, nType, nVersion);
nSize += ::GetSerializeSize(updateToNOut, nType, nVersion);
}
return nSize;
}
template<typename Stream>
void Serialize(Stream& s, int nType, int nVersion) const
{
::Serialize(s, txhash, nType, nVersion);
::Serialize(s, nOut, nType, nVersion);
::Serialize(s, nAmount, nType, nVersion);
::Serialize(s, nHeight, nType, nVersion);
::Serialize(s, nValidAtHeight, nType, nVersion);
::Serialize(s, fIsUpdate, nType, nVersion);
if (fIsUpdate)
{
::Serialize(s, updateToTxhash, nType, nVersion);
::Serialize(s, updateToNOut, nType, nVersion);
}
}
template<typename Stream>
void Unserialize(Stream& s, int nType, int nVersion)
{
::Unserialize(s, txhash, nType, nVersion);
::Unserialize(s, nOut, nType, nVersion);
::Unserialize(s, nAmount, nType, nVersion);
::Unserialize(s, nHeight, nType, nVersion);
::Unserialize(s, nValidAtHeight, nType, nVersion);
::Unserialize(s, fIsUpdate, nType, nVersion);
if (fIsUpdate)
{
::Unserialize(s, updateToTxhash, nType, nVersion);
::Unserialize(s, updateToNOut, nType, nVersion);
}
}
/*ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation> template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@ -115,7 +66,7 @@ public:
READWRITE(nAmount); READWRITE(nAmount);
READWRITE(nHeight); READWRITE(nHeight);
READWRITE(nValidAtHeight); READWRITE(nValidAtHeight);
}*/ }
bool operator<(const CClaimValue& other) const bool operator<(const CClaimValue& other) const
{ {
@ -204,11 +155,11 @@ typedef std::pair<std::string, CClaimTrieNode> namedNodeType;
class CClaimTrieNode class CClaimTrieNode
{ {
public: public:
CClaimTrieNode() {} CClaimTrieNode() : nHeightOfLastTakeover(0) {}
CClaimTrieNode(uint256 hash) : hash(hash) {} CClaimTrieNode(uint256 hash) : hash(hash), nHeightOfLastTakeover(0) {}
uint256 hash; uint256 hash;
nodeMapType children; nodeMapType children;
int nBlocksSinceTakeover; int nHeightOfLastTakeover;
std::vector<CClaimValue> claims; std::vector<CClaimValue> claims;
bool insertClaim(CClaimValue claim); bool insertClaim(CClaimValue claim);
@ -224,6 +175,7 @@ public:
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(hash); READWRITE(hash);
READWRITE(claims); READWRITE(claims);
READWRITE(nHeightOfLastTakeover);
} }
bool operator==(const CClaimTrieNode& other) const bool operator==(const CClaimTrieNode& other) const
@ -270,10 +222,10 @@ class CClaimTrieCache;
class CClaimTrie class CClaimTrie
{ {
public: public:
CClaimTrie(bool fMemory = false, bool fWipe = false) CClaimTrie(bool fMemory = false, bool fWipe = false, bool fConstantDelay = false)
: db(GetDataDir() / "claimtrie", 100, fMemory, fWipe, false) : db(GetDataDir() / "claimtrie", 100, fMemory, fWipe, false)
, nCurrentHeight(0), nExpirationTime(262974) , nCurrentHeight(0), nExpirationTime(262974)
, fConstantDelay(false), nConstantDelayHeight(100) , fConstantDelay(fConstantDelay), nConstantDelayHeight(100)
, nProportionalDelayBits(5) , nProportionalDelayBits(5)
, root(uint256S("0000000000000000000000000000000000000000000000000000000000000001")) , root(uint256S("0000000000000000000000000000000000000000000000000000000000000001"))
{} {}
@ -283,13 +235,14 @@ public:
bool empty() const; bool empty() const;
void clear(); void clear();
bool checkConsistency(); bool checkConsistency() const;
bool WriteToDisk(); bool WriteToDisk();
bool ReadFromDisk(bool check = false); bool ReadFromDisk(bool check = false);
std::vector<namedNodeType> flattenTrie() const; std::vector<namedNodeType> flattenTrie() const;
bool getInfoForName(const std::string& name, CClaimValue& claim) const; bool getInfoForName(const std::string& name, CClaimValue& claim) const;
bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const;
bool queueEmpty() const; bool queueEmpty() const;
bool supportEmpty() const; bool supportEmpty() const;
@ -332,7 +285,10 @@ public:
private: private:
void clear(CClaimTrieNode* current); void clear(CClaimTrieNode* current);
const CClaimTrieNode* getNodeForName(const std::string& name) const;
bool update(nodeCacheType& cache, hashMapType& hashes, bool update(nodeCacheType& cache, hashMapType& hashes,
std::map<std::string, int>& takeoverHeights,
const uint256& hashBlock, claimQueueType& queueCache, const uint256& hashBlock, claimQueueType& queueCache,
claimQueueNamesType& queueNameCache, claimQueueNamesType& queueNameCache,
claimQueueType& expirationQueueCache, int nNewHeight, claimQueueType& expirationQueueCache, int nNewHeight,
@ -341,9 +297,10 @@ private:
supportQueueNamesType& supportQueueNameCache); supportQueueNamesType& supportQueueNameCache);
bool updateName(const std::string& name, CClaimTrieNode* updatedNode); bool updateName(const std::string& name, CClaimTrieNode* updatedNode);
bool updateHash(const std::string& name, uint256& hash); bool updateHash(const std::string& name, uint256& hash);
bool updateTakeoverHeight(const std::string& name, int nTakeoverHeight);
bool recursiveNullify(CClaimTrieNode* node, std::string& name); bool recursiveNullify(CClaimTrieNode* node, std::string& name);
bool recursiveCheckConsistency(CClaimTrieNode* node); bool recursiveCheckConsistency(const CClaimTrieNode* node) const;
bool InsertFromDisk(const std::string& name, CClaimTrieNode* node); bool InsertFromDisk(const std::string& name, CClaimTrieNode* node);
@ -393,7 +350,9 @@ private:
class CClaimTrieCache class CClaimTrieCache
{ {
public: public:
CClaimTrieCache(CClaimTrie* base): base(base) CClaimTrieCache(CClaimTrie* base, bool fRequireTakeoverHeights = true)
: base(base),
fRequireTakeoverHeights(fRequireTakeoverHeights)
{ {
assert(base); assert(base);
nCurrentHeight = base->nCurrentHeight; nCurrentHeight = base->nCurrentHeight;
@ -437,19 +396,25 @@ public:
bool incrementBlock(claimQueueRowType& insertUndo, bool incrementBlock(claimQueueRowType& insertUndo,
claimQueueRowType& expireUndo, claimQueueRowType& expireUndo,
supportQueueRowType& insertSupportUndo) const; supportQueueRowType& insertSupportUndo,
std::vector<std::pair<std::string, int> >& takeoverHeightUndo) const;
bool decrementBlock(claimQueueRowType& insertUndo, bool decrementBlock(claimQueueRowType& insertUndo,
claimQueueRowType& expireUndo, claimQueueRowType& expireUndo,
supportQueueRowType& insertSupportUndo) const; supportQueueRowType& insertSupportUndo,
std::vector<std::pair<std::string, int> >& takeoverHeightUndo) const;
~CClaimTrieCache() { clear(); } ~CClaimTrieCache() { clear(); }
bool insertClaimIntoTrie(const std::string name, CClaimValue claim) const; bool insertClaimIntoTrie(const std::string name, CClaimValue claim,
bool fCheckTakeover = false) const;
bool removeClaimFromTrie(const std::string name, uint256 txhash, bool removeClaimFromTrie(const std::string name, uint256 txhash,
uint32_t nOut, int& nValidAtHeight) const; uint32_t nOut, int& nValidAtHeight,
bool fCheckTakeover = false) const;
private: private:
CClaimTrie* base; CClaimTrie* base;
bool fRequireTakeoverHeights;
mutable nodeCacheType cache; mutable nodeCacheType cache;
mutable std::set<std::string> dirtyHashes; mutable std::set<std::string> dirtyHashes;
mutable hashMapType cacheHashes; mutable hashMapType cacheHashes;
@ -459,6 +424,8 @@ private:
mutable supportMapType supportCache; mutable supportMapType supportCache;
mutable supportQueueType supportQueueCache; mutable supportQueueType supportQueueCache;
mutable supportQueueNamesType supportQueueNameCache; mutable supportQueueNamesType supportQueueNameCache;
mutable std::set<std::string> namesToCheckForTakeover;
mutable std::map<std::string, int> cacheTakeoverHeights;
mutable int nCurrentHeight; // Height of the block that is being worked on, which is mutable int nCurrentHeight; // Height of the block that is being worked on, which is
// one greater than the height of the chain's tip // one greater than the height of the chain's tip
@ -466,7 +433,7 @@ private:
uint256 computeHash() const; uint256 computeHash() const;
bool reorderTrieNode(const std::string name) const; bool reorderTrieNode(const std::string name, bool fCheckTakeover) const;
bool recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent, bool recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent,
std::string sPos) const; std::string sPos) const;
bool recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, bool recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos,
@ -476,11 +443,9 @@ private:
bool clear() const; bool clear() const;
bool removeClaim(const std::string name, uint256 txhash, uint32_t nOut, bool removeClaim(const std::string name, uint256 txhash, uint32_t nOut,
int nHeight, int& nValidAtHeight) const; int nHeight, int& nValidAtHeight, bool fCheckTakeover) const;
bool addClaimToQueues(const std::string name, uint256 txhash, bool addClaimToQueues(const std::string name, CClaimValue& claim) const;
uint32_t nOut, CAmount nAmount, int nHeight,
int nValidAtHeight) const;
bool removeClaimFromQueue(const std::string name, uint256 txhash, bool removeClaimFromQueue(const std::string name, uint256 txhash,
uint32_t nOut, int& nValidAtHeight) const; uint32_t nOut, int& nValidAtHeight) const;
void addToExpirationQueue(claimQueueEntryType& entry) const; void addToExpirationQueue(claimQueueEntryType& entry) const;
@ -496,14 +461,16 @@ private:
bool removeSupport(const std::string name, uint256 txhash, uint32_t nOut, bool removeSupport(const std::string name, uint256 txhash, uint32_t nOut,
uint256 supportedTxhash, uint32_t supportednOut, uint256 supportedTxhash, uint32_t supportednOut,
int nHeight, int& nValidAtHeight) const; int nHeight, int& nValidAtHeight,
bool fCheckTakeover) const;
bool removeSupportFromMap(const std::string name, uint256 txhash, bool removeSupportFromMap(const std::string name, uint256 txhash,
uint32_t nOut, uint256 supportedTxhash, uint32_t nOut, uint256 supportedTxhash,
uint32_t supportednOut, int nHeight, uint32_t supportednOut, int nHeight,
int& nValidAtHeight) const; int& nValidAtHeight, bool fCheckTakeover) const;
bool insertSupportIntoMap(const std::string name, bool insertSupportIntoMap(const std::string name,
CSupportValue support) const; CSupportValue support,
bool fCheckTakeover) const;
supportQueueType::iterator getSupportQueueCacheRow(int nHeight, supportQueueType::iterator getSupportQueueCacheRow(int nHeight,
bool createIfNotExists) const; bool createIfNotExists) const;
@ -522,6 +489,8 @@ private:
bool getSupportsForName(const std::string name, bool getSupportsForName(const std::string name,
supportMapEntryType& node) const; supportMapEntryType& node) const;
bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const;
int getDelayForName(const std::string name) const; int getDelayForName(const std::string name) const;
}; };

View file

@ -1602,7 +1602,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
if (blockUndo.vtxundo.size() + 1 != block.vtx.size()) if (blockUndo.vtxundo.size() + 1 != block.vtx.size())
return error("DisconnectBlock(): block and undo data inconsistent"); return error("DisconnectBlock(): block and undo data inconsistent");
assert(trieCache.decrementBlock(blockUndo.insertUndo, blockUndo.expireUndo, blockUndo.insertSupportUndo)); assert(trieCache.decrementBlock(blockUndo.insertUndo, blockUndo.expireUndo, blockUndo.insertSupportUndo, blockUndo.takeoverHeightUndo));
// undo transactions in reverse order // undo transactions in reverse order
for (int i = block.vtx.size() - 1; i >= 0; i--) { for (int i = block.vtx.size() - 1; i >= 0; i--) {
@ -2023,7 +2023,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
} }
assert(trieCache.incrementBlock(blockundo.insertUndo, blockundo.expireUndo, blockundo.insertSupportUndo)); assert(trieCache.incrementBlock(blockundo.insertUndo, blockundo.expireUndo, blockundo.insertSupportUndo, blockundo.takeoverHeightUndo));
if (trieCache.getMerkleHash() != block.hashClaimTrie) if (trieCache.getMerkleHash() != block.hashClaimTrie)
return state.DoS(100, return state.DoS(100,

View file

@ -437,7 +437,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
claimQueueRowType dummyInsertUndo; claimQueueRowType dummyInsertUndo;
claimQueueRowType dummyExpireUndo; claimQueueRowType dummyExpireUndo;
supportQueueRowType dummyInsertSupportUndo; supportQueueRowType dummyInsertSupportUndo;
trieCache.incrementBlock(dummyInsertUndo, dummyExpireUndo, dummyInsertSupportUndo); std::vector<std::pair<std::string, int> > dummyTakeoverHeightUndo;
trieCache.incrementBlock(dummyInsertUndo, dummyExpireUndo, dummyInsertSupportUndo, dummyTakeoverHeightUndo);
pblock->hashClaimTrie = trieCache.getMerkleHash(); pblock->hashClaimTrie = trieCache.getMerkleHash();
CValidationState state; CValidationState state;

View file

@ -158,20 +158,20 @@ BOOST_AUTO_TEST_CASE(claimtrie_merkle_hash)
CMutableTransaction tx6 = BuildTransaction(tx5.GetHash()); CMutableTransaction tx6 = BuildTransaction(tx5.GetHash());
uint256 hash1; uint256 hash1;
hash1.SetHex("09732c6efebb4065a27f184285a6b66280a978cf972b1f41a563f0d3644f3e5c"); hash1.SetHex("4bbf61ec5669c721bf007c71c59f85e6658f1de7b4562078e22f69f8f7ebcafd");
uint256 hash2; uint256 hash2;
hash2.SetHex("8db92b76b6b0416d7abda4fd7404ba69e340853dfe9ffc04843c50142b857471"); hash2.SetHex("33d00d8f4707eb0abef7297a7ff4975e7354fe1ed81455f28301dbceb939494d");
uint256 hash3; uint256 hash3;
hash3.SetHex("2e38561067f3e83d6ca0b627861689de72bba77cb5aca69d13b3685b5229525b"); hash3.SetHex("eb19bbaeecfd6dee77a8cb69286ac01226caee3c3883f55b86d0ca5a2f4252d7");
uint256 hash4; uint256 hash4;
hash4.SetHex("6ec84089eb4ca1aeead6cf3538d4def78baebb44715c31be8790e627e0dcbc28"); hash4.SetHex("a889778ba28603294c1e5c7cec469a9019332ec93838b2f1331ebba547c5fd22");
BOOST_CHECK(pclaimTrie->empty()); BOOST_CHECK(pclaimTrie->empty());
CClaimTrieCache ntState(pclaimTrie); CClaimTrieCache ntState(pclaimTrie, false);
ntState.insertClaimIntoTrie(std::string("test"), CClaimValue(tx1.GetHash(), 0, 50, 100, 200)); ntState.insertClaimIntoTrie(std::string("test"), CClaimValue(tx1.GetHash(), 0, 50, 100, 200));
ntState.insertClaimIntoTrie(std::string("test2"), CClaimValue(tx2.GetHash(), 0, 50, 100, 200)); ntState.insertClaimIntoTrie(std::string("test2"), CClaimValue(tx2.GetHash(), 0, 50, 100, 200));
@ -192,7 +192,7 @@ BOOST_AUTO_TEST_CASE(claimtrie_merkle_hash)
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2); BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2);
BOOST_CHECK(pclaimTrie->checkConsistency()); BOOST_CHECK(pclaimTrie->checkConsistency());
CClaimTrieCache ntState1(pclaimTrie); CClaimTrieCache ntState1(pclaimTrie, false);
ntState1.removeClaimFromTrie(std::string("test"), tx1.GetHash(), 0, unused); ntState1.removeClaimFromTrie(std::string("test"), tx1.GetHash(), 0, unused);
ntState1.removeClaimFromTrie(std::string("test2"), tx2.GetHash(), 0, unused); ntState1.removeClaimFromTrie(std::string("test2"), tx2.GetHash(), 0, unused);
ntState1.removeClaimFromTrie(std::string("test"), tx3.GetHash(), 0, unused); ntState1.removeClaimFromTrie(std::string("test"), tx3.GetHash(), 0, unused);
@ -200,7 +200,7 @@ BOOST_AUTO_TEST_CASE(claimtrie_merkle_hash)
BOOST_CHECK(ntState1.getMerkleHash() == hash0); BOOST_CHECK(ntState1.getMerkleHash() == hash0);
CClaimTrieCache ntState2(pclaimTrie); CClaimTrieCache ntState2(pclaimTrie, false);
ntState2.insertClaimIntoTrie(std::string("abab"), CClaimValue(tx6.GetHash(), 0, 50, 100, 200)); ntState2.insertClaimIntoTrie(std::string("abab"), CClaimValue(tx6.GetHash(), 0, 50, 100, 200));
ntState2.removeClaimFromTrie(std::string("test"), tx1.GetHash(), 0, unused); ntState2.removeClaimFromTrie(std::string("test"), tx1.GetHash(), 0, unused);
@ -212,7 +212,7 @@ BOOST_AUTO_TEST_CASE(claimtrie_merkle_hash)
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash3); BOOST_CHECK(pclaimTrie->getMerkleHash() == hash3);
BOOST_CHECK(pclaimTrie->checkConsistency()); BOOST_CHECK(pclaimTrie->checkConsistency());
CClaimTrieCache ntState3(pclaimTrie); CClaimTrieCache ntState3(pclaimTrie, false);
ntState3.insertClaimIntoTrie(std::string("test"), CClaimValue(tx1.GetHash(), 0, 50, 100, 200)); ntState3.insertClaimIntoTrie(std::string("test"), CClaimValue(tx1.GetHash(), 0, 50, 100, 200));
BOOST_CHECK(ntState3.getMerkleHash() == hash4); BOOST_CHECK(ntState3.getMerkleHash() == hash4);
ntState3.flush(); ntState3.flush();
@ -220,7 +220,7 @@ BOOST_AUTO_TEST_CASE(claimtrie_merkle_hash)
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash4); BOOST_CHECK(pclaimTrie->getMerkleHash() == hash4);
BOOST_CHECK(pclaimTrie->checkConsistency()); BOOST_CHECK(pclaimTrie->checkConsistency());
CClaimTrieCache ntState4(pclaimTrie); CClaimTrieCache ntState4(pclaimTrie, false);
ntState4.removeClaimFromTrie(std::string("abab"), tx6.GetHash(), 0, unused); ntState4.removeClaimFromTrie(std::string("abab"), tx6.GetHash(), 0, unused);
BOOST_CHECK(ntState4.getMerkleHash() == hash2); BOOST_CHECK(ntState4.getMerkleHash() == hash2);
ntState4.flush(); ntState4.flush();
@ -228,7 +228,7 @@ BOOST_AUTO_TEST_CASE(claimtrie_merkle_hash)
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2); BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2);
BOOST_CHECK(pclaimTrie->checkConsistency()); BOOST_CHECK(pclaimTrie->checkConsistency());
CClaimTrieCache ntState5(pclaimTrie); CClaimTrieCache ntState5(pclaimTrie, false);
ntState5.removeClaimFromTrie(std::string("test"), tx3.GetHash(), 0, unused); ntState5.removeClaimFromTrie(std::string("test"), tx3.GetHash(), 0, unused);
BOOST_CHECK(ntState5.getMerkleHash() == hash2); BOOST_CHECK(ntState5.getMerkleHash() == hash2);
@ -237,7 +237,7 @@ BOOST_AUTO_TEST_CASE(claimtrie_merkle_hash)
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2); BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2);
BOOST_CHECK(pclaimTrie->checkConsistency()); BOOST_CHECK(pclaimTrie->checkConsistency());
CClaimTrieCache ntState6(pclaimTrie); CClaimTrieCache ntState6(pclaimTrie, false);
ntState6.insertClaimIntoTrie(std::string("test"), CClaimValue(tx3.GetHash(), 0, 50, 101, 201)); ntState6.insertClaimIntoTrie(std::string("test"), CClaimValue(tx3.GetHash(), 0, 50, 101, 201));
BOOST_CHECK(ntState6.getMerkleHash() == hash2); BOOST_CHECK(ntState6.getMerkleHash() == hash2);
@ -246,7 +246,7 @@ BOOST_AUTO_TEST_CASE(claimtrie_merkle_hash)
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2); BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2);
BOOST_CHECK(pclaimTrie->checkConsistency()); BOOST_CHECK(pclaimTrie->checkConsistency());
CClaimTrieCache ntState7(pclaimTrie); CClaimTrieCache ntState7(pclaimTrie, false);
ntState7.removeClaimFromTrie(std::string("test"), tx3.GetHash(), 0, unused); ntState7.removeClaimFromTrie(std::string("test"), tx3.GetHash(), 0, unused);
ntState7.removeClaimFromTrie(std::string("test"), tx1.GetHash(), 0, unused); ntState7.removeClaimFromTrie(std::string("test"), tx1.GetHash(), 0, unused);
ntState7.removeClaimFromTrie(std::string("tes"), tx4.GetHash(), 0, unused); ntState7.removeClaimFromTrie(std::string("tes"), tx4.GetHash(), 0, unused);

View file

@ -59,7 +59,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
pblocktree = new CBlockTreeDB(1 << 20, true); pblocktree = new CBlockTreeDB(1 << 20, true);
pcoinsdbview = new CCoinsViewDB(1 << 23, true); pcoinsdbview = new CCoinsViewDB(1 << 23, true);
pcoinsTip = new CCoinsViewCache(pcoinsdbview); pcoinsTip = new CCoinsViewCache(pcoinsdbview);
pclaimTrie = new CClaimTrie(true); pclaimTrie = new CClaimTrie(true, false, true);
InitBlockIndex(); InitBlockIndex();
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
bool fFirstRun; bool fFirstRun;

View file

@ -83,6 +83,7 @@ public:
claimQueueRowType insertUndo; // any claims that went from the queue to the trie claimQueueRowType insertUndo; // any claims that went from the queue to the trie
claimQueueRowType expireUndo; // any claims that expired claimQueueRowType expireUndo; // any claims that expired
supportQueueRowType insertSupportUndo; // any claims that went from the support queue to the support map supportQueueRowType insertSupportUndo; // any claims that went from the support queue to the support map
std::vector<std::pair<std::string, int> > takeoverHeightUndo; // for any name that was taken over, the previous time that name was taken over
ADD_SERIALIZE_METHODS; ADD_SERIALIZE_METHODS;
@ -92,6 +93,7 @@ public:
READWRITE(insertUndo); READWRITE(insertUndo);
READWRITE(expireUndo); READWRITE(expireUndo);
READWRITE(insertSupportUndo); READWRITE(insertSupportUndo);
READWRITE(takeoverHeightUndo);
} }
}; };