diff --git a/src/claimtrie.cpp b/src/claimtrie.cpp index 401a57498..2e32d2f1e 100644 --- a/src/claimtrie.cpp +++ b/src/claimtrie.cpp @@ -61,7 +61,7 @@ template auto findOutPoint(T& cont, const C& point) -> decltype(cont.begin()) { using type = typename T::value_type; - static_assert(std::is_same::type, std::vector>::value, "T should be a vector type"); + static_assert(std::is_same::type, std::vector>::value, "T should be a vector type"); return std::find_if(cont.begin(), cont.end(), [&point](const type& val) { return equals(val, point); }); @@ -135,19 +135,31 @@ bool CClaimTrie::SyncToDisk() return db && db->Sync(); } -template -typename Container::value_type* getQueue(CDBWrapper& db, uint8_t dbkey, const Key& key, Container& queue, bool create) +template +using rm_ref = typename std::remove_reference::type; + +template +auto getRow(const CDBWrapper& db, uint8_t dbkey, const Key& key, Map& queue) -> COptional> { - auto itQueue = queue.find(key); - if (itQueue != queue.end()) - return &(*itQueue); - typename Container::mapped_type row; - if (db.Read(std::make_pair(dbkey, key), row) || create) { - auto ret = queue.insert(std::make_pair(key, row)); + auto it = queue.find(key); + if (it != queue.end()) + return {&(it->second)}; + typename Map::mapped_type row; + if (db.Read(std::make_pair(dbkey, key), row)) + return {std::move(row)}; + return {}; +} + +template +Value* getQueue(const CDBWrapper& db, uint8_t dbkey, const Key& key, std::map& queue, bool create) +{ + auto row = getRow(db, dbkey, key, queue); + if (row.unique() || (!row && create)) { + auto ret = queue.emplace(key, row ? std::move(*row) : Value{}); assert(ret.second); - return &(*ret.first); + return &(ret.first->second); } - return nullptr; + return row; } template @@ -158,57 +170,95 @@ inline constexpr bool supportedType() } template <> -std::pair>>* CClaimTrieCacheBase::getQueueCacheRow(int nHeight, bool createIfNotExists) +std::vector>* CClaimTrieCacheBase::getQueueCacheRow(int nHeight, bool createIfNotExists) { return getQueue(*(base->db), CLAIM_QUEUE_ROW, nHeight, claimQueueCache, createIfNotExists); } template <> -std::pair>>* CClaimTrieCacheBase::getQueueCacheRow(int nHeight, bool createIfNotExists) +std::vector>* CClaimTrieCacheBase::getQueueCacheRow(int nHeight, bool createIfNotExists) { return getQueue(*(base->db), SUPPORT_QUEUE_ROW, nHeight, supportQueueCache, createIfNotExists); } template -std::pair>>* CClaimTrieCacheBase::getQueueCacheRow(int, bool) +std::vector>* CClaimTrieCacheBase::getQueueCacheRow(int, bool) { supportedType(); return nullptr; } template <> -typename queueNameType::value_type* CClaimTrieCacheBase::getQueueCacheNameRow(const std::string& name, bool createIfNotExists) +COptional>> CClaimTrieCacheBase::getQueueCacheRow(int nHeight) const +{ + return getRow(*(base->db), CLAIM_QUEUE_ROW, nHeight, claimQueueCache); +} + +template <> +COptional>> CClaimTrieCacheBase::getQueueCacheRow(int nHeight) const +{ + return getRow(*(base->db), SUPPORT_QUEUE_ROW, nHeight, supportQueueCache); +} + +template +COptional>> CClaimTrieCacheBase::getQueueCacheRow(int) const +{ + supportedType(); + return {}; +} + +template <> +queueNameRowType* CClaimTrieCacheBase::getQueueCacheNameRow(const std::string& name, bool createIfNotExists) { return getQueue(*(base->db), CLAIM_QUEUE_NAME_ROW, name, claimQueueNameCache, createIfNotExists); } template <> -typename queueNameType::value_type* CClaimTrieCacheBase::getQueueCacheNameRow(const std::string& name, bool createIfNotExists) +queueNameRowType* CClaimTrieCacheBase::getQueueCacheNameRow(const std::string& name, bool createIfNotExists) { return getQueue(*(base->db), SUPPORT_QUEUE_NAME_ROW, name, supportQueueNameCache, createIfNotExists); } template -typename queueNameType::value_type* CClaimTrieCacheBase::getQueueCacheNameRow(const std::string&, bool) +queueNameRowType* CClaimTrieCacheBase::getQueueCacheNameRow(const std::string&, bool) { supportedType(); return nullptr; } template <> -typename expirationQueueType::value_type* CClaimTrieCacheBase::getExpirationQueueCacheRow(int nHeight, bool createIfNotExists) +COptional CClaimTrieCacheBase::getQueueCacheNameRow(const std::string& name) const +{ + return getRow(*(base->db), CLAIM_QUEUE_NAME_ROW, name, claimQueueNameCache); +} + +template <> +COptional CClaimTrieCacheBase::getQueueCacheNameRow(const std::string& name) const +{ + return getRow(*(base->db), SUPPORT_QUEUE_NAME_ROW, name, supportQueueNameCache); +} + +template +COptional CClaimTrieCacheBase::getQueueCacheNameRow(const std::string&) const +{ + supportedType(); + return {}; +} + +template <> +expirationQueueRowType* CClaimTrieCacheBase::getExpirationQueueCacheRow(int nHeight, bool createIfNotExists) { return getQueue(*(base->db), CLAIM_EXP_QUEUE_ROW, nHeight, expirationQueueCache, createIfNotExists); } template <> -typename expirationQueueType::value_type* CClaimTrieCacheBase::getExpirationQueueCacheRow(int nHeight, bool createIfNotExists) +expirationQueueRowType* CClaimTrieCacheBase::getExpirationQueueCacheRow(int nHeight, bool createIfNotExists) { return getQueue(*(base->db), SUPPORT_EXP_QUEUE_ROW, nHeight, supportExpirationQueueCache, createIfNotExists); } template -typename expirationQueueType::value_type* CClaimTrieCacheBase::getExpirationQueueCacheRow(int, bool) +expirationQueueRowType* CClaimTrieCacheBase::getExpirationQueueCacheRow(int, bool) { supportedType(); return nullptr; @@ -244,16 +294,16 @@ supportEntryType CClaimTrieCacheBase::getSupportsForName(const std::string& name } template -bool CClaimTrieCacheBase::haveInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) +bool CClaimTrieCacheBase::haveInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const { supportedType(); if (auto nameRow = getQueueCacheNameRow(name)) { - auto itNameRow = findOutPoint(nameRow->second, outPoint); - if (itNameRow != nameRow->second.end()) { + auto itNameRow = findOutPoint(*nameRow, outPoint); + if (itNameRow != nameRow->end()) { nValidAtHeight = itNameRow->nHeight; if (auto row = getQueueCacheRow(nValidAtHeight)) { - auto iRow = findOutPoint(row->second, CNameOutPointType{name, outPoint}); - if (iRow != row->second.end()) { + auto iRow = findOutPoint(*row, CNameOutPointType{name, outPoint}); + if (iRow != row->end()) { if (iRow->second.nValidAtHeight != nValidAtHeight) LogPrintf("%s: An inconsistency was found in the support queue. Please report this to the developers:\nDifferent nValidAtHeight between named queue and height queue\n: name: %s, txid: %s, nOut: %d, nValidAtHeight in named queue: %d, nValidAtHeight in height queue: %d current height: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nValidAtHeight, iRow->second.nValidAtHeight, nNextHeight); return true; @@ -265,20 +315,19 @@ bool CClaimTrieCacheBase::haveInQueue(const std::string& name, const COutPoint& return false; } -bool CClaimTrieCacheBase::haveClaimInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) +bool CClaimTrieCacheBase::haveClaimInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const { return haveInQueue(name, outPoint, nValidAtHeight); } -bool CClaimTrieCacheBase::haveSupportInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) +bool CClaimTrieCacheBase::haveSupportInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const { return haveInQueue(name, outPoint, nValidAtHeight); } void CClaimTrie::recurseNodes(const std::string& name, const CClaimTrieDataNode& current, std::function function) const { CClaimTrieData data; - if (!find(name, data)) - data = {}; + find(name, data); data.hash = current.hash; data.flags |= current.children.empty() ? 0 : CClaimTrieDataFlags::POTENTIAL_CHILDREN; @@ -286,8 +335,9 @@ void CClaimTrie::recurseNodes(const std::string& name, const CClaimTrieDataNode& for (auto& child: current.children) { CClaimTrieDataNode node; - if (find(name + child, node)) - recurseNodes(name + child, node, function); + auto childName = name + child; + if (find(childName, node)) + recurseNodes(childName, node, function); } } @@ -295,8 +345,8 @@ std::size_t CClaimTrie::getTotalNamesInTrie() const { std::size_t count = 0; CClaimTrieDataNode node; - if (find("", node)) - recurseNodes("", node, [&count](const std::string &name, const CClaimTrieData &data, const std::vector& children) { + if (find({}, node)) + recurseNodes({}, node, [&count](const std::string &name, const CClaimTrieData &data, const std::vector& children) { count += !data.empty(); }); return count; @@ -306,8 +356,8 @@ std::size_t CClaimTrie::getTotalClaimsInTrie() const { std::size_t count = 0; CClaimTrieDataNode node; - if (find("", node)) - recurseNodes("", node, [&count] + if (find({}, node)) + recurseNodes({}, node, [&count] (const std::string &name, const CClaimTrieData &data, const std::vector& children) { count += data.claims.size(); }); @@ -318,8 +368,8 @@ CAmount CClaimTrie::getTotalValueOfClaimsInTrie(bool fControllingOnly) const { CAmount value_in_subtrie = 0; CClaimTrieDataNode node; - if (find("", node)) - recurseNodes("", node, [&value_in_subtrie, fControllingOnly] + if (find({}, node)) + recurseNodes({}, node, [&value_in_subtrie, fControllingOnly] (const std::string &name, const CClaimTrieData &data, const std::vector& children) { for (const auto &claim : data.claims) { value_in_subtrie += claim.nAmount; @@ -398,7 +448,7 @@ using iCbType = std::function; bool CClaimTrie::checkConsistency(const uint256& rootHash) const { CClaimTrieDataNode node; - if (!find("", node) || node.hash != rootHash) { + if (!find({}, node) || node.hash != rootHash) { if (rootHash == one) return true; @@ -406,7 +456,7 @@ bool CClaimTrie::checkConsistency(const uint256& rootHash) const } bool success = true; - recurseNodes("", node, [&success, this](const std::string &name, const CClaimTrieData &data, const std::vector& children) { + recurseNodes({}, node, [&success, this](const std::string &name, const CClaimTrieData &data, const std::vector& children) { if (!success) return; std::vector vchToHash; @@ -438,9 +488,10 @@ std::vector> CClaimTrie::nodes(const std::vector> ret; CClaimTrieDataNode node; - if (!find("", node)) + if (!find({}, node)) return ret; - ret.emplace_back("", node); + + ret.emplace_back(std::string{}, node); std::string partialKey = key; @@ -473,7 +524,7 @@ bool CClaimTrie::contains(const std::string &key) const { } bool CClaimTrie::empty() const { - return !contains(""); + return !contains({}); } bool CClaimTrie::find(const std::string& key, CClaimTrieDataNode &node) const { @@ -533,17 +584,8 @@ bool CClaimTrieCacheBase::flush() auto rootHash = getMerkleHash(); - std::set forDeletion; - for (const auto& nodeName : nodesToDelete) { - // TODO: we don't need to deserialize all the nodes right here - // we could be smarter about this and fill in the whole list in removeClaimFromTrie - auto nodes = base->nodes(nodeName); - for (auto& node : nodes) - forDeletion.insert(node.first); - } - for (auto it = nodesToAddOrUpdate.begin(); it != nodesToAddOrUpdate.end(); ++it) { - bool removed = forDeletion.erase(it.key()); + bool removed = forDeleteFromBase.erase(it.key()); if (it->flags & CClaimTrieDataFlags::HASH_DIRTY) { CClaimTrieDataNode node; node.hash = it->hash; @@ -557,7 +599,7 @@ bool CClaimTrieCacheBase::flush() } } - for (auto& name: forDeletion) { + for (auto& name: forDeleteFromBase) { batch.Erase(std::make_pair(TRIE_NODE_CHILDREN, name)); batch.Erase(std::make_pair(TRIE_NODE_CLAIMS, name)); } @@ -652,19 +694,16 @@ uint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(CClaimPrefixTrie::iterat vchToHash.insert(vchToHash.end(), valueHash.begin(), valueHash.end()); } - auto ret = Hash(vchToHash.begin(), vchToHash.end()); - it->hash = ret; - return ret; + return it->hash = Hash(vchToHash.begin(), vchToHash.end()); } uint256 CClaimTrieCacheBase::getMerkleHash() { - auto it = nodesToAddOrUpdate.begin(); - if (it) + if (auto it = nodesToAddOrUpdate.begin()) return recursiveComputeMerkleHash(it); if (nodesToDelete.empty() && nodesAlreadyCached.empty()) { CClaimTrieDataNode node; - if (base->find("", node)) + if (base->find({}, node)) return node.hash; // it may be valuable to have base cache its current root hash } return one; // we have no data or we deleted everything @@ -694,8 +733,7 @@ CClaimPrefixTrie::iterator CClaimTrieCacheBase::cacheData(const std::string& nam if (nodesAlreadyCached.insert(node.first).second) { // do not insert nodes that are already present CClaimTrieData data; - if (!base->find(node.first, data)) - data = {}; + base->find(node.first, data); data.hash = node.second.hash; data.flags = node.second.children.empty() ? 0 : CClaimTrieDataFlags::POTENTIAL_CHILDREN; nodesToAddOrUpdate.insert(node.first, data); @@ -707,7 +745,7 @@ CClaimPrefixTrie::iterator CClaimTrieCacheBase::cacheData(const std::string& nam if (!base->find(childKey, childData)) childData = {}; CClaimTrieDataNode childNode; - if (base->find(childKey, childNode)) { // TODO: can we eliminate this expensive lookup? + if (base->find(childKey, childNode)) { childData.hash = childNode.hash; childData.flags = childNode.children.empty() ? 0 : CClaimTrieDataFlags::POTENTIAL_CHILDREN; } @@ -790,11 +828,12 @@ bool CClaimTrieCacheBase::removeClaimFromTrie(const std::string& name, const COu it->reorderClaims(supports); } else { // in case we pull a child into our spot; we will then need their kids for hash - bool hasChild = false; - for (auto& child: it.children()) { - hasChild = true; + bool hasChild = it.hasChildren(); + for (auto& child: it.children()) cacheData(child.key(), false); - } + + for (auto& node : nodesToAddOrUpdate.nodes(name)) + forDeleteFromBase.emplace(node.key()); nodesToAddOrUpdate.erase(name); nodesToDelete.insert(name); @@ -842,11 +881,11 @@ bool CClaimTrieCacheBase::addToQueue(const std::string& name, const T& value) supportedType(); const auto newName = adjustNameForValidHeight(name, value.nValidAtHeight); auto itQueueCache = getQueueCacheRow(value.nValidAtHeight, true); - itQueueCache->second.emplace_back(newName, value); + itQueueCache->emplace_back(newName, value); auto itQueueName = getQueueCacheNameRow(newName, true); - itQueueName->second.emplace_back(value.outPoint, value.nValidAtHeight); + itQueueName->emplace_back(value.outPoint, value.nValidAtHeight); auto itQueueExpiration = getExpirationQueueCacheRow(value.nHeight + expirationTime(), true); - itQueueExpiration->second.emplace_back(newName, value.outPoint); + itQueueExpiration->emplace_back(newName, value.outPoint); return true; } @@ -875,7 +914,7 @@ bool CClaimTrieCacheBase::undoSpend(const std::string& name, const T& value, int supportedType(); if (nValidAtHeight < nNextHeight) { auto itQueueExpiration = getExpirationQueueCacheRow(value.nHeight + expirationTime(), true); - itQueueExpiration->second.emplace_back(adjustNameForValidHeight(name, nValidAtHeight), value.outPoint); + itQueueExpiration->emplace_back(adjustNameForValidHeight(name, nValidAtHeight), value.outPoint); return addToCache(name, value, false); } return addToQueue(name, value); @@ -900,15 +939,15 @@ template bool CClaimTrieCacheBase::removeFromQueue(const std::string& name, const COutPoint& outPoint, T& value) { supportedType(); - if (auto itQueueNameRow = getQueueCacheNameRow(name)) { - auto itQueueName = findOutPoint(itQueueNameRow->second, outPoint); - if (itQueueName != itQueueNameRow->second.end()) { - if (auto itQueueRow = getQueueCacheRow(itQueueName->nHeight)) { - auto itQueue = findOutPoint(itQueueRow->second, CNameOutPointType{name, outPoint}); - if (itQueue != itQueueRow->second.end()) { + if (auto itQueueNameRow = getQueueCacheNameRow(name, false)) { + auto itQueueName = findOutPoint(*itQueueNameRow, outPoint); + if (itQueueName != itQueueNameRow->end()) { + if (auto itQueueRow = getQueueCacheRow(itQueueName->nHeight, false)) { + auto itQueue = findOutPoint(*itQueueRow, CNameOutPointType{name, outPoint}); + if (itQueue != itQueueRow->end()) { std::swap(value, itQueue->second); - itQueueNameRow->second.erase(itQueueName); - itQueueRow->second.erase(itQueue); + itQueueNameRow->erase(itQueueName); + itQueueRow->erase(itQueue); return true; } } @@ -970,8 +1009,8 @@ bool CClaimTrieCacheBase::remove(T& value, const std::string& name, const COutPo if (removeFromQueue(adjusted, outPoint, value) || removeFromCache(name, outPoint, value, fCheckTakeover)) { int expirationHeight = value.nHeight + expirationTime(); - if (auto itQueueRow = getExpirationQueueCacheRow(expirationHeight)) - eraseOutPoint(itQueueRow->second, CNameOutPointType{adjusted, outPoint}); + if (auto itQueueRow = getExpirationQueueCacheRow(expirationHeight, false)) + eraseOutPoint(*itQueueRow, CNameOutPointType{adjusted, outPoint}); nValidAtHeight = value.nValidAtHeight; return true; } @@ -1103,10 +1142,10 @@ template void CClaimTrieCacheBase::undoIncrement(insertUndoType& insertUndo, std::vector>& expireUndo, std::set* deleted) { supportedType(); - if (auto itQueueRow = getQueueCacheRow(nNextHeight)) { - for (const auto& itEntry : itQueueRow->second) { - if (auto itQueueNameRow = getQueueCacheNameRow(itEntry.first)) { - auto& points = itQueueNameRow->second; + if (auto itQueueRow = getQueueCacheRow(nNextHeight, false)) { + for (const auto& itEntry : *itQueueRow) { + if (auto itQueueNameRow = getQueueCacheNameRow(itEntry.first, false)) { + auto& points = *itQueueNameRow; auto itQueueName = std::find_if(points.begin(), points.end(), [&itEntry, this](const COutPointHeightType& point) { return point.outPoint == itEntry.second.outPoint && point.nHeight == nNextHeight; }); @@ -1115,7 +1154,7 @@ void CClaimTrieCacheBase::undoIncrement(insertUndoType& insertUndo, std::vector< } else { LogPrintf("%s: An inconsistency was found in the queue. Please report this to the developers:\nFound in height queue but not in named queue: name: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d\n", __func__, itEntry.first, itEntry.second.outPoint.hash.GetHex(), itEntry.second.outPoint.n, itEntry.second.nValidAtHeight, nNextHeight); LogPrintf("Elements found for that name:\n"); - for (const auto& itQueueNameInner : itQueueNameRow->second) + for (const auto& itQueueNameInner : points) LogPrintf("\ttxid: %s, nOut: %d, nValidAtHeight: %d\n", itQueueNameInner.outPoint.hash.GetHex(), itQueueNameInner.outPoint.n, itQueueNameInner.nHeight); assert(false); } @@ -1126,17 +1165,17 @@ void CClaimTrieCacheBase::undoIncrement(insertUndoType& insertUndo, std::vector< addToCache(itEntry.first, itEntry.second, true); insertUndo.emplace_back(itEntry.first, itEntry.second.outPoint, itEntry.second.nValidAtHeight); } - itQueueRow->second.clear(); + itQueueRow->clear(); } - if (auto itExpirationRow = getExpirationQueueCacheRow(nNextHeight)) { - for (const auto& itEntry : itExpirationRow->second) { + if (auto itExpirationRow = getExpirationQueueCacheRow(nNextHeight, false)) { + for (const auto& itEntry : *itExpirationRow) { T value; assert(removeFromCache(itEntry.name, itEntry.outPoint, value, true)); expireUndo.emplace_back(itEntry.name, value); addTo(deleted, value); } - itExpirationRow->second.clear(); + itExpirationRow->clear(); } } @@ -1144,12 +1183,12 @@ template void CClaimTrieCacheBase::undoIncrement(const std::string& name, insertUndoType& insertUndo, std::vector>& expireUndo) { supportedType(); - if (auto itQueueNameRow = getQueueCacheNameRow(name)) { - for (const auto& itQueueName : itQueueNameRow->second) { + if (auto itQueueNameRow = getQueueCacheNameRow(name, false)) { + for (const auto& itQueueName : *itQueueNameRow) { bool found = false; // Pull those claims out of the height-based queue - if (auto itQueueRow = getQueueCacheRow(itQueueName.nHeight)) { - auto& points = itQueueRow->second; + if (auto itQueueRow = getQueueCacheRow(itQueueName.nHeight, false)) { + auto& points = *itQueueRow; auto itQueue = std::find_if(points.begin(), points.end(), [&name, &itQueueName](const queueEntryType& point) { return name == point.first && point.second.outPoint == itQueueName.outPoint && point.second.nValidAtHeight == itQueueName.nHeight; }); @@ -1169,7 +1208,7 @@ void CClaimTrieCacheBase::undoIncrement(const std::string& name, insertUndoType& assert(found); } // remove all claims from the queue for that name - itQueueNameRow->second.clear(); + itQueueNameRow->clear(); } } @@ -1265,12 +1304,13 @@ void CClaimTrieCacheBase::undoDecrement(insertUndoType& insertUndo, std::vector< { supportedType(); if (!expireUndo.empty()) { - auto itExpireRow = getExpirationQueueCacheRow(nNextHeight, true); for (auto itExpireUndo = expireUndo.crbegin(); itExpireUndo != expireUndo.crend(); ++itExpireUndo) { addToCache(itExpireUndo->first, itExpireUndo->second, false); addToIndex(index, itExpireUndo->first, itExpireUndo->second); - if (nNextHeight == itExpireUndo->second.nHeight + expirationTime()) - itExpireRow->second.emplace_back(itExpireUndo->first, itExpireUndo->second.outPoint); + if (nNextHeight == itExpireUndo->second.nHeight + expirationTime()) { + auto itExpireRow = getExpirationQueueCacheRow(nNextHeight, true); + itExpireRow->emplace_back(itExpireUndo->first, itExpireUndo->second.outPoint); + } } } @@ -1283,8 +1323,8 @@ void CClaimTrieCacheBase::undoDecrement(insertUndoType& insertUndo, std::vector< value.nValidAtHeight = itInsertUndo->nHeight; auto itQueueRow = getQueueCacheRow(itInsertUndo->nHeight, true); auto itQueueNameRow = getQueueCacheNameRow(itInsertUndo->name, true); - itQueueRow->second.emplace_back(itInsertUndo->name, value); - itQueueNameRow->second.emplace_back(itInsertUndo->outPoint, value.nValidAtHeight); + itQueueRow->emplace_back(itInsertUndo->name, value); + itQueueNameRow->emplace_back(itInsertUndo->outPoint, value.nValidAtHeight); } else { addTo(deleted, value); } @@ -1324,13 +1364,13 @@ void CClaimTrieCacheBase::reactivate(const expirationQueueRowType& row, int heig supportedType(); for (auto& e: row) { // remove and insert with new expiration time - if (auto itQueueRow = getExpirationQueueCacheRow(height)) - eraseOutPoint(itQueueRow->second, CNameOutPointType{e.name, e.outPoint}); + if (auto itQueueRow = getExpirationQueueCacheRow(height, false)) + eraseOutPoint(*itQueueRow, CNameOutPointType{e.name, e.outPoint}); int extend_expiration = Params().GetConsensus().nExtendedClaimExpirationTime - Params().GetConsensus().nOriginalClaimExpirationTime; int new_expiration_height = increment ? height + extend_expiration : height - extend_expiration; auto itQueueExpiration = getExpirationQueueCacheRow(new_expiration_height, true); - itQueueExpiration->second.emplace_back(e.name, e.outPoint); + itQueueExpiration->emplace_back(e.name, e.outPoint); } } @@ -1352,11 +1392,8 @@ int CClaimTrieCacheBase::getNumBlocksOfContinuousOwnership(const std::string& na that->removalWorkaround.erase(hit); return 0; } - auto it = nodesToAddOrUpdate.find(name); - if (it && !it->empty()) - return nNextHeight - it->nHeightOfLastTakeover; - if (it) // we specifically ignore deleted nodes here to allow this to fall into the base lookup in that scenario - return 0; + if (auto it = nodesToAddOrUpdate.find(name)) + return it->empty() ? 0 : nNextHeight - it->nHeightOfLastTakeover; CClaimTrieData data; if (base->find(name, data) && !data.empty()) return nNextHeight - data.nHeightOfLastTakeover; @@ -1387,6 +1424,7 @@ std::string CClaimTrieCacheBase::adjustNameForValidHeight(const std::string& nam bool CClaimTrieCacheBase::clear() { + forDeleteFromBase.clear(); nodesToAddOrUpdate.clear(); claimsToAddToByIdIndex.clear(); supportCache.clear(); diff --git a/src/claimtrie.h b/src/claimtrie.h index 7b50e9314..e8b5d3471 100644 --- a/src/claimtrie.h +++ b/src/claimtrie.h @@ -398,6 +398,56 @@ struct CClaimTrieProof int nHeightOfLastTakeover; }; +template +class COptional +{ + bool own; + T* value; +public: + COptional(T* value = nullptr) : own(false), value(value) {} + COptional(COptional&& o) + { + own = o.own; + value = o.value; + o.own = false; + o.value = nullptr; + } + COptional(T&& o) : own(true) + { + value = new T(std::move(o)); + } + ~COptional() + { + if (own) + delete value; + } + COptional& operator=(COptional&&) = delete; + bool unique() const + { + return own; + } + operator bool() const + { + return value; + } + operator T*() const + { + return value; + } + T* operator->() const + { + return value; + } + operator T&() const + { + return *value; + } + T& operator*() const + { + return *value; + } +}; + template using queueEntryType = std::pair; @@ -435,10 +485,10 @@ public: bool ReadFromDisk(const CBlockIndex* tip); bool haveClaim(const std::string& name, const COutPoint& outPoint) const; - bool haveClaimInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight); + bool haveClaimInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const; bool haveSupport(const std::string& name, const COutPoint& outPoint) const; - bool haveSupportInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight); + bool haveSupportInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const; bool addClaim(const std::string& name, const COutPoint& outPoint, const uint160& claimId, CAmount nAmount, int nHeight); bool undoAddClaim(const std::string& name, const COutPoint& outPoint, int nHeight); @@ -533,6 +583,7 @@ private: std::unordered_set nodesAlreadyCached; // set of nodes already pulled into cache from base std::unordered_map takeoverWorkaround; std::unordered_set removalWorkaround; + std::unordered_set forDeleteFromBase; bool shouldUseTakeoverWorkaround(const std::string& key) const; void addTakeoverWorkaroundPotential(const std::string& key); @@ -547,16 +598,22 @@ private: bool validateTrieConsistency(const CBlockIndex* tip); template - std::pair>>* getQueueCacheRow(int nHeight, bool createIfNotExists = false); + std::vector>* getQueueCacheRow(int nHeight, bool createIfNotExists); template - typename queueNameType::value_type* getQueueCacheNameRow(const std::string& name, bool createIfNotExists = false); + COptional>> getQueueCacheRow(int nHeight) const; template - typename expirationQueueType::value_type* getExpirationQueueCacheRow(int nHeight, bool createIfNotExists = false); + queueNameRowType* getQueueCacheNameRow(const std::string& name, bool createIfNotExists); template - bool haveInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight); + COptional getQueueCacheNameRow(const std::string& name) const; + + template + expirationQueueRowType* getExpirationQueueCacheRow(int nHeight, bool createIfNotExists); + + template + bool haveInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const; template T add(const std::string& name, const COutPoint& outPoint, const uint160& claimId, CAmount nAmount, int nHeight); diff --git a/src/prefixtrie.h b/src/prefixtrie.h index d821bd283..559eefd48 100644 --- a/src/prefixtrie.h +++ b/src/prefixtrie.h @@ -9,6 +9,10 @@ #include #include +#include + +namespace bc = boost::container; + template class CPrefixTrie { @@ -17,7 +21,7 @@ class CPrefixTrie template friend class Iterator; friend class CPrefixTrie; - std::map> children; + bc::flat_map> children; public: Node() = default;