From 44d1d2f3f80029603f430867ac4e3f62dd731d7e Mon Sep 17 00:00:00 2001 From: Anthony Fieroni Date: Sat, 19 May 2018 23:55:32 +0300 Subject: [PATCH 01/25] Separate disk related functions in CClaimTrieDb, a generalized key value storage class Signed-off-by: Anthony Fieroni --- src/Makefile.am | 2 + src/Makefile.test.include | 1 + src/claimtrie.cpp | 2028 ++++++++----------------- src/claimtrie.h | 673 ++++---- src/claimtriedb.cpp | 227 +++ src/claimtriedb.h | 94 ++ src/test/claimtriebranching_tests.cpp | 815 +++++----- src/test/claimtriecache_tests.cpp | 2 +- src/test/claimtriedb_tests.cpp | 91 ++ 9 files changed, 1788 insertions(+), 2145 deletions(-) create mode 100644 src/claimtriedb.cpp create mode 100644 src/claimtriedb.h create mode 100644 src/test/claimtriedb_tests.cpp diff --git a/src/Makefile.am b/src/Makefile.am index a9f0a949c..0352c3df7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -119,6 +119,7 @@ BITCOIN_CORE_H = \ miner.h \ nameclaim.h \ claimtrie.h \ + claimtriedb.h \ lbry.h \ net.h \ netbase.h \ @@ -191,6 +192,7 @@ libbitcoin_server_a_SOURCES = \ merkleblock.cpp \ miner.cpp \ claimtrie.cpp \ + claimtriedb.cpp \ net.cpp \ noui.cpp \ policy/fees.cpp \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 05f88b3ea..4baf40724 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -62,6 +62,7 @@ BITCOIN_TESTS =\ test/multisig_tests.cpp \ test/claimtriecache_tests.cpp \ test/claimtriebranching_tests.cpp \ + test/claimtriedb_tests.cpp \ test/nameclaim_tests.cpp \ test/netbase_tests.cpp \ test/pmt_tests.cpp \ diff --git a/src/claimtrie.cpp b/src/claimtrie.cpp index 06f19b115..79e429108 100644 --- a/src/claimtrie.cpp +++ b/src/claimtrie.cpp @@ -2,9 +2,13 @@ #include "coins.h" #include "hash.h" -#include -#include #include +#include + +#define HASH_BLOCK 'h' +#define CURRENT_HEIGHT 't' + +const uint256 one = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); std::vector heightToVch(int n) { @@ -21,7 +25,7 @@ std::vector heightToVch(int n) return vchHeight; } -uint256 getValueHash(COutPoint outPoint, int nHeightOfLastTakeover) +uint256 getValueHash(const COutPoint& outPoint, int nHeightOfLastTakeover) { CHash256 txHasher; txHasher.Write(outPoint.hash.begin(), outPoint.hash.size()); @@ -32,7 +36,7 @@ uint256 getValueHash(COutPoint outPoint, int nHeightOfLastTakeover) std::stringstream ss; ss << outPoint.n; std::string snOut = ss.str(); - nOutHasher.Write((unsigned char*) snOut.data(), snOut.size()); + nOutHasher.Write((unsigned char*)snOut.data(), snOut.size()); std::vector vchnOutHash(nOutHasher.OUTPUT_SIZE); nOutHasher.Finalize(&(vchnOutHash[0])); @@ -53,7 +57,7 @@ uint256 getValueHash(COutPoint outPoint, int nHeightOfLastTakeover) return valueHash; } -bool CClaimTrieNode::insertClaim(CClaimValue claim) +bool CClaimTrieNode::insertClaim(const CClaimValue& claim) { LogPrintf("%s: Inserting %s:%d (amount: %d) into the claim trie\n", __func__, claim.outPoint.hash.ToString(), claim.outPoint.n, claim.nAmount); claims.push_back(claim); @@ -65,24 +69,18 @@ bool CClaimTrieNode::removeClaim(const COutPoint& outPoint, CClaimValue& claim) LogPrintf("%s: Removing txid: %s, nOut: %d from the claim trie\n", __func__, outPoint.hash.ToString(), outPoint.n); std::vector::iterator itClaims; - for (itClaims = claims.begin(); itClaims != claims.end(); ++itClaims) - { - if (itClaims->outPoint == outPoint) - { + for (itClaims = claims.begin(); itClaims != claims.end(); ++itClaims) { + if (itClaims->outPoint == outPoint) { std::swap(claim, *itClaims); break; } } - if (itClaims != claims.end()) - { + if (itClaims != claims.end()) { claims.erase(itClaims); - } - else - { + } else { LogPrintf("CClaimTrieNode::%s() : asked to remove a claim that doesn't exist\n", __func__); LogPrintf("CClaimTrieNode::%s() : claims that do exist:\n", __func__); - for (unsigned int i = 0; i < claims.size(); i++) - { + for (unsigned int i = 0; i < claims.size(); i++) { LogPrintf("\ttxhash: %s, nOut: %d:\n", claims[i].outPoint.hash.ToString(), claims[i].outPoint.n); } return false; @@ -92,12 +90,9 @@ bool CClaimTrieNode::removeClaim(const COutPoint& outPoint, CClaimValue& claim) bool CClaimTrieNode::getBestClaim(CClaimValue& claim) const { - if (claims.empty()) - { + if (claims.empty()) { return false; - } - else - { + } else { claim = claims.front(); return true; } @@ -105,10 +100,8 @@ bool CClaimTrieNode::getBestClaim(CClaimValue& claim) const bool CClaimTrieNode::haveClaim(const COutPoint& outPoint) const { - for (std::vector::const_iterator itclaim = claims.begin(); itclaim != claims.end(); ++itclaim) - { - if (itclaim->outPoint == outPoint) - return true; + for (std::vector::const_iterator itclaim = claims.begin(); itclaim != claims.end(); ++itclaim) { + if (itclaim->outPoint == outPoint) return true; } return false; } @@ -117,17 +110,13 @@ void CClaimTrieNode::reorderClaims(supportMapEntryType& supports) { std::vector::iterator itclaim; - for (itclaim = claims.begin(); itclaim != claims.end(); ++itclaim) - { + for (itclaim = claims.begin(); itclaim != claims.end(); ++itclaim) { itclaim->nEffectiveAmount = itclaim->nAmount; } - for (supportMapEntryType::iterator itsupport = supports.begin(); itsupport != supports.end(); ++itsupport) - { - for (itclaim = claims.begin(); itclaim != claims.end(); ++itclaim) - { - if (itsupport->supportedClaimId == itclaim->claimId) - { + for (supportMapEntryType::iterator itsupport = supports.begin(); itsupport != supports.end(); ++itsupport) { + for (itclaim = claims.begin(); itclaim != claims.end(); ++itclaim) { + if (itsupport->supportedClaimId == itclaim->claimId) { itclaim->nEffectiveAmount += itsupport->nAmount; break; } @@ -137,6 +126,20 @@ void CClaimTrieNode::reorderClaims(supportMapEntryType& supports) std::make_heap(claims.begin(), claims.end()); } +bool CClaimTrieNode::empty() const +{ + return children.empty() && claims.empty(); +} + +CClaimTrie::CClaimTrie(bool fMemory, bool fWipe, int nProportionalDelayFactor) + : nCurrentHeight(0), nExpirationTime(Params().GetConsensus().nOriginalClaimExpirationTime), nProportionalDelayFactor(nProportionalDelayFactor), db(fMemory, fWipe), root(one) +{ +} + +CClaimTrie::~CClaimTrie() +{ +} + uint256 CClaimTrie::getMerkleHash() { return root.hash; @@ -147,72 +150,24 @@ bool CClaimTrie::empty() const return root.empty(); } -template bool CClaimTrie::keyTypeEmpty(char keyType, K& dummy) const -{ - boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); - pcursor->SeekToFirst(); - - while (pcursor->Valid()) - { - std::pair key; - if (pcursor->GetKey(key)) - { - if (key.first == keyType) - { - return false; - } - } - else - { - break; - } - pcursor->Next(); - } - return true; -} - bool CClaimTrie::queueEmpty() const { - for (claimQueueType::const_iterator itRow = dirtyQueueRows.begin(); itRow != dirtyQueueRows.end(); ++itRow) - { - if (!itRow->second.empty()) - return false; - } - int dummy; - return keyTypeEmpty(CLAIM_QUEUE_ROW, dummy); + return db.keyTypeEmpty(); } bool CClaimTrie::expirationQueueEmpty() const { - for (expirationQueueType::const_iterator itRow = dirtyExpirationQueueRows.begin(); itRow != dirtyExpirationQueueRows.end(); ++itRow) - { - if (!itRow->second.empty()) - return false; - } - int dummy; - return keyTypeEmpty(EXP_QUEUE_ROW, dummy); + return db.keyTypeEmpty(); } bool CClaimTrie::supportEmpty() const { - for (supportMapType::const_iterator itNode = dirtySupportNodes.begin(); itNode != dirtySupportNodes.end(); ++itNode) - { - if (!itNode->second.empty()) - return false; - } - std::string dummy; - return keyTypeEmpty(SUPPORT, dummy); + return db.keyTypeEmpty(); } bool CClaimTrie::supportQueueEmpty() const { - for (supportQueueType::const_iterator itRow = dirtySupportQueueRows.begin(); itRow != dirtySupportQueueRows.end(); ++itRow) - { - if (!itRow->second.empty()) - return false; - } - int dummy; - return keyTypeEmpty(SUPPORT_QUEUE_ROW, dummy); + return db.keyTypeEmpty(); } void CClaimTrie::setExpirationTime(int t) @@ -228,37 +183,25 @@ void CClaimTrie::clear() void CClaimTrie::clear(CClaimTrieNode* current) { - for (nodeMapType::const_iterator itchildren = current->children.begin(); itchildren != current->children.end(); ++itchildren) - { + for (nodeMapType::const_iterator itchildren = current->children.begin(); itchildren != current->children.end(); ++itchildren) { clear(itchildren->second); delete itchildren->second; } + current->children.clear(); } bool CClaimTrie::haveClaim(const std::string& name, const COutPoint& outPoint) const { - const CClaimTrieNode* current = &root; - for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname) - { - nodeMapType::const_iterator itchildren = current->children.find(*itname); - if (itchildren == current->children.end()) - return false; - current = itchildren->second; - } - return current->haveClaim(outPoint); + const CClaimTrieNode* current = getNodeForName(name); + return current && current->haveClaim(outPoint); } bool CClaimTrie::haveSupport(const std::string& name, const COutPoint& outPoint) const { supportMapEntryType node; - if (!getSupportNode(name, node)) - { - return false; - } - for (supportMapEntryType::const_iterator itnode = node.begin(); itnode != node.end(); ++itnode) - { - if (itnode->outPoint == outPoint) - return true; + if (!db.getQueueRow(name, node)) return false; + for (supportMapEntryType::const_iterator itnode = node.begin(); itnode != node.end(); ++itnode) { + if (itnode->outPoint == outPoint) return true; } return false; } @@ -266,32 +209,20 @@ bool CClaimTrie::haveSupport(const std::string& name, const COutPoint& outPoint) bool CClaimTrie::haveClaimInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const { queueNameRowType nameRow; - if (!getQueueNameRow(name, nameRow)) - { - return false; - } + if (!db.getQueueRow(name, nameRow)) return false; queueNameRowType::const_iterator itNameRow; - for (itNameRow = nameRow.begin(); itNameRow != nameRow.end(); ++itNameRow) - { - if (itNameRow->outPoint == outPoint) - { + for (itNameRow = nameRow.begin(); itNameRow != nameRow.end(); ++itNameRow) { + if (itNameRow->outPoint == outPoint) { nValidAtHeight = itNameRow->nHeight; break; } } - if (itNameRow == nameRow.end()) - { - return false; - } + if (itNameRow == nameRow.end()) return false; claimQueueRowType row; - if (getQueueRow(nValidAtHeight, row)) - { - for (claimQueueRowType::const_iterator itRow = row.begin(); itRow != row.end(); ++itRow) - { - if (itRow->first == name && itRow->second.outPoint == outPoint) - { - if (itRow->second.nValidAtHeight != nValidAtHeight) - { + if (db.getQueueRow(nValidAtHeight, row)) { + for (claimQueueRowType::const_iterator itRow = row.begin(); itRow != row.end(); ++itRow) { + if (itRow->first == name && itRow->second.outPoint == outPoint) { + if (itRow->second.nValidAtHeight != nValidAtHeight) { LogPrintf("%s: An inconsistency was found in the claim 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, itRow->second.nValidAtHeight, nCurrentHeight); } return true; @@ -304,33 +235,21 @@ bool CClaimTrie::haveClaimInQueue(const std::string& name, const COutPoint& outP bool CClaimTrie::haveSupportInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const { - queueNameRowType nameRow; - if (!getSupportQueueNameRow(name, nameRow)) - { - return false; - } - queueNameRowType::const_iterator itNameRow; - for (itNameRow = nameRow.begin(); itNameRow != nameRow.end(); ++itNameRow) - { - if (itNameRow->outPoint == outPoint) - { + supportQueueNameRowType nameRow; + if (!db.getQueueRow(name, nameRow)) return false; + supportQueueNameRowType::const_iterator itNameRow; + for (itNameRow = nameRow.begin(); itNameRow != nameRow.end(); ++itNameRow) { + if (itNameRow->outPoint == outPoint) { nValidAtHeight = itNameRow->nHeight; break; } } - if (itNameRow == nameRow.end()) - { - return false; - } + if (itNameRow == nameRow.end()) return false; supportQueueRowType row; - if (getSupportQueueRow(nValidAtHeight, row)) - { - for (supportQueueRowType::const_iterator itRow = row.begin(); itRow != row.end(); ++itRow) - { - if (itRow->first == name && itRow->second.outPoint == outPoint) - { - if (itRow->second.nValidAtHeight != nValidAtHeight) - { + if (db.getQueueRow(nValidAtHeight, row)) { + for (supportQueueRowType::const_iterator itRow = row.begin(); itRow != row.end(); ++itRow) { + if (itRow->first == name && itRow->second.outPoint == outPoint) { + if (itRow->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, itRow->second.nValidAtHeight, nCurrentHeight); } return true; @@ -343,8 +262,7 @@ bool CClaimTrie::haveSupportInQueue(const std::string& name, const COutPoint& ou unsigned int CClaimTrie::getTotalNamesInTrie() const { - if (empty()) - return 0; + if (empty()) return 0; const CClaimTrieNode* current = &root; return getTotalNamesRecursive(current); } @@ -352,10 +270,10 @@ unsigned int CClaimTrie::getTotalNamesInTrie() const unsigned int CClaimTrie::getTotalNamesRecursive(const CClaimTrieNode* current) const { unsigned int names_in_subtrie = 0; - if (!(current->claims.empty())) + if (!(current->claims.empty())) { names_in_subtrie += 1; - for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) - { + } + for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) { names_in_subtrie += getTotalNamesRecursive(it->second); } return names_in_subtrie; @@ -363,8 +281,7 @@ unsigned int CClaimTrie::getTotalNamesRecursive(const CClaimTrieNode* current) c unsigned int CClaimTrie::getTotalClaimsInTrie() const { - if (empty()) - return 0; + if (empty()) return 0; const CClaimTrieNode* current = &root; return getTotalClaimsRecursive(current); } @@ -372,8 +289,7 @@ unsigned int CClaimTrie::getTotalClaimsInTrie() const unsigned int CClaimTrie::getTotalClaimsRecursive(const CClaimTrieNode* current) const { unsigned int claims_in_subtrie = current->claims.size(); - for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) - { + for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) { claims_in_subtrie += getTotalClaimsRecursive(it->second); } return claims_in_subtrie; @@ -381,8 +297,7 @@ unsigned int CClaimTrie::getTotalClaimsRecursive(const CClaimTrieNode* current) CAmount CClaimTrie::getTotalValueOfClaimsInTrie(bool fControllingOnly) const { - if (empty()) - return 0; + if (empty()) return 0; const CClaimTrieNode* current = &root; return getTotalValueOfClaimsRecursive(current, fControllingOnly); } @@ -390,29 +305,23 @@ CAmount CClaimTrie::getTotalValueOfClaimsInTrie(bool fControllingOnly) const CAmount CClaimTrie::getTotalValueOfClaimsRecursive(const CClaimTrieNode* current, bool fControllingOnly) const { CAmount value_in_subtrie = 0; - for (std::vector::const_iterator itclaim = current->claims.begin(); itclaim != current->claims.end(); ++itclaim) - { + for (std::vector::const_iterator itclaim = current->claims.begin(); itclaim != current->claims.end(); ++itclaim) { value_in_subtrie += itclaim->nAmount; - if (fControllingOnly) - break; + if (fControllingOnly) break; } - for (nodeMapType::const_iterator itchild = current->children.begin(); itchild != current->children.end(); ++itchild) - { - value_in_subtrie += getTotalValueOfClaimsRecursive(itchild->second, fControllingOnly); - } - return value_in_subtrie; + for (nodeMapType::const_iterator itchild = current->children.begin(); itchild != current->children.end(); ++itchild) { + value_in_subtrie += getTotalValueOfClaimsRecursive(itchild->second, fControllingOnly); + } + return value_in_subtrie; } bool CClaimTrie::recursiveFlattenTrie(const std::string& name, const CClaimTrieNode* current, std::vector& nodes) const { - namedNodeType node(name, *current); - nodes.push_back(node); - for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) - { + nodes.push_back(namedNodeType(name, *current)); + for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) { std::stringstream ss; ss << name << it->first; - if (!recursiveFlattenTrie(ss.str(), it->second, nodes)) - return false; + if (!recursiveFlattenTrie(ss.str(), it->second, nodes)) return false; } return true; } @@ -420,19 +329,18 @@ bool CClaimTrie::recursiveFlattenTrie(const std::string& name, const CClaimTrieN std::vector CClaimTrie::flattenTrie() const { std::vector nodes; - if (!recursiveFlattenTrie("", &root, nodes)) + if (!recursiveFlattenTrie("", &root, nodes)) { LogPrintf("%s: Something went wrong flattening the trie", __func__); + } return nodes; } const CClaimTrieNode* CClaimTrie::getNodeForName(const std::string& name) const { 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); - if (itchildren == current->children.end()) - return NULL; + if (itchildren == current->children.end()) return NULL; current = itchildren->second; } return current; @@ -441,22 +349,18 @@ const CClaimTrieNode* CClaimTrie::getNodeForName(const std::string& name) const bool CClaimTrie::getInfoForName(const std::string& name, CClaimValue& claim) const { const CClaimTrieNode* current = getNodeForName(name); - if (current) - { - return current->getBestClaim(claim); - } - return false; + return current && current->getBestClaim(claim); } bool CClaimTrie::getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const { const CClaimTrieNode* current = getNodeForName(name); - if (current && !current->claims.empty()) - { + if (current && !current->claims.empty()) { lastTakeoverHeight = current->nHeightOfLastTakeover; return true; + } else { + return false; } - return false; } claimsForNameType CClaimTrie::getClaimsForName(const std::string& name) const @@ -465,56 +369,41 @@ claimsForNameType CClaimTrie::getClaimsForName(const std::string& name) const std::vector supports; int nLastTakeoverHeight = 0; const CClaimTrieNode* current = getNodeForName(name); - if (current) - { - if (!current->claims.empty()) - { + if (current) { + if (!current->claims.empty()) { nLastTakeoverHeight = current->nHeightOfLastTakeover; } - for (std::vector::const_iterator itClaims = current->claims.begin(); itClaims != current->claims.end(); ++itClaims) - { + for (std::vector::const_iterator itClaims = current->claims.begin(); itClaims != current->claims.end(); ++itClaims) { claims.push_back(*itClaims); } } supportMapEntryType supportNode; - if (getSupportNode(name, supportNode)) - { - for (std::vector::const_iterator itSupports = supportNode.begin(); itSupports != supportNode.end(); ++itSupports) - { + if (db.getQueueRow(name, supportNode)) { + for (std::vector::const_iterator itSupports = supportNode.begin(); itSupports != supportNode.end(); ++itSupports) { supports.push_back(*itSupports); } } queueNameRowType namedClaimRow; - if (getQueueNameRow(name, namedClaimRow)) - { - for (queueNameRowType::const_iterator itClaimsForName = namedClaimRow.begin(); itClaimsForName != namedClaimRow.end(); ++itClaimsForName) - { + if (db.getQueueRow(name, namedClaimRow)) { + for (queueNameRowType::const_iterator itClaimsForName = namedClaimRow.begin(); itClaimsForName != namedClaimRow.end(); ++itClaimsForName) { claimQueueRowType claimRow; - if (getQueueRow(itClaimsForName->nHeight, claimRow)) - { - for (claimQueueRowType::const_iterator itClaimRow = claimRow.begin(); itClaimRow != claimRow.end(); ++itClaimRow) - { - if (itClaimRow->first == name && itClaimRow->second.outPoint == itClaimsForName->outPoint) - { - claims.push_back(itClaimRow->second); - break; - } - } + if (db.getQueueRow(itClaimsForName->nHeight, claimRow)) { + for (claimQueueRowType::const_iterator itClaimRow = claimRow.begin(); itClaimRow != claimRow.end(); ++itClaimRow) { + if (itClaimRow->first == name && itClaimRow->second.outPoint == itClaimsForName->outPoint) { + claims.push_back(itClaimRow->second); + break; + } + } } } } - queueNameRowType namedSupportRow; - if (getSupportQueueNameRow(name, namedSupportRow)) - { - for (queueNameRowType::const_iterator itSupportsForName = namedSupportRow.begin(); itSupportsForName != namedSupportRow.end(); ++itSupportsForName) - { + supportQueueNameRowType namedSupportRow; + if (db.getQueueRow(name, namedSupportRow)) { + for (supportQueueNameRowType::const_iterator itSupportsForName = namedSupportRow.begin(); itSupportsForName != namedSupportRow.end(); ++itSupportsForName) { supportQueueRowType supportRow; - if (getSupportQueueRow(itSupportsForName->nHeight, supportRow)) - { - for (supportQueueRowType::const_iterator itSupportRow = supportRow.begin(); itSupportRow != supportRow.end(); ++itSupportRow) - { - if (itSupportRow->first == name && itSupportRow->second.outPoint == itSupportsForName->outPoint) - { + if (db.getQueueRow(itSupportsForName->nHeight, supportRow)) { + for (supportQueueRowType::const_iterator itSupportRow = supportRow.begin(); itSupportRow != supportRow.end(); ++itSupportRow) { + if (itSupportRow->first == name && itSupportRow->second.outPoint == itSupportsForName->outPoint) { supports.push_back(itSupportRow->second); break; } @@ -527,35 +416,28 @@ claimsForNameType CClaimTrie::getClaimsForName(const std::string& name) const } //return effective amount from claim, retuns 0 if claim is not found -CAmount CClaimTrie::getEffectiveAmountForClaim(const std::string& name, uint160 claimId) const +CAmount CClaimTrie::getEffectiveAmountForClaim(const std::string& name, const uint160& claimId) const { std::vector supports; return getEffectiveAmountForClaimWithSupports(name, claimId, supports); } //return effective amount from claim and the supports used as inputs, retuns 0 if claim is not found -CAmount CClaimTrie::getEffectiveAmountForClaimWithSupports(const std::string& name, uint160 claimId, - std::vector& supports) const +CAmount CClaimTrie::getEffectiveAmountForClaimWithSupports(const std::string& name, const uint160& claimId, std::vector& supports) const { claimsForNameType claims = getClaimsForName(name); CAmount effectiveAmount = 0; bool claim_found = false; - for (std::vector::iterator it=claims.claims.begin(); it!=claims.claims.end(); ++it) - { - if (it->claimId == claimId && it->nValidAtHeight < nCurrentHeight) - { + for (std::vector::iterator it = claims.claims.begin(); it != claims.claims.end(); ++it) { + if (it->claimId == claimId && it->nValidAtHeight < nCurrentHeight) { effectiveAmount += it->nAmount; claim_found = true; break; } } - if (!claim_found) - return effectiveAmount; - - for (std::vector::iterator it=claims.supports.begin(); it!=claims.supports.end(); ++it) - { - if (it->supportedClaimId == claimId && it->nValidAtHeight < nCurrentHeight) - { + if (!claim_found) return effectiveAmount; + for (std::vector::iterator it = claims.supports.begin(); it != claims.supports.end(); ++it) { + if (it->supportedClaimId == claimId && it->nValidAtHeight < nCurrentHeight) { effectiveAmount += it->nAmount; supports.push_back(*it); } @@ -565,8 +447,7 @@ CAmount CClaimTrie::getEffectiveAmountForClaimWithSupports(const std::string& na bool CClaimTrie::checkConsistency() const { - if (empty()) - return true; + if (empty()) return true; return recursiveCheckConsistency(&root); } @@ -574,22 +455,19 @@ bool CClaimTrie::recursiveCheckConsistency(const CClaimTrieNode* node) const { std::vector vchToHash; - for (nodeMapType::const_iterator it = node->children.begin(); it != node->children.end(); ++it) - { - if (recursiveCheckConsistency(it->second)) - { + for (nodeMapType::const_iterator it = node->children.begin(); it != node->children.end(); ++it) { + if (recursiveCheckConsistency(it->second)) { vchToHash.push_back(it->first); vchToHash.insert(vchToHash.end(), it->second->hash.begin(), it->second->hash.end()); - } - else + } else { return false; + } } CClaimValue claim; bool hasClaim = node->getBestClaim(claim); - if (hasClaim) - { + if (hasClaim) { uint256 valueHash = getValueHash(claim.outPoint, node->nHeightOfLastTakeover); vchToHash.insert(vchToHash.end(), valueHash.begin(), valueHash.end()); } @@ -604,317 +482,76 @@ bool CClaimTrie::recursiveCheckConsistency(const CClaimTrieNode* node) const void CClaimTrie::addToClaimIndex(const std::string& name, const CClaimValue& claim) { - CClaimIndexElement element = { name, claim }; LogPrintf("%s: ClaimIndex[%s] updated %s\n", __func__, claim.claimId.GetHex(), name); - db.Write(std::make_pair(CLAIM_BY_ID, claim.claimId), element); + + CClaimIndexElement element = {name, claim}; + db.updateQueueRow(claim.claimId, element); } void CClaimTrie::removeFromClaimIndex(const CClaimValue& claim) { LogPrintf("%s: ClaimIndex[%s] removed\n", __func__, claim.claimId.GetHex()); - db.Erase(std::make_pair(CLAIM_BY_ID, claim.claimId)); + + CClaimIndexElement element; + db.updateQueueRow(claim.claimId, element); } -bool CClaimTrie::getClaimById(const uint160 claimId, std::string& name, CClaimValue& claim) const +bool CClaimTrie::getClaimById(const uint160& claimId, std::string& name, CClaimValue& claim) const { CClaimIndexElement element; - if (db.Read(std::make_pair(CLAIM_BY_ID, claimId), element)) - { - if (element.claim.claimId == claimId) { - name = element.name; - claim = element.claim; - return true; - } else { - LogPrintf("%s: ClaimIndex[%s] returned unmatched claimId %s when looking for %s\n", - __func__, claimId.GetHex(), element.claim.claimId.GetHex(), name); - } - } - return false; -} - -bool CClaimTrie::getQueueRow(int nHeight, claimQueueRowType& row) const -{ - claimQueueType::const_iterator itQueueRow = dirtyQueueRows.find(nHeight); - if (itQueueRow != dirtyQueueRows.end()) - { - row = itQueueRow->second; + if (db.getQueueRow(claimId, element) && !element.empty()) { + name = element.name; + claim = element.claim; return true; + } else { + LogPrintf("%s: ClaimIndex[%s] returned unmatched claimId %s when looking for %s\n", + __func__, claimId.GetHex(), element.claim.claimId.GetHex(), name); + return false; } - return db.Read(std::make_pair(CLAIM_QUEUE_ROW, nHeight), row); } -bool CClaimTrie::getQueueNameRow(const std::string& name, queueNameRowType& row) const -{ - queueNameType::const_iterator itQueueNameRow = dirtyQueueNameRows.find(name); - if (itQueueNameRow != dirtyQueueNameRows.end()) - { - row = itQueueNameRow->second; - return true; - } - return db.Read(std::make_pair(CLAIM_QUEUE_NAME_ROW, name), row); -} - -bool CClaimTrie::getExpirationQueueRow(int nHeight, expirationQueueRowType& row) const -{ - expirationQueueType::const_iterator itQueueRow = dirtyExpirationQueueRows.find(nHeight); - if (itQueueRow != dirtyExpirationQueueRows.end()) - { - row = itQueueRow->second; - return true; - } - return db.Read(std::make_pair(EXP_QUEUE_ROW, nHeight), row); -} - -void CClaimTrie::updateQueueRow(int nHeight, claimQueueRowType& row) -{ - claimQueueType::iterator itQueueRow = dirtyQueueRows.find(nHeight); - if (itQueueRow == dirtyQueueRows.end()) - { - claimQueueRowType newRow; - std::pair ret; - ret = dirtyQueueRows.insert(std::pair(nHeight, newRow)); - assert(ret.second); - itQueueRow = ret.first; - } - itQueueRow->second.swap(row); -} - -void CClaimTrie::updateQueueNameRow(const std::string& name, queueNameRowType& row) -{ - queueNameType::iterator itQueueRow = dirtyQueueNameRows.find(name); - if (itQueueRow == dirtyQueueNameRows.end()) - { - queueNameRowType newRow; - std::pair ret; - ret = dirtyQueueNameRows.insert(std::pair(name, newRow)); - assert(ret.second); - itQueueRow = ret.first; - } - itQueueRow->second.swap(row); -} - -void CClaimTrie::updateExpirationRow(int nHeight, expirationQueueRowType& row) -{ - expirationQueueType::iterator itQueueRow = dirtyExpirationQueueRows.find(nHeight); - if (itQueueRow == dirtyExpirationQueueRows.end()) - { - expirationQueueRowType newRow; - std::pair ret; - ret = dirtyExpirationQueueRows.insert(std::pair(nHeight, newRow)); - assert(ret.second); - itQueueRow = ret.first; - } - itQueueRow->second.swap(row); -} - -void CClaimTrie::updateSupportMap(const std::string& name, supportMapEntryType& node) -{ - supportMapType::iterator itNode = dirtySupportNodes.find(name); - if (itNode == dirtySupportNodes.end()) - { - supportMapEntryType newNode; - std::pair ret; - ret = dirtySupportNodes.insert(std::pair(name, newNode)); - assert(ret.second); - itNode = ret.first; - } - itNode->second.swap(node); -} - -void CClaimTrie::updateSupportQueue(int nHeight, supportQueueRowType& row) -{ - supportQueueType::iterator itQueueRow = dirtySupportQueueRows.find(nHeight); - if (itQueueRow == dirtySupportQueueRows.end()) - { - supportQueueRowType newRow; - std::pair ret; - ret = dirtySupportQueueRows.insert(std::pair(nHeight, newRow)); - assert(ret.second); - itQueueRow = ret.first; - } - itQueueRow->second.swap(row); -} - -void CClaimTrie::updateSupportNameQueue(const std::string& name, queueNameRowType& row) -{ - queueNameType::iterator itQueueRow = dirtySupportQueueNameRows.find(name); - if (itQueueRow == dirtySupportQueueNameRows.end()) - { - queueNameRowType newRow; - std::pair ret; - ret = dirtySupportQueueNameRows.insert(std::pair(name, newRow)); - assert(ret.second); - itQueueRow = ret.first; - } - itQueueRow->second.swap(row); -} - -void CClaimTrie::updateSupportExpirationQueue(int nHeight, expirationQueueRowType& row) -{ - expirationQueueType::iterator itQueueRow = dirtySupportExpirationQueueRows.find(nHeight); - if (itQueueRow == dirtySupportExpirationQueueRows.end()) - { - expirationQueueRowType newRow; - std::pair ret; - ret = dirtySupportExpirationQueueRows.insert(std::pair(nHeight, newRow)); - assert(ret.second); - itQueueRow = ret.first; - } - itQueueRow->second.swap(row); -} - -bool CClaimTrie::getSupportNode(std::string name, supportMapEntryType& node) const -{ - supportMapType::const_iterator itNode = dirtySupportNodes.find(name); - if (itNode != dirtySupportNodes.end()) - { - node = itNode->second; - return true; - } - return db.Read(std::make_pair(SUPPORT, name), node); -} - -bool CClaimTrie::getSupportQueueRow(int nHeight, supportQueueRowType& row) const -{ - supportQueueType::const_iterator itQueueRow = dirtySupportQueueRows.find(nHeight); - if (itQueueRow != dirtySupportQueueRows.end()) - { - row = itQueueRow->second; - return true; - } - return db.Read(std::make_pair(SUPPORT_QUEUE_ROW, nHeight), row); -} - -bool CClaimTrie::getSupportQueueNameRow(const std::string& name, queueNameRowType& row) const -{ - queueNameType::const_iterator itQueueNameRow = dirtySupportQueueNameRows.find(name); - if (itQueueNameRow != dirtySupportQueueNameRows.end()) - { - row = itQueueNameRow->second; - return true; - } - return db.Read(std::make_pair(SUPPORT_QUEUE_NAME_ROW, name), row); -} - -bool CClaimTrie::getSupportExpirationQueueRow(int nHeight, expirationQueueRowType& row) const -{ - expirationQueueType::const_iterator itQueueRow = dirtySupportExpirationQueueRows.find(nHeight); - if (itQueueRow != dirtySupportExpirationQueueRows.end()) - { - row = itQueueRow->second; - return true; - } - return db.Read(std::make_pair(SUPPORT_EXP_QUEUE_ROW, nHeight), row); -} - -bool CClaimTrie::update(nodeCacheType& cache, hashMapType& hashes, std::map& takeoverHeights, const uint256& hashBlockIn, claimQueueType& queueCache, queueNameType& queueNameCache, expirationQueueType& expirationQueueCache, int nNewHeight, supportMapType& supportCache, supportQueueType& supportQueueCache, queueNameType& supportQueueNameCache, expirationQueueType& supportExpirationQueueCache) -{ - for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache) - { - if (!updateName(itcache->first, itcache->second)) - { - LogPrintf("%s: Failed to update name for:%s\n", __func__, itcache->first); - return false; - } - } - for (hashMapType::iterator ithash = hashes.begin(); ithash != hashes.end(); ++ithash) - { - if (!updateHash(ithash->first, ithash->second)) - { - LogPrintf("%s: Failed to update hash for:%s\n", __func__, ithash->first); - return false; - } - } - for (std::map::iterator itheight = takeoverHeights.begin(); itheight != takeoverHeights.end(); ++itheight) - { - if (!updateTakeoverHeight(itheight->first, itheight->second)) - { - LogPrintf("%s: Failed to update takeover height for:%s\n", __func__, itheight->first); - return false; - } - } - for (claimQueueType::iterator itQueueCacheRow = queueCache.begin(); itQueueCacheRow != queueCache.end(); ++itQueueCacheRow) - { - updateQueueRow(itQueueCacheRow->first, itQueueCacheRow->second); - } - for (queueNameType::iterator itQueueNameCacheRow = queueNameCache.begin(); itQueueNameCacheRow != queueNameCache.end(); ++itQueueNameCacheRow) - { - updateQueueNameRow(itQueueNameCacheRow->first, itQueueNameCacheRow->second); - } - for (expirationQueueType::iterator itExpirationRow = expirationQueueCache.begin(); itExpirationRow != expirationQueueCache.end(); ++itExpirationRow) - { - updateExpirationRow(itExpirationRow->first, itExpirationRow->second); - } - for (supportMapType::iterator itSupportCache = supportCache.begin(); itSupportCache != supportCache.end(); ++itSupportCache) - { - updateSupportMap(itSupportCache->first, itSupportCache->second); - } - for (supportQueueType::iterator itSupportQueue = supportQueueCache.begin(); itSupportQueue != supportQueueCache.end(); ++itSupportQueue) - { - updateSupportQueue(itSupportQueue->first, itSupportQueue->second); - } - for (queueNameType::iterator itSupportNameQueue = supportQueueNameCache.begin(); itSupportNameQueue != supportQueueNameCache.end(); ++itSupportNameQueue) - { - updateSupportNameQueue(itSupportNameQueue->first, itSupportNameQueue->second); - } - for (expirationQueueType::iterator itSupportExpirationQueue = supportExpirationQueueCache.begin(); itSupportExpirationQueue != supportExpirationQueueCache.end(); ++itSupportExpirationQueue) - { - updateSupportExpirationQueue(itSupportExpirationQueue->first, itSupportExpirationQueue->second); - } - hashBlock = hashBlockIn; - nCurrentHeight = nNewHeight; - return true; -} - -void CClaimTrie::markNodeDirty(const std::string &name, CClaimTrieNode* node) +void CClaimTrie::markNodeDirty(const std::string& name, CClaimTrieNode* node) { std::pair ret; ret = dirtyNodes.insert(std::pair(name, node)); - if (ret.second == false) + if (ret.second == false) { ret.first->second = node; + } } -bool CClaimTrie::updateName(const std::string &name, CClaimTrieNode* updatedNode) +bool CClaimTrie::updateName(const std::string& name, CClaimTrieNode* updatedNode) { 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::iterator itchild = current->children.find(*itname); - if (itchild == current->children.end()) - { - if (itname + 1 == name.end()) - { + if (itchild == current->children.end()) { + if (itname + 1 == name.end()) { CClaimTrieNode* newNode = new CClaimTrieNode(); current->children[*itname] = newNode; current = newNode; - } - else + } else { return false; - } - else - { + } + } else { current = itchild->second; } } assert(current != NULL); current->claims.swap(updatedNode->claims); markNodeDirty(name, current); - for (nodeMapType::iterator itchild = current->children.begin(); itchild != current->children.end();) - { + for (nodeMapType::iterator itchild = current->children.begin(); itchild != current->children.end();) { nodeMapType::iterator itupdatechild = updatedNode->children.find(itchild->first); - if (itupdatechild == updatedNode->children.end()) - { + if (itupdatechild == updatedNode->children.end()) { // This character has apparently been deleted, so delete // all descendents from this child. std::stringstream ss; ss << name << itchild->first; std::string newName = ss.str(); - if (!recursiveNullify(itchild->second, newName)) - return false; + if (!recursiveNullify(itchild->second, newName)) return false; current->children.erase(itchild++); - } - else + } else { ++itchild; + } } return true; } @@ -922,13 +559,11 @@ bool CClaimTrie::updateName(const std::string &name, CClaimTrieNode* updatedNode bool CClaimTrie::recursiveNullify(CClaimTrieNode* node, std::string& name) { assert(node != NULL); - for (nodeMapType::iterator itchild = node->children.begin(); itchild != node->children.end(); ++itchild) - { + for (nodeMapType::iterator itchild = node->children.begin(); itchild != node->children.end(); ++itchild) { std::stringstream ss; ss << name << itchild->first; std::string newName = ss.str(); - if (!recursiveNullify(itchild->second, newName)) - return false; + if (!recursiveNullify(itchild->second, newName)) return false; } node->children.clear(); markNodeDirty(name, NULL); @@ -936,14 +571,12 @@ bool CClaimTrie::recursiveNullify(CClaimTrieNode* node, std::string& name) return true; } -bool CClaimTrie::updateHash(const std::string& name, uint256& hash) +bool CClaimTrie::updateHash(const std::string& name, const uint256& hash) { 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::iterator itchild = current->children.find(*itname); - if (itchild == current->children.end()) - return false; + if (itchild == current->children.end()) return false; current = itchild->second; } assert(current != NULL); @@ -955,11 +588,9 @@ bool CClaimTrie::updateHash(const std::string& name, uint256& hash) bool CClaimTrie::updateTakeoverHeight(const std::string& name, int nTakeoverHeight) { 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::iterator itchild = current->children.find(*itname); - if (itchild == current->children.end()) - return false; + if (itchild == current->children.end()) return false; current = itchild->second; } assert(current != NULL); @@ -968,164 +599,41 @@ bool CClaimTrie::updateTakeoverHeight(const std::string& name, int nTakeoverHeig return true; } -void CClaimTrie::BatchWriteNode(CDBBatch& batch, const std::string& name, const CClaimTrieNode* pNode) const -{ - uint32_t num_claims = 0; - if (pNode) - num_claims = pNode->claims.size(); - LogPrintf("%s: Writing %s to disk with %d claims\n", __func__, name, num_claims); - if (pNode) - batch.Write(std::make_pair(TRIE_NODE, name), *pNode); - else - batch.Erase(std::make_pair(TRIE_NODE, name)); -} - -void CClaimTrie::BatchWriteQueueRows(CDBBatch& batch) -{ - for (claimQueueType::iterator itQueue = dirtyQueueRows.begin(); itQueue != dirtyQueueRows.end(); ++itQueue) - { - if (itQueue->second.empty()) - { - batch.Erase(std::make_pair(CLAIM_QUEUE_ROW, itQueue->first)); - } - else - { - batch.Write(std::make_pair(CLAIM_QUEUE_ROW, itQueue->first), itQueue->second); - } - } -} - -void CClaimTrie::BatchWriteQueueNameRows(CDBBatch& batch) -{ - for (queueNameType::iterator itQueue = dirtyQueueNameRows.begin(); itQueue != dirtyQueueNameRows.end(); ++itQueue) - { - if (itQueue->second.empty()) - { - batch.Erase(std::make_pair(CLAIM_QUEUE_NAME_ROW, itQueue->first)); - } - else - { - batch.Write(std::make_pair(CLAIM_QUEUE_NAME_ROW, itQueue->first), itQueue->second); - } - } -} - -void CClaimTrie::BatchWriteExpirationQueueRows(CDBBatch& batch) -{ - for (expirationQueueType::iterator itQueue = dirtyExpirationQueueRows.begin(); itQueue != dirtyExpirationQueueRows.end(); ++itQueue) - { - if (itQueue->second.empty()) - { - batch.Erase(std::make_pair(EXP_QUEUE_ROW, itQueue->first)); - } - else - { - batch.Write(std::make_pair(EXP_QUEUE_ROW, itQueue->first), itQueue->second); - } - } -} - -void CClaimTrie::BatchWriteSupportNodes(CDBBatch& batch) -{ - for (supportMapType::iterator itSupport = dirtySupportNodes.begin(); itSupport != dirtySupportNodes.end(); ++itSupport) - { - if (itSupport->second.empty()) - { - batch.Erase(std::make_pair(SUPPORT, itSupport->first)); - } - else - { - batch.Write(std::make_pair(SUPPORT, itSupport->first), itSupport->second); - } - } -} - -void CClaimTrie::BatchWriteSupportQueueRows(CDBBatch& batch) -{ - for (supportQueueType::iterator itQueue = dirtySupportQueueRows.begin(); itQueue != dirtySupportQueueRows.end(); ++itQueue) - { - if (itQueue->second.empty()) - { - batch.Erase(std::make_pair(SUPPORT_QUEUE_ROW, itQueue->first)); - } - else - { - batch.Write(std::make_pair(SUPPORT_QUEUE_ROW, itQueue->first), itQueue->second); - } - } -} - -void CClaimTrie::BatchWriteSupportQueueNameRows(CDBBatch& batch) -{ - for (queueNameType::iterator itQueue = dirtySupportQueueNameRows.begin(); itQueue != dirtySupportQueueNameRows.end(); ++itQueue) - { - if (itQueue->second.empty()) - { - batch.Erase(std::make_pair(SUPPORT_QUEUE_NAME_ROW, itQueue->first)); - } - else - { - batch.Write(std::make_pair(SUPPORT_QUEUE_NAME_ROW, itQueue->first), itQueue->second); - } - } -} - -void CClaimTrie::BatchWriteSupportExpirationQueueRows(CDBBatch& batch) -{ - for (expirationQueueType::iterator itQueue = dirtySupportExpirationQueueRows.begin(); itQueue != dirtySupportExpirationQueueRows.end(); ++itQueue) - { - if (itQueue->second.empty()) - { - batch.Erase(std::make_pair(SUPPORT_EXP_QUEUE_ROW, itQueue->first)); - } - else - { - batch.Write(std::make_pair(SUPPORT_EXP_QUEUE_ROW, itQueue->first), itQueue->second); - } - } -} - bool CClaimTrie::WriteToDisk() { - CDBBatch batch(&db.GetObfuscateKey()); - for (nodeCacheType::iterator itcache = dirtyNodes.begin(); itcache != dirtyNodes.end(); ++itcache) - BatchWriteNode(batch, itcache->first, itcache->second); + for (nodeCacheType::iterator itcache = dirtyNodes.begin(); itcache != dirtyNodes.end(); ++itcache) { + CClaimTrieNode* pNode = itcache->second; + uint32_t num_claims = pNode ? pNode->claims.size() : 0; + LogPrintf("%s: Writing %s to disk with %d claims\n", __func__, itcache->first, num_claims); + if (pNode) { + CClaimTrieNode copy(*pNode); + db.updateQueueRow(itcache->first, copy); + } else { + CClaimTrieNode emptyNode; + db.updateQueueRow(itcache->first, emptyNode); + } + } + dirtyNodes.clear(); - BatchWriteQueueRows(batch); - dirtyQueueRows.clear(); - BatchWriteQueueNameRows(batch); - dirtyQueueNameRows.clear(); - BatchWriteExpirationQueueRows(batch); - dirtyExpirationQueueRows.clear(); - BatchWriteSupportNodes(batch); - dirtySupportNodes.clear(); - BatchWriteSupportQueueRows(batch); - dirtySupportQueueRows.clear(); - BatchWriteSupportQueueNameRows(batch); - dirtySupportQueueNameRows.clear(); - BatchWriteSupportExpirationQueueRows(batch); - dirtySupportExpirationQueueRows.clear(); - batch.Write(HASH_BLOCK, hashBlock); - batch.Write(CURRENT_HEIGHT, nCurrentHeight); - return db.WriteBatch(batch); + db.writeQueues(); + db.Write(HASH_BLOCK, hashBlock); + db.Write(CURRENT_HEIGHT, nCurrentHeight); + return db.Sync(); } bool CClaimTrie::InsertFromDisk(const std::string& name, CClaimTrieNode* node) { - if (name.size() == 0) - { + if (name.empty()) { root = *node; return true; } CClaimTrieNode* current = &root; - for (std::string::const_iterator itname = name.begin(); itname + 1 != name.end(); ++itname) - { + for (std::string::const_iterator itname = name.begin(); itname + 1 != name.end(); ++itname) { nodeMapType::iterator itchild = current->children.find(*itname); - if (itchild == current->children.end()) - return false; + if (itchild == current->children.end()) return false; current = itchild->second; } - current->children[name[name.size()-1]] = node; + current->children[name[name.size() - 1]] = new CClaimTrieNode(*node); return true; } @@ -1135,91 +643,84 @@ bool CClaimTrie::ReadFromDisk(bool check) LogPrintf("%s: Couldn't read the best block's hash\n", __func__); if (!db.Read(CURRENT_HEIGHT, nCurrentHeight)) LogPrintf("%s: Couldn't read the current height\n", __func__); - setExpirationTime(Params().GetConsensus().GetExpirationTime(nCurrentHeight-1)); - boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); + setExpirationTime(Params().GetConsensus().GetExpirationTime(nCurrentHeight - 1)); - pcursor->SeekToFirst(); - while (pcursor->Valid()) - { - std::pair key; - if (pcursor->GetKey(key)) - { - if (key.first == TRIE_NODE) - { - CClaimTrieNode* node = new CClaimTrieNode(); - if (pcursor->GetValue(*node)) - { - if (!InsertFromDisk(key.second, node)) - { - return error("%s(): error restoring claim trie from disk", __func__); - } - } - else - { - return error("%s(): error reading claim trie from disk", __func__); - } - } - } - pcursor->Next(); + typedef std::map trieNodeMapType; + + trieNodeMapType nodes; + if (!db.seekByKey(nodes)) { + return error("%s(): error reading claim trie from disk", __func__); } - if (check) - { + for (trieNodeMapType::iterator it = nodes.begin(); it != nodes.end(); ++it) { + if (!InsertFromDisk(it->first, &(it->second))) { + return error("%s(): error restoring claim trie from disk", __func__); + } + } + + if (check) { LogPrintf("Checking Claim trie consistency..."); - if (checkConsistency()) - { + if (checkConsistency()) { LogPrintf("consistent\n"); return true; + } else { + LogPrintf("inconsistent!\n"); + return false; } - LogPrintf("inconsistent!\n"); - return false; } return true; } -bool CClaimTrieCache::recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent, std::string sPos) const +CClaimTrieCache::CClaimTrieCache(CClaimTrie* base, bool fRequireTakeoverHeights) + : base(base), fRequireTakeoverHeights(fRequireTakeoverHeights) { - if (sPos == "" && tnCurrent->empty()) - { - cacheHashes[""] = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); + assert(base); + hashBlock = base->hashBlock; + nCurrentHeight = base->nCurrentHeight; +} + +CClaimTrieCache::~CClaimTrieCache() +{ + clear(); +} + +bool CClaimTrieCache::recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent, const std::string& sPos) const +{ + if (sPos == "" && tnCurrent->empty()) { + cacheHashes[""] = one; return true; } std::vector vchToHash; - nodeCacheType::iterator cachedNode; + nodeCacheType::const_iterator cachedNode; - for (nodeMapType::iterator it = tnCurrent->children.begin(); it != tnCurrent->children.end(); ++it) - { + for (nodeMapType::iterator it = tnCurrent->children.begin(); it != tnCurrent->children.end(); ++it) { std::stringstream ss; ss << it->first; std::string sNextPos = sPos + ss.str(); - if (dirtyHashes.count(sNextPos) != 0) - { + if (dirtyHashes.count(sNextPos) != 0) { // the child might be in the cache, so look for it there cachedNode = cache.find(sNextPos); - if (cachedNode != cache.end()) + if (cachedNode != cache.end()) { recursiveComputeMerkleHash(cachedNode->second, sNextPos); - else + } else { recursiveComputeMerkleHash(it->second, sNextPos); + } } vchToHash.push_back(it->first); hashMapType::iterator ithash = cacheHashes.find(sNextPos); - if (ithash != cacheHashes.end()) - { + if (ithash != cacheHashes.end()) { vchToHash.insert(vchToHash.end(), ithash->second.begin(), ithash->second.end()); - } - else - { + } else { vchToHash.insert(vchToHash.end(), it->second->hash.begin(), it->second->hash.end()); } } - + CClaimValue claim; bool hasClaim = tnCurrent->getBestClaim(claim); - if (hasClaim) - { + if (hasClaim) { int nHeightOfLastTakeover; assert(getLastTakeoverForName(sPos, nHeightOfLastTakeover)); uint256 valueHash = getValueHash(claim.outPoint, nHeightOfLastTakeover); @@ -1232,31 +733,29 @@ bool CClaimTrieCache::recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent, std: hasher.Finalize(&(vchHash[0])); cacheHashes[sPos] = uint256(vchHash); std::set::iterator itDirty = dirtyHashes.find(sPos); - if (itDirty != dirtyHashes.end()) + if (itDirty != dirtyHashes.end()) { dirtyHashes.erase(itDirty); + } return true; } uint256 CClaimTrieCache::getMerkleHash() const { - if (empty()) - { - uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); - return one; - } - if (dirty()) - { - nodeCacheType::iterator cachedNode = cache.find(""); - if (cachedNode != cache.end()) + if (empty()) return one; + if (dirty()) { + nodeCacheType::const_iterator cachedNode = cache.find(""); + if (cachedNode != cache.end()) { recursiveComputeMerkleHash(cachedNode->second, ""); - else + } else { recursiveComputeMerkleHash(&(base->root), ""); + } } - hashMapType::iterator ithash = cacheHashes.find(""); - if (ithash != cacheHashes.end()) + hashMapType::const_iterator ithash = cacheHashes.find(""); + if (ithash != cacheHashes.end()) { return ithash->second; - else + } else { return base->root.hash; + } } bool CClaimTrieCache::empty() const @@ -1264,26 +763,27 @@ bool CClaimTrieCache::empty() const return base->empty() && cache.empty(); } -CClaimTrieNode* CClaimTrieCache::addNodeToCache(const std::string& position, CClaimTrieNode* original) const +CClaimTrieNode* CClaimTrieCache::addNodeToCache(const std::string& position, CClaimTrieNode* original) { // create a copy of the node in the cache, if new node, create empty node CClaimTrieNode* cacheCopy; - if(!original) + if (!original) { cacheCopy = new CClaimTrieNode(); - else + } else { cacheCopy = new CClaimTrieNode(*original); + } cache[position] = cacheCopy; // check to see if there is the original node in block_originals, // if not, add it to block_originals cache nodeCacheType::const_iterator itOriginals = block_originals.find(position); - if (block_originals.end() == itOriginals) - { + if (block_originals.end() == itOriginals) { CClaimTrieNode* originalCopy; - if(!original) + if (!original) { originalCopy = new CClaimTrieNode(); - else + } else { originalCopy = new CClaimTrieNode(*original); + } block_originals[position] = originalCopy; } return cacheCopy; @@ -1292,39 +792,36 @@ CClaimTrieNode* CClaimTrieCache::addNodeToCache(const std::string& position, CCl bool CClaimTrieCache::getOriginalInfoForName(const std::string& name, CClaimValue& claim) const { nodeCacheType::const_iterator itOriginalCache = block_originals.find(name); - if (itOriginalCache == block_originals.end()) - { + if (itOriginalCache == block_originals.end()) { return base->getInfoForName(name, claim); } return itOriginalCache->second->getBestClaim(claim); } -bool CClaimTrieCache::insertClaimIntoTrie(const std::string& name, CClaimValue claim, bool fCheckTakeover) const +bool CClaimTrieCache::insertClaimIntoTrie(const std::string& name, const CClaimValue& claim, bool fCheckTakeover) { assert(base); CClaimTrieNode* currentNode = &(base->root); nodeCacheType::iterator cachedNode; cachedNode = cache.find(""); - if (cachedNode != cache.end()) + if (cachedNode != cache.end()) { currentNode = cachedNode->second; - for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) - { + } + for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) { std::string sCurrentSubstring(name.begin(), itCur); std::string sNextSubstring(name.begin(), itCur + 1); cachedNode = cache.find(sNextSubstring); - if (cachedNode != cache.end()) - { + if (cachedNode != cache.end()) { currentNode = cachedNode->second; continue; } nodeMapType::iterator childNode = currentNode->children.find(*itCur); - if (childNode != currentNode->children.end()) - { + if (childNode != currentNode->children.end()) { currentNode = childNode->second; continue; } - + // This next substring doesn't exist in the cache and the next // character doesn't exist in current node's children, so check // if the current node is in the cache, and if it's not, copy @@ -1335,12 +832,9 @@ bool CClaimTrieCache::insertClaimIntoTrie(const std::string& name, CClaimValue c // used to find the child in the cache. This is necessary in // order to calculate the merkle hash. cachedNode = cache.find(sCurrentSubstring); - if (cachedNode != cache.end()) - { + if (cachedNode != cache.end()) { assert(cachedNode->second == currentNode); - } - else - { + } else { currentNode = addNodeToCache(sCurrentSubstring, currentNode); } CClaimTrieNode* newNode = addNodeToCache(sNextSubstring, NULL); @@ -1349,68 +843,59 @@ bool CClaimTrieCache::insertClaimIntoTrie(const std::string& name, CClaimValue c } cachedNode = cache.find(name); - if (cachedNode != cache.end()) - { + if (cachedNode != cache.end()) { assert(cachedNode->second == currentNode); - } - else - { + } else { currentNode = addNodeToCache(name, currentNode); } bool fChanged = false; - if (currentNode->claims.empty()) - { + if (currentNode->claims.empty()) { fChanged = true; currentNode->insertClaim(claim); - } - else - { + } else { CClaimValue currentTop = currentNode->claims.front(); currentNode->insertClaim(claim); supportMapEntryType node; getSupportsForName(name, node); currentNode->reorderClaims(node); - if (currentTop != currentNode->claims.front()) + if (currentTop != currentNode->claims.front()) { fChanged = true; + } } - - if (fChanged) - { - for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) - { + if (fChanged) { + for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) { std::string sub(name.begin(), itCur); dirtyHashes.insert(sub); } dirtyHashes.insert(name); - if (fCheckTakeover) + if (fCheckTakeover) { namesToCheckForTakeover.insert(name); + } } return true; } -bool CClaimTrieCache::removeClaimFromTrie(const std::string& name, const COutPoint& outPoint, CClaimValue& claim, bool fCheckTakeover) const +bool CClaimTrieCache::removeClaimFromTrie(const std::string& name, const COutPoint& outPoint, CClaimValue& claim, bool fCheckTakeover) { assert(base); CClaimTrieNode* currentNode = &(base->root); nodeCacheType::iterator cachedNode; cachedNode = cache.find(""); - if (cachedNode != cache.end()) + if (cachedNode != cache.end()) { currentNode = cachedNode->second; + } assert(currentNode != NULL); // If there is no root in either the trie or the cache, how can there be any names to remove? - for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) - { + for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) { std::string sCurrentSubstring(name.begin(), itCur); std::string sNextSubstring(name.begin(), itCur + 1); cachedNode = cache.find(sNextSubstring); - if (cachedNode != cache.end()) - { + if (cachedNode != cache.end()) { currentNode = cachedNode->second; continue; } nodeMapType::iterator childNode = currentNode->children.find(*itCur); - if (childNode != currentNode->children.end()) - { + if (childNode != currentNode->children.end()) { currentNode = childNode->second; continue; } @@ -1419,87 +904,80 @@ bool CClaimTrieCache::removeClaimFromTrie(const std::string& name, const COutPoi } cachedNode = cache.find(name); - if (cachedNode != cache.end()) + if (cachedNode != cache.end()) { assert(cachedNode->second == currentNode); - else - { + } else { currentNode = addNodeToCache(name, currentNode); } bool fChanged = false; assert(currentNode != NULL); bool success = false; - - if (currentNode->claims.empty()) - { + + if (currentNode->claims.empty()) { LogPrintf("%s: Asked to remove claim from node without claims\n", __func__); return false; } CClaimValue currentTop = currentNode->claims.front(); success = currentNode->removeClaim(outPoint, claim); - if (!currentNode->claims.empty()) - { + if (!currentNode->claims.empty()) { supportMapEntryType node; getSupportsForName(name, node); currentNode->reorderClaims(node); - if (currentTop != currentNode->claims.front()) + if (currentTop != currentNode->claims.front()) { fChanged = true; - } - else + } + } else { fChanged = true; + } - if (!success) - { + if (!success) { LogPrintf("%s: Removing a claim was unsuccessful. name = %s, txhash = %s, nOut = %d", __func__, name.c_str(), outPoint.hash.GetHex(), outPoint.n); return false; } - if (fChanged) - { - for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) - { + if (fChanged) { + for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) { std::string sub(name.begin(), itCur); dirtyHashes.insert(sub); } dirtyHashes.insert(name); - if (fCheckTakeover) + if (fCheckTakeover) { namesToCheckForTakeover.insert(name); + } } CClaimTrieNode* rootNode = &(base->root); cachedNode = cache.find(""); - if (cachedNode != cache.end()) + if (cachedNode != cache.end()) { rootNode = cachedNode->second; + } return recursivePruneName(rootNode, 0, name); } -bool CClaimTrieCache::recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, std::string sName, bool* pfNullified) const +bool CClaimTrieCache::recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, const std::string& sName, bool* pfNullified) { // Recursively prune leaf node(s) without any claims in it and store // the modified nodes in the cache bool fNullified = false; std::string sCurrentSubstring = sName.substr(0, nPos); - if (nPos < sName.size()) - { + if (nPos < sName.size()) { std::string sNextSubstring = sName.substr(0, nPos + 1); unsigned char cNext = sName.at(nPos); CClaimTrieNode* tnNext = NULL; nodeCacheType::iterator cachedNode = cache.find(sNextSubstring); - if (cachedNode != cache.end()) + if (cachedNode != cache.end()) { tnNext = cachedNode->second; - else - { + } else { nodeMapType::iterator childNode = tnCurrent->children.find(cNext); - if (childNode != tnCurrent->children.end()) + if (childNode != tnCurrent->children.end()) { tnNext = childNode->second; + } } - if (tnNext == NULL) - return false; + if (tnNext == NULL) return false; bool fChildNullified = false; - if (!recursivePruneName(tnNext, nPos + 1, sName, &fChildNullified)) - return false; - if (fChildNullified) - { + if (!recursivePruneName(tnNext, nPos + 1, sName, &fChildNullified)) return false; + if (fChildNullified) { // If the child nullified itself, the child should already be // out of the cache, and the character must now be removed // from the current node's map of child nodes to ensure that @@ -1507,15 +985,14 @@ bool CClaimTrieCache::recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int // tnCurrent isn't necessarily in the cache. If it's not, it // has to be added to the cache, so nothing is changed in the // trie. If the current node is added to the cache, however, - // that does not imply that the parent node must be altered to + // that does not imply that the parent node must be altered to // reflect that its child is now in the cache, since it // already has a character in its child map which will be used // when calculating the merkle root. // First, find out if this node is in the cache. cachedNode = cache.find(sCurrentSubstring); - if (cachedNode == cache.end()) - { + if (cachedNode == cache.end()) { // it isn't, so make a copy, stick it in the cache, // and make it the new current node tnCurrent = addNodeToCache(sCurrentSubstring, tnCurrent); @@ -1523,272 +1000,189 @@ bool CClaimTrieCache::recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int // erase the character from the current node, which is // now guaranteed to be in the cache nodeMapType::iterator childNode = tnCurrent->children.find(cNext); - if (childNode != tnCurrent->children.end()) + if (childNode != tnCurrent->children.end()) { tnCurrent->children.erase(childNode); - else + } else { return false; + } } } - if (sCurrentSubstring.size() != 0 && tnCurrent->empty()) - { + if (sCurrentSubstring.size() != 0 && tnCurrent->empty()) { // If the current node is in the cache, remove it from there nodeCacheType::iterator cachedNode = cache.find(sCurrentSubstring); - if (cachedNode != cache.end()) - { + if (cachedNode != cache.end()) { assert(tnCurrent == cachedNode->second); delete tnCurrent; cache.erase(cachedNode); } fNullified = true; } - if (pfNullified) + if (pfNullified) { *pfNullified = fNullified; + } return true; } -claimQueueType::iterator CClaimTrieCache::getQueueCacheRow(int nHeight, bool createIfNotExists) const -{ - claimQueueType::iterator itQueueRow = claimQueueCache.find(nHeight); - if (itQueueRow == claimQueueCache.end()) - { - // Have to make a new row it put in the cache, if createIfNotExists is true - claimQueueRowType queueRow; - // If the row exists in the base, copy its claims into the new row. - bool exists = base->getQueueRow(nHeight, queueRow); - if (!exists) - if (!createIfNotExists) - return itQueueRow; - // Stick the new row in the cache - std::pair ret; - ret = claimQueueCache.insert(std::pair(nHeight, queueRow)); - assert(ret.second); - itQueueRow = ret.first; - } - return itQueueRow; -} - -queueNameType::iterator CClaimTrieCache::getQueueCacheNameRow(const std::string& name, bool createIfNotExists) const -{ - queueNameType::iterator itQueueNameRow = claimQueueNameCache.find(name); - if (itQueueNameRow == claimQueueNameCache.end()) - { - // Have to make a new name row and put it in the cache, if createIfNotExists is true - queueNameRowType queueNameRow; - // If the row exists in the base, copy its claims into the new row. - bool exists = base->getQueueNameRow(name, queueNameRow); - if (!exists) - if (!createIfNotExists) - return itQueueNameRow; - // Stick the new row in the cache - std::pair ret; - ret = claimQueueNameCache.insert(std::pair(name, queueNameRow)); - assert(ret.second); - itQueueNameRow = ret.first; - } - return itQueueNameRow; -} - -bool CClaimTrieCache::addClaim(const std::string& name, const COutPoint& outPoint, uint160 claimId, CAmount nAmount, int nHeight) const +bool CClaimTrieCache::addClaim(const std::string& name, const COutPoint& outPoint, const uint160& claimId, const CAmount& nAmount, int nHeight) { LogPrintf("%s: name: %s, txhash: %s, nOut: %d, claimId: %s, nAmount: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, claimId.GetHex(), nAmount, nHeight, nCurrentHeight); assert(nHeight == nCurrentHeight); CClaimValue currentClaim; int delayForClaim; - if (getOriginalInfoForName(name, currentClaim) && currentClaim.claimId == claimId) - { + if (getOriginalInfoForName(name, currentClaim) && currentClaim.claimId == claimId) { LogPrintf("%s: This is an update to a best claim.\n", __func__); delayForClaim = 0; - } - else - { + } else { delayForClaim = getDelayForName(name); } CClaimValue newClaim(outPoint, claimId, nAmount, nHeight, nHeight + delayForClaim); return addClaimToQueues(name, newClaim); } -bool CClaimTrieCache::undoSpendClaim(const std::string& name, const COutPoint& outPoint, uint160 claimId, CAmount nAmount, int nHeight, int nValidAtHeight) const +bool CClaimTrieCache::undoSpendClaim(const std::string& name, const COutPoint& outPoint, const uint160& claimId, const CAmount& nAmount, int nHeight, int nValidAtHeight) { LogPrintf("%s: name: %s, txhash: %s, nOut: %d, claimId: %s, nAmount: %d, nHeight: %d, nValidAtHeight: %d, nCurrentHeight: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, claimId.GetHex(), nAmount, nHeight, nValidAtHeight, nCurrentHeight); CClaimValue claim(outPoint, claimId, nAmount, nHeight, nValidAtHeight); - if (nValidAtHeight < nCurrentHeight) - { + if (nValidAtHeight < nCurrentHeight) { nameOutPointType entry(name, claim.outPoint); addToExpirationQueue(claim.nHeight + base->nExpirationTime, entry); - CClaimIndexElement element = {name, claim}; - claimsToAdd.push_back(element); + base->addToClaimIndex(name, claim); return insertClaimIntoTrie(name, claim, false); - } - else - { + } else { return addClaimToQueues(name, claim); } } -bool CClaimTrieCache::addClaimToQueues(const std::string& name, CClaimValue& claim) const +template +typename std::map::iterator CClaimTrieCache::getQueueCacheRow(const K& key, std::map& map, bool createIfNotExists) +{ + typename std::map::iterator itQueueRow = map.find(key); + if (itQueueRow == map.end()) { + // Have to make a new row it put in the cache, if createIfNotExists is true + V queueRow; + // If the row exists in the base, copy its claims into the new row. + bool exists = base->db.getQueueRow(key, queueRow); + if (!exists && !createIfNotExists) return itQueueRow; + // Stick the new row in the cache + itQueueRow = map.insert(itQueueRow, std::make_pair(key, queueRow)); + } + return itQueueRow; +} + +bool CClaimTrieCache::addClaimToQueues(const std::string& name, CClaimValue& claim) { LogPrintf("%s: nValidAtHeight: %d\n", __func__, claim.nValidAtHeight); claimQueueEntryType entry(name, claim); - claimQueueType::iterator itQueueRow = getQueueCacheRow(claim.nValidAtHeight, true); - queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(name, true); + claimQueueType::iterator itQueueRow = getQueueCacheRow(claim.nValidAtHeight, claimQueueCache, true); + queueNameType::iterator itQueueNameRow = getQueueCacheRow(name, claimQueueNameCache, true); itQueueRow->second.push_back(entry); itQueueNameRow->second.push_back(outPointHeightType(claim.outPoint, claim.nValidAtHeight)); nameOutPointType expireEntry(name, claim.outPoint); addToExpirationQueue(claim.nHeight + base->nExpirationTime, expireEntry); - CClaimIndexElement element = {name, claim}; - claimsToAdd.push_back(element); + base->addToClaimIndex(name, claim); return true; } -bool CClaimTrieCache::removeClaimFromQueue(const std::string& name, const COutPoint& outPoint, CClaimValue& claim) const +bool CClaimTrieCache::removeClaimFromQueue(const std::string& name, const COutPoint& outPoint, CClaimValue& claim) { - queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(name, false); - if (itQueueNameRow == claimQueueNameCache.end()) - { - return false; - } + queueNameType::iterator itQueueNameRow = getQueueCacheRow(name, claimQueueNameCache, false); + if (itQueueNameRow == claimQueueNameCache.end()) return false; queueNameRowType::iterator itQueueName; - for (itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) - { - if (itQueueName->outPoint == outPoint) - { - break; - } + for (itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) { + if (itQueueName->outPoint == outPoint) break; } - if (itQueueName == itQueueNameRow->second.end()) - { - return false; - } - claimQueueType::iterator itQueueRow = getQueueCacheRow(itQueueName->nHeight, false); - if (itQueueRow != claimQueueCache.end()) - { + if (itQueueName == itQueueNameRow->second.end()) return false; + claimQueueType::iterator itQueueRow = getQueueCacheRow(itQueueName->nHeight, claimQueueCache, false); + if (itQueueRow != claimQueueCache.end()) { claimQueueRowType::iterator itQueue; - for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) - { - if (name == itQueue->first && itQueue->second.outPoint == outPoint) - { - break; + for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) { + if (name == itQueue->first && itQueue->second.outPoint == outPoint) { + std::swap(claim, itQueue->second); + itQueueNameRow->second.erase(itQueueName); + itQueueRow->second.erase(itQueue); + return true; } } - if (itQueue != itQueueRow->second.end()) - { - std::swap(claim, itQueue->second); - itQueueNameRow->second.erase(itQueueName); - itQueueRow->second.erase(itQueue); - return true; - } } LogPrintf("%s: An inconsistency was found in the claim queue. Please report this to the developers:\nFound in named queue but not in height queue: name: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, itQueueName->nHeight, nCurrentHeight); return false; } -bool CClaimTrieCache::undoAddClaim(const std::string& name, const COutPoint& outPoint, int nHeight) const +bool CClaimTrieCache::undoAddClaim(const std::string& name, const COutPoint& outPoint, int nHeight) { int throwaway; return removeClaim(name, outPoint, nHeight, throwaway, false); } -bool CClaimTrieCache::spendClaim(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight) const +bool CClaimTrieCache::spendClaim(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight) { return removeClaim(name, outPoint, nHeight, nValidAtHeight, true); } -bool CClaimTrieCache::removeClaim(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight, bool fCheckTakeover) const +bool CClaimTrieCache::removeClaim(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight, bool fCheckTakeover) { LogPrintf("%s: name: %s, txhash: %s, nOut: %s, nHeight: %s, nCurrentHeight: %s\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nHeight, nCurrentHeight); bool removed = false; CClaimValue claim; - if (removeClaimFromQueue(name, outPoint, claim)) - { + if (removeClaimFromQueue(name, outPoint, claim)) { removed = true; } - if (removed == false && removeClaimFromTrie(name, outPoint, claim, fCheckTakeover)) - { + if (removed == false && removeClaimFromTrie(name, outPoint, claim, fCheckTakeover)) { removed = true; } - if (removed == true) - { + if (removed == true) { nValidAtHeight = claim.nValidAtHeight; int expirationHeight = nHeight + base->nExpirationTime; removeFromExpirationQueue(name, outPoint, expirationHeight); - claimsToDelete.insert(claim); + base->removeFromClaimIndex(claim); } return removed; } -void CClaimTrieCache::addToExpirationQueue(int nExpirationHeight, nameOutPointType& entry) const +void CClaimTrieCache::addToExpirationQueue(int nExpirationHeight, nameOutPointType& entry) { - expirationQueueType::iterator itQueueRow = getExpirationQueueCacheRow(nExpirationHeight, true); + expirationQueueType::iterator itQueueRow = getQueueCacheRow(nExpirationHeight, expirationQueueCache, true); itQueueRow->second.push_back(entry); } -void CClaimTrieCache::removeFromExpirationQueue(const std::string& name, const COutPoint& outPoint, int expirationHeight) const +void CClaimTrieCache::removeFromExpirationQueue(const std::string& name, const COutPoint& outPoint, int expirationHeight) { - expirationQueueType::iterator itQueueRow = getExpirationQueueCacheRow(expirationHeight, false); + expirationQueueType::iterator itQueueRow = getQueueCacheRow(expirationHeight, expirationQueueCache, false); expirationQueueRowType::iterator itQueue; - if (itQueueRow != expirationQueueCache.end()) - { - for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) - { - if (name == itQueue->name && outPoint == itQueue->outPoint) + if (itQueueRow != expirationQueueCache.end()) { + for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) { + if (name == itQueue->name && outPoint == itQueue->outPoint) { + itQueueRow->second.erase(itQueue); break; - } - - if (itQueue != itQueueRow->second.end()) - { - itQueueRow->second.erase(itQueue); + } } } } -expirationQueueType::iterator CClaimTrieCache::getExpirationQueueCacheRow(int nHeight, bool createIfNotExists) const -{ - expirationQueueType::iterator itQueueRow = expirationQueueCache.find(nHeight); - if (itQueueRow == expirationQueueCache.end()) - { - // Have to make a new row it put in the cache, if createIfNotExists is true - expirationQueueRowType queueRow; - // If the row exists in the base, copy its claims into the new row. - bool exists = base->getExpirationQueueRow(nHeight, queueRow); - if (!exists) - if (!createIfNotExists) - return itQueueRow; - // Stick the new row in the cache - std::pair ret; - ret = expirationQueueCache.insert(std::pair(nHeight, queueRow)); - assert(ret.second); - itQueueRow = ret.first; - } - return itQueueRow; -} - -bool CClaimTrieCache::reorderTrieNode(const std::string& name, bool fCheckTakeover) const +bool CClaimTrieCache::reorderTrieNode(const std::string& name, bool fCheckTakeover) { assert(base); nodeCacheType::iterator cachedNode; cachedNode = cache.find(name); - if (cachedNode == cache.end()) - { + if (cachedNode == cache.end()) { CClaimTrieNode* currentNode; cachedNode = cache.find(""); - if(cachedNode == cache.end()) + if (cachedNode == cache.end()) { currentNode = &(base->root); - else + } else { currentNode = cachedNode->second; - for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) - { + } + for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) { std::string sCurrentSubstring(name.begin(), itCur); std::string sNextSubstring(name.begin(), itCur + 1); cachedNode = cache.find(sNextSubstring); - if (cachedNode != cache.end()) - { + if (cachedNode != cache.end()) { currentNode = cachedNode->second; continue; } nodeMapType::iterator childNode = currentNode->children.find(*itCur); - if (childNode != currentNode->children.end()) - { + if (childNode != currentNode->children.end()) { currentNode = childNode->second; continue; } @@ -1802,59 +1196,52 @@ bool CClaimTrieCache::reorderTrieNode(const std::string& name, bool fCheckTakeov cachedNode = ret.first; } bool fChanged = false; - if (cachedNode->second->claims.empty()) - { + if (cachedNode->second->claims.empty()) { // Nothing in there to reorder return true; - } - else - { + } else { CClaimValue currentTop = cachedNode->second->claims.front(); supportMapEntryType node; getSupportsForName(name, node); cachedNode->second->reorderClaims(node); - if (cachedNode->second->claims.front() != currentTop) + if (cachedNode->second->claims.front() != currentTop) { fChanged = true; + } } - if (fChanged) - { - for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) - { + if (fChanged) { + for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) { std::string sub(name.begin(), itCur); dirtyHashes.insert(sub); } dirtyHashes.insert(name); - if (fCheckTakeover) + if (fCheckTakeover) { namesToCheckForTakeover.insert(name); + } } return true; } bool CClaimTrieCache::getSupportsForName(const std::string& name, supportMapEntryType& node) const { - supportMapType::iterator cachedNode; + supportMapType::const_iterator cachedNode; cachedNode = supportCache.find(name); - if (cachedNode != supportCache.end()) - { + if (cachedNode != supportCache.end()) { node = cachedNode->second; return true; - } - else - { - return base->getSupportNode(name, node); + } else { + return base->db.getQueueRow(name, node); } } -bool CClaimTrieCache::insertSupportIntoMap(const std::string& name, CSupportValue support, bool fCheckTakeover) const +bool CClaimTrieCache::insertSupportIntoMap(const std::string& name, const CSupportValue& support, bool fCheckTakeover) { supportMapType::iterator cachedNode; // If this node is already in the cache, use that cachedNode = supportCache.find(name); // If not, copy the one from base if it exists, and use that - if (cachedNode == supportCache.end()) - { + if (cachedNode == supportCache.end()) { supportMapEntryType node; - base->getSupportNode(name, node); + base->db.getQueueRow(name, node); std::pair ret; ret = supportCache.insert(std::pair(name, node)); assert(ret.second); @@ -1862,18 +1249,16 @@ bool CClaimTrieCache::insertSupportIntoMap(const std::string& name, CSupportValu } cachedNode->second.push_back(support); // See if this changed the biggest bid - return reorderTrieNode(name, fCheckTakeover); + return reorderTrieNode(name, fCheckTakeover); } -bool CClaimTrieCache::removeSupportFromMap(const std::string& name, const COutPoint& outPoint, CSupportValue& support, bool fCheckTakeover) const +bool CClaimTrieCache::removeSupportFromMap(const std::string& name, const COutPoint& outPoint, CSupportValue& support, bool fCheckTakeover) { supportMapType::iterator cachedNode; cachedNode = supportCache.find(name); - if (cachedNode == supportCache.end()) - { + if (cachedNode == supportCache.end()) { supportMapEntryType node; - if (!base->getSupportNode(name, node)) - { + if (!base->db.getQueueRow(name, node)) { // clearly, this support does not exist return false; } @@ -1883,70 +1268,23 @@ bool CClaimTrieCache::removeSupportFromMap(const std::string& name, const COutPo cachedNode = ret.first; } supportMapEntryType::iterator itSupport; - for (itSupport = cachedNode->second.begin(); itSupport != cachedNode->second.end(); ++itSupport) - { - if (itSupport->outPoint == outPoint) - { - break; + for (itSupport = cachedNode->second.begin(); itSupport != cachedNode->second.end(); ++itSupport) { + if (itSupport->outPoint == outPoint) { + std::swap(support, *itSupport); + cachedNode->second.erase(itSupport); + return reorderTrieNode(name, fCheckTakeover); } } - if (itSupport != cachedNode->second.end()) - { - std::swap(support, *itSupport); - cachedNode->second.erase(itSupport); - return reorderTrieNode(name, fCheckTakeover); - } - else - { - LogPrintf("CClaimTrieCache::%s() : asked to remove a support that doesn't exist\n", __func__); - return false; - } + LogPrintf("CClaimTrieCache::%s() : asked to remove a support that doesn't exist\n", __func__); + return false; } -supportQueueType::iterator CClaimTrieCache::getSupportQueueCacheRow(int nHeight, bool createIfNotExists) const -{ - supportQueueType::iterator itQueueRow = supportQueueCache.find(nHeight); - if (itQueueRow == supportQueueCache.end()) - { - supportQueueRowType queueRow; - bool exists = base->getSupportQueueRow(nHeight, queueRow); - if (!exists) - if (!createIfNotExists) - return itQueueRow; - // Stick the new row in the cache - std::pair ret; - ret = supportQueueCache.insert(std::pair(nHeight, queueRow)); - assert(ret.second); - itQueueRow = ret.first; - } - return itQueueRow; -} - -queueNameType::iterator CClaimTrieCache::getSupportQueueCacheNameRow(const std::string& name, bool createIfNotExists) const -{ - queueNameType::iterator itQueueNameRow = supportQueueNameCache.find(name); - if (itQueueNameRow == supportQueueNameCache.end()) - { - queueNameRowType queueNameRow; - bool exists = base->getSupportQueueNameRow(name, queueNameRow); - if (!exists) - if (!createIfNotExists) - return itQueueNameRow; - // Stick the new row in the name cache - std::pair ret; - ret = supportQueueNameCache.insert(std::pair(name, queueNameRow)); - assert(ret.second); - itQueueNameRow = ret.first; - } - return itQueueNameRow; -} - -bool CClaimTrieCache::addSupportToQueues(const std::string& name, CSupportValue& support) const +bool CClaimTrieCache::addSupportToQueues(const std::string& name, CSupportValue& support) { LogPrintf("%s: nValidAtHeight: %d\n", __func__, support.nValidAtHeight); supportQueueEntryType entry(name, support); - supportQueueType::iterator itQueueRow = getSupportQueueCacheRow(support.nValidAtHeight, true); - queueNameType::iterator itQueueNameRow = getSupportQueueCacheNameRow(name, true); + supportQueueType::iterator itQueueRow = getQueueCacheRow(support.nValidAtHeight, supportQueueCache, true); + supportQueueNameType::iterator itQueueNameRow = getQueueCacheRow(name, supportQueueNameCache, true); itQueueRow->second.push_back(entry); itQueueNameRow->second.push_back(outPointHeightType(support.outPoint, support.nValidAtHeight)); nameOutPointType expireEntry(name, support.outPoint); @@ -1954,94 +1292,71 @@ bool CClaimTrieCache::addSupportToQueues(const std::string& name, CSupportValue& return true; } -bool CClaimTrieCache::removeSupportFromQueue(const std::string& name, const COutPoint& outPoint, CSupportValue& support) const +bool CClaimTrieCache::removeSupportFromQueue(const std::string& name, const COutPoint& outPoint, CSupportValue& support) { - queueNameType::iterator itQueueNameRow = getSupportQueueCacheNameRow(name, false); - if (itQueueNameRow == supportQueueNameCache.end()) - { - return false; + supportQueueNameType::iterator itQueueNameRow = getQueueCacheRow(name, supportQueueNameCache, false); + if (itQueueNameRow == supportQueueNameCache.end()) return false; + supportQueueNameRowType::iterator itQueueName; + for (itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) { + if (itQueueName->outPoint == outPoint) break; } - queueNameRowType::iterator itQueueName; - for (itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) - { - if (itQueueName->outPoint == outPoint) - { - break; - } - } - if (itQueueName == itQueueNameRow->second.end()) - { - return false; - } - supportQueueType::iterator itQueueRow = getSupportQueueCacheRow(itQueueName->nHeight, false); - if (itQueueRow != supportQueueCache.end()) - { + if (itQueueName == itQueueNameRow->second.end()) return false; + supportQueueType::iterator itQueueRow = getQueueCacheRow(itQueueName->nHeight, supportQueueCache, false); + if (itQueueRow != supportQueueCache.end()) { supportQueueRowType::iterator itQueue; - for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) - { - CSupportValue& support = itQueue->second; - if (name == itQueue->first && support.outPoint == outPoint) - { - break; + for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) { + if (name == itQueue->first && itQueue->second.outPoint == outPoint) { + std::swap(support, itQueue->second); + itQueueNameRow->second.erase(itQueueName); + itQueueRow->second.erase(itQueue); + return true; } } - if (itQueue != itQueueRow->second.end()) - { - std::swap(support, itQueue->second); - itQueueNameRow->second.erase(itQueueName); - itQueueRow->second.erase(itQueue); - return true; - } } LogPrintf("%s: An inconsistency was found in the claim queue. Please report this to the developers:\nFound in named support queue but not in height support queue: name: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, itQueueName->nHeight, nCurrentHeight); return false; } -bool CClaimTrieCache::addSupport(const std::string& name, const COutPoint& outPoint, CAmount nAmount, uint160 supportedClaimId, int nHeight) const +bool CClaimTrieCache::addSupport(const std::string& name, const COutPoint& outPoint, const CAmount& nAmount, const uint160& supportedClaimId, int nHeight) { LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nAmount: %d, supportedClaimId: %s, nHeight: %d, nCurrentHeight: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nAmount, supportedClaimId.GetHex(), nHeight, nCurrentHeight); assert(nHeight == nCurrentHeight); CClaimValue claim; int delayForSupport; - if (getOriginalInfoForName(name, claim) && claim.claimId == supportedClaimId) - { + if (getOriginalInfoForName(name, claim) && claim.claimId == supportedClaimId) { LogPrintf("%s: This is a support to a best claim.\n", __func__); delayForSupport = 0; - } - else - { + } else { delayForSupport = getDelayForName(name); } CSupportValue support(outPoint, supportedClaimId, nAmount, nHeight, nHeight + delayForSupport); return addSupportToQueues(name, support); } -bool CClaimTrieCache::undoSpendSupport(const std::string& name, const COutPoint& outPoint, uint160 supportedClaimId, CAmount nAmount, int nHeight, int nValidAtHeight) const +bool CClaimTrieCache::undoSpendSupport(const std::string& name, const COutPoint& outPoint, const uint160& supportedClaimId, const CAmount& nAmount, int nHeight, int nValidAtHeight) { LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nAmount: %d, supportedClaimId: %s, nHeight: %d, nCurrentHeight: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nAmount, supportedClaimId.GetHex(), nHeight, nCurrentHeight); CSupportValue support(outPoint, supportedClaimId, nAmount, nHeight, nValidAtHeight); - if (nValidAtHeight < nCurrentHeight) - { + if (nValidAtHeight < nCurrentHeight) { nameOutPointType entry(name, support.outPoint); addSupportToExpirationQueue(support.nHeight + base->nExpirationTime, entry); return insertSupportIntoMap(name, support, false); - } - else - { + } else { return addSupportToQueues(name, support); } } -bool CClaimTrieCache::removeSupport(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight, bool fCheckTakeover) const +bool CClaimTrieCache::removeSupport(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight, bool fCheckTakeover) { bool removed = false; CSupportValue support; - if (removeSupportFromQueue(name, outPoint, support)) + if (removeSupportFromQueue(name, outPoint, support)) { removed = true; - if (removed == false && removeSupportFromMap(name, outPoint, support, fCheckTakeover)) + } + if (removed == false && removeSupportFromMap(name, outPoint, support, fCheckTakeover)) { removed = true; - if (removed) - { + } + if (removed) { int expirationHeight = nHeight + base->nExpirationTime; removeSupportFromExpirationQueue(name, outPoint, expirationHeight); nValidAtHeight = support.nValidAtHeight; @@ -2049,100 +1364,65 @@ bool CClaimTrieCache::removeSupport(const std::string& name, const COutPoint& ou return removed; } -void CClaimTrieCache::addSupportToExpirationQueue(int nExpirationHeight, nameOutPointType& entry) const +void CClaimTrieCache::addSupportToExpirationQueue(int nExpirationHeight, nameOutPointType& entry) { - expirationQueueType::iterator itQueueRow = getSupportExpirationQueueCacheRow(nExpirationHeight, true); + supportExpirationQueueType::iterator itQueueRow = getQueueCacheRow(nExpirationHeight, supportExpirationQueueCache, true); itQueueRow->second.push_back(entry); } -void CClaimTrieCache::removeSupportFromExpirationQueue(const std::string& name, const COutPoint& outPoint, int expirationHeight) const +void CClaimTrieCache::removeSupportFromExpirationQueue(const std::string& name, const COutPoint& outPoint, int expirationHeight) { - expirationQueueType::iterator itQueueRow = getSupportExpirationQueueCacheRow(expirationHeight, false); - expirationQueueRowType::iterator itQueue; - if (itQueueRow != supportExpirationQueueCache.end()) - { - for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) - { - if (name == itQueue->name && outPoint == itQueue->outPoint) + supportExpirationQueueType::iterator itQueueRow = getQueueCacheRow(expirationHeight, supportExpirationQueueCache, false); + supportExpirationQueueRowType::iterator itQueue; + if (itQueueRow != supportExpirationQueueCache.end()) { + for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) { + if (name == itQueue->name && outPoint == itQueue->outPoint) { + itQueueRow->second.erase(itQueue); break; + } } } - if (itQueue != itQueueRow->second.end()) - { - itQueueRow->second.erase(itQueue); - } } -expirationQueueType::iterator CClaimTrieCache::getSupportExpirationQueueCacheRow(int nHeight, bool createIfNotExists) const -{ - expirationQueueType::iterator itQueueRow = supportExpirationQueueCache.find(nHeight); - if (itQueueRow == supportExpirationQueueCache.end()) - { - // Have to make a new row it put in the cache, if createIfNotExists is true - expirationQueueRowType queueRow; - // If the row exists in the base, copy its claims into the new row. - bool exists = base->getSupportExpirationQueueRow(nHeight, queueRow); - if (!exists) - if (!createIfNotExists) - return itQueueRow; - // Stick the new row in the cache - std::pair ret; - ret = supportExpirationQueueCache.insert(std::pair(nHeight, queueRow)); - assert(ret.second); - itQueueRow = ret.first; - } - return itQueueRow; -} - -bool CClaimTrieCache::undoAddSupport(const std::string& name, const COutPoint& outPoint, int nHeight) const +bool CClaimTrieCache::undoAddSupport(const std::string& name, const COutPoint& outPoint, int nHeight) { LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nHeight, nCurrentHeight); int throwaway; return removeSupport(name, outPoint, nHeight, throwaway, false); } -bool CClaimTrieCache::spendSupport(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight) const +bool CClaimTrieCache::spendSupport(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight) { LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nHeight, nCurrentHeight); return removeSupport(name, outPoint, nHeight, nValidAtHeight, true); } -bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowType& expireUndo, insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo, std::vector >& takeoverHeightUndo) const +bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowType& expireUndo, insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo, std::vector >& takeoverHeightUndo) { LogPrintf("%s: nCurrentHeight (before increment): %d\n", __func__, nCurrentHeight); - claimQueueType::iterator itQueueRow = getQueueCacheRow(nCurrentHeight, false); - if (itQueueRow != claimQueueCache.end()) - { - for (claimQueueRowType::iterator itEntry = itQueueRow->second.begin(); itEntry != itQueueRow->second.end(); ++itEntry) - { + claimQueueType::iterator itQueueRow = getQueueCacheRow(nCurrentHeight, claimQueueCache, false); + if (itQueueRow != claimQueueCache.end()) { + for (claimQueueRowType::iterator itEntry = itQueueRow->second.begin(); itEntry != itQueueRow->second.end(); ++itEntry) { bool found = false; - queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(itEntry->first, false); - if (itQueueNameRow != claimQueueNameCache.end()) - { - for (queueNameRowType::iterator itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) - { - if (itQueueName->outPoint == itEntry->second.outPoint && itQueueName->nHeight == nCurrentHeight) - { + queueNameType::iterator itQueueNameRow = getQueueCacheRow(itEntry->first, claimQueueNameCache, false); + if (itQueueNameRow != claimQueueNameCache.end()) { + for (queueNameRowType::iterator itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) { + if (itQueueName->outPoint == itEntry->second.outPoint && itQueueName->nHeight == nCurrentHeight) { found = true; itQueueNameRow->second.erase(itQueueName); break; } } } - if (!found) - { + if (!found) { LogPrintf("%s: An inconsistency was found in the claim 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, nCurrentHeight); - if (itQueueNameRow != claimQueueNameCache.end()) - { + if (itQueueNameRow != claimQueueNameCache.end()) { LogPrintf("Claims found for that name:\n"); - for (queueNameRowType::iterator itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) - { + for (queueNameRowType::iterator itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) { LogPrintf("\ttxid: %s, nOut: %d, nValidAtHeight: %d\n", itQueueName->outPoint.hash.GetHex(), itQueueName->outPoint.n, itQueueName->nHeight); } - } - else - { + } else { LogPrintf("No claims found for that name\n"); } } @@ -2152,51 +1432,39 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy } itQueueRow->second.clear(); } - expirationQueueType::iterator itExpirationRow = getExpirationQueueCacheRow(nCurrentHeight, false); - if (itExpirationRow != expirationQueueCache.end()) - { - for (expirationQueueRowType::iterator itEntry = itExpirationRow->second.begin(); itEntry != itExpirationRow->second.end(); ++itEntry) - { + expirationQueueType::iterator itExpirationRow = getQueueCacheRow(nCurrentHeight, expirationQueueCache, false); + if (itExpirationRow != expirationQueueCache.end()) { + for (expirationQueueRowType::iterator itEntry = itExpirationRow->second.begin(); itEntry != itExpirationRow->second.end(); ++itEntry) { CClaimValue claim; assert(removeClaimFromTrie(itEntry->name, itEntry->outPoint, claim, true)); - claimsToDelete.insert(claim); + base->removeFromClaimIndex(claim); expireUndo.push_back(std::make_pair(itEntry->name, claim)); LogPrintf("Expiring claim %s: %s, nHeight: %d, nValidAtHeight: %d\n", claim.claimId.GetHex(), itEntry->name, claim.nHeight, claim.nValidAtHeight); } itExpirationRow->second.clear(); } - supportQueueType::iterator itSupportRow = getSupportQueueCacheRow(nCurrentHeight, false); - if (itSupportRow != supportQueueCache.end()) - { - for (supportQueueRowType::iterator itSupport = itSupportRow->second.begin(); itSupport != itSupportRow->second.end(); ++itSupport) - { + supportQueueType::iterator itSupportRow = getQueueCacheRow(nCurrentHeight, supportQueueCache, false); + if (itSupportRow != supportQueueCache.end()) { + for (supportQueueRowType::iterator itSupport = itSupportRow->second.begin(); itSupport != itSupportRow->second.end(); ++itSupport) { bool found = false; - queueNameType::iterator itSupportNameRow = getSupportQueueCacheNameRow(itSupport->first, false); - if (itSupportNameRow != supportQueueNameCache.end()) - { - for (queueNameRowType::iterator itSupportName = itSupportNameRow->second.begin(); itSupportName != itSupportNameRow->second.end(); ++itSupportName) - { - if (itSupportName->outPoint == itSupport->second.outPoint && itSupportName->nHeight == itSupport->second.nValidAtHeight) - { + supportQueueNameType::iterator itSupportNameRow = getQueueCacheRow(itSupport->first, supportQueueNameCache, false); + if (itSupportNameRow != supportQueueNameCache.end()) { + for (supportQueueNameRowType::iterator itSupportName = itSupportNameRow->second.begin(); itSupportName != itSupportNameRow->second.end(); ++itSupportName) { + if (itSupportName->outPoint == itSupport->second.outPoint && itSupportName->nHeight == itSupport->second.nValidAtHeight) { found = true; itSupportNameRow->second.erase(itSupportName); break; } } } - if (!found) - { + if (!found) { LogPrintf("%s: An inconsistency was found in the support queue. Please report this to the developers:\nFound in height queue but not in named queue: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d\n", __func__, itSupport->first, itSupport->second.outPoint.hash.GetHex(), itSupport->second.outPoint.n, itSupport->second.nValidAtHeight, nCurrentHeight); - if (itSupportNameRow != supportQueueNameCache.end()) - { + if (itSupportNameRow != supportQueueNameCache.end()) { LogPrintf("Supports found for that name:\n"); - for (queueNameRowType::iterator itSupportName = itSupportNameRow->second.begin(); itSupportName != itSupportNameRow->second.end(); ++itSupportName) - { + for (supportQueueNameRowType::iterator itSupportName = itSupportNameRow->second.begin(); itSupportName != itSupportNameRow->second.end(); ++itSupportName) { LogPrintf("\ttxid: %s, nOut: %d, nValidAtHeight: %d\n", itSupportName->outPoint.hash.GetHex(), itSupportName->outPoint.n, itSupportName->nHeight); } - } - else - { + } else { LogPrintf("No support found for that name\n"); } } @@ -2205,11 +1473,9 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy } itSupportRow->second.clear(); } - expirationQueueType::iterator itSupportExpirationRow = getSupportExpirationQueueCacheRow(nCurrentHeight, false); - if (itSupportExpirationRow != supportExpirationQueueCache.end()) - { - for (expirationQueueRowType::iterator itEntry = itSupportExpirationRow->second.begin(); itEntry != itSupportExpirationRow->second.end(); ++itEntry) - { + supportExpirationQueueType::iterator itSupportExpirationRow = getQueueCacheRow(nCurrentHeight, supportExpirationQueueCache, false); + if (itSupportExpirationRow != supportExpirationQueueCache.end()) { + for (supportExpirationQueueRowType::iterator itEntry = itSupportExpirationRow->second.begin(); itEntry != itSupportExpirationRow->second.end(); ++itEntry) { CSupportValue support; assert(removeSupportFromMap(itEntry->name, itEntry->outPoint, support, true)); expireSupportUndo.push_back(std::make_pair(itEntry->name, support)); @@ -2218,14 +1484,13 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy itSupportExpirationRow->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 + // 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::iterator itNamesToCheck = namesToCheckForTakeover.begin(); itNamesToCheck != namesToCheckForTakeover.end(); ++itNamesToCheck) - { + for (std::set::iterator itNamesToCheck = namesToCheckForTakeover.begin(); itNamesToCheck != namesToCheckForTakeover.end(); ++itNamesToCheck) { // Check if a takeover has occurred nodeCacheType::iterator itCachedNode = cache.find(*itNamesToCheck); // many possibilities @@ -2242,56 +1507,40 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy CClaimValue claimInTrie; bool haveClaimInCache; bool haveClaimInTrie; - if (itCachedNode == cache.end()) - { + if (itCachedNode == cache.end()) { haveClaimInCache = false; - } - else - { + } else { haveClaimInCache = itCachedNode->second->getBestClaim(claimInCache); } haveClaimInTrie = getOriginalInfoForName(*itNamesToCheck, claimInTrie); bool takeoverHappened = false; - if (!haveClaimInTrie) - { + if (!haveClaimInTrie) { takeoverHappened = true; - } - else if (!haveClaimInCache) - { + } else if (!haveClaimInCache) { takeoverHappened = true; - } - else if (claimInCache != claimInTrie) - { - if (claimInCache.claimId != claimInTrie.claimId) - { + } else if (claimInCache != claimInTrie) { + if (claimInCache.claimId != claimInTrie.claimId) { takeoverHappened = true; } } - if (takeoverHappened) - { + if (takeoverHappened) { // Get all claims in the queue for that name - queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(*itNamesToCheck, false); - if (itQueueNameRow != claimQueueNameCache.end()) - { - for (queueNameRowType::iterator itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) - { + queueNameType::iterator itQueueNameRow = getQueueCacheRow(*itNamesToCheck, claimQueueNameCache, false); + if (itQueueNameRow != claimQueueNameCache.end()) { + for (queueNameRowType::iterator itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) { bool found = false; // Pull those claims out of the height-based queue - claimQueueType::iterator itQueueRow = getQueueCacheRow(itQueueName->nHeight, false); + claimQueueType::iterator itQueueRow = getQueueCacheRow(itQueueName->nHeight, claimQueueCache, false); claimQueueRowType::iterator itQueue; - if (itQueueRow != claimQueueCache.end()) - { - for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) - { - if (*itNamesToCheck == itQueue->first && itQueue->second.outPoint == itQueueName->outPoint && itQueue->second.nValidAtHeight == itQueueName->nHeight) - { + if (itQueueRow != claimQueueCache.end()) { + for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) { + if (*itNamesToCheck == itQueue->first && itQueue->second.outPoint == itQueueName->outPoint && itQueue->second.nValidAtHeight == itQueueName->nHeight) { found = true; break; } } } - if (found) - { + if (found) { // Insert them into the queue undo with their previous nValidAtHeight insertUndo.push_back(nameOutPointHeightType(itQueue->first, itQueue->second.outPoint, itQueue->second.nValidAtHeight)); // Insert them into the name trie with the new nValidAtHeight @@ -2299,9 +1548,7 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy insertClaimIntoTrie(itQueue->first, itQueue->second, false); // Delete them from the height-based queue itQueueRow->second.erase(itQueue); - } - else - { + } else { LogPrintf("%s(): An inconsistency was found in the claim queue. Please report this to the developers:\nClaim found in name queue but not in height based queue:\nname: %s, txid: %s, nOut: %d, nValidAtHeight in name based queue: %d, current height: %d\n", __func__, *itNamesToCheck, itQueueName->outPoint.hash.GetHex(), itQueueName->outPoint.n, itQueueName->nHeight, nCurrentHeight); } assert(found); @@ -2309,27 +1556,19 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy // remove all claims from the queue for that name itQueueNameRow->second.clear(); } - // + // // Then, get all supports in the queue for that name - queueNameType::iterator itSupportQueueNameRow = getSupportQueueCacheNameRow(*itNamesToCheck, false); - if (itSupportQueueNameRow != supportQueueNameCache.end()) - { - for (queueNameRowType::iterator itSupportQueueName = itSupportQueueNameRow->second.begin(); itSupportQueueName != itSupportQueueNameRow->second.end(); ++itSupportQueueName) - { + supportQueueNameType::iterator itSupportQueueNameRow = getQueueCacheRow(*itNamesToCheck, supportQueueNameCache, false); + if (itSupportQueueNameRow != supportQueueNameCache.end()) { + for (supportQueueNameRowType::iterator itSupportQueueName = itSupportQueueNameRow->second.begin(); itSupportQueueName != itSupportQueueNameRow->second.end(); ++itSupportQueueName) { // Pull those supports out of the height-based queue - supportQueueType::iterator itSupportQueueRow = getSupportQueueCacheRow(itSupportQueueName->nHeight, false); - if (itSupportQueueRow != supportQueueCache.end()) - { + supportQueueType::iterator itSupportQueueRow = getQueueCacheRow(itSupportQueueName->nHeight, supportQueueCache, false); + if (itSupportQueueRow != supportQueueCache.end()) { supportQueueRowType::iterator itSupportQueue; - for (itSupportQueue = itSupportQueueRow->second.begin(); itSupportQueue != itSupportQueueRow->second.end(); ++itSupportQueue) - { - if (*itNamesToCheck == itSupportQueue->first && itSupportQueue->second.outPoint == itSupportQueueName->outPoint && itSupportQueue->second.nValidAtHeight == itSupportQueueName->nHeight) - { - break; - } + for (itSupportQueue = itSupportQueueRow->second.begin(); itSupportQueue != itSupportQueueRow->second.end(); ++itSupportQueue) { + if (*itNamesToCheck == itSupportQueue->first && itSupportQueue->second.outPoint == itSupportQueueName->outPoint && itSupportQueue->second.nValidAtHeight == itSupportQueueName->nHeight) break; } - if (itSupportQueue != itSupportQueueRow->second.end()) - { + if (itSupportQueue != itSupportQueueRow->second.end()) { // Insert them into the support queue undo with the previous nValidAtHeight insertSupportUndo.push_back(nameOutPointHeightType(itSupportQueue->first, itSupportQueue->second.outPoint, itSupportQueue->second.nValidAtHeight)); // Insert them into the support map with the new nValidAtHeight @@ -2337,14 +1576,10 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy insertSupportIntoMap(itSupportQueue->first, itSupportQueue->second, false); // Delete them from the height-based queue itSupportQueueRow->second.erase(itSupportQueue); - } - else - { + } else { // here be problems TODO: show error, assert false } - } - else - { + } else { // here be problems } } @@ -2353,26 +1588,22 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy } // save the old last height so that it can be restored if the block is undone - if (haveClaimInTrie) - { + if (haveClaimInTrie) { int nHeightOfLastTakeover; assert(getLastTakeoverForName(*itNamesToCheck, nHeightOfLastTakeover)); takeoverHeightUndo.push_back(std::make_pair(*itNamesToCheck, nHeightOfLastTakeover)); } itCachedNode = cache.find(*itNamesToCheck); - if (itCachedNode != cache.end()) - { + if (itCachedNode != cache.end()) { cacheTakeoverHeights[*itNamesToCheck] = nCurrentHeight; } } } - for (nodeCacheType::const_iterator itOriginals = block_originals.begin(); itOriginals != block_originals.end(); ++itOriginals) - { + for (nodeCacheType::const_iterator itOriginals = block_originals.begin(); itOriginals != block_originals.end(); ++itOriginals) { delete itOriginals->second; } block_originals.clear(); - for (nodeCacheType::const_iterator itCache = cache.begin(); itCache != cache.end(); ++itCache) - { + for (nodeCacheType::const_iterator itCache = cache.begin(); itCache != cache.end(); ++itCache) { block_originals[itCache->first] = new CClaimTrieNode(*(itCache->second)); } namesToCheckForTakeover.clear(); @@ -2380,70 +1611,60 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy return true; } -bool CClaimTrieCache::decrementBlock(insertUndoType& insertUndo, claimQueueRowType& expireUndo, insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo, std::vector >& takeoverHeightUndo) const +bool CClaimTrieCache::decrementBlock(insertUndoType& insertUndo, claimQueueRowType& expireUndo, insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo, std::vector >& takeoverHeightUndo) { LogPrintf("%s: nCurrentHeight (before decrement): %d\n", __func__, nCurrentHeight); nCurrentHeight--; - if (expireSupportUndo.begin() != expireSupportUndo.end()) - { - expirationQueueType::iterator itSupportExpireRow = getSupportExpirationQueueCacheRow(nCurrentHeight, true); - for (supportQueueRowType::iterator itSupportExpireUndo = expireSupportUndo.begin(); itSupportExpireUndo != expireSupportUndo.end(); ++itSupportExpireUndo) - { + if (expireSupportUndo.begin() != expireSupportUndo.end()) { + supportExpirationQueueType::iterator itSupportExpireRow = getQueueCacheRow(nCurrentHeight, supportExpirationQueueCache, true); + for (supportQueueRowType::iterator itSupportExpireUndo = expireSupportUndo.begin(); itSupportExpireUndo != expireSupportUndo.end(); ++itSupportExpireUndo) { insertSupportIntoMap(itSupportExpireUndo->first, itSupportExpireUndo->second, false); itSupportExpireRow->second.push_back(nameOutPointType(itSupportExpireUndo->first, itSupportExpireUndo->second.outPoint)); } } - for (insertUndoType::iterator itSupportUndo = insertSupportUndo.begin(); itSupportUndo != insertSupportUndo.end(); ++itSupportUndo) - { - supportQueueType::iterator itSupportRow = getSupportQueueCacheRow(itSupportUndo->nHeight, true); + for (insertUndoType::iterator itSupportUndo = insertSupportUndo.begin(); itSupportUndo != insertSupportUndo.end(); ++itSupportUndo) { + supportQueueType::iterator itSupportRow = getQueueCacheRow(itSupportUndo->nHeight, supportQueueCache, true); CSupportValue support; assert(removeSupportFromMap(itSupportUndo->name, itSupportUndo->outPoint, support, false)); - queueNameType::iterator itSupportNameRow = getSupportQueueCacheNameRow(itSupportUndo->name, true); + supportQueueNameType::iterator itSupportNameRow = getQueueCacheRow(itSupportUndo->name, supportQueueNameCache, true); itSupportRow->second.push_back(std::make_pair(itSupportUndo->name, support)); itSupportNameRow->second.push_back(outPointHeightType(support.outPoint, support.nValidAtHeight)); } - if (expireUndo.begin() != expireUndo.end()) - { - expirationQueueType::iterator itExpireRow = getExpirationQueueCacheRow(nCurrentHeight, true); - for (claimQueueRowType::iterator itExpireUndo = expireUndo.begin(); itExpireUndo != expireUndo.end(); ++itExpireUndo) - { + if (expireUndo.begin() != expireUndo.end()) { + expirationQueueType::iterator itExpireRow = getQueueCacheRow(nCurrentHeight, expirationQueueCache, true); + for (claimQueueRowType::iterator itExpireUndo = expireUndo.begin(); itExpireUndo != expireUndo.end(); ++itExpireUndo) { insertClaimIntoTrie(itExpireUndo->first, itExpireUndo->second, false); - CClaimIndexElement element = {itExpireUndo->first, itExpireUndo->second}; - claimsToAdd.push_back(element); + base->addToClaimIndex(itExpireUndo->first, itExpireUndo->second); itExpireRow->second.push_back(nameOutPointType(itExpireUndo->first, itExpireUndo->second.outPoint)); } } - for (insertUndoType::iterator itInsertUndo = insertUndo.begin(); itInsertUndo != insertUndo.end(); ++itInsertUndo) - { - claimQueueType::iterator itQueueRow = getQueueCacheRow(itInsertUndo->nHeight, true); + for (insertUndoType::iterator itInsertUndo = insertUndo.begin(); itInsertUndo != insertUndo.end(); ++itInsertUndo) { + claimQueueType::iterator itQueueRow = getQueueCacheRow(itInsertUndo->nHeight, claimQueueCache, true); CClaimValue claim; assert(removeClaimFromTrie(itInsertUndo->name, itInsertUndo->outPoint, claim, false)); - queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(itInsertUndo->name, true); + queueNameType::iterator itQueueNameRow = getQueueCacheRow(itInsertUndo->name, claimQueueNameCache, true); itQueueRow->second.push_back(std::make_pair(itInsertUndo->name, claim)); - itQueueNameRow->second.push_back(outPointHeightType(itInsertUndo->outPoint, itInsertUndo->nHeight)); + itQueueNameRow->second.push_back(outPointHeightType(itInsertUndo->outPoint, itInsertUndo->nHeight)); } - for (std::vector >::iterator itTakeoverHeightUndo = takeoverHeightUndo.begin(); itTakeoverHeightUndo != takeoverHeightUndo.end(); ++itTakeoverHeightUndo) - { + for (std::vector >::iterator itTakeoverHeightUndo = takeoverHeightUndo.begin(); itTakeoverHeightUndo != takeoverHeightUndo.end(); ++itTakeoverHeightUndo) { cacheTakeoverHeights[itTakeoverHeightUndo->first] = itTakeoverHeightUndo->second; } return true; } -bool CClaimTrieCache::finalizeDecrement() const +bool CClaimTrieCache::finalizeDecrement() { - for (nodeCacheType::iterator itOriginals = block_originals.begin(); itOriginals != block_originals.end(); ++itOriginals) - { + for (nodeCacheType::iterator itOriginals = block_originals.begin(); itOriginals != block_originals.end(); ++itOriginals) { delete itOriginals->second; } block_originals.clear(); - for (nodeCacheType::const_iterator itCache = cache.begin(); itCache != cache.end(); ++itCache) - { + for (nodeCacheType::const_iterator itCache = cache.begin(); itCache != cache.end(); ++itCache) { block_originals[itCache->first] = new CClaimTrieNode(*(itCache->second)); } return true; @@ -2451,14 +1672,12 @@ bool CClaimTrieCache::finalizeDecrement() const bool CClaimTrieCache::getLastTakeoverForName(const std::string& name, int& nLastTakeoverForName) const { - if (!fRequireTakeoverHeights) - { + if (!fRequireTakeoverHeights) { nLastTakeoverForName = 0; return true; } - std::map::iterator itHeights = cacheTakeoverHeights.find(name); - if (itHeights == cacheTakeoverHeights.end()) - { + std::map::const_iterator itHeights = cacheTakeoverHeights.find(name); + if (itHeights == cacheTakeoverHeights.end()) { return base->getLastTakeoverForName(name, nLastTakeoverForName); } nLastTakeoverForName = itHeights->second; @@ -2469,16 +1688,13 @@ int CClaimTrieCache::getNumBlocksOfContinuousOwnership(const std::string& name) { const CClaimTrieNode* node = NULL; nodeCacheType::const_iterator itCache = cache.find(name); - if (itCache != cache.end()) - { + if (itCache != cache.end()) { node = itCache->second; } - if (!node) - { + if (!node) { node = base->getNodeForName(name); } - if (!node || node->claims.empty()) - { + if (!node || node->claims.empty()) { return 0; } int nLastTakeoverHeight; @@ -2488,19 +1704,13 @@ int CClaimTrieCache::getNumBlocksOfContinuousOwnership(const std::string& name) int CClaimTrieCache::getDelayForName(const std::string& name) const { - if (!fRequireTakeoverHeights) - { - return 0; - } + if (!fRequireTakeoverHeights) return 0; int nBlocksOfContinuousOwnership = getNumBlocksOfContinuousOwnership(name); return std::min(nBlocksOfContinuousOwnership / base->nProportionalDelayFactor, 4032); } -uint256 CClaimTrieCache::getBestBlock() +uint256 CClaimTrieCache::getBestBlock() const { - if (hashBlock.IsNull()) - if (base != NULL) - hashBlock = base->hashBlock; return hashBlock; } @@ -2509,15 +1719,13 @@ void CClaimTrieCache::setBestBlock(const uint256& hashBlockIn) hashBlock = hashBlockIn; } -bool CClaimTrieCache::clear() const +bool CClaimTrieCache::clear() { - for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache) - { + for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache) { delete itcache->second; } cache.clear(); - for (nodeCacheType::iterator itOriginals = block_originals.begin(); itOriginals != block_originals.end(); ++itOriginals) - { + for (nodeCacheType::iterator itOriginals = block_originals.begin(); itOriginals != block_originals.end(); ++itOriginals) { delete itOriginals->second; } block_originals.clear(); @@ -2535,91 +1743,102 @@ bool CClaimTrieCache::clear() const return true; } +template +void CClaimTrieCache::update(std::map& map) +{ + for (typename std::map::iterator itQueue = map.begin(); itQueue != map.end(); ++itQueue) { + base->db.updateQueueRow(itQueue->first, itQueue->second); + } +} + bool CClaimTrieCache::flush() { - if (dirty()) - getMerkleHash(); + if (dirty()) getMerkleHash(); + for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache) { + if (!base->updateName(itcache->first, itcache->second)) { + LogPrintf("%s: Failed to update name for:%s\n", __func__, itcache->first); + return false; + } + } + for (hashMapType::iterator ithash = cacheHashes.begin(); ithash != cacheHashes.end(); ++ithash) { + if (!base->updateHash(ithash->first, ithash->second)) { + LogPrintf("%s: Failed to update hash for:%s\n", __func__, ithash->first); + return false; + } + } + for (std::map::iterator itheight = cacheTakeoverHeights.begin(); itheight != cacheTakeoverHeights.end(); ++itheight) { + if (!base->updateTakeoverHeight(itheight->first, itheight->second)) { + LogPrintf("%s: Failed to update takeover height for:%s\n", __func__, itheight->first); + return false; + } + } + update(claimQueueCache); + update(claimQueueNameCache); + update(expirationQueueCache); + update(supportCache); + update(supportQueueCache); + update(supportQueueNameCache); + update(supportExpirationQueueCache); + base->hashBlock = getBestBlock(); + base->nCurrentHeight = nCurrentHeight; + return clear(); +} - if (!claimsToDelete.empty()) { - for (claimIndexClaimListType::iterator it = claimsToDelete.begin(); it != claimsToDelete.end(); ++it) - base->removeFromClaimIndex(*it); - claimsToDelete.clear(); - } - if (!claimsToAdd.empty()) { - for (claimIndexElementListType::iterator it = claimsToAdd.begin(); it != claimsToAdd.end(); ++it) - base->addToClaimIndex(it->name, it->claim); - claimsToAdd.clear(); - } - - bool success = base->update(cache, cacheHashes, cacheTakeoverHeights, getBestBlock(), claimQueueCache, claimQueueNameCache, expirationQueueCache, nCurrentHeight, supportCache, supportQueueCache, supportQueueNameCache, supportExpirationQueueCache); - if (success) - { - success = clear(); - } - return success; +bool CClaimTrieCache::dirty() const +{ + return !dirtyHashes.empty(); } uint256 CClaimTrieCache::getLeafHashForProof(const std::string& currentPosition, unsigned char nodeChar, const CClaimTrieNode* currentNode) const { std::stringstream leafPosition; leafPosition << currentPosition << nodeChar; - hashMapType::iterator cachedHash = cacheHashes.find(leafPosition.str()); - if (cachedHash != cacheHashes.end()) - { + hashMapType::const_iterator cachedHash = cacheHashes.find(leafPosition.str()); + if (cachedHash != cacheHashes.end()) { return cachedHash->second; - } - else - { + } else { return currentNode->hash; } } CClaimTrieProof CClaimTrieCache::getProofForName(const std::string& name) const { - if (dirty()) - getMerkleHash(); + if (dirty()) getMerkleHash(); std::vector nodes; CClaimTrieNode* current = &(base->root); nodeCacheType::const_iterator cachedNode; bool fNameHasValue = false; COutPoint outPoint; int nHeightOfLastTakeover = 0; - for (std::string::const_iterator itName = name.begin(); current; ++itName) - { + for (std::string::const_iterator itName = name.begin(); current; ++itName) { std::string currentPosition(name.begin(), itName); cachedNode = cache.find(currentPosition); - if (cachedNode != cache.end()) + if (cachedNode != cache.end()) { current = cachedNode->second; + } CClaimValue claim; bool fNodeHasValue = current->getBestClaim(claim); uint256 valueHash; - if (fNodeHasValue) - { + if (fNodeHasValue) { int nHeightOfLastTakeover; assert(getLastTakeoverForName(currentPosition, nHeightOfLastTakeover)); valueHash = getValueHash(claim.outPoint, nHeightOfLastTakeover); } std::vector > children; CClaimTrieNode* nextCurrent = NULL; - for (nodeMapType::const_iterator itChildren = current->children.begin(); itChildren != current->children.end(); ++itChildren) - { - if (itName == name.end() || itChildren->first != *itName) // Leaf node - { + for (nodeMapType::const_iterator itChildren = current->children.begin(); itChildren != current->children.end(); ++itChildren) { + if (itName == name.end() || itChildren->first != *itName) { // Leaf node uint256 childHash = getLeafHashForProof(currentPosition, itChildren->first, itChildren->second); children.push_back(std::make_pair(itChildren->first, childHash)); - } - else // Full node - { + } else { // Full node nextCurrent = itChildren->second; uint256 childHash; children.push_back(std::make_pair(itChildren->first, childHash)); } } - if (currentPosition == name) - { + if (currentPosition == name) { fNameHasValue = fNodeHasValue; - if (fNameHasValue) - { + if (fNameHasValue) { outPoint = claim.outPoint; assert(getLastTakeoverForName(name, nHeightOfLastTakeover)); } @@ -2629,15 +1848,12 @@ CClaimTrieProof CClaimTrieCache::getProofForName(const std::string& name) const nodes.push_back(node); current = nextCurrent; } - return CClaimTrieProof(nodes, fNameHasValue, outPoint, - nHeightOfLastTakeover); + return CClaimTrieProof(nodes, fNameHasValue, outPoint, nHeightOfLastTakeover); } - -void CClaimTrieCache::removeAndAddToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const +void CClaimTrieCache::removeAndAddToExpirationQueue(expirationQueueRowType& row, int height, bool increment) { - for (expirationQueueRowType::iterator e = row.begin(); e != row.end(); ++e) - { + for (expirationQueueRowType::iterator e = row.begin(); e != row.end(); ++e) { // remove and insert with new expiration time removeFromExpirationQueue(e->name, e->outPoint, height); int extend_expiration = Params().GetConsensus().nExtendedClaimExpirationTime - Params().GetConsensus().nOriginalClaimExpirationTime; @@ -2645,13 +1861,11 @@ void CClaimTrieCache::removeAndAddToExpirationQueue(expirationQueueRowType &row, nameOutPointType entry(e->name, e->outPoint); addToExpirationQueue(new_expiration_height, entry); } - } -void CClaimTrieCache::removeAndAddSupportToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const +void CClaimTrieCache::removeAndAddSupportToExpirationQueue(supportExpirationQueueRowType& row, int height, bool increment) { - for (expirationQueueRowType::iterator e = row.begin(); e != row.end(); ++e) - { + for (supportExpirationQueueRowType::iterator e = row.begin(); e != row.end(); ++e) { // remove and insert with new expiration time removeSupportFromExpirationQueue(e->name, e->outPoint, height); int extend_expiration = Params().GetConsensus().nExtendedClaimExpirationTime - Params().GetConsensus().nOriginalClaimExpirationTime; @@ -2659,10 +1873,9 @@ void CClaimTrieCache::removeAndAddSupportToExpirationQueue(expirationQueueRowTyp nameOutPointType entry(e->name, e->outPoint); addSupportToExpirationQueue(new_expiration_height, entry); } - } -bool CClaimTrieCache::forkForExpirationChange(bool increment) const +bool CClaimTrieCache::forkForExpirationChange(bool increment) { /* If increment is True, we have forked to extend the expiration time, thus items in the expiration queue @@ -2672,66 +1885,27 @@ bool CClaimTrieCache::forkForExpirationChange(bool increment) const will have their expiration extension removed. */ - // look through dirty expiration queues - std::set dirtyHeights; - for (expirationQueueType::const_iterator i = base->dirtyExpirationQueueRows.begin(); i != base->dirtyExpirationQueueRows.end(); ++i) - { + expirationQueueType dirtyExpirationQueueRows; + if (!base->db.getQueueMap(dirtyExpirationQueueRows)) { + return error("%s(): error reading expiration queue rows from disk", __func__); + } + + supportExpirationQueueType dirtySupportExpirationQueueRows; + if (!base->db.getQueueMap(dirtySupportExpirationQueueRows)) { + return error("%s(): error reading support expiration queue rows from disk", __func__); + } + + for (expirationQueueType::const_iterator i = dirtyExpirationQueueRows.begin(); i != dirtyExpirationQueueRows.end(); ++i) { int height = i->first; - dirtyHeights.insert(height); expirationQueueRowType row = i->second; removeAndAddToExpirationQueue(row, height, increment); } - std::set dirtySupportHeights; - for (expirationQueueType::const_iterator i = base->dirtySupportExpirationQueueRows.begin(); i != base->dirtySupportExpirationQueueRows.end(); ++i) - { + for (supportExpirationQueueType::const_iterator i = dirtySupportExpirationQueueRows.begin(); i != dirtySupportExpirationQueueRows.end(); ++i) { int height = i->first; - dirtySupportHeights.insert(height); - expirationQueueRowType row = i->second; + supportExpirationQueueRowType row = i->second; removeAndAddSupportToExpirationQueue(row, height, increment); } - - //look through db for expiration queues, if we haven't already found it in dirty expiration queue - boost::scoped_ptr pcursor(const_cast(&base->db)->NewIterator()); - pcursor->SeekToFirst(); - while (pcursor->Valid()) - { - std::pair key; - if (pcursor->GetKey(key)) - { - int height = key.second; - // if we've looked through this in dirtyExprirationQueueRows, don't use it - // because its stale - if ((key.first == EXP_QUEUE_ROW) & (dirtyHeights.count(height) == 0)) - { - expirationQueueRowType row; - if (pcursor->GetValue(row)) - { - removeAndAddToExpirationQueue(row, height, increment); - } - else - { - return error("%s(): error reading expiration queue rows from disk", __func__); - } - } - else if ((key.first == SUPPORT_EXP_QUEUE_ROW) & (dirtySupportHeights.count(height) == 0)) - { - expirationQueueRowType row; - if (pcursor->GetValue(row)) - { - removeAndAddSupportToExpirationQueue(row, height, increment); - } - else - { - return error("%s(): error reading support expiration queue rows from disk", __func__); - } - } - - } - pcursor->Next(); - } - return true; } - diff --git a/src/claimtrie.h b/src/claimtrie.h index 617232bd7..a7ac02748 100644 --- a/src/claimtrie.h +++ b/src/claimtrie.h @@ -2,55 +2,35 @@ #define BITCOIN_CLAIMTRIE_H #include "amount.h" +#include "chainparams.h" +#include "claimtriedb.h" +#include "primitives/transaction.h" #include "serialize.h" #include "uint256.h" #include "util.h" -#include "dbwrapper.h" -#include "chainparams.h" -#include "primitives/transaction.h" #include #include -#include -// leveldb keys -#define HASH_BLOCK 'h' -#define CURRENT_HEIGHT 't' -#define TRIE_NODE 'n' -#define CLAIM_BY_ID 'i' -#define CLAIM_QUEUE_ROW 'r' -#define CLAIM_QUEUE_NAME_ROW 'm' -#define EXP_QUEUE_ROW 'e' -#define SUPPORT 's' -#define SUPPORT_QUEUE_ROW 'u' -#define SUPPORT_QUEUE_NAME_ROW 'p' -#define SUPPORT_EXP_QUEUE_ROW 'x' - -uint256 getValueHash(COutPoint outPoint, int nHeightOfLastTakeover); +uint256 getValueHash(const COutPoint& outPoint, int nHeightOfLastTakeover); class CClaimValue { public: - COutPoint outPoint; - uint160 claimId; - CAmount nAmount; - CAmount nEffectiveAmount; - int nHeight; - int nValidAtHeight; + CClaimValue() + { + } - CClaimValue() {}; - - CClaimValue(COutPoint outPoint, uint160 claimId, CAmount nAmount, int nHeight, - int nValidAtHeight) - : outPoint(outPoint), claimId(claimId) - , nAmount(nAmount), nEffectiveAmount(nAmount) - , nHeight(nHeight), nValidAtHeight(nValidAtHeight) - {} + CClaimValue(const COutPoint& outPoint, const uint160& claimId, const CAmount& nAmount, const int nHeight, const int nValidAtHeight) + : outPoint(outPoint), claimId(claimId), nAmount(nAmount), nEffectiveAmount(nAmount), nHeight(nHeight), nValidAtHeight(nValidAtHeight) + { + } ADD_SERIALIZE_METHODS; template - 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(outPoint); READWRITE(claimId); READWRITE(nAmount); @@ -60,16 +40,15 @@ public: bool operator<(const CClaimValue& other) const { - if (nEffectiveAmount < other.nEffectiveAmount) + if (nEffectiveAmount < other.nEffectiveAmount) { return true; - else if (nEffectiveAmount == other.nEffectiveAmount) - { - if (nHeight > other.nHeight) + } else if (nEffectiveAmount == other.nEffectiveAmount) { + if (nHeight > other.nHeight) { return true; - else if (nHeight == other.nHeight) - { - if (outPoint != other.outPoint && !(outPoint < other.outPoint)) + } else if (nHeight == other.nHeight) { + if (outPoint != other.outPoint && !(outPoint < other.outPoint)) { return true; + } } } return false; @@ -84,29 +63,36 @@ public: { return !(*this == other); } + + COutPoint outPoint; + uint160 claimId; + CAmount nAmount; + CAmount nEffectiveAmount; + int nHeight; + int nValidAtHeight; }; class CSupportValue { public: - COutPoint outPoint; - uint160 supportedClaimId; - CAmount nAmount; - int nHeight; - int nValidAtHeight; + CSupportValue() + { + } - CSupportValue() {}; - CSupportValue(COutPoint outPoint, uint160 supportedClaimId, - CAmount nAmount, int nHeight, int nValidAtHeight) - : outPoint(outPoint), supportedClaimId(supportedClaimId) - , nAmount(nAmount), nHeight(nHeight) - , nValidAtHeight(nValidAtHeight) - {} + CSupportValue(const COutPoint& outPoint, + const uint160& supportedClaimId, + const CAmount& nAmount, + const int nHeight, + const int nValidAtHeight) + : outPoint(outPoint), supportedClaimId(supportedClaimId), nAmount(nAmount), nHeight(nHeight), nValidAtHeight(nValidAtHeight) + { + } ADD_SERIALIZE_METHODS; template - 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(outPoint); READWRITE(supportedClaimId); READWRITE(nAmount); @@ -123,6 +109,12 @@ public: { return !(*this == other); } + + COutPoint outPoint; + uint160 supportedClaimId; + CAmount nAmount; + int nHeight; + int nValidAtHeight; }; class CClaimTrieNode; @@ -137,24 +129,31 @@ typedef std::pair namedNodeType; class CClaimTrieNode { public: - CClaimTrieNode() : nHeightOfLastTakeover(0) {} - CClaimTrieNode(uint256 hash) : hash(hash), nHeightOfLastTakeover(0) {} - uint256 hash; - nodeMapType children; - int nHeightOfLastTakeover; - std::vector claims; + CClaimTrieNode() : nHeightOfLastTakeover(0) + { + } + + CClaimTrieNode(const uint256& hash) : hash(hash), nHeightOfLastTakeover(0) + { + } + + bool insertClaim(const CClaimValue& claim); - bool insertClaim(CClaimValue claim); bool removeClaim(const COutPoint& outPoint, CClaimValue& claim); + bool getBestClaim(CClaimValue& claim) const; - bool empty() const {return children.empty() && claims.empty();} + + bool empty() const; + bool haveClaim(const COutPoint& outPoint) const; + void reorderClaims(supportMapEntryType& supports); ADD_SERIALIZE_METHODS; template - 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(claims); READWRITE(nHeightOfLastTakeover); @@ -169,27 +168,37 @@ public: { return !(*this == other); } + + uint256 hash; + nodeMapType children; + int nHeightOfLastTakeover; + std::vector claims; }; -struct nodenamecompare +class nodeNameCompare { - bool operator() (const std::string& i, const std::string& j) const +public: + bool operator()(const std::string& i, const std::string& j) const { - if (i.size() == j.size()) + if (i.size() == j.size()) { return i < j; + } return i.size() < j.size(); } }; -struct outPointHeightType +class outPointHeightType { - COutPoint outPoint; - int nHeight; +public: + outPointHeightType() + { + } - outPointHeightType() {} - - outPointHeightType(COutPoint outPoint, int nHeight) - : outPoint(outPoint), nHeight(nHeight) {} + outPointHeightType(const COutPoint& outPoint, + const int nHeight) + : outPoint(outPoint), nHeight(nHeight) + { + } ADD_SERIALIZE_METHODS; @@ -200,19 +209,22 @@ struct outPointHeightType READWRITE(nHeight); } -}; - -struct nameOutPointHeightType -{ - std::string name; COutPoint outPoint; int nHeight; +}; - nameOutPointHeightType() {} +class nameOutPointHeightType +{ +public: + nameOutPointHeightType() + { + } + + nameOutPointHeightType(const std::string& name, const COutPoint& outPoint, const int nHeight) + : name(name), outPoint(outPoint), nHeight(nHeight) + { + } - nameOutPointHeightType(std::string name, COutPoint outPoint, int nHeight) - : name(name), outPoint(outPoint), nHeight(nHeight) {} - ADD_SERIALIZE_METHODS; template @@ -222,17 +234,23 @@ struct nameOutPointHeightType READWRITE(outPoint); READWRITE(nHeight); } -}; -struct nameOutPointType -{ std::string name; COutPoint outPoint; + int nHeight; +}; - nameOutPointType() {} +class nameOutPointType +{ +public: + nameOutPointType() + { + } - nameOutPointType(std::string name, COutPoint outPoint) - : name(name), outPoint(outPoint) {} + nameOutPointType(const std::string& name, const COutPoint& outPoint) + : name(name), outPoint(outPoint) + { + } ADD_SERIALIZE_METHODS; @@ -242,58 +260,129 @@ struct nameOutPointType READWRITE(name); READWRITE(outPoint); } + + std::string name; + COutPoint outPoint; }; class CClaimIndexElement { - public: +public: ADD_SERIALIZE_METHODS; template - 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(name); READWRITE(claim); } + bool empty() const + { + return name.empty() && claim.claimId.IsNull(); + } + std::string name; CClaimValue claim; }; -typedef std::pair claimQueueEntryType; +// Helpers to separate queue types from each other +class claimQueueEntryHelper; +class supportQueueEntryHelper; -typedef std::pair supportQueueEntryType; +class queueNameRowHelper; +class supportQueueNameRowHelper; + +class expirationQueueRowHelper; +class supportExpirationQueueRowHelper; + +template +class CGeneric : public Base +{ +public: + CGeneric() : Base() + { + } + + CGeneric(const Base& base) : Base(base) + { + } + + CGeneric(const CGeneric& CGeneric) : Base(CGeneric) + { + } +}; + +// Make std::swap to work with custom types +namespace std { +template +inline void swap(CGeneric& CGeneric, Base& base) +{ + Base base1 = CGeneric; + CGeneric = base; + base = base1; +} + +template +inline void swap(Base& base, CGeneric& CGeneric) +{ + swap(CGeneric, base); +} +} // namespace std + +// Each of these CGeneric types will be stored in the database +typedef CGeneric claimQueueValueType; +typedef CGeneric supportQueueValueType; + +typedef CGeneric queueNameRowValueType; +typedef CGeneric supportQueueNameRowValueType; + +typedef CGeneric expirationQueueRowValueType; +typedef CGeneric supportExpirationQueueRowValueType; + +typedef std::pair claimQueueEntryType; + +typedef std::pair supportQueueEntryType; typedef std::map supportMapType; -typedef std::vector queueNameRowType; +typedef std::vector queueNameRowType; typedef std::map queueNameType; +typedef std::vector supportQueueNameRowType; +typedef std::map supportQueueNameType; + typedef std::vector insertUndoType; -typedef std::vector expirationQueueRowType; +typedef std::vector expirationQueueRowType; typedef std::map expirationQueueType; +typedef std::vector supportExpirationQueueRowType; +typedef std::map supportExpirationQueueType; + typedef std::vector claimQueueRowType; typedef std::map claimQueueType; typedef std::vector supportQueueRowType; typedef std::map supportQueueType; -typedef std::map nodeCacheType; +typedef std::map nodeCacheType; typedef std::map hashMapType; -typedef std::set claimIndexClaimListType; -typedef std::vector claimIndexElementListType; - -struct claimsForNameType +class claimsForNameType { +public: + claimsForNameType(const std::vector& claims, + const std::vector& supports, + const int nLastTakeoverHeight) + : claims(claims), supports(supports), nLastTakeoverHeight(nLastTakeoverHeight) + { + } + std::vector claims; std::vector supports; int nLastTakeoverHeight; - - claimsForNameType(std::vector claims, std::vector supports, int nLastTakeoverHeight) - : claims(claims), supports(supports), nLastTakeoverHeight(nLastTakeoverHeight) {} }; class CClaimTrieCache; @@ -301,88 +390,85 @@ class CClaimTrieCache; class CClaimTrie { public: - CClaimTrie(bool fMemory = false, bool fWipe = false, int nProportionalDelayFactor = 32) - : db(GetDataDir() / "claimtrie", 100, fMemory, fWipe, false) - , nCurrentHeight(0), nExpirationTime(Params().GetConsensus().nOriginalClaimExpirationTime) - , nProportionalDelayFactor(nProportionalDelayFactor) - , root(uint256S("0000000000000000000000000000000000000000000000000000000000000001")) - {} + CClaimTrie(bool fMemory = false, bool fWipe = false, int nProportionalDelayFactor = 32); + + ~CClaimTrie(); uint256 getMerkleHash(); bool empty() const; + void clear(); bool checkConsistency() const; bool WriteToDisk(); + bool ReadFromDisk(bool check = false); std::vector flattenTrie() const; + bool getInfoForName(const std::string& name, CClaimValue& claim) const; + bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const; claimsForNameType getClaimsForName(const std::string& name) const; - CAmount getEffectiveAmountForClaim(const std::string& name, uint160 claimId) const; - CAmount getEffectiveAmountForClaimWithSupports(const std::string& name, uint160 claimId, - std::vector& supports) const; + + CAmount getEffectiveAmountForClaim(const std::string& name, const uint160& claimId) const; + + CAmount getEffectiveAmountForClaimWithSupports(const std::string& name, + const uint160& claimId, + std::vector& supports) const; bool queueEmpty() const; + bool supportEmpty() const; + bool supportQueueEmpty() const; + bool expirationQueueEmpty() const; + bool supportExpirationQueueEmpty() const; void setExpirationTime(int t); void addToClaimIndex(const std::string& name, const CClaimValue& claim); + void removeFromClaimIndex(const CClaimValue& claim); - bool getClaimById(const uint160 claimId, std::string& name, CClaimValue& claim) const; - bool getQueueRow(int nHeight, claimQueueRowType& row) const; - bool getQueueNameRow(const std::string& name, queueNameRowType& row) const; - bool getExpirationQueueRow(int nHeight, expirationQueueRowType& row) const; - bool getSupportNode(std::string name, supportMapEntryType& node) const; - bool getSupportQueueRow(int nHeight, supportQueueRowType& row) const; - bool getSupportQueueNameRow(const std::string& name, queueNameRowType& row) const; - bool getSupportExpirationQueueRow(int nHeight, expirationQueueRowType& row) const; - + bool getClaimById(const uint160& claimId, std::string& name, CClaimValue& claim) const; bool haveClaim(const std::string& name, const COutPoint& outPoint) const; - bool haveClaimInQueue(const std::string& name, const COutPoint& outPoint, - int& nValidAtHeight) const; + + 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) const; + + bool haveSupportInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const; unsigned int getTotalNamesInTrie() const; + unsigned int getTotalClaimsInTrie() const; + CAmount getTotalValueOfClaimsInTrie(bool fControllingOnly) const; friend class CClaimTrieCache; - CDBWrapper db; int nCurrentHeight; int nExpirationTime; int nProportionalDelayFactor; + private: void clear(CClaimTrieNode* current); const CClaimTrieNode* getNodeForName(const std::string& name) const; - bool update(nodeCacheType& cache, hashMapType& hashes, - std::map& takeoverHeights, - const uint256& hashBlock, claimQueueType& queueCache, - queueNameType& queueNameCache, - expirationQueueType& expirationQueueCache, int nNewHeight, - supportMapType& supportCache, - supportQueueType& supportQueueCache, - queueNameType& supportQueueNameCache, - expirationQueueType& supportExpirationQueueCache); bool updateName(const std::string& name, CClaimTrieNode* updatedNode); - bool updateHash(const std::string& name, uint256& hash); + + bool updateHash(const std::string& name, const uint256& hash); + bool updateTakeoverHeight(const std::string& name, int nTakeoverHeight); + bool recursiveNullify(CClaimTrieNode* node, std::string& name); bool recursiveCheckConsistency(const CClaimTrieNode* node) const; @@ -390,60 +476,37 @@ private: bool InsertFromDisk(const std::string& name, CClaimTrieNode* node); unsigned int getTotalNamesRecursive(const CClaimTrieNode* current) const; + unsigned int getTotalClaimsRecursive(const CClaimTrieNode* current) const; - CAmount getTotalValueOfClaimsRecursive(const CClaimTrieNode* current, - bool fControllingOnly) const; + + CAmount getTotalValueOfClaimsRecursive(const CClaimTrieNode* current, bool fControllingOnly) const; + bool recursiveFlattenTrie(const std::string& name, - const CClaimTrieNode* current, - std::vector& nodes) const; + const CClaimTrieNode* current, + std::vector& nodes) const; void markNodeDirty(const std::string& name, CClaimTrieNode* node); - void updateQueueRow(int nHeight, claimQueueRowType& row); - void updateQueueNameRow(const std::string& name, - queueNameRowType& row); - void updateExpirationRow(int nHeight, expirationQueueRowType& row); - void updateSupportMap(const std::string& name, supportMapEntryType& node); - void updateSupportQueue(int nHeight, supportQueueRowType& row); - void updateSupportNameQueue(const std::string& name, - queueNameRowType& row); - void updateSupportExpirationQueue(int nHeight, expirationQueueRowType& row); - - void BatchWriteNode(CDBBatch& batch, const std::string& name, - const CClaimTrieNode* pNode) const; - void BatchEraseNode(CDBBatch& batch, const std::string& nome) const; - void BatchWriteClaimIndex(CDBBatch& batch) const; - void BatchWriteQueueRows(CDBBatch& batch); - void BatchWriteQueueNameRows(CDBBatch& batch); - void BatchWriteExpirationQueueRows(CDBBatch& batch); - void BatchWriteSupportNodes(CDBBatch& batch); - void BatchWriteSupportQueueRows(CDBBatch& batch); - void BatchWriteSupportQueueNameRows(CDBBatch& batch); - void BatchWriteSupportExpirationQueueRows(CDBBatch& batch); - template bool keyTypeEmpty(char key, K& dummy) const; + CClaimTrieDb db; CClaimTrieNode root; uint256 hashBlock; - - claimQueueType dirtyQueueRows; - queueNameType dirtyQueueNameRows; - expirationQueueType dirtyExpirationQueueRows; - - supportQueueType dirtySupportQueueRows; - queueNameType dirtySupportQueueNameRows; - expirationQueueType dirtySupportExpirationQueueRows; - nodeCacheType dirtyNodes; - supportMapType dirtySupportNodes; }; class CClaimTrieProofNode { public: - CClaimTrieProofNode() {}; - CClaimTrieProofNode(std::vector > children, - bool hasValue, uint256 valHash) + CClaimTrieProofNode() + { + } + + CClaimTrieProofNode(const std::vector >& children, + const bool hasValue, + const uint256& valHash) : children(children), hasValue(hasValue), valHash(valHash) - {}; + { + } + std::vector > children; bool hasValue; uint256 valHash; @@ -452,8 +515,18 @@ public: class CClaimTrieProof { public: - CClaimTrieProof() {}; - CClaimTrieProof(std::vector nodes, bool hasValue, COutPoint outPoint, int nHeightOfLastTakeover) : nodes(nodes), hasValue(hasValue), outPoint(outPoint), nHeightOfLastTakeover(nHeightOfLastTakeover) {} + CClaimTrieProof() + { + } + + CClaimTrieProof(const std::vector& nodes, + const bool hasValue, + const COutPoint& outPoint, + const int nHeightOfLastTakeover) + : nodes(nodes), hasValue(hasValue), outPoint(outPoint), nHeightOfLastTakeover(nHeightOfLastTakeover) + { + } + std::vector nodes; bool hasValue; COutPoint outPoint; @@ -463,168 +536,178 @@ public: class CClaimTrieCache { public: - CClaimTrieCache(CClaimTrie* base, bool fRequireTakeoverHeights = true) - : base(base), - fRequireTakeoverHeights(fRequireTakeoverHeights) - { - assert(base); - nCurrentHeight = base->nCurrentHeight; - } + CClaimTrieCache(CClaimTrie* base, bool fRequireTakeoverHeights = true); uint256 getMerkleHash() const; bool empty() const; + bool flush(); - bool dirty() const { return !dirtyHashes.empty(); } - bool addClaim(const std::string& name, const COutPoint& outPoint, - uint160 claimId, CAmount nAmount, int nHeight) const; - bool undoAddClaim(const std::string& name, const COutPoint& outPoint, - int nHeight) const; - bool spendClaim(const std::string& name, const COutPoint& outPoint, - int nHeight, int& nValidAtHeight) const; - bool undoSpendClaim(const std::string& name, const COutPoint& outPoint, - uint160 claimId, CAmount nAmount, int nHeight, - int nValidAtHeight) const; + bool dirty() const; - bool addSupport(const std::string& name, const COutPoint& outPoint, - CAmount nAmount, uint160 supportedClaimId, - int nHeight) const; - bool undoAddSupport(const std::string& name, const COutPoint& outPoint, - int nHeight) const; - bool spendSupport(const std::string& name, const COutPoint& outPoint, - int nHeight, int& nValidAtHeight) const; - bool undoSpendSupport(const std::string& name, const COutPoint& outPoint, - uint160 supportedClaimId, CAmount nAmount, - int nHeight, int nValidAtHeight) const; + bool addClaim(const std::string& name, + const COutPoint& outPoint, + const uint160& claimId, + const CAmount& nAmount, + int nHeight); + + bool undoAddClaim(const std::string& name, const COutPoint& outPoint, int nHeight); + + bool spendClaim(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight); + + bool undoSpendClaim(const std::string& name, + const COutPoint& outPoint, + const uint160& claimId, + const CAmount& nAmount, + int nHeight, + int nValidAtHeight); + + bool addSupport(const std::string& name, + const COutPoint& outPoint, + const CAmount& nAmount, + const uint160& supportedClaimId, + int nHeight); + + bool undoAddSupport(const std::string& name, const COutPoint& outPoint, int nHeight); + + bool spendSupport(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight); + + bool undoSpendSupport(const std::string& name, + const COutPoint& outPoint, + const uint160& supportedClaimId, + const CAmount& nAmount, + int nHeight, + int nValidAtHeight); + + uint256 getBestBlock() const; - uint256 getBestBlock(); void setBestBlock(const uint256& hashBlock); bool incrementBlock(insertUndoType& insertUndo, - claimQueueRowType& expireUndo, - insertUndoType& insertSupportUndo, - supportQueueRowType& expireSupportUndo, - std::vector >& takeoverHeightUndo) const; + claimQueueRowType& expireUndo, + insertUndoType& insertSupportUndo, + supportQueueRowType& expireSupportUndo, + std::vector >& takeoverHeightUndo); + bool decrementBlock(insertUndoType& insertUndo, - claimQueueRowType& expireUndo, - insertUndoType& insertSupportUndo, - supportQueueRowType& expireSupportUndo, - std::vector >& takeoverHeightUndo) const; + claimQueueRowType& expireUndo, + insertUndoType& insertSupportUndo, + supportQueueRowType& expireSupportUndo, + std::vector >& takeoverHeightUndo); - ~CClaimTrieCache() { clear(); } + ~CClaimTrieCache(); + + bool insertClaimIntoTrie(const std::string& name, + const CClaimValue& claim, + bool fCheckTakeover = false); + + bool removeClaimFromTrie(const std::string& name, + const COutPoint& outPoint, + CClaimValue& claim, + bool fCheckTakeover = false); - bool insertClaimIntoTrie(const std::string& name, CClaimValue claim, - bool fCheckTakeover = false) const; - bool removeClaimFromTrie(const std::string& name, const COutPoint& outPoint, - CClaimValue& claim, - bool fCheckTakeover = false) const; CClaimTrieProof getProofForName(const std::string& name) const; - bool finalizeDecrement() const; + bool finalizeDecrement(); - void removeAndAddSupportToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const; - void removeAndAddToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const; + void removeAndAddSupportToExpirationQueue(supportExpirationQueueRowType& row, int height, bool increment); - bool forkForExpirationChange(bool increment) const; + void removeAndAddToExpirationQueue(expirationQueueRowType& row, int height, bool increment); + bool forkForExpirationChange(bool increment); protected: - CClaimTrie* base; - - bool fRequireTakeoverHeights; - - mutable nodeCacheType cache; - mutable nodeCacheType block_originals; - mutable std::set dirtyHashes; - mutable hashMapType cacheHashes; - mutable claimQueueType claimQueueCache; - mutable queueNameType claimQueueNameCache; - mutable expirationQueueType expirationQueueCache; - mutable supportMapType supportCache; - mutable supportQueueType supportQueueCache; - mutable queueNameType supportQueueNameCache; - mutable expirationQueueType supportExpirationQueueCache; - mutable std::set namesToCheckForTakeover; - mutable std::map cacheTakeoverHeights; - mutable int nCurrentHeight; // Height of the block that is being worked on, which is - // one greater than the height of the chain's tip - mutable claimIndexElementListType claimsToAdd; - mutable claimIndexClaimListType claimsToDelete; - - uint256 hashBlock; - uint256 computeHash() const; - bool reorderTrieNode(const std::string& name, bool fCheckTakeover) const; - bool recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent, - std::string sPos) const; - bool recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, - std::string sName, - bool* pfNullified = NULL) const; + bool reorderTrieNode(const std::string& name, bool fCheckTakeover); - bool clear() const; + bool recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent, const std::string& sPos) const; - bool removeClaim(const std::string& name, const COutPoint& outPoint, - int nHeight, int& nValidAtHeight, bool fCheckTakeover) const; + bool recursivePruneName(CClaimTrieNode* tnCurrent, + unsigned int nPos, + const std::string& sName, + bool* pfNullified = NULL); - bool addClaimToQueues(const std::string& name, CClaimValue& claim) const; - bool removeClaimFromQueue(const std::string& name, const COutPoint& outPoint, - CClaimValue& claim) const; - void addToExpirationQueue(int nExpirationHeight, nameOutPointType& entry) const; - void removeFromExpirationQueue(const std::string& name, const COutPoint& outPoint, - int nHeight) const; + bool clear(); - claimQueueType::iterator getQueueCacheRow(int nHeight, - bool createIfNotExists) const; - queueNameType::iterator getQueueCacheNameRow(const std::string& name, - bool createIfNotExists) const; - expirationQueueType::iterator getExpirationQueueCacheRow(int nHeight, - bool createIfNotExists) const; + bool removeClaim(const std::string& name, + const COutPoint& outPoint, + int nHeight, + int& nValidAtHeight, + bool fCheckTakeover); - bool removeSupport(const std::string& name, const COutPoint& outPoint, - int nHeight, int& nValidAtHeight, - bool fCheckTakeover) const; - bool removeSupportFromMap(const std::string& name, const COutPoint& outPoint, - CSupportValue& support, - bool fCheckTakeover) const; + bool addClaimToQueues(const std::string& name, CClaimValue& claim); - bool insertSupportIntoMap(const std::string& name, - CSupportValue support, - bool fCheckTakeover) const; + bool removeClaimFromQueue(const std::string& name, const COutPoint& outPoint, CClaimValue& claim); - supportQueueType::iterator getSupportQueueCacheRow(int nHeight, - bool createIfNotExists) const; - queueNameType::iterator getSupportQueueCacheNameRow(const std::string& name, - bool createIfNotExists) const; - expirationQueueType::iterator getSupportExpirationQueueCacheRow(int nHeight, - bool createIfNotExists) const; + void addToExpirationQueue(int nExpirationHeight, nameOutPointType& entry); - bool addSupportToQueues(const std::string& name, CSupportValue& support) const; - bool removeSupportFromQueue(const std::string& name, const COutPoint& outPoint, - CSupportValue& support) const; + void removeFromExpirationQueue(const std::string& name, const COutPoint& outPoint, int nHeight); - void addSupportToExpirationQueue(int nExpirationHeight, - nameOutPointType& entry) const; - void removeSupportFromExpirationQueue(const std::string& name, - const COutPoint& outPoint, - int nHeight) const; + bool removeSupport(const std::string& name, + const COutPoint& outPoint, + int nHeight, + int& nValidAtHeight, + bool fCheckTakeover); - bool getSupportsForName(const std::string& name, - supportMapEntryType& node) const; + bool removeSupportFromMap(const std::string& name, + const COutPoint& outPoint, + CSupportValue& support, + bool fCheckTakeover); + + bool insertSupportIntoMap(const std::string& name, const CSupportValue& support, bool fCheckTakeover); + + bool addSupportToQueues(const std::string& name, CSupportValue& support); + + bool removeSupportFromQueue(const std::string& name, const COutPoint& outPoint, CSupportValue& support); + + void addSupportToExpirationQueue(int nExpirationHeight, nameOutPointType& entry); + + void removeSupportFromExpirationQueue(const std::string& name, const COutPoint& outPoint, int nHeight); + + bool getSupportsForName(const std::string& name, supportMapEntryType& node) const; bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const; int getDelayForName(const std::string& name) const; - uint256 getLeafHashForProof(const std::string& currentPosition, unsigned char nodeChar, - const CClaimTrieNode* currentNode) const; + uint256 getLeafHashForProof(const std::string& currentPosition, + unsigned char nodeChar, + const CClaimTrieNode* currentNode) const; - CClaimTrieNode* addNodeToCache(const std::string& position, CClaimTrieNode* original) const; + CClaimTrieNode* addNodeToCache(const std::string& position, CClaimTrieNode* original); bool getOriginalInfoForName(const std::string& name, CClaimValue& claim) const; int getNumBlocksOfContinuousOwnership(const std::string& name) const; + + template + void update(std::map& map); + + template + typename std::map::iterator getQueueCacheRow(const K& key, std::map& map, bool createIfNotExists); + + CClaimTrie* base; + bool fRequireTakeoverHeights; + nodeCacheType cache; + nodeCacheType block_originals; + claimQueueType claimQueueCache; + queueNameType claimQueueNameCache; + expirationQueueType expirationQueueCache; + supportMapType supportCache; + supportQueueType supportQueueCache; + supportQueueNameType supportQueueNameCache; + supportExpirationQueueType supportExpirationQueueCache; + std::set namesToCheckForTakeover; + std::map cacheTakeoverHeights; + int nCurrentHeight; // Height of the block that is being worked on, which is + // one greater than the height of the chain's tip + + // used in merkle hash computing + mutable hashMapType cacheHashes; + mutable std::set dirtyHashes; + uint256 hashBlock; }; #endif // BITCOIN_CLAIMTRIE_H diff --git a/src/claimtriedb.cpp b/src/claimtriedb.cpp new file mode 100644 index 000000000..bc74a5862 --- /dev/null +++ b/src/claimtriedb.cpp @@ -0,0 +1,227 @@ + +#include "claimtriedb.h" +#include "claimtrie.h" + +#include +#include +#include + +/** + * Function to provide unique char of types pair + */ +template +unsigned char hashType(); + +#define TEMPLATE_HASH_TYPE(type1, type2, ret) \ + template <> \ + unsigned char hashType() \ + { \ + return ret; \ + } + +TEMPLATE_HASH_TYPE(std::string, CClaimTrieNode, 'n') +TEMPLATE_HASH_TYPE(uint160, CClaimIndexElement, 'i') +TEMPLATE_HASH_TYPE(int, claimQueueRowType, 'r') +TEMPLATE_HASH_TYPE(std::string, queueNameRowType, 'm') +TEMPLATE_HASH_TYPE(int, expirationQueueRowType, 'e') +TEMPLATE_HASH_TYPE(std::string, supportMapEntryType, 's') +TEMPLATE_HASH_TYPE(int, supportQueueRowType, 'u') +TEMPLATE_HASH_TYPE(std::string, supportQueueNameRowType, 'p') +TEMPLATE_HASH_TYPE(int, supportExpirationQueueRowType, 'x') + +/* + * Concrete implementation of buffer + */ +template +class CActualBuffer : public CAbstractBuffer +{ +public: + CActualBuffer() : data() + { + } + + typedef std::list > dataType; + + typename dataType::iterator find(const K& key) + { + typename dataType::iterator itData = data.begin(); + while (itData != data.end()) { + if (key == itData->first) break; + ++itData; + } + return itData; + } + + typename dataType::iterator end() + { + return data.end(); + } + + typename dataType::iterator push_back(const std::pair& element) + { + return data.insert(data.end(), element); + } + + void write(const unsigned char key, CClaimTrieDb* db) + { + for (typename dataType::iterator it = data.begin(); it != data.end(); ++it) { + if (it->second.empty()) { + db->Erase(std::make_pair(key, it->first)); + } else { + db->Write(std::make_pair(key, it->first), it->second); + } + } + data.clear(); + } + + dataType data; +}; + +CClaimTrieDb::CClaimTrieDb(bool fMemory, bool fWipe) + : CDBWrapper(GetDataDir() / "claimtrie", 100, fMemory, fWipe, false) +{ +} + +CClaimTrieDb::~CClaimTrieDb() +{ + for (std::map::iterator itQueue = queues.begin(); itQueue != queues.end(); ++itQueue) { + delete itQueue->second; + } +} + +void CClaimTrieDb::writeQueues() +{ + for (std::map::iterator itQueue = queues.begin(); itQueue != queues.end(); ++itQueue) { + itQueue->second->write(itQueue->first, this); + } +} + +template +bool CClaimTrieDb::getQueueRow(const K& key, V& row) const +{ + const unsigned char hash = hashType(); + std::map::const_iterator itQueue = queues.find(hash); + if (itQueue != queues.end()) { + CActualBuffer* map = static_cast*>(itQueue->second); + typename CActualBuffer::dataType::const_iterator itData = map->find(key); + if (itData != map->end()) { + row = itData->second; + return true; + } + } + return Read(std::make_pair(hash, key), row); +} + +template +void CClaimTrieDb::updateQueueRow(const K& key, V& row) +{ + const unsigned char hash = hashType(); + std::map::iterator itQueue = queues.find(hash); + if (itQueue == queues.end()) { + itQueue = queues.insert(itQueue, std::pair(hash, new CActualBuffer)); + } + CActualBuffer* map = static_cast*>(itQueue->second); + typename CActualBuffer::dataType::iterator itData = map->find(key); + if (itData == map->end()) { + itData = map->push_back(std::make_pair(key, V())); + } + std::swap(itData->second, row); +} + +template +bool CClaimTrieDb::keyTypeEmpty() const +{ + const unsigned char hash = hashType(); + std::map::const_iterator itQueue = queues.find(hash); + if (itQueue != queues.end()) { + const typename CActualBuffer::dataType& data = (static_cast*>(itQueue->second))->data; + for (typename CActualBuffer::dataType::const_iterator itData = data.begin(); itData != data.end(); ++itData) { + if (!itData->second.empty()) return false; + } + } + + boost::scoped_ptr pcursor(const_cast(this)->NewIterator()); + + for (pcursor->SeekToFirst(); pcursor->Valid(); pcursor->Next()) { + std::pair key; + if (pcursor->GetKey(key)) { + if (hash == key.first) return false; + } else { + break; + } + } + return true; +} + +template +bool CClaimTrieDb::seekByKey(std::map& map) const +{ + const unsigned char hash = hashType(); + boost::scoped_ptr pcursor(const_cast(this)->NewIterator()); + + for (pcursor->SeekToFirst(); pcursor->Valid(); pcursor->Next()) { + std::pair key; + if (pcursor->GetKey(key)) { + if (hash == key.first) { + V value; + if (!pcursor->GetValue(value)) return false; + map.insert(std::make_pair(key.second, value)); + } + } + } + return true; +} + +template +bool CClaimTrieDb::getQueueMap(std::map& map) const +{ + const unsigned char hash = hashType(); + std::map::const_iterator itQueue = queues.find(hash); + if (itQueue != queues.end()) { + const typename CActualBuffer::dataType& data = (static_cast*>(itQueue->second))->data; + std::copy(data.begin(), data.end(), std::inserter(map, map.end())); + } + + boost::scoped_ptr pcursor(const_cast(this)->NewIterator()); + + for (pcursor->SeekToFirst(); pcursor->Valid(); pcursor->Next()) { + std::pair key; + if (pcursor->GetKey(key)) { + if (hash == key.first) { + typename std::map::iterator itMap = map.find(key.second); + if (itMap != map.end()) continue; + V value; + if (!pcursor->GetValue(value)) return false; + map.insert(itMap, std::make_pair(key.second, value)); + } + } + } + return true; +} + +/* + * Explicit template instantiation for every pair of types + */ +#define TEMPLATE_INSTANTIATE2(type1, type2) \ + template bool CClaimTrieDb::getQueueMap<>(std::map & map) const; \ + template bool CClaimTrieDb::getQueueRow<>(const type1& key, type2& row) const; \ + template void CClaimTrieDb::updateQueueRow<>(const type1& key, type2& row); \ + template bool CClaimTrieDb::keyTypeEmpty() const; \ + template bool CClaimTrieDb::seekByKey<>(std::map & map) const + +#define TEMPLATE_INSTANTIATE3(type1, type2, type3) \ + template bool CClaimTrieDb::getQueueMap<>(std::map & map) const; \ + template bool CClaimTrieDb::getQueueRow<>(const type1& key, type2& row) const; \ + template void CClaimTrieDb::updateQueueRow<>(const type1& key, type2& row); \ + template bool CClaimTrieDb::keyTypeEmpty() const; \ + template bool CClaimTrieDb::seekByKey<>(std::map & map) const + +TEMPLATE_INSTANTIATE3(std::string, CClaimTrieNode, nodeNameCompare); +TEMPLATE_INSTANTIATE2(uint160, CClaimIndexElement); +TEMPLATE_INSTANTIATE2(int, claimQueueRowType); +TEMPLATE_INSTANTIATE2(std::string, queueNameRowType); +TEMPLATE_INSTANTIATE2(int, expirationQueueRowType); +TEMPLATE_INSTANTIATE2(std::string, supportMapEntryType); +TEMPLATE_INSTANTIATE2(int, supportQueueRowType); +TEMPLATE_INSTANTIATE2(std::string, supportQueueNameRowType); +TEMPLATE_INSTANTIATE2(int, supportExpirationQueueRowType); diff --git a/src/claimtriedb.h b/src/claimtriedb.h new file mode 100644 index 000000000..17b8c6d74 --- /dev/null +++ b/src/claimtriedb.h @@ -0,0 +1,94 @@ +#ifndef BITCOIN_CLAIMTRIE_DB_H +#define BITCOIN_CLAIMTRIE_DB_H + +#include "dbwrapper.h" + +#include + +#include + + +class CClaimTrieDb; + +/** + * Interface between buffer and database + */ +class CAbstractBuffer +{ +public: + virtual ~CAbstractBuffer() + { + } + + virtual void write(const unsigned char key, CClaimTrieDb* db) = 0; +}; + +/** + * This class implements key value storage. It is used by the CClaimTrie + * class to store queues of claim information. It allows for the storage + * of values of datatype V that can be retrieved using key datatype K. + * Changes to the key value storage is buffered until they are written to + * disk using writeQueues() + */ +class CClaimTrieDb : public CDBWrapper +{ +public: + CClaimTrieDb(bool fMemory = false, bool fWipe = false); + + ~CClaimTrieDb(); + + /** + * Write to disk the buffered changes to the key value storage + */ + void writeQueues(); + + /** + * Gets a map representation of K type / V type stored by their hash + * on disk with buffered changes applied. + * @param[out] map key / value pairs to read + */ + template + bool getQueueMap(std::map& map) const; + + /** + * Gets a value of type V found by key of type K stored by their hash + * on disk with with buffered changes applied. + * @param[in] key key to look for + * @param[out] row value which is found + */ + template + bool getQueueRow(const K& key, V& row) const; + + /** + * Update value of type V by key of type K in the buffer through + * their hash + * @param[in] key key to look for + * @param[in/out] row update value and gets its last value + */ + template + void updateQueueRow(const K& key, V& row); + + /** + * Check that there are no data stored under key datatype K and value + * datatype V. Checks both the buffer and disk + */ + template + bool keyTypeEmpty() const; + + /** + * Get a map representation of K type / V type stored by their hash. + * Look only in the disk, and not the buffer. + * Returns false if database read fails. + * @param[out] map key / value pairs readed only from disk + */ + template + bool seekByKey(std::map& map) const; + +private: + /** + * Represents buffer of changes before being stored to disk + */ + std::map queues; +}; + +#endif // BITCOIN_CLAIMTRIE_DB_H diff --git a/src/test/claimtriebranching_tests.cpp b/src/test/claimtriebranching_tests.cpp index 5e832d629..a25801cb2 100644 --- a/src/test/claimtriebranching_tests.cpp +++ b/src/test/claimtriebranching_tests.cpp @@ -2,58 +2,56 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://opensource.org/licenses/mit-license.php -#include "main.h" -#include "consensus/validation.h" -#include "consensus/merkle.h" -#include "primitives/transaction.h" -#include "miner.h" -#include "txmempool.h" -#include "claimtrie.h" -#include "nameclaim.h" -#include "coins.h" -#include "streams.h" #include "chainparams.h" +#include "claimtrie.h" +#include "coins.h" +#include "consensus/merkle.h" +#include "consensus/validation.h" +#include "main.h" +#include "miner.h" +#include "nameclaim.h" #include "policy/policy.h" +#include "primitives/transaction.h" +#include "streams.h" +#include "test/test_bitcoin.h" +#include "txmempool.h" #include #include -#include "test/test_bitcoin.h" using namespace std; BOOST_FIXTURE_TEST_SUITE(claimtriebranching_tests, RegTestingSetup) -//is a claim in queue +//is a claim in queue boost::test_tools::predicate_result -is_claim_in_queue(std::string name, const CTransaction &tx) +is_claim_in_queue(std::string name, const CTransaction& tx) { COutPoint outPoint(tx.GetHash(), 0); - int validAtHeight; - bool have_claim = pclaimTrie->haveClaimInQueue(name,outPoint,validAtHeight); - if (have_claim){ + int validAtHeight; + bool have_claim = pclaimTrie->haveClaimInQueue(name, outPoint, validAtHeight); + if (have_claim) { return true; - } - else{ + } else { boost::test_tools::predicate_result res(false); - res.message()<<"Is not a claim in queue."; + res.message() << "Is not a claim in queue."; return res; } } -// check if tx is best claim based on outpoint +// check if tx is best claim based on outpoint boost::test_tools::predicate_result -is_best_claim(std::string name, const CTransaction &tx) +is_best_claim(std::string name, const CTransaction& tx) { CClaimValue val; COutPoint outPoint(tx.GetHash(), 0); - bool have_claim = pclaimTrie->haveClaim(name,outPoint); + bool have_claim = pclaimTrie->haveClaim(name, outPoint); bool have_info = pclaimTrie->getInfoForName(name, val); - if (have_claim && have_info && val.outPoint == outPoint){ + if (have_claim && have_info && val.outPoint == outPoint) { return true; - } - else{ + } else { boost::test_tools::predicate_result res(false); - res.message()<<"Is not best claim"; + res.message() << "Is not best claim"; return res; } } @@ -63,29 +61,23 @@ best_claim_effective_amount_equals(std::string name, CAmount amount) { CClaimValue val; bool have_info = pclaimTrie->getInfoForName(name, val); - if (!have_info) - { + if (!have_info) { boost::test_tools::predicate_result res(false); - res.message()<<"No claim found"; + res.message() << "No claim found"; return res; - } - else - { + } else { CAmount effective_amount = pclaimTrie->getEffectiveAmountForClaim(name, val.claimId); - if (effective_amount != amount) - { + if (effective_amount != amount) { boost::test_tools::predicate_result res(false); - res.message()<WriteToDisk(); pclaimTrie->clear(); - pclaimTrie->ReadFromDisk(true); + BOOST_CHECK(pclaimTrie->ReadFromDisk(true)); } }; @@ -337,8 +316,8 @@ struct ClaimTrieChainFixture{ there is a competing bid inserted same height check the greater one wins - quantity is same, check outpoint greater wins - there is an existing competing bid - check that rules for delays are observed + there is an existing competing bid + check that rules for delays are observed check that a greater amount wins check that a smaller amount does not win @@ -347,161 +326,161 @@ BOOST_AUTO_TEST_CASE(claim_test) { // no competing bids ClaimTrieChainFixture fixture; - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx1)); + BOOST_CHECK(is_best_claim("test", tx1)); fixture.DecrementBlocks(1); - BOOST_CHECK(!is_best_claim("test",tx1)); - + BOOST_CHECK(!is_best_claim("test", tx1)); + // there is a competing bid inserted same height - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); + CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx3)); + BOOST_CHECK(is_best_claim("test", tx3)); BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); - fixture.DecrementBlocks(1); - BOOST_CHECK(!is_best_claim("test",tx2)); - BOOST_CHECK(!is_best_claim("test",tx3)); + fixture.DecrementBlocks(1); + BOOST_CHECK(!is_best_claim("test", tx2)); + BOOST_CHECK(!is_best_claim("test", tx3)); BOOST_CHECK_EQUAL(0U, pclaimTrie->getClaimsForName("test").claims.size()); - // make two claims , one older - CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx4)); - CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(),"test","two",1); + // make two claims , one older + CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_claim_in_queue("test",tx5)); - BOOST_CHECK(is_best_claim("test",tx4)); + BOOST_CHECK(is_best_claim("test", tx4)); + CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "two", 1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx4)); + BOOST_CHECK(is_claim_in_queue("test", tx5)); + BOOST_CHECK(is_best_claim("test", tx4)); + fixture.IncrementBlocks(1); + BOOST_CHECK(is_best_claim("test", tx4)); BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); - fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx4)); - BOOST_CHECK(is_claim_in_queue("test",tx5)); - fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx4)); + fixture.DecrementBlocks(1); + BOOST_CHECK(is_best_claim("test", tx4)); + BOOST_CHECK(is_claim_in_queue("test", tx5)); + fixture.DecrementBlocks(1); + BOOST_CHECK(is_best_claim("test", tx4)); fixture.DecrementBlocks(1); // check claim takeover, note that CClaimTrie.nProportionalDelayFactor is set to 1 // instead of 32 in test_bitcoin.cpp - CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - fixture.IncrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx6)); - CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(),"test","two",2); + CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); + fixture.IncrementBlocks(10); + BOOST_CHECK(is_best_claim("test", tx6)); + CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "two", 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_claim_in_queue("test",tx7)); + BOOST_CHECK(is_claim_in_queue("test", tx7)); BOOST_CHECK(is_best_claim("test", tx6)); fixture.IncrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx7)); + BOOST_CHECK(is_best_claim("test", tx7)); BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); fixture.DecrementBlocks(10); - BOOST_CHECK(is_claim_in_queue("test",tx7)); - BOOST_CHECK(is_best_claim("test",tx6)); + BOOST_CHECK(is_claim_in_queue("test", tx7)); + BOOST_CHECK(is_best_claim("test", tx6)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx6)); + BOOST_CHECK(is_best_claim("test", tx6)); fixture.DecrementBlocks(10); } /* spent claims - spending winning claim will make losing active claim winner + spending winning claim will make losing active claim winner spending winning claim will make inactive claim winner - spending winning claim will empty out claim trie + spending winning claim will empty out claim trie */ BOOST_AUTO_TEST_CASE(spend_claim_test) { ClaimTrieChainFixture fixture; - // spending winning claim will make losing active claim winner - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); + // spending winning claim will make losing active claim winner + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx1)); + BOOST_CHECK(is_best_claim("test", tx1)); fixture.Spend(tx1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx2)); - + BOOST_CHECK(is_best_claim("test", tx2)); + + fixture.DecrementBlocks(1); + BOOST_CHECK(is_best_claim("test", tx1)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx1)); - fixture.DecrementBlocks(1); // spending winning claim will make inactive claim winner - CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx3)); - CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); - fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx3)); + BOOST_CHECK(is_best_claim("test", tx3)); + CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); + fixture.IncrementBlocks(1); + BOOST_CHECK(is_best_claim("test", tx3)); fixture.Spend(tx3); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx4)); + BOOST_CHECK(is_best_claim("test", tx4)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx3)); + BOOST_CHECK(is_best_claim("test", tx3)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx3)); + BOOST_CHECK(is_best_claim("test", tx3)); fixture.DecrementBlocks(10); - //spending winning claim will empty out claim trie - CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + //spending winning claim will empty out claim trie + CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx5)); + BOOST_CHECK(is_best_claim("test", tx5)); fixture.Spend(tx5); fixture.IncrementBlocks(1); - BOOST_CHECK(!is_best_claim("test",tx5)); + BOOST_CHECK(!is_best_claim("test", tx5)); BOOST_CHECK(pclaimTrie->empty()); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx5)); + BOOST_CHECK(is_best_claim("test", tx5)); fixture.DecrementBlocks(1); } /* supports - check support with wrong name does not work + check support with wrong name does not work check claim with more support wins - check support delay + check support delay */ BOOST_AUTO_TEST_CASE(support_test) { ClaimTrieChainFixture fixture; - // check claim with more support wins - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx1,"test",1); - CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(),tx2,"test",10); + // check claim with more support wins + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 1); + CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), tx2, "test", 10); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx2)); - BOOST_CHECK(best_claim_effective_amount_equals("test",11)); + BOOST_CHECK(is_best_claim("test", tx2)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 11)); fixture.DecrementBlocks(1); - // check support delay - CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(),"test","two",2); + // check support delay + CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); + CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "two", 2); fixture.IncrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx4)); - BOOST_CHECK(best_claim_effective_amount_equals("test",2)); - CMutableTransaction s4 = fixture.MakeSupport(fixture.GetCoinbase(),tx3,"test",10); //10 delay + BOOST_CHECK(is_best_claim("test", tx4)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 2)); + CMutableTransaction s4 = fixture.MakeSupport(fixture.GetCoinbase(), tx3, "test", 10); //10 delay fixture.IncrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx4)); - BOOST_CHECK(best_claim_effective_amount_equals("test",2)); + BOOST_CHECK(is_best_claim("test", tx4)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 2)); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx3)); - BOOST_CHECK(best_claim_effective_amount_equals("test",11)); + BOOST_CHECK(is_best_claim("test", tx3)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 11)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx4)); - BOOST_CHECK(best_claim_effective_amount_equals("test",2)); + BOOST_CHECK(is_best_claim("test", tx4)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 2)); fixture.DecrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx4)); - BOOST_CHECK(best_claim_effective_amount_equals("test",2)); + BOOST_CHECK(is_best_claim("test", tx4)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 2)); fixture.DecrementBlocks(10); } @@ -516,35 +495,34 @@ BOOST_AUTO_TEST_CASE(support_test) BOOST_AUTO_TEST_CASE(support_on_abandon_test) { ClaimTrieChainFixture fixture; - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(1); //supporting and abandoing on the same block will cause it to crash - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx1,"test",1); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 1); fixture.Spend(tx1); fixture.IncrementBlocks(1); - BOOST_CHECK(!is_best_claim("test",tx1)); + BOOST_CHECK(!is_best_claim("test", tx1)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx1)); - + BOOST_CHECK(is_best_claim("test", tx1)); } BOOST_AUTO_TEST_CASE(support_on_abandon_2_test) { ClaimTrieChainFixture fixture; - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx1,"test",1); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 1); fixture.IncrementBlocks(1); //abandoning a support and abandoing claim on the same block will cause it to crash fixture.Spend(tx1); fixture.Spend(s1); fixture.IncrementBlocks(1); - BOOST_CHECK(!is_best_claim("test",tx1)); + BOOST_CHECK(!is_best_claim("test", tx1)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx1)); + BOOST_CHECK(is_best_claim("test", tx1)); } BOOST_AUTO_TEST_CASE(update_on_support_test) @@ -553,15 +531,15 @@ BOOST_AUTO_TEST_CASE(update_on_support_test) // updates happening on the same block as a support // (it should not) ClaimTrieChainFixture fixture; - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",3); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 3); fixture.IncrementBlocks(1); - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx1,"test",1); - CMutableTransaction u1 = fixture.MakeUpdate(tx1,"test","two",ClaimIdHash(tx1.GetHash(),0),1); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 1); + CMutableTransaction u1 = fixture.MakeUpdate(tx1, "test", "two", ClaimIdHash(tx1.GetHash(), 0), 1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",u1)); - BOOST_CHECK(best_claim_effective_amount_equals("test",2)); + BOOST_CHECK(is_best_claim("test", u1)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 2)); fixture.DecrementBlocks(1); BOOST_CHECK(is_best_claim("test", tx1)); @@ -571,36 +549,35 @@ BOOST_AUTO_TEST_CASE(update_on_support_test) support spend spending suport on winning claim will cause it to lose - spending a support on txin[i] where i is not 0 + spending a support on txin[i] where i is not 0 */ BOOST_AUTO_TEST_CASE(support_spend_test) { - ClaimTrieChainFixture fixture; - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx1,"test",2); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx1)); + BOOST_CHECK(is_best_claim("test", tx1)); CMutableTransaction sp1 = fixture.Spend(s1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx2)); + BOOST_CHECK(is_best_claim("test", tx2)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx1)); + BOOST_CHECK(is_best_claim("test", tx1)); fixture.DecrementBlocks(1); - // spend a support on txin[i] where i is not 0 - - CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"x","one",3); - CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(),"test","two",2); - CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(),"test","three",1); - CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(),tx5,"test",2); + // spend a support on txin[i] where i is not 0 + + CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "x", "one", 3); + CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "two", 2); + CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "three", 1); + CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), tx5, "test", 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx5)); + BOOST_CHECK(is_best_claim("test", tx5)); BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); - // build the spend where s2 is sppent on txin[1] and tx3 is spent on txin[0] + // build the spend where s2 is sppent on txin[1] and tx3 is spent on txin[0] uint32_t prevout = 0; CMutableTransaction tx; tx.nVersion = 1; @@ -618,73 +595,73 @@ BOOST_AUTO_TEST_CASE(support_spend_test) tx.vout[0].scriptPubKey = CScript() << OP_TRUE; tx.vout[0].nValue = 1; - fixture.CommitTx(tx); + fixture.CommitTx(tx); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx4)); + BOOST_CHECK(is_best_claim("test", tx4)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx5)); + BOOST_CHECK(is_best_claim("test", tx5)); } /* update update preserves claim id - update preserves supports + update preserves supports winning update on winning claim happens without delay losing update on winning claim happens without delay update on losing claim happens with delay , and wins - - + + */ BOOST_AUTO_TEST_CASE(claimtrie_update_test) { - //update preserves claim id + //update preserves claim id ClaimTrieChainFixture fixture; - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); - CMutableTransaction u1 = fixture.MakeUpdate(tx1,"test","one",ClaimIdHash(tx1.GetHash(),0),2); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); + CMutableTransaction u1 = fixture.MakeUpdate(tx1, "test", "one", ClaimIdHash(tx1.GetHash(), 0), 2); fixture.IncrementBlocks(1); - CClaimValue val; - pclaimTrie->getInfoForName("test",val); - BOOST_CHECK(val.claimId == ClaimIdHash(tx1.GetHash(),0)); - BOOST_CHECK(is_best_claim("test",u1)); - fixture.DecrementBlocks(1); - + CClaimValue val; + pclaimTrie->getInfoForName("test", val); + BOOST_CHECK(val.claimId == ClaimIdHash(tx1.GetHash(), 0)); + BOOST_CHECK(is_best_claim("test", u1)); + fixture.DecrementBlocks(1); + // update preserves supports - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx2,"test",1); - CMutableTransaction u2 = fixture.MakeUpdate(tx2,"test","one",ClaimIdHash(tx2.GetHash(),0),1); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx2, "test", 1); + CMutableTransaction u2 = fixture.MakeUpdate(tx2, "test", "one", ClaimIdHash(tx2.GetHash(), 0), 1); fixture.IncrementBlocks(1); - BOOST_CHECK(best_claim_effective_amount_equals("test",2)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 2)); fixture.DecrementBlocks(1); // winning update on winning claim happens without delay - CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); - CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); + CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); + CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); fixture.IncrementBlocks(10); - CMutableTransaction u3 = fixture.MakeUpdate(tx3,"test","one",ClaimIdHash(tx3.GetHash(),0),2); + CMutableTransaction u3 = fixture.MakeUpdate(tx3, "test", "one", ClaimIdHash(tx3.GetHash(), 0), 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",u3)); + BOOST_CHECK(is_best_claim("test", u3)); BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); fixture.DecrementBlocks(11); // losing update on winning claim happens without delay - CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",3); - CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 3); + CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(10); BOOST_CHECK(is_best_claim("test", tx5)); BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); CMutableTransaction u4 = fixture.MakeUpdate(tx5, "test", "one", ClaimIdHash(tx5.GetHash(), 0), 1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx6)); + BOOST_CHECK(is_best_claim("test", tx6)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx5)); + BOOST_CHECK(is_best_claim("test", tx5)); fixture.DecrementBlocks(10); // update on losing claim happens with delay , and wins - CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",3); - CMutableTransaction tx8 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 3); + CMutableTransaction tx8 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx7)); + BOOST_CHECK(is_best_claim("test", tx7)); CMutableTransaction tx; tx.nVersion = 1; @@ -699,17 +676,17 @@ BOOST_AUTO_TEST_CASE(claimtrie_update_test) tx.vin[1].prevout.n = 0; tx.vin[1].scriptSig = CScript(); tx.vin[1].nSequence = std::numeric_limits::max(); - tx.vout[0].scriptPubKey = UpdateClaimScript("test",ClaimIdHash(tx8.GetHash(),0),"one"); + tx.vout[0].scriptPubKey = UpdateClaimScript("test", ClaimIdHash(tx8.GetHash(), 0), "one"); tx.vout[0].nValue = 4; - fixture.CommitTx(tx); + fixture.CommitTx(tx); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx7)); + BOOST_CHECK(is_best_claim("test", tx7)); fixture.IncrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx)); + BOOST_CHECK(is_best_claim("test", tx)); fixture.DecrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx7)); + BOOST_CHECK(is_best_claim("test", tx7)); fixture.DecrementBlocks(11); } @@ -717,7 +694,7 @@ BOOST_AUTO_TEST_CASE(claimtrie_update_test) expiration check claims expire and loses claim check claims expire and is not updateable (may be changed in future soft fork) - check supports expire and can cause supported bid to lose claim + check supports expire and can cause supported bid to lose claim */ BOOST_AUTO_TEST_CASE(claimtrie_expire_test) { @@ -725,58 +702,58 @@ BOOST_AUTO_TEST_CASE(claimtrie_expire_test) pclaimTrie->setExpirationTime(5); // check claims expire and loses claim - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(pclaimTrie->nExpirationTime); - BOOST_CHECK(is_best_claim("test",tx1)); - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); + BOOST_CHECK(is_best_claim("test", tx1)); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx2)); + BOOST_CHECK(is_best_claim("test", tx2)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx1)); + BOOST_CHECK(is_best_claim("test", tx1)); fixture.DecrementBlocks(pclaimTrie->nExpirationTime); // check claims expire and is not updateable (may be changed in future soft fork) - CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx3)); + BOOST_CHECK(is_best_claim("test", tx3)); fixture.IncrementBlocks(pclaimTrie->nExpirationTime); - CMutableTransaction u1 = fixture.MakeUpdate(tx3,"test","two",ClaimIdHash(tx3.GetHash(),0) ,2); - BOOST_CHECK(!is_best_claim("test",u1)); + CMutableTransaction u1 = fixture.MakeUpdate(tx3, "test", "two", ClaimIdHash(tx3.GetHash(), 0), 2); + BOOST_CHECK(!is_best_claim("test", u1)); fixture.DecrementBlocks(pclaimTrie->nExpirationTime); - BOOST_CHECK(is_best_claim("test",tx3)); + BOOST_CHECK(is_best_claim("test", tx3)); fixture.DecrementBlocks(1); // check supports expire and can cause supported bid to lose claim - CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx4,"test",2); + CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); + CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx4, "test", 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx4)); - CMutableTransaction u2 = fixture.MakeUpdate(tx4,"test","two",ClaimIdHash(tx4.GetHash(),0) ,1); - CMutableTransaction u3 = fixture.MakeUpdate(tx5,"test","two",ClaimIdHash(tx5.GetHash(),0) ,2); + BOOST_CHECK(is_best_claim("test", tx4)); + CMutableTransaction u2 = fixture.MakeUpdate(tx4, "test", "two", ClaimIdHash(tx4.GetHash(), 0), 1); + CMutableTransaction u3 = fixture.MakeUpdate(tx5, "test", "two", ClaimIdHash(tx5.GetHash(), 0), 2); fixture.IncrementBlocks(pclaimTrie->nExpirationTime); - BOOST_CHECK(is_best_claim("test",u3)); + BOOST_CHECK(is_best_claim("test", u3)); fixture.DecrementBlocks(pclaimTrie->nExpirationTime); - BOOST_CHECK(is_best_claim("test",tx4)); + BOOST_CHECK(is_best_claim("test", tx4)); fixture.DecrementBlocks(1); // check updated claims will extend expiration - CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx6)); - CMutableTransaction u4 = fixture.MakeUpdate(tx6,"test","two",ClaimIdHash(tx6.GetHash(),0) ,2); + BOOST_CHECK(is_best_claim("test", tx6)); + CMutableTransaction u4 = fixture.MakeUpdate(tx6, "test", "two", ClaimIdHash(tx6.GetHash(), 0), 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",u4)); - fixture.IncrementBlocks(pclaimTrie->nExpirationTime-1); - BOOST_CHECK(is_best_claim("test",u4)); + BOOST_CHECK(is_best_claim("test", u4)); + fixture.IncrementBlocks(pclaimTrie->nExpirationTime - 1); + BOOST_CHECK(is_best_claim("test", u4)); fixture.IncrementBlocks(1); - BOOST_CHECK(!is_best_claim("test",u4)); + BOOST_CHECK(!is_best_claim("test", u4)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",u4)); + BOOST_CHECK(is_best_claim("test", u4)); fixture.DecrementBlocks(pclaimTrie->nExpirationTime); - BOOST_CHECK(is_best_claim("test",tx6)); + BOOST_CHECK(is_best_claim("test", tx6)); } /* @@ -885,6 +862,89 @@ BOOST_AUTO_TEST_CASE(get_claim_by_id_test) BOOST_CHECK(claimValue2.claimId != claimId); } +BOOST_AUTO_TEST_CASE(get_claim_by_id_test_2) +{ + ClaimTrieChainFixture fixture; + const std::string name = "test"; + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 1); + uint160 claimId = ClaimIdHash(tx1.GetHash(), 0); + CMutableTransaction txx = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 1); + uint160 claimIdx = ClaimIdHash(txx.GetHash(), 0); + + fixture.IncrementBlocks(1); + + CClaimValue claimValue; + std::string claimName; + pclaimTrie->getClaimById(claimId, claimName, claimValue); + BOOST_CHECK(claimName == name); + BOOST_CHECK(claimValue.claimId == claimId); + + CMutableTransaction txa = fixture.Spend(tx1); + CMutableTransaction txb = fixture.Spend(txx); + + fixture.IncrementBlocks(1); + BOOST_CHECK(!pclaimTrie->getClaimById(claimId, claimName, claimValue)); + BOOST_CHECK(!pclaimTrie->getClaimById(claimIdx, claimName, claimValue)); + + fixture.DecrementBlocks(1); + pclaimTrie->getClaimById(claimId, claimName, claimValue); + BOOST_CHECK(claimName == name); + BOOST_CHECK(claimValue.claimId == claimId); + + pclaimTrie->getClaimById(claimIdx, claimName, claimValue); + BOOST_CHECK(claimName == name); + BOOST_CHECK(claimValue.claimId == claimIdx); +} + +BOOST_AUTO_TEST_CASE(get_claim_by_id_test_3) +{ + ClaimTrieChainFixture fixture; + pclaimTrie->setExpirationTime(5); + const std::string name = "test"; + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 1); + uint160 claimId = ClaimIdHash(tx1.GetHash(), 0); + + fixture.IncrementBlocks(1); + + CClaimValue claimValue; + std::string claimName; + pclaimTrie->getClaimById(claimId, claimName, claimValue); + BOOST_CHECK(claimName == name); + BOOST_CHECK(claimValue.claimId == claimId); + // make second claim with activation delay 1 + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 2); + uint160 claimId2 = ClaimIdHash(tx2.GetHash(), 0); + + fixture.IncrementBlocks(1); + // second claim is not activated yet, but can still access by claim id + BOOST_CHECK(is_best_claim(name, tx1)); + BOOST_CHECK(pclaimTrie->getClaimById(claimId2, claimName, claimValue)); + BOOST_CHECK(claimName == name); + BOOST_CHECK(claimValue.claimId == claimId2); + + fixture.IncrementBlocks(1); + // second claim has activated + BOOST_CHECK(is_best_claim(name, tx2)); + BOOST_CHECK(pclaimTrie->getClaimById(claimId2, claimName, claimValue)); + BOOST_CHECK(claimName == name); + BOOST_CHECK(claimValue.claimId == claimId2); + + fixture.DecrementBlocks(1); + // second claim has been deactivated via decrement + // should still be accesible via claim id + BOOST_CHECK(is_best_claim(name, tx1)); + BOOST_CHECK(pclaimTrie->getClaimById(claimId2, claimName, claimValue)); + BOOST_CHECK(claimName == name); + BOOST_CHECK(claimValue.claimId == claimId2); + + fixture.IncrementBlocks(1); + // second claim should have been re activated via increment + BOOST_CHECK(is_best_claim(name, tx2)); + BOOST_CHECK(pclaimTrie->getClaimById(claimId2, claimName, claimValue)); + BOOST_CHECK(claimName == name); + BOOST_CHECK(claimValue.claimId == claimId2); +} + /* claim expiration for hard fork check claims do not expire post ExpirationForkHeight @@ -896,19 +956,19 @@ BOOST_AUTO_TEST_CASE(hardfork_claim_test) BOOST_CHECK_EQUAL(pclaimTrie->nExpirationTime, fixture.originalExpiration); // First create a claim and make sure it expires pre-fork - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",3); - fixture.IncrementBlocks(fixture.originalExpiration+1); - BOOST_CHECK(!is_best_claim("test",tx1)); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 3); + fixture.IncrementBlocks(fixture.originalExpiration + 1); + BOOST_CHECK(!is_best_claim("test", tx1)); fixture.DecrementBlocks(fixture.originalExpiration); - BOOST_CHECK(is_best_claim("test",tx1)); + BOOST_CHECK(is_best_claim("test", tx1)); fixture.IncrementBlocks(fixture.originalExpiration); - BOOST_CHECK(!is_best_claim("test",tx1)); + BOOST_CHECK(!is_best_claim("test", tx1)); // Create a claim 1 block before the fork height that will expire after the fork height - fixture.IncrementBlocks(fixture.expirationForkHeight - chainActive.Height() -2); - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test2","one",3); + fixture.IncrementBlocks(fixture.expirationForkHeight - chainActive.Height() - 2); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "test2", "one", 3); fixture.IncrementBlocks(1); - BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight -1); + BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight - 1); // Disable future expirations and fast-forward past the fork height fixture.IncrementBlocks(1); @@ -923,49 +983,49 @@ BOOST_AUTO_TEST_CASE(hardfork_claim_test) // make sure that claim created 1 block before the fork expires as expected // at the extended expiration times BOOST_CHECK(is_best_claim("test2", tx2)); - fixture.IncrementBlocks(fixture.extendedExpiration-1); + fixture.IncrementBlocks(fixture.extendedExpiration - 1); BOOST_CHECK(!is_best_claim("test2", tx2)); - fixture.DecrementBlocks(fixture.extendedExpiration-1); + fixture.DecrementBlocks(fixture.extendedExpiration - 1); // This first claim is still expired since it's pre-fork, even // after fork activation - BOOST_CHECK(!is_best_claim("test",tx1)); + BOOST_CHECK(!is_best_claim("test", tx1)); // This new claim created at the fork height cannot expire at original expiration BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight); - CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); + CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); fixture.IncrementBlocks(1); fixture.IncrementBlocks(fixture.originalExpiration); - BOOST_CHECK(is_best_claim("test",tx3)); - BOOST_CHECK(!is_best_claim("test",tx1)); + BOOST_CHECK(is_best_claim("test", tx3)); + BOOST_CHECK(!is_best_claim("test", tx1)); fixture.DecrementBlocks(fixture.originalExpiration); // but it expires at the extended expiration, and not a single block below fixture.IncrementBlocks(fixture.extendedExpiration); - BOOST_CHECK(!is_best_claim("test",tx3)); + BOOST_CHECK(!is_best_claim("test", tx3)); fixture.DecrementBlocks(fixture.extendedExpiration); - fixture.IncrementBlocks(fixture.extendedExpiration-1); - BOOST_CHECK(is_best_claim("test",tx3)); - fixture.DecrementBlocks(fixture.extendedExpiration-1); + fixture.IncrementBlocks(fixture.extendedExpiration - 1); + BOOST_CHECK(is_best_claim("test", tx3)); + fixture.DecrementBlocks(fixture.extendedExpiration - 1); // Ensure that we cannot update the original pre-fork expired claim - CMutableTransaction u1 = fixture.MakeUpdate(tx1,"test","two",ClaimIdHash(tx1.GetHash(),0), 3); + CMutableTransaction u1 = fixture.MakeUpdate(tx1, "test", "two", ClaimIdHash(tx1.GetHash(), 0), 3); fixture.IncrementBlocks(1); - BOOST_CHECK(!is_best_claim("test",u1)); + BOOST_CHECK(!is_best_claim("test", u1)); // Ensure that supports for the expired claim don't support it - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),u1,"test",10); - BOOST_CHECK(!is_best_claim("test",u1)); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), u1, "test", 10); + BOOST_CHECK(!is_best_claim("test", u1)); // Ensure that we can update the new post-fork claim - CMutableTransaction u2 = fixture.MakeUpdate(tx3,"test","two",ClaimIdHash(tx3.GetHash(),0), 1); + CMutableTransaction u2 = fixture.MakeUpdate(tx3, "test", "two", ClaimIdHash(tx3.GetHash(), 0), 1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",u2)); + BOOST_CHECK(is_best_claim("test", u2)); // Ensure that supports for the new post-fork claim - CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(),u2,"test",3); - BOOST_CHECK(is_best_claim("test",u2)); + CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), u2, "test", 3); + BOOST_CHECK(is_best_claim("test", u2)); } /* @@ -976,48 +1036,47 @@ BOOST_AUTO_TEST_CASE(hardfork_support_test) ClaimTrieChainFixture fixture; int blocks_before_fork = 10; - fixture.IncrementBlocks(fixture.expirationForkHeight - chainActive.Height() - blocks_before_fork-1); + fixture.IncrementBlocks(fixture.expirationForkHeight - chainActive.Height() - blocks_before_fork - 1); // Create claim and support it before the fork height - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx1,"test",2); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 2); // this claim will win without the support - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(1); fixture.IncrementBlocks(blocks_before_fork); // check that the claim expires as expected at the extended time, as does the support fixture.IncrementBlocks(fixture.originalExpiration - blocks_before_fork); - BOOST_CHECK(is_best_claim("test",tx1)); - BOOST_CHECK(best_claim_effective_amount_equals("test",3)); + BOOST_CHECK(is_best_claim("test", tx1)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 3)); fixture.DecrementBlocks(fixture.originalExpiration - blocks_before_fork); fixture.IncrementBlocks(fixture.extendedExpiration - blocks_before_fork); - BOOST_CHECK(!is_best_claim("test",tx1)); + BOOST_CHECK(!is_best_claim("test", tx1)); fixture.DecrementBlocks(fixture.extendedExpiration - blocks_before_fork); fixture.IncrementBlocks(fixture.extendedExpiration - blocks_before_fork - 1); - BOOST_CHECK(is_best_claim("test",tx1)); - BOOST_CHECK(best_claim_effective_amount_equals("test",3)); + BOOST_CHECK(is_best_claim("test", tx1)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 3)); fixture.DecrementBlocks(fixture.extendedExpiration - blocks_before_fork - 1); // update the claims at fork fixture.DecrementBlocks(1); - CMutableTransaction u1 = fixture.MakeUpdate(tx1,"test","two",ClaimIdHash(tx1.GetHash(),0),1); - CMutableTransaction u2 = fixture.MakeUpdate(tx2,"test","two",ClaimIdHash(tx2.GetHash(),0),2); + CMutableTransaction u1 = fixture.MakeUpdate(tx1, "test", "two", ClaimIdHash(tx1.GetHash(), 0), 1); + CMutableTransaction u2 = fixture.MakeUpdate(tx2, "test", "two", ClaimIdHash(tx2.GetHash(), 0), 2); fixture.IncrementBlocks(1); BOOST_CHECK_EQUAL(fixture.expirationForkHeight, chainActive.Height()); BOOST_CHECK(is_best_claim("test", u1)); - BOOST_CHECK(best_claim_effective_amount_equals("test",3)); - BOOST_CHECK(!is_claim_in_queue("test",tx1)); - BOOST_CHECK(!is_claim_in_queue("test",tx2)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 3)); + BOOST_CHECK(!is_claim_in_queue("test", tx1)); + BOOST_CHECK(!is_claim_in_queue("test", tx2)); // check that the support expires as expected fixture.IncrementBlocks(fixture.extendedExpiration - blocks_before_fork); BOOST_CHECK(is_best_claim("test", u2)); fixture.DecrementBlocks(fixture.extendedExpiration - blocks_before_fork); fixture.IncrementBlocks(fixture.extendedExpiration - blocks_before_fork - 1); - BOOST_CHECK(is_best_claim("test",u1)); - BOOST_CHECK(best_claim_effective_amount_equals("test",3)); - + BOOST_CHECK(is_best_claim("test", u1)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 3)); } /* @@ -1039,38 +1098,38 @@ BOOST_AUTO_TEST_CASE(hardfork_disk_test) // Reset to disk, increment past the fork height and make sure we get // proper behavior fixture.DecrementBlocks(2); - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx1,"test",1); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 1); fixture.IncrementBlocks(1); - BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight -1); + BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight - 1); fixture.WriteClearReadClaimTrie(); - BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight-1); + BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight - 1); BOOST_CHECK_EQUAL(pclaimTrie->nExpirationTime, fixture.originalExpiration); fixture.IncrementBlocks(1); BOOST_CHECK_EQUAL(pclaimTrie->nExpirationTime, fixture.extendedExpiration); BOOST_CHECK(is_best_claim("test", tx1)); - BOOST_CHECK(best_claim_effective_amount_equals("test",2)); - fixture.IncrementBlocks(fixture.originalExpiration-1); + BOOST_CHECK(best_claim_effective_amount_equals("test", 2)); + fixture.IncrementBlocks(fixture.originalExpiration - 1); BOOST_CHECK(is_best_claim("test", tx1)); - BOOST_CHECK(best_claim_effective_amount_equals("test",2)); - fixture.DecrementBlocks(fixture.originalExpiration-1); - fixture.IncrementBlocks(fixture.extendedExpiration-1); + BOOST_CHECK(best_claim_effective_amount_equals("test", 2)); + fixture.DecrementBlocks(fixture.originalExpiration - 1); + fixture.IncrementBlocks(fixture.extendedExpiration - 1); BOOST_CHECK(!is_best_claim("test", tx1)); // Create a claim and support before the fork height, reset to disk, update the claim // increment past the fork height and make sure we get proper behavior - int height_of_update_before_expiration = 50; - fixture.DecrementBlocks(chainActive.Height() - fixture.expirationForkHeight + height_of_update_before_expiration+2); - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test2","one",1); - CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(),tx2,"test2",1); + int height_of_update_before_expiration = 50; + fixture.DecrementBlocks(chainActive.Height() - fixture.expirationForkHeight + height_of_update_before_expiration + 2); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "test2", "one", 1); + CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), tx2, "test2", 1); fixture.IncrementBlocks(1); fixture.WriteClearReadClaimTrie(); - CMutableTransaction u2 = fixture.MakeUpdate(tx2,"test2","two",ClaimIdHash(tx2.GetHash(),0),1); + CMutableTransaction u2 = fixture.MakeUpdate(tx2, "test2", "two", ClaimIdHash(tx2.GetHash(), 0), 1); // increment to fork fixture.IncrementBlocks(fixture.expirationForkHeight - chainActive.Height()); BOOST_CHECK(is_best_claim("test2", u2)); - BOOST_CHECK(best_claim_effective_amount_equals("test2",2)); + BOOST_CHECK(best_claim_effective_amount_equals("test2", 2)); // increment to original expiration, should not be expired fixture.IncrementBlocks(fixture.originalExpiration - height_of_update_before_expiration); BOOST_CHECK(is_best_claim("test2", u2)); @@ -3045,92 +3104,4 @@ BOOST_AUTO_TEST_CASE(bogus_claimtrie_hash_test) delete pblockTemp; } -/* - * tests for CClaimTrie::getClaimById basic consistency checks - */ -BOOST_AUTO_TEST_CASE(get_claim_by_id_test_2) -{ - ClaimTrieChainFixture fixture; - const std::string name = "test"; - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 1); - uint160 claimId = ClaimIdHash(tx1.GetHash(), 0); - CMutableTransaction txx = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 1); - uint160 claimIdx = ClaimIdHash(txx.GetHash(), 0); - - fixture.IncrementBlocks(1); - - CClaimValue claimValue; - std::string claimName; - pclaimTrie->getClaimById(claimId, claimName, claimValue); - BOOST_CHECK(claimName == name); - BOOST_CHECK(claimValue.claimId == claimId); - - CMutableTransaction txa = fixture.Spend(tx1); - CMutableTransaction txb = fixture.Spend(txx); - - fixture.IncrementBlocks(1); - BOOST_CHECK(!pclaimTrie->getClaimById(claimId, claimName, claimValue)); - BOOST_CHECK(!pclaimTrie->getClaimById(claimIdx, claimName, claimValue)); - - fixture.DecrementBlocks(1); - pclaimTrie->getClaimById(claimId, claimName, claimValue); - BOOST_CHECK(claimName == name); - BOOST_CHECK(claimValue.claimId == claimId); - - // this test fails - pclaimTrie->getClaimById(claimIdx, claimName, claimValue); - BOOST_CHECK(claimName == name); - BOOST_CHECK(claimValue.claimId == claimIdx); -} - -BOOST_AUTO_TEST_CASE(get_claim_by_id_test_3) -{ - ClaimTrieChainFixture fixture; - pclaimTrie->setExpirationTime(5); - const std::string name = "test"; - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 1); - uint160 claimId = ClaimIdHash(tx1.GetHash(), 0); - - fixture.IncrementBlocks(1); - - CClaimValue claimValue; - std::string claimName; - pclaimTrie->getClaimById(claimId, claimName, claimValue); - BOOST_CHECK(claimName == name); - BOOST_CHECK(claimValue.claimId == claimId); - // make second claim with activation delay 1 - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 2); - uint160 claimId2 = ClaimIdHash(tx2.GetHash(), 0); - - fixture.IncrementBlocks(1); - // second claim is not activated yet, but can still access by claim id - BOOST_CHECK(is_best_claim(name, tx1)); - BOOST_CHECK(pclaimTrie->getClaimById(claimId2, claimName, claimValue)); - BOOST_CHECK(claimName == name); - BOOST_CHECK(claimValue.claimId == claimId2); - - fixture.IncrementBlocks(1); - // second claim has activated - BOOST_CHECK(is_best_claim(name, tx2)); - BOOST_CHECK(pclaimTrie->getClaimById(claimId2, claimName, claimValue)); - BOOST_CHECK(claimName == name); - BOOST_CHECK(claimValue.claimId == claimId2); - - - fixture.DecrementBlocks(1); - // second claim has been deactivated via decrement - // should still be accesible via claim id - BOOST_CHECK(is_best_claim(name, tx1)); - BOOST_CHECK(pclaimTrie->getClaimById(claimId2, claimName, claimValue)); - BOOST_CHECK(claimName == name); - BOOST_CHECK(claimValue.claimId == claimId2); - - fixture.IncrementBlocks(1); - // second claim should have been re activated via increment - BOOST_CHECK(is_best_claim(name, tx2)); - BOOST_CHECK(pclaimTrie->getClaimById(claimId2, claimName, claimValue)); - BOOST_CHECK(claimName == name); - BOOST_CHECK(claimValue.claimId == claimId2); -} - BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/claimtriecache_tests.cpp b/src/test/claimtriecache_tests.cpp index e94624268..28dc60855 100644 --- a/src/test/claimtriecache_tests.cpp +++ b/src/test/claimtriecache_tests.cpp @@ -18,7 +18,7 @@ public: return CClaimTrieCache::recursiveComputeMerkleHash(tnCurrent, sPos); } - bool recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, std::string sName, bool* pfNullified) const + bool recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, std::string sName, bool* pfNullified) { return CClaimTrieCache::recursivePruneName(tnCurrent,nPos,sName, pfNullified); } diff --git a/src/test/claimtriedb_tests.cpp b/src/test/claimtriedb_tests.cpp new file mode 100644 index 000000000..ef64d427f --- /dev/null +++ b/src/test/claimtriedb_tests.cpp @@ -0,0 +1,91 @@ +#include "claimtrie.h" +#include "main.h" +#include "uint256.h" + +#include "test/test_bitcoin.h" +#include +using namespace std; + +BOOST_FIXTURE_TEST_SUITE(claimtriedb_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(compatibility_test) +{ + const int value = 20; + const std::string test("test"); + + CClaimTrieNode base_node; + const CClaimValue test_claim(COutPoint(), uint160(), CAmount(value), 0, 0); + const CClaimIndexElement test_element = {test, test_claim}; + const CSupportValue test_support(COutPoint(), uint160(), CAmount(value), 0, 0); + + base_node.claims.push_back(test_claim); + const supportMapEntryType supportMap(1, test_support); + const queueNameRowType nameRows(1, outPointHeightType(COutPoint(), value)); + const claimQueueRowType claimRows(1, claimQueueEntryType(test, test_claim)); + const supportQueueRowType supportRows(1, supportQueueEntryType(test, test_support)); + const expirationQueueRowType expirationRows(1, nameOutPointType(test, COutPoint())); + const supportQueueNameRowType supportNameRows(1, outPointHeightType(COutPoint(), value)); + const supportExpirationQueueRowType supportExpirationRows(1, nameOutPointType(test, COutPoint())); + + CClaimTrieDb db(true, false); + + /// fill out char keys + db.Write(std::make_pair('n', test), base_node); + db.Write(std::make_pair('i', uint160()), test_element); + db.Write(std::make_pair('r', value), claimRows); + db.Write(std::make_pair('m', test), nameRows); + db.Write(std::make_pair('e', value), expirationRows); + db.Write(std::make_pair('s', test), supportMap); + db.Write(std::make_pair('u', value), supportRows); + db.Write(std::make_pair('p', test), supportNameRows); + db.Write(std::make_pair('x', value), supportExpirationRows); + db.Sync(); + + /// it should read same by types + CClaimTrieNode node; + db.getQueueRow(test, node); + BOOST_CHECK(node == base_node); + + CClaimIndexElement element; + db.getQueueRow(uint160(), element); + BOOST_CHECK(element.name == test_element.name); + BOOST_CHECK(element.claim == test_element.claim); + + claimQueueRowType claims; + db.getQueueRow(value, claims); + BOOST_CHECK(claims.size() == 1); + BOOST_CHECK(claims[0].first == claimRows[0].first); + BOOST_CHECK(claims[0].second == claimRows[0].second); + + queueNameRowType names; + db.getQueueRow(test, names); + BOOST_CHECK(names.size() == 1); + BOOST_CHECK(names[0].nHeight == nameRows[0].nHeight); + + expirationQueueRowType exps; + db.getQueueRow(value, exps); + BOOST_CHECK(exps.size() == 1); + BOOST_CHECK(exps[0].name == expirationRows[0].name); + + supportMapEntryType sups; + db.getQueueRow(test, sups); + BOOST_CHECK(sups.size() == 1); + BOOST_CHECK(sups[0] == supportMap[0]); + + supportQueueRowType supRows; + db.getQueueRow(value, supRows); + BOOST_CHECK(supRows.size() == 1); + BOOST_CHECK(supRows[0] == supportRows[0]); + + supportQueueNameRowType supNames; + db.getQueueRow(test, supNames); + BOOST_CHECK(supNames.size() == 1); + BOOST_CHECK(supNames[0].nHeight == supportNameRows[0].nHeight); + + supportExpirationQueueRowType supExps; + db.getQueueRow(value, supExps); + BOOST_CHECK(supExps.size() == 1); + BOOST_CHECK(supExps[0].name == supportExpirationRows[0].name); +} + +BOOST_AUTO_TEST_SUITE_END() -- 2.45.3 From ebeb2bd092734035887ca3d8d0e69628bd2d3900 Mon Sep 17 00:00:00 2001 From: Anthony Fieroni Date: Mon, 6 Aug 2018 09:18:22 +0300 Subject: [PATCH 02/25] Specify non-standard transaction error when it's dust Signed-off-by: Anthony Fieroni --- src/main.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index a894999b6..d910d8da8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1034,8 +1034,12 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // Rather not work on nonstandard transactions (unless -testnet/-regtest) string reason; - if (fRequireStandard && !IsStandardTx(tx, reason)) - return state.DoS(0, false, REJECT_NONSTANDARD, reason); + if (fRequireStandard && !IsStandardTx(tx, reason)) { + if (reason == "dust") + return state.DoS(0, false, REJECT_DUST, reason); + else + return state.DoS(0, false, REJECT_NONSTANDARD, reason); + } // Don't relay version 2 transactions until CSV is active, and we can be // sure that such transactions will be mined (unless we're on -- 2.45.3 From fa35ccbe784d20def5d5c314501099c5186e6b61 Mon Sep 17 00:00:00 2001 From: Brannon King Date: Wed, 26 Sep 2018 13:14:20 -0600 Subject: [PATCH 03/25] bumped release version to 0.12.2.2 --- configure.ac | 2 +- src/clientversion.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 7445545d5..082f6c5d3 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 12) define(_CLIENT_VERSION_REVISION, 2) -define(_CLIENT_VERSION_BUILD, 0) +define(_CLIENT_VERSION_BUILD, 2) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2016) define(_COPYRIGHT_HOLDERS,[The %s developers]) diff --git a/src/clientversion.h b/src/clientversion.h index e8e8417ca..44dd229d3 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -17,7 +17,7 @@ #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 12 #define CLIENT_VERSION_REVISION 2 -#define CLIENT_VERSION_BUILD 0 +#define CLIENT_VERSION_BUILD 2 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true -- 2.45.3 From bdfda3c267950cd159dc1e2882e685f9b0ac43cc Mon Sep 17 00:00:00 2001 From: Brannon King Date: Mon, 1 Oct 2018 11:32:53 -0600 Subject: [PATCH 04/25] Deployment: added S3, added SHA256, renewed GitHub credentials, brew upgrade --- .travis.yml | 117 ++++++++++++++++++++++++++-------------------------- 1 file changed, 59 insertions(+), 58 deletions(-) diff --git a/.travis.yml b/.travis.yml index 293fbd9ed..829422909 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,68 +1,69 @@ matrix: - include: - - os: linux - sudo: required - dist: trusty - language: c - env: TARGET=linux - - os: linux - sudo: required - dist: trusty - language: c - env: TARGET=windows - - os: osx - language: c - osx_image: xcode7.3 - env: TARGET=osx - + include: + - os: linux + sudo: required + dist: trusty + language: c + env: TARGET=linux + - os: linux + sudo: required + dist: trusty + language: c + env: TARGET=windows + - os: osx + language: c + osx_image: xcode7.3 + env: TARGET=osx cache: apt: true ccache: true directories: - - build - - depends/built - + - build + - depends/built before_install: - - date +%s > "${TRAVIS_BUILD_DIR}/start_time" - - ls -lh build - - du -h -d 2 build - +- date +%s > "${TRAVIS_BUILD_DIR}/start_time" +- ls -lh build +- du -h -d 2 build +- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update; fi +- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install ccache; fi +- if [ "$TRAVIS_OS_NAME" == "osx" ]; then export PATH="/usr/local/opt/ccache/libexec:$PATH"; fi install: true script: - - if [[ "${TARGET}" == "osx" ]]; then ./reproducible_build.sh -t -o -c; fi - - if [[ "${TARGET}" == "linux" ]]; then ./reproducible_build.sh -t -o -c -f; fi - - if [[ "${TARGET}" == "windows" ]]; then ./packaging/build_windows.sh; fi - - if [[ "${TARGET}" == "osx" ]]; then zip -j "lbrycrd-${TARGET}.zip" src/lbrycrdd src/lbrycrd-cli src/lbrycrd-tx; fi - - if [[ "${TARGET}" == "linux" ]]; then zip -j "lbrycrd-${TARGET}.zip" src/lbrycrdd src/lbrycrd-cli src/lbrycrd-tx; fi - - if [[ "${TARGET}" == "windows" ]]; then zip -j "lbrycrd-${TARGET}.zip" src/lbrycrdd.exe src/lbrycrd-cli.exe src/lbrycrd-tx.exe; fi - +- mkdir -p "dist/${TRAVIS_BRANCH}" +- if [[ "${TARGET}" == "osx" ]]; then ./reproducible_build.sh -t -o -c; fi +- if [[ "${TARGET}" == "linux" ]]; then ./reproducible_build.sh -t -o -c -f; fi +- if [[ "${TARGET}" == "windows" ]]; then ./packaging/build_windows.sh; fi +- if [[ "${TARGET}" == "osx" ]]; then zip -j "dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip" src/lbrycrdd src/lbrycrd-cli src/lbrycrd-tx; fi +- if [[ "${TARGET}" == "linux" ]]; then zip -j "dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip" src/lbrycrdd src/lbrycrd-cli src/lbrycrd-tx; fi +- if [[ "${TARGET}" == "windows" ]]; then zip -j "dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip" src/lbrycrdd.exe src/lbrycrd-cli.exe src/lbrycrd-tx.exe; fi +- if [[ "${TARGET}" == "osx" ]]; then shasum -a 256 dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip > dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}-sha256.txt; fi +- if [[ "${TARGET}" == "linux" ]]; then sha256sum -b dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip > dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}-sha256.txt; fi +- if [[ "${TARGET}" == "windows" ]]; then sha256sum -b dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip > dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}-sha256.txt; fi +- cat dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}-sha256.txt before_cache: - - ls -lh build - - du -h -d 2 build - +- ls -lh build +- du -h -d 2 build deploy: - - provider: releases - file: lbrycrd-linux.zip - skip_cleanup: true - on: - tags: true - condition: "$TARGET = linux" - api_key: - secure: "ibN+PQg84f0tgJLV3KaHjkHmgFNOPqBLIrSU42moen22xxT2VIn0j7DkFaLLts1fs/+/gxmrvhOQ0vUFJqmflZ3kCeyedP/CVgZz7D7HRVK0cYUMJ2F9VWMZAFIX6A67OUlypqZqzKAKrZHx3HXky6Z8NBU23JgWqDm8PcrbbgMLvB2lvWVASjJVKreaL9BOxFOOOrAj6xAIm9ogTOnFVI/AhufNOKOTZaiprcbqMngwHeaILbwEJVqv5P2YUurC6Sq+QaH26tX00DtsYOW+n8AA3Fe48+L6rqa6Q8ru+dhPuR/Apr2+DTZ+npzY8leV3A7mYUeLo4JLaEH6n1TLVt65cX7nuesS7KsSKBSxs7q7bsqeapDcMskZz5JR4EK4S96CuHZEnn6+efpH8IrxWpbeO3EibJfyT8tMJKw7Zym5mPr+sz6xSlVMoBVcCm+7z9e7Zcqukdvdy8jM7sGP9qusqEhpojh0o+gPgr9p13SfR+6OCpj9gwxPCnZO8RBfh1cbz9vFSVlDyUYcpI2CCCpPazA1glTsEDk+VtznnUMmWksXWfxBFV81jQB2SnoZKlnsiEuNMwhiMCMEkRFo74+AsUr2UjmKJ5KC8ACwsn475PoLZBh2J6fyXBHMdbrGfK+Zt5K2IHRRtDaZVT4eHqYzxh8KhalsuBNxCo3FygI=" - - provider: releases - file: lbrycrd-osx.zip - skip_cleanup: true - on: - tags: true - condition: "$TARGET = osx" - api_key: - secure: "ibN+PQg84f0tgJLV3KaHjkHmgFNOPqBLIrSU42moen22xxT2VIn0j7DkFaLLts1fs/+/gxmrvhOQ0vUFJqmflZ3kCeyedP/CVgZz7D7HRVK0cYUMJ2F9VWMZAFIX6A67OUlypqZqzKAKrZHx3HXky6Z8NBU23JgWqDm8PcrbbgMLvB2lvWVASjJVKreaL9BOxFOOOrAj6xAIm9ogTOnFVI/AhufNOKOTZaiprcbqMngwHeaILbwEJVqv5P2YUurC6Sq+QaH26tX00DtsYOW+n8AA3Fe48+L6rqa6Q8ru+dhPuR/Apr2+DTZ+npzY8leV3A7mYUeLo4JLaEH6n1TLVt65cX7nuesS7KsSKBSxs7q7bsqeapDcMskZz5JR4EK4S96CuHZEnn6+efpH8IrxWpbeO3EibJfyT8tMJKw7Zym5mPr+sz6xSlVMoBVcCm+7z9e7Zcqukdvdy8jM7sGP9qusqEhpojh0o+gPgr9p13SfR+6OCpj9gwxPCnZO8RBfh1cbz9vFSVlDyUYcpI2CCCpPazA1glTsEDk+VtznnUMmWksXWfxBFV81jQB2SnoZKlnsiEuNMwhiMCMEkRFo74+AsUr2UjmKJ5KC8ACwsn475PoLZBh2J6fyXBHMdbrGfK+Zt5K2IHRRtDaZVT4eHqYzxh8KhalsuBNxCo3FygI=" - - provider: releases - file: lbrycrd-windows.zip - skip_cleanup: true - on: - tags: true - condition: "$TARGET = windows" - api_key: - secure: "ibN+PQg84f0tgJLV3KaHjkHmgFNOPqBLIrSU42moen22xxT2VIn0j7DkFaLLts1fs/+/gxmrvhOQ0vUFJqmflZ3kCeyedP/CVgZz7D7HRVK0cYUMJ2F9VWMZAFIX6A67OUlypqZqzKAKrZHx3HXky6Z8NBU23JgWqDm8PcrbbgMLvB2lvWVASjJVKreaL9BOxFOOOrAj6xAIm9ogTOnFVI/AhufNOKOTZaiprcbqMngwHeaILbwEJVqv5P2YUurC6Sq+QaH26tX00DtsYOW+n8AA3Fe48+L6rqa6Q8ru+dhPuR/Apr2+DTZ+npzY8leV3A7mYUeLo4JLaEH6n1TLVt65cX7nuesS7KsSKBSxs7q7bsqeapDcMskZz5JR4EK4S96CuHZEnn6+efpH8IrxWpbeO3EibJfyT8tMJKw7Zym5mPr+sz6xSlVMoBVcCm+7z9e7Zcqukdvdy8jM7sGP9qusqEhpojh0o+gPgr9p13SfR+6OCpj9gwxPCnZO8RBfh1cbz9vFSVlDyUYcpI2CCCpPazA1glTsEDk+VtznnUMmWksXWfxBFV81jQB2SnoZKlnsiEuNMwhiMCMEkRFo74+AsUr2UjmKJ5KC8ACwsn475PoLZBh2J6fyXBHMdbrGfK+Zt5K2IHRRtDaZVT4eHqYzxh8KhalsuBNxCo3FygI=" - +- provider: releases + draft: true + file: "dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip" + name: "${TRAVIS_BRANCH}" + skip_cleanup: true + target_commitish: $TRAVIS_COMMIT + tag_name: $TRAVIS_TAG + on: + tags: true + api_key: + secure: "Ni5WZNR5CefWXpyDUQLMQbQ2LH4Iot+0SqIoM9c4maW06al1M8vu57vWuj2cESsW7JsaBehCE45Cwmo5kWyEjAiZY8sIMmvixkMP/8uPWuLgNmnIbm7U+d0j652DmZshDYtt8EomqV2RhAx/rmBnzGkruLOw9WTp9ZdBN3WbTt/IpZ2gMgVbGWYGOx+uRw7/yGw8m4gShQheto/dycbyyR3XV2WP9wuLmNYkcQ6JumSoQdDWXcvVfbCwylGq2sLDKwhvfTr4iwYyYsWdmhfdEQl0WcIv5C8xgdiY2vzhi2LmLqFbS/fvKNC26Tfo4bOHFG/eOnvqc+yyEB8B/xqW9Gs+A0TUh/3N30vHYZGcpiDU35DwAN5bZ1+s+mr/ZrNzBJ5BgT8io3g0Ko8gykbDvFQVpg7kxFsqA1YCikEpG86lVGk6clTa5guJvAHse+DfnbWO1nfDxYQXW0md861m0txk8RpTC/TVNyH/lL/vsS7LB67EHhRdZY+O1+5sUGMdtvvhMoxJYCwQGpLkh43KRsKynkMUR94w2O9hc8cknXdV3wrndVz00XNdcur6y4D7HTll1tBrF68CA2yKUSY5hsjtPmdlN+DW8ou/rJiKOpQZ/Xzp69AQEheOFfDPItxQRYxWj0dMOk8eszf0wFvi1N7J/hT/IHnuX5ITfa/T4NE=" +- provider: s3 + access_key_id: AKIAICKFHNTR5RITASAQ + secret_access_key: + secure: Qfgs8vGnEUvgiZNP2S9zY8qHEzaDOceF/XTv32jRBOISWfTqOTE56DZbOp8WKHPAqn0dx04jKA1NfV9f06sXU1NVbiJ2VYISo6XAk0n3RBJL3/mhNxvut/zM2DHkFPljWTkWEColS0ZyA3m4eUyJvAw/i+mOBT/zDD/oIlS5Uo5l/x3LmF9fYBuei0ucwSQeNOr2wCMIl+pXrIU7B3lEzXh1asayW6A9y7DOqMLnrSQ7TLlSssbnhuhDVpFx0xxX/U2NPraotbGKdo3wwMbms/lluBe60I/LsDNp9/SZXMDXh2YLGUImr97octwpdzIMjF+kU7QAZJzM7grz8PU9+MQh2V5sn6Xsww2x4PdkmHGz/2FMzhrCrlPf5JCaPBH49G+w4/29HYmMrlimOOVx4qXCpQ/XtWWne/d6MF0qqT6JhdPuD9ohmTpxcHRkCe2fxUw6Yn3dj+/+YoCywAcwcBm5jLpAotmWoCmmcnm9rvB7bIuPPZAjJUZViCnyvwY4Tj3Fb+sOuK4b/O5D2+cuS+WgQRkN/RspYlXrXTIh8Efv/yhW5L9WdzG1OExJDw2hX5VTccRRgIKZxZp80U2eYqn2M07+1nU+ShX4kgiSon46k5cfacLgzLKWEyCxWSSTbsYcwRxvDEjtYy4wxAYx8+J3dgQPs/opDXoQTJMjud0= + bucket: build.lbry.io + upload-dir: lbrycrd + acl: public_read + local_dir: dist + skip_cleanup: true + on: + repo: lbryio/lbrycrd + all_branches: true -- 2.45.3 From 7eca4f00a7a6d24d8386dab733e136940ef457f2 Mon Sep 17 00:00:00 2001 From: kay kurokawa Date: Sat, 13 Oct 2018 15:15:01 -0400 Subject: [PATCH 05/25] Remove excessive logging when writing nodes on claimtrie to disk --- src/claimtrie.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/claimtrie.cpp b/src/claimtrie.cpp index 06f19b115..b4d0b4da1 100644 --- a/src/claimtrie.cpp +++ b/src/claimtrie.cpp @@ -973,7 +973,6 @@ void CClaimTrie::BatchWriteNode(CDBBatch& batch, const std::string& name, const uint32_t num_claims = 0; if (pNode) num_claims = pNode->claims.size(); - LogPrintf("%s: Writing %s to disk with %d claims\n", __func__, name, num_claims); if (pNode) batch.Write(std::make_pair(TRIE_NODE, name), *pNode); else -- 2.45.3 From d5db27b61af3c592dc1a29b017e802fae18f7ef2 Mon Sep 17 00:00:00 2001 From: kay kurokawa Date: Mon, 15 Oct 2018 13:29:45 -0400 Subject: [PATCH 06/25] Remove lines that are no longer used after removal of logging line in 7eca4f0 --- src/claimtrie.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/claimtrie.cpp b/src/claimtrie.cpp index b4d0b4da1..ff72ccb43 100644 --- a/src/claimtrie.cpp +++ b/src/claimtrie.cpp @@ -970,9 +970,6 @@ bool CClaimTrie::updateTakeoverHeight(const std::string& name, int nTakeoverHeig void CClaimTrie::BatchWriteNode(CDBBatch& batch, const std::string& name, const CClaimTrieNode* pNode) const { - uint32_t num_claims = 0; - if (pNode) - num_claims = pNode->claims.size(); if (pNode) batch.Write(std::make_pair(TRIE_NODE, name), *pNode); else -- 2.45.3 From 451f4b4acaef74b70fd2c690a446774b59a654e8 Mon Sep 17 00:00:00 2001 From: kay kurokawa Date: Mon, 15 Oct 2018 13:42:36 -0400 Subject: [PATCH 07/25] bumped release version to 0.12.2.3 --- configure.ac | 2 +- src/clientversion.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 082f6c5d3..6be5a02b9 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 12) define(_CLIENT_VERSION_REVISION, 2) -define(_CLIENT_VERSION_BUILD, 2) +define(_CLIENT_VERSION_BUILD, 3) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2016) define(_COPYRIGHT_HOLDERS,[The %s developers]) diff --git a/src/clientversion.h b/src/clientversion.h index 44dd229d3..67a55a4a9 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -17,7 +17,7 @@ #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 12 #define CLIENT_VERSION_REVISION 2 -#define CLIENT_VERSION_BUILD 2 +#define CLIENT_VERSION_BUILD 3 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true -- 2.45.3 From 15788075035aba6525855056b4b3c28b17073c74 Mon Sep 17 00:00:00 2001 From: Anthony Fieroni Date: Wed, 19 Sep 2018 10:44:18 +0300 Subject: [PATCH 08/25] Remove unnecessary copies Signed-off-by: Anthony Fieroni --- src/rpc/claimtrie.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rpc/claimtrie.cpp b/src/rpc/claimtrie.cpp index 252de232b..b0b3d0d49 100644 --- a/src/rpc/claimtrie.cpp +++ b/src/rpc/claimtrie.cpp @@ -7,7 +7,7 @@ // Maximum block decrement that is allowed from rpc calls const int MAX_RPC_BLOCK_DECREMENTS = 50; -uint160 ParseClaimtrieId(const UniValue& v, std::string strName) +uint160 ParseClaimtrieId(const UniValue& v, const std::string& strName) { std::string strHex; if (v.isStr()) @@ -221,8 +221,8 @@ typedef std::map > supportsWithoutClaimsMapT UniValue claimsAndSupportsToJSON(claimSupportMapType::const_iterator itClaimsAndSupports, int nCurrentHeight) { UniValue ret(UniValue::VOBJ); - const CClaimValue claim = itClaimsAndSupports->second.first; - const std::vector supports = itClaimsAndSupports->second.second; + const CClaimValue& claim = itClaimsAndSupports->second.first; + const std::vector& supports = itClaimsAndSupports->second.second; CAmount nEffectiveAmount = 0; UniValue supportObjs(UniValue::VARR); for (std::vector::const_iterator itSupports = supports.begin(); itSupports != supports.end(); ++itSupports) @@ -262,7 +262,7 @@ UniValue claimsAndSupportsToJSON(claimSupportMapType::const_iterator itClaimsAnd UniValue supportsWithoutClaimsToJSON(supportsWithoutClaimsMapType::const_iterator itSupportsWithoutClaims, int nCurrentHeight) { - const std::vector supports = itSupportsWithoutClaims->second; + const std::vector& supports = itSupportsWithoutClaims->second; UniValue ret(UniValue::VOBJ); UniValue supportObjs(UniValue::VARR); ret.push_back(Pair("claimId (no matching claim)", itSupportsWithoutClaims->first.GetHex())); -- 2.45.3 From 24da3ac57ae7ac7e1809b8080fc1d18b2122a55e Mon Sep 17 00:00:00 2001 From: Brannon King Date: Tue, 16 Oct 2018 12:30:07 -0600 Subject: [PATCH 09/25] fixed incompatibility with newer lbssl --- CMakeLists.txt | 8 +++++--- src/qt/paymentrequestplus.cpp | 17 +++++++++++------ src/wallet/crypter.cpp | 28 ++++++++++++++++------------ 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ac283aec0..fa1258b08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,9 +4,11 @@ project(lbrycrd_clion) # Do not use for full compile. This is for CLion syntax c set (CMAKE_CXX_STANDARD 98) # 03 is not supported by cmake, but this will soon be 11 (after upstream bitcoin merge) # I thought that setting the standard would disable the clang-tidy c++11 tips; nope. -set(BOOST_ROOT "build/boost" CACHE PATH "Boost library path") -set(Boost_NO_SYSTEM_PATHS on CACHE BOOL "Do not search system for Boost") -find_package(Boost REQUIRED COMPONENTS filesystem program_options thread chrono) # locale coming shortly +if(EXISTS "build/boost") + set(BOOST_ROOT "build/boost" CACHE PATH "Boost library path") + set(Boost_NO_SYSTEM_PATHS on CACHE BOOL "Do not search system for Boost") +endif() +find_package(Boost REQUIRED COMPONENTS filesystem program_options thread chrono locale) file(GLOB sources src/*.h src/*.cpp diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp index 20e1f79ff..ff96ccaa2 100644 --- a/src/qt/paymentrequestplus.cpp +++ b/src/qt/paymentrequestplus.cpp @@ -159,14 +159,19 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c std::string data_to_verify; // Everything but the signature rcopy.SerializeToString(&data_to_verify); - EVP_MD_CTX ctx; - EVP_PKEY *pubkey = X509_get_pubkey(signing_cert); - EVP_MD_CTX_init(&ctx); - if (!EVP_VerifyInit_ex(&ctx, digestAlgorithm, NULL) || - !EVP_VerifyUpdate(&ctx, data_to_verify.data(), data_to_verify.size()) || - !EVP_VerifyFinal(&ctx, (const unsigned char*)paymentRequest.signature().data(), (unsigned int)paymentRequest.signature().size(), pubkey)) { + EVP_MD_CTX* ctx = EVP_MD_CTX_new(); + if (!ctx) + throw SSLVerifyError("Unable to allocate OpenSSL context."); + + EVP_PKEY* pubkey = X509_get_pubkey(signing_cert); + EVP_MD_CTX_init(ctx); + if (!EVP_VerifyInit_ex(ctx, digestAlgorithm, NULL) || + !EVP_VerifyUpdate(ctx, data_to_verify.data(), data_to_verify.size()) || + !EVP_VerifyFinal(ctx, (const unsigned char*)paymentRequest.signature().data(), (unsigned int)paymentRequest.signature().size(), pubkey)) { + EVP_MD_CTX_free(ctx); throw SSLVerifyError("Bad signature, invalid payment request."); } + EVP_MD_CTX_free(ctx); // OpenSSL API for getting human printable strings from certs is baroque. int textlen = X509_NAME_get_text_by_NID(certname, NID_commonName, NULL, 0); diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 95aa4c259..5b7878b32 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -58,15 +58,17 @@ bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector (nCLen); - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); + if (!ctx) return false; bool fOk = true; - EVP_CIPHER_CTX_init(&ctx); - if (fOk) fOk = EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV) != 0; - if (fOk) fOk = EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen) != 0; - if (fOk) fOk = EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0]) + nCLen, &nFLen) != 0; - EVP_CIPHER_CTX_cleanup(&ctx); + EVP_CIPHER_CTX_init(ctx); + if (fOk) fOk = EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, chKey, chIV) != 0; + if (fOk) fOk = EVP_EncryptUpdate(ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen) != 0; + if (fOk) fOk = EVP_EncryptFinal_ex(ctx, (&vchCiphertext[0]) + nCLen, &nFLen) != 0; + EVP_CIPHER_CTX_cleanup(ctx); + EVP_CIPHER_CTX_free(ctx); if (!fOk) return false; @@ -85,15 +87,17 @@ bool CCrypter::Decrypt(const std::vector& vchCiphertext, CKeyingM vchPlaintext = CKeyingMaterial(nPLen); - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); + if (!ctx) return false; bool fOk = true; - EVP_CIPHER_CTX_init(&ctx); - if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV) != 0; - if (fOk) fOk = EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen) != 0; - if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0]) + nPLen, &nFLen) != 0; - EVP_CIPHER_CTX_cleanup(&ctx); + EVP_CIPHER_CTX_init(ctx); + if (fOk) fOk = EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, chKey, chIV) != 0; + if (fOk) fOk = EVP_DecryptUpdate(ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen) != 0; + if (fOk) fOk = EVP_DecryptFinal_ex(ctx, (&vchPlaintext[0]) + nPLen, &nFLen) != 0; + EVP_CIPHER_CTX_cleanup(ctx); + EVP_CIPHER_CTX_free(ctx); if (!fOk) return false; -- 2.45.3 From f86eb54077263ac9ebe1ef08de76072b5335f21d Mon Sep 17 00:00:00 2001 From: Anthony Fieroni Date: Fri, 10 Aug 2018 17:12:35 -0600 Subject: [PATCH 10/25] Add block hash parameter to claimtrie rpc methods Signed-off-by: Anthony Fieroni --- src/claimtrie.cpp | 191 +++++++++--- src/claimtrie.h | 19 +- src/main.cpp | 59 ++-- src/main.h | 2 + src/rpc/claimtrie.cpp | 401 ++++++++++++++------------ src/test/claimtriebranching_tests.cpp | 269 +++++++++++++++-- 6 files changed, 650 insertions(+), 291 deletions(-) diff --git a/src/claimtrie.cpp b/src/claimtrie.cpp index ff72ccb43..d7fae5fed 100644 --- a/src/claimtrie.cpp +++ b/src/claimtrie.cpp @@ -527,39 +527,26 @@ claimsForNameType CClaimTrie::getClaimsForName(const std::string& name) const } //return effective amount from claim, retuns 0 if claim is not found -CAmount CClaimTrie::getEffectiveAmountForClaim(const std::string& name, uint160 claimId) const +CAmount CClaimTrie::getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector* supports) const { - std::vector supports; - return getEffectiveAmountForClaimWithSupports(name, claimId, supports); + return getEffectiveAmountForClaim(getClaimsForName(name), claimId, supports); } -//return effective amount from claim and the supports used as inputs, retuns 0 if claim is not found -CAmount CClaimTrie::getEffectiveAmountForClaimWithSupports(const std::string& name, uint160 claimId, - std::vector& supports) const +CAmount CClaimTrie::getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector* supports) const { - claimsForNameType claims = getClaimsForName(name); CAmount effectiveAmount = 0; - bool claim_found = false; - for (std::vector::iterator it=claims.claims.begin(); it!=claims.claims.end(); ++it) - { - if (it->claimId == claimId && it->nValidAtHeight < nCurrentHeight) - { + for (std::vector::const_iterator it = claims.claims.begin(); it != claims.claims.end(); ++it) { + if (it->claimId == claimId && it->nValidAtHeight < nCurrentHeight) { effectiveAmount += it->nAmount; - claim_found = true; + for (std::vector::const_iterator it = claims.supports.begin(); it != claims.supports.end(); ++it) { + if (it->supportedClaimId == claimId && it->nValidAtHeight < nCurrentHeight) { + effectiveAmount += it->nAmount; + if (supports) supports->push_back(*it); + } + } break; } } - if (!claim_found) - return effectiveAmount; - - for (std::vector::iterator it=claims.supports.begin(); it!=claims.supports.end(); ++it) - { - if (it->supportedClaimId == claimId && it->nValidAtHeight < nCurrentHeight) - { - effectiveAmount += it->nAmount; - supports.push_back(*it); - } - } return effectiveAmount; } @@ -2463,25 +2450,26 @@ bool CClaimTrieCache::getLastTakeoverForName(const std::string& name, int& nLast int CClaimTrieCache::getNumBlocksOfContinuousOwnership(const std::string& name) const { - const CClaimTrieNode* node = NULL; - nodeCacheType::const_iterator itCache = cache.find(name); - if (itCache != cache.end()) - { - node = itCache->second; - } - if (!node) - { - node = base->getNodeForName(name); - } - if (!node || node->claims.empty()) - { - return 0; - } + const CClaimTrieNode* node = getNodeForName(name); + if (!node || node->claims.empty()) return 0; int nLastTakeoverHeight; assert(getLastTakeoverForName(name, nLastTakeoverHeight)); return nCurrentHeight - nLastTakeoverHeight; } +const CClaimTrieNode* CClaimTrieCache::getNodeForName(const std::string& name) const +{ + const CClaimTrieNode* node = NULL; + nodeCacheType::const_iterator itCache = cache.find(name); + if (itCache != cache.end()) { + node = itCache->second; + } + if (!node) { + node = base->getNodeForName(name); + } + return node; +} + int CClaimTrieCache::getDelayForName(const std::string& name) const { if (!fRequireTakeoverHeights) @@ -2570,10 +2558,125 @@ uint256 CClaimTrieCache::getLeafHashForProof(const std::string& currentPosition, } } -CClaimTrieProof CClaimTrieCache::getProofForName(const std::string& name) const +void CClaimTrieCache::recursiveFlattenTrie(const std::string& name, const CClaimTrieNode* current, std::vector& nodes) const +{ + nodes.push_back(std::make_pair(name, *current)); + nodeCacheType::const_iterator cachedNode; + for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) { + const std::string str = name + char(it->first); + cachedNode = cache.find(str); + if (cachedNode != cache.end()) + recursiveFlattenTrie(str, cachedNode->second, nodes); + else + recursiveFlattenTrie(str, it->second, nodes); + } +} + +std::vector CClaimTrieCache::flattenTrie() const +{ + std::vector nodes; + recursiveFlattenTrie("", &(base->root), nodes); + return nodes; +} + +claimsForNameType CClaimTrieCache::getClaimsForName(const std::string& name) const +{ + int nLastTakeoverHeight = 0; + std::vector claims; + if (const CClaimTrieNode* node = getNodeForName(name)) { + claims = node->claims; + getLastTakeoverForName(name, nLastTakeoverHeight); + } + supportMapEntryType supports; + getSupportsForName(name, supports); + queueNameType::const_iterator itQueueNameCache = getQueueCacheNameRow(name, false); + if (itQueueNameCache != claimQueueNameCache.end()) { + const queueNameRowType& namedClaimRow = itQueueNameCache->second; + for (queueNameRowType::const_iterator itClaimsForName = namedClaimRow.begin(); itClaimsForName != namedClaimRow.end(); ++itClaimsForName) { + claimQueueType::const_iterator itQueueCache = getQueueCacheRow(itClaimsForName->nHeight, false); + if (itQueueCache != claimQueueCache.end()) { + const claimQueueRowType& claimRow = itQueueCache->second; + for (claimQueueRowType::const_iterator itClaimRow = claimRow.begin(); itClaimRow != claimRow.end(); ++itClaimRow) { + if (itClaimRow->first == name && itClaimRow->second.outPoint == itClaimsForName->outPoint) { + claims.push_back(itClaimRow->second); + break; + } + } + } + } + } + queueNameType::const_iterator itSupportQueueNameCache = getSupportQueueCacheNameRow(name, false); + if (itSupportQueueNameCache != supportQueueNameCache.end()) { + const queueNameRowType& namedSupportRow = itSupportQueueNameCache->second; + for (queueNameRowType::const_iterator itSupportsForName = namedSupportRow.begin(); itSupportsForName != namedSupportRow.end(); ++itSupportsForName) { + supportQueueType::const_iterator itSupportQueueCache = getSupportQueueCacheRow(itSupportsForName->nHeight, false); + if (itSupportQueueCache != supportQueueCache.end()) { + const supportQueueRowType& supportRow = itSupportQueueCache->second; + for (supportQueueRowType::const_iterator itSupportRow = supportRow.begin(); itSupportRow != supportRow.end(); ++itSupportRow) { + if (itSupportRow->first == name && itSupportRow->second.outPoint == itSupportsForName->outPoint) { + supports.push_back(itSupportRow->second); + break; + } + } + } + } + } + return claimsForNameType(claims, supports, nLastTakeoverHeight); +} + +CAmount CClaimTrieCache::getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector* supports) const +{ + return getEffectiveAmountForClaim(getClaimsForName(name), claimId, supports); +} + +CAmount CClaimTrieCache::getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector* supports) const +{ + CAmount effectiveAmount = 0; + for (std::vector::const_iterator it = claims.claims.begin(); it != claims.claims.end(); ++it) { + if (it->claimId == claimId && it->nValidAtHeight < nCurrentHeight) { + effectiveAmount += it->nAmount; + for (std::vector::const_iterator it = claims.supports.begin(); it != claims.supports.end(); ++it) { + if (it->supportedClaimId == claimId && it->nValidAtHeight < nCurrentHeight) { + effectiveAmount += it->nAmount; + if (supports) supports->push_back(*it); + } + } + break; + } + } + return effectiveAmount; +} + +bool CClaimTrieCache::getInfoForName(const std::string& name, CClaimValue& claim) const { if (dirty()) getMerkleHash(); + + CClaimTrieNode* current = &(base->root); + nodeCacheType::const_iterator cachedNode; + + for (std::string::const_iterator itName = name.begin(); current; ++itName) { + std::string currentPosition(name.begin(), itName); + cachedNode = cache.find(currentPosition); + if (cachedNode != cache.end()) + current = cachedNode->second; + + if (itName == name.end()) + return current->getBestClaim(claim); + + nodeMapType::const_iterator itChildren = current->children.find(*itName); + if (itChildren != current->children.end()) { + current = itChildren->second; + } + } + return false; +} + +bool CClaimTrieCache::getProofForName(const std::string& name, CClaimTrieProof& proof) const +{ + if (dirty()) + getMerkleHash(); + std::vector nodes; CClaimTrieNode* current = &(base->root); nodeCacheType::const_iterator cachedNode; @@ -2592,7 +2695,8 @@ CClaimTrieProof CClaimTrieCache::getProofForName(const std::string& name) const if (fNodeHasValue) { int nHeightOfLastTakeover; - assert(getLastTakeoverForName(currentPosition, nHeightOfLastTakeover)); + if (!getLastTakeoverForName(currentPosition, nHeightOfLastTakeover)) + return false; valueHash = getValueHash(claim.outPoint, nHeightOfLastTakeover); } std::vector > children; @@ -2617,7 +2721,8 @@ CClaimTrieProof CClaimTrieCache::getProofForName(const std::string& name) const if (fNameHasValue) { outPoint = claim.outPoint; - assert(getLastTakeoverForName(name, nHeightOfLastTakeover)); + if (!getLastTakeoverForName(name, nHeightOfLastTakeover)) + return false; } valueHash.SetNull(); } @@ -2625,8 +2730,8 @@ CClaimTrieProof CClaimTrieCache::getProofForName(const std::string& name) const nodes.push_back(node); current = nextCurrent; } - return CClaimTrieProof(nodes, fNameHasValue, outPoint, - nHeightOfLastTakeover); + proof = CClaimTrieProof(nodes, fNameHasValue, outPoint, nHeightOfLastTakeover); + return true; } diff --git a/src/claimtrie.h b/src/claimtrie.h index 617232bd7..14a5c0fe3 100644 --- a/src/claimtrie.h +++ b/src/claimtrie.h @@ -323,9 +323,8 @@ public: bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const; claimsForNameType getClaimsForName(const std::string& name) const; - CAmount getEffectiveAmountForClaim(const std::string& name, uint160 claimId) const; - CAmount getEffectiveAmountForClaimWithSupports(const std::string& name, uint160 claimId, - std::vector& supports) const; + CAmount getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector* supports = NULL) const; + CAmount getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector* supports = NULL) const; bool queueEmpty() const; bool supportEmpty() const; @@ -519,7 +518,9 @@ public: bool removeClaimFromTrie(const std::string& name, const COutPoint& outPoint, CClaimValue& claim, bool fCheckTakeover = false) const; - CClaimTrieProof getProofForName(const std::string& name) const; + + bool getProofForName(const std::string& name, CClaimTrieProof& proof) const; + bool getInfoForName(const std::string& name, CClaimValue& claim) const; bool finalizeDecrement() const; @@ -528,6 +529,12 @@ public: bool forkForExpirationChange(bool increment) const; + std::vector flattenTrie() const; + + claimsForNameType getClaimsForName(const std::string& name) const; + + CAmount getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector* supports = NULL) const; + CAmount getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector* supports = NULL) const; protected: CClaimTrie* base; @@ -625,6 +632,10 @@ protected: bool getOriginalInfoForName(const std::string& name, CClaimValue& claim) const; int getNumBlocksOfContinuousOwnership(const std::string& name) const; + + void recursiveFlattenTrie(const std::string& name, const CClaimTrieNode* current, std::vector& nodes) const; + + const CClaimTrieNode* getNodeForName(const std::string& name) const; }; #endif // BITCOIN_CLAIMTRIE_H diff --git a/src/main.cpp b/src/main.cpp index d910d8da8..bde0cd1ba 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4267,40 +4267,43 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, return true; } +bool RollBackTo(const CBlockIndex* targetIndex, CCoinsViewCache& coinsCache, CClaimTrieCache& trieCache) +{ + AssertLockHeld(cs_main); + for (CBlockIndex* index = chainActive.Tip(); index && index != targetIndex; index = index->pprev) { + boost::this_thread::interruption_point(); + CBlock block; + + if (!ReadBlockFromDisk(block, index, Params().GetConsensus())) + return false; // return error() instead? + + if (coinsCache.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage() > nCoinCacheUsage) + return false; // don't allow a single query to chew up all our memory? + + if (ShutdownRequested()) + return false; + + CValidationState state; + if (!DisconnectBlock(block, state, index, coinsCache, trieCache)) + return false; + + if (state.IsError()) + return false; + } + return true; +} + bool GetProofForName(const CBlockIndex* pindexProof, const std::string& name, CClaimTrieProof& proof) { AssertLockHeld(cs_main); if (!chainActive.Contains(pindexProof)) - { return false; - } - CCoinsViewCache coins(pcoinsTip); + + CCoinsViewCache coinsCache(pcoinsTip); CClaimTrieCache trieCache(pclaimTrie); - CBlockIndex* pindexState = chainActive.Tip(); - CValidationState state; - for (CBlockIndex *pindex = chainActive.Tip(); pindex && pindex->pprev && pindexState != pindexProof; pindex=pindex->pprev) - { - boost::this_thread::interruption_point(); - CBlock block; - if (!ReadBlockFromDisk(block, pindex, Params().GetConsensus())) - { - return false; - } - if (pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) - { - bool fClean = true; - if (!DisconnectBlock(block, state, pindex, coins, trieCache, &fClean)) - { - return false; - } - pindexState = pindex->pprev; - } - if (ShutdownRequested()) - return false; - } - assert(pindexState == pindexProof); - proof = trieCache.getProofForName(name); - return true; + if (RollBackTo(pindexProof, coinsCache, trieCache)) + return trieCache.getProofForName(name, proof); + return false; } void UnloadBlockIndex() diff --git a/src/main.h b/src/main.h index 4dfc5b2ca..3c9f845ee 100644 --- a/src/main.h +++ b/src/main.h @@ -225,6 +225,8 @@ FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false); FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false); /** Translation to a filesystem path */ boost::filesystem::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix); +/** Utility method for going back to a previous state **/ +bool RollBackTo(const CBlockIndex* targetIndex, CCoinsViewCache& coinsCache, CClaimTrieCache& trieCache); /** Get a cryptographic proof that a name maps to a value **/ bool GetProofForName(const CBlockIndex* pindexProof, const std::string& name, CClaimTrieProof& proof); /** Import blocks from an external file */ diff --git a/src/rpc/claimtrie.cpp b/src/rpc/claimtrie.cpp index b0b3d0d49..53cd4c3ce 100644 --- a/src/rpc/claimtrie.cpp +++ b/src/rpc/claimtrie.cpp @@ -1,8 +1,10 @@ +#include "boost/scope_exit.hpp" +#include "consensus/validation.h" #include "main.h" #include "nameclaim.h" #include "rpc/server.h" -#include "univalue.h" #include "txmempool.h" +#include "univalue.h" // Maximum block decrement that is allowed from rpc calls const int MAX_RPC_BLOCK_DECREMENTS = 50; @@ -22,143 +24,177 @@ uint160 ParseClaimtrieId(const UniValue& v, const std::string& strName) return result; } +static CBlockIndex* BlockHashIndex(const uint256& blockHash) +{ + AssertLockHeld(cs_main); + + if (mapBlockIndex.count(blockHash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + CBlockIndex* pblockIndex = mapBlockIndex[blockHash]; + if (!chainActive.Contains(pblockIndex)) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not in main chain"); + + if (chainActive.Tip()->nHeight > (pblockIndex->nHeight + MAX_RPC_BLOCK_DECREMENTS)) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Block too deep to regenerate it"); + + return pblockIndex; +} UniValue getclaimsintrie(const UniValue& params, bool fHelp) { - if (fHelp || params.size() > 0) + if (fHelp || params.size() > 1) throw std::runtime_error( "getclaimsintrie\n" "Return all claims in the name trie.\n" "Arguments:\n" - "None\n" + "1. \"blockhash\" (string, optional) get claims in the trie\n" + " at the block specified\n" + " by this block hash.\n" + " If none is given,\n" + " the latest active\n" + " block will be used.\n" "Result: \n" "[\n" " {\n" - " \"name\" (string) the name claimed\n" - " \"claims\": [ (array of object) the claims for this name\n" + " \"name\" (string) the name claimed\n" + " \"claims\": [ (array of object) the claims for this name\n" " {\n" - " \"claimId\" (string) the claimId of the claim\n" - " \"txid\" (string) the txid of the claim\n" - " \"n\" (numeric) the vout value of the claim\n" - " \"amount\" (numeric) txout amount\n" - " \"height\" (numeric) the height of the block in which this transaction is located\n" - " \"value\" (string) the value of this claim\n" + " \"claimId\" (string) the claimId of the claim\n" + " \"txid\" (string) the txid of the claim\n" + " \"n\" (numeric) the vout value of the claim\n" + " \"amount\" (numeric) txout amount\n" + " \"height\" (numeric) the height of the block in which this transaction is located\n" + " \"value\" (string) the value of this claim\n" " }\n" " ]\n" " }\n" - "]\n" - ); - + "]\n"); + LOCK(cs_main); + + CCoinsViewCache coinsCache(pcoinsTip); + CClaimTrieCache trieCache(pclaimTrie); + + if (!params.empty()) { + CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[0], "blockhash (optional parameter 1)")); + if (!RollBackTo(blockIndex, coinsCache, trieCache)) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Rollback failure"); + } + UniValue ret(UniValue::VARR); + std::vector nodes = trieCache.flattenTrie(); + for (std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it) { + if (it->second.claims.empty()) continue; - CCoinsViewCache view(pcoinsTip); - std::vector nodes = pclaimTrie->flattenTrie(); - - for (std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it) - { - if (!it->second.claims.empty()) - { - UniValue node(UniValue::VOBJ); - node.push_back(Pair("name", it->first)); - UniValue claims(UniValue::VARR); - for (std::vector::iterator itClaims = it->second.claims.begin(); itClaims != it->second.claims.end(); ++itClaims) - { - UniValue claim(UniValue::VOBJ); - claim.push_back(Pair("claimId", itClaims->claimId.GetHex())); - claim.push_back(Pair("txid", itClaims->outPoint.hash.GetHex())); - claim.push_back(Pair("n", (int)itClaims->outPoint.n)); - claim.push_back(Pair("amount", ValueFromAmount(itClaims->nAmount))); - claim.push_back(Pair("height", itClaims->nHeight)); - const CCoins* coin = view.AccessCoins(itClaims->outPoint.hash); - if (!coin) - { - LogPrintf("%s: %s does not exist in the coins view, despite being associated with a name\n", - __func__, itClaims->outPoint.hash.GetHex()); - claim.push_back(Pair("error", "No value found for claim")); + UniValue claims(UniValue::VARR); + for (std::vector::iterator itClaims = it->second.claims.begin(); itClaims != it->second.claims.end(); ++itClaims) { + UniValue claim(UniValue::VOBJ); + claim.push_back(Pair("claimId", itClaims->claimId.GetHex())); + claim.push_back(Pair("txid", itClaims->outPoint.hash.GetHex())); + claim.push_back(Pair("n", (int)itClaims->outPoint.n)); + claim.push_back(Pair("amount", ValueFromAmount(itClaims->nAmount))); + claim.push_back(Pair("height", itClaims->nHeight)); + const CCoins* coin = coinsCache.AccessCoins(itClaims->outPoint.hash); + if (!coin) { + LogPrintf("%s: %s does not exist in the coins view, despite being associated with a name\n", + __func__, itClaims->outPoint.hash.GetHex()); + claim.push_back(Pair("error", "No value found for claim")); + } else if (!coin->IsAvailable(itClaims->outPoint.n)) { + LogPrintf("%s: the specified txout of %s appears to have been spent\n", __func__, itClaims->outPoint.hash.GetHex()); + claim.push_back(Pair("error", "Txout spent")); + } else { + int op; + std::vector > vvchParams; + if (!DecodeClaimScript(coin->vout[itClaims->outPoint.n].scriptPubKey, op, vvchParams)) { + LogPrintf("%s: the specified txout of %s does not have an claim command\n", __func__, itClaims->outPoint.hash.GetHex()); } - else if (!coin->IsAvailable(itClaims->outPoint.n)) - { - LogPrintf("%s: the specified txout of %s appears to have been spent\n", __func__, itClaims->outPoint.hash.GetHex()); - claim.push_back(Pair("error", "Txout spent")); - } - else - { - int op; - std::vector > vvchParams; - if (!DecodeClaimScript(coin->vout[itClaims->outPoint.n].scriptPubKey, op, vvchParams)) - { - LogPrintf("%s: the specified txout of %s does not have an claim command\n", __func__, itClaims->outPoint.hash.GetHex()); - } - std::string sValue(vvchParams[1].begin(), vvchParams[1].end()); - claim.push_back(Pair("value", sValue)); - } - claims.push_back(claim); + std::string sValue(vvchParams[1].begin(), vvchParams[1].end()); + claim.push_back(Pair("value", sValue)); } - node.push_back(Pair("claims", claims)); - ret.push_back(node); + claims.push_back(claim); } + + UniValue node(UniValue::VOBJ); + node.push_back(Pair("name", it->first)); + node.push_back(Pair("claims", claims)); + ret.push_back(node); } return ret; } UniValue getclaimtrie(const UniValue& params, bool fHelp) { - if (fHelp || params.size() > 0) + if (fHelp || params.size() > 1) throw std::runtime_error( "getclaimtrie\n" "Return the entire name trie.\n" "Arguments:\n" - "None\n" + "1. \"blockhash\" (string, optional) get claim in the trie\n" + " at the block specified\n" + " by this block hash.\n" + " If none is given,\n" + " the latest active\n" + " block will be used.\n" "Result: \n" - "{\n" + "[\n" + " {\n" " \"name\" (string) the name of the node\n" " \"hash\" (string) the hash of the node\n" " \"txid\" (string) (if value exists) the hash of the transaction which has successfully claimed this name\n" " \"n\" (numeric) (if value exists) vout value\n" " \"value\" (numeric) (if value exists) txout value\n" " \"height\" (numeric) (if value exists) the height of the block in which this transaction is located\n" - "}\n" - ); + " }\n" + "]\n"); LOCK(cs_main); - UniValue ret(UniValue::VARR); - std::vector nodes = pclaimTrie->flattenTrie(); + CCoinsViewCache coinsCache(pcoinsTip); + CClaimTrieCache trieCache(pclaimTrie); + + if (!params.empty()) { + CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[0], "blockhash (optional parameter 1)")); + if (!RollBackTo(blockIndex, coinsCache, trieCache)) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Rollback failure"); + } + + UniValue ret(UniValue::VARR); + std::vector nodes = trieCache.flattenTrie(); for (std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it) { UniValue node(UniValue::VOBJ); - node.push_back(Pair("name", it->first)); + node.push_back(Pair("name", it->first)); node.push_back(Pair("hash", it->second.hash.GetHex())); CClaimValue claim; if (it->second.getBestClaim(claim)) { - node.push_back(Pair("txid", claim.outPoint.hash.GetHex())); - node.push_back(Pair("n", (int)claim.outPoint.n)); - node.push_back(Pair("value", ValueFromAmount(claim.nAmount))); - node.push_back(Pair("height", claim.nHeight)); + node.push_back(Pair("txid", claim.outPoint.hash.GetHex())); + node.push_back(Pair("n", (int)claim.outPoint.n)); + node.push_back(Pair("value", ValueFromAmount(claim.nAmount))); + node.push_back(Pair("height", claim.nHeight)); } ret.push_back(node); } return ret; } -bool getValueForClaim(const COutPoint& out, std::string& sValue) +bool getValueForClaim(const CCoinsViewCache& coinsCache, const COutPoint& out, std::string& sValue) { - CCoinsViewCache view(pcoinsTip); - const CCoins* coin = view.AccessCoins(out.hash); + const CCoins* coin = coinsCache.AccessCoins(out.hash); if (!coin) { LogPrintf("%s: %s does not exist in the coins view, despite being associated with a name\n", __func__, out.hash.GetHex()); return true; } + if(!coin->IsAvailable(out.n)) { LogPrintf("%s: the specified txout of %s appears to have been spent\n", __func__, out.hash.GetHex()); return true; } - + int op; std::vector > vvchParams; if (!DecodeClaimScript(coin->vout[out.n].scriptPubKey, op, vvchParams)) @@ -180,118 +216,113 @@ bool getValueForClaim(const COutPoint& out, std::string& sValue) UniValue getvalueforname(const UniValue& params, bool fHelp) { - if (fHelp || params.size() != 1) + if (fHelp || params.size() > 2) throw std::runtime_error( "getvalueforname \"name\"\n" "Return the value associated with a name, if one exists\n" "Arguments:\n" - "1. \"name\" (string) the name to look up\n" + "1. \"name\" (string) the name to look up\n" + "2. \"blockhash\" (string, optional) get the value\n" + " associated with the name\n" + " at the block specified\n" + " by this block hash.\n" + " If none is given,\n" + " the latest active\n" + " block will be used.\n" "Result: \n" - "\"value\" (string) the value of the name, if it exists\n" - "\"claimId\" (string) the claimId for this name claim\n" - "\"txid\" (string) the hash of the transaction which successfully claimed the name\n" - "\"n\" (numeric) vout value\n" - "\"amount\" (numeric) txout amount\n" - "\"effective amount\" (numeric) txout amount plus amount from all supports associated with the claim\n" - "\"height\" (numeric) the height of the block in which this transaction is located\n" - ); + "\"value\" (string) the value of the name, if it exists\n" + "\"claimId\" (string) the claimId for this name claim\n" + "\"txid\" (string) the hash of the transaction which successfully claimed the name\n" + "\"n\" (numeric) vout value\n" + "\"amount\" (numeric) txout amount\n" + "\"effective amount\" (numeric) txout amount plus amount from all supports associated with the claim\n" + "\"height\" (numeric) the height of the block in which this transaction is located\n"); + LOCK(cs_main); - std::string name = params[0].get_str(); + + CCoinsViewCache coinsCache(pcoinsTip); + CClaimTrieCache trieCache(pclaimTrie); + + if (params.size() > 1) { + CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[1], "blockhash (optional parameter 2)")); + if (!RollBackTo(blockIndex, coinsCache, trieCache)) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Rollback failure"); + } + CClaimValue claim; UniValue ret(UniValue::VOBJ); - if (!pclaimTrie->getInfoForName(name, claim)) - return ret; + std::string name = params[0].get_str(); + if (!trieCache.getInfoForName(name, claim)) + return ret; // they may have asked for a name that doesn't exist (which is not an error) + std::string sValue; - if (!getValueForClaim(claim.outPoint, sValue)) + if (!getValueForClaim(coinsCache, claim.outPoint, sValue)) return ret; + + CAmount nEffectiveAmount = trieCache.getEffectiveAmountForClaim(name, claim.claimId); + ret.push_back(Pair("value", sValue)); ret.push_back(Pair("claimId", claim.claimId.GetHex())); ret.push_back(Pair("txid", claim.outPoint.hash.GetHex())); ret.push_back(Pair("n", (int)claim.outPoint.n)); ret.push_back(Pair("amount", claim.nAmount)); - ret.push_back(Pair("effective amount", pclaimTrie->getEffectiveAmountForClaim(name, claim.claimId))); + ret.push_back(Pair("effective amount", nEffectiveAmount)); ret.push_back(Pair("height", claim.nHeight)); return ret; } typedef std::pair > claimAndSupportsType; typedef std::map claimSupportMapType; -typedef std::map > supportsWithoutClaimsMapType; -UniValue claimsAndSupportsToJSON(claimSupportMapType::const_iterator itClaimsAndSupports, int nCurrentHeight) +UniValue supportToJSON(const CSupportValue& support) +{ + UniValue ret(UniValue::VOBJ); + ret.push_back(Pair("txid", support.outPoint.hash.GetHex())); + ret.push_back(Pair("n", (int)support.outPoint.n)); + ret.push_back(Pair("nHeight", support.nHeight)); + ret.push_back(Pair("nValidAtHeight", support.nValidAtHeight)); + ret.push_back(Pair("nAmount", support.nAmount)); + return ret; +} + +UniValue claimAndSupportsToJSON(CAmount nEffectiveAmount, claimSupportMapType::const_iterator itClaimsAndSupports) { UniValue ret(UniValue::VOBJ); const CClaimValue& claim = itClaimsAndSupports->second.first; const std::vector& supports = itClaimsAndSupports->second.second; - CAmount nEffectiveAmount = 0; UniValue supportObjs(UniValue::VARR); - for (std::vector::const_iterator itSupports = supports.begin(); itSupports != supports.end(); ++itSupports) - { - UniValue supportObj(UniValue::VOBJ); - supportObj.push_back(Pair("txid", itSupports->outPoint.hash.GetHex())); - supportObj.push_back(Pair("n", (int)itSupports->outPoint.n)); - supportObj.push_back(Pair("nHeight", itSupports->nHeight)); - supportObj.push_back(Pair("nValidAtHeight", itSupports->nValidAtHeight)); - if (itSupports->nValidAtHeight < nCurrentHeight) - { - nEffectiveAmount += itSupports->nAmount; - } - supportObj.push_back(Pair("nAmount", itSupports->nAmount)); - supportObjs.push_back(supportObj); + for (std::vector::const_iterator itSupports = supports.begin(); itSupports != supports.end(); ++itSupports) { + supportObjs.push_back(supportToJSON(*itSupports)); } ret.push_back(Pair("claimId", itClaimsAndSupports->first.GetHex())); ret.push_back(Pair("txid", claim.outPoint.hash.GetHex())); ret.push_back(Pair("n", (int)claim.outPoint.n)); ret.push_back(Pair("nHeight", claim.nHeight)); ret.push_back(Pair("nValidAtHeight", claim.nValidAtHeight)); - if (claim.nValidAtHeight < nCurrentHeight) - { - nEffectiveAmount += claim.nAmount; - } ret.push_back(Pair("nAmount", claim.nAmount)); - std::string sValue; - if (getValueForClaim(claim.outPoint, sValue)) - { - ret.push_back(Pair("value", sValue)); - } ret.push_back(Pair("nEffectiveAmount", nEffectiveAmount)); ret.push_back(Pair("supports", supportObjs)); - - return ret; -} - -UniValue supportsWithoutClaimsToJSON(supportsWithoutClaimsMapType::const_iterator itSupportsWithoutClaims, int nCurrentHeight) -{ - const std::vector& supports = itSupportsWithoutClaims->second; - UniValue ret(UniValue::VOBJ); - UniValue supportObjs(UniValue::VARR); - ret.push_back(Pair("claimId (no matching claim)", itSupportsWithoutClaims->first.GetHex())); - for (std::vector::const_iterator itSupports = supports.begin(); itSupports != supports.end(); ++itSupports) - { - UniValue supportObj(UniValue::VOBJ); - supportObj.push_back(Pair("txid", itSupports->outPoint.hash.GetHex())); - supportObj.push_back(Pair("n", (int)itSupports->outPoint.n)); - supportObj.push_back(Pair("nHeight", itSupports->nHeight)); - supportObj.push_back(Pair("nValidAtHeight", itSupports->nValidAtHeight)); - supportObj.push_back(Pair("nAmount", itSupports->nAmount)); - supportObjs.push_back(supportObj); - } - ret.push_back(Pair("supports", supportObjs)); return ret; } UniValue getclaimsforname(const UniValue& params, bool fHelp) { - if (fHelp || params.size() != 1) + if (fHelp || params.size() > 2) throw std::runtime_error( "getclaimsforname\n" "Return all claims and supports for a name\n" "Arguments: \n" - "1. \"name\" (string) the name for which to get claims and supports\n" + "1. \"name\" (string) the name for which to get claims and supports\n" + "2. \"blockhash\" (string, optional) get claims for name\n" + " at the block specified\n" + " by this block hash.\n" + " If none is given,\n" + " the latest active\n" + " block will be used.\n" "Result:\n" "{\n" - " \"nLastTakeoverheight\" (numeric) the last height at which ownership of the name changed\n" - " \"claims\": [ (array of object) claims for this name\n" + " \"nLastTakeoverHeight\" (numeric) the last height at which ownership of the name changed\n" + " \"claims\": [ (array of object) claims for this name\n" " {\n" " \"claimId\" (string) the claimId of this claim\n" " \"txid\" (string) the txid of this claim\n" @@ -318,50 +349,51 @@ UniValue getclaimsforname(const UniValue& params, bool fHelp) " \"nAmount\" (numeric) the amount of the support\n" " }\n" " ]\n" - "}\n" - ); + "}\n"); LOCK(cs_main); - std::string name = params[0].get_str(); - claimsForNameType claimsForName = pclaimTrie->getClaimsForName(name); - int nCurrentHeight = chainActive.Height(); + CCoinsViewCache coinsCache(pcoinsTip); + CClaimTrieCache trieCache(pclaimTrie); + + if (params.size() > 1) { + CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[1], "blockhash (optional parameter 2)")); + if (!RollBackTo(blockIndex, coinsCache, trieCache)) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Rollback failure"); + } + + std::string name = params[0].get_str(); + claimsForNameType claimsForName = trieCache.getClaimsForName(name); + + UniValue claimObjs(UniValue::VARR); claimSupportMapType claimSupportMap; - supportsWithoutClaimsMapType supportsWithoutClaims; - for (std::vector::const_iterator itClaims = claimsForName.claims.begin(); itClaims != claimsForName.claims.end(); ++itClaims) - { + UniValue unmatchedSupports(UniValue::VARR); + + for (std::vector::const_iterator itClaims = claimsForName.claims.begin(); itClaims != claimsForName.claims.end(); ++itClaims) { claimAndSupportsType claimAndSupports = std::make_pair(*itClaims, std::vector()); claimSupportMap.insert(std::pair(itClaims->claimId, claimAndSupports)); } - for (std::vector::const_iterator itSupports = claimsForName.supports.begin(); itSupports != claimsForName.supports.end(); ++itSupports) - { + + for (std::vector::const_iterator itSupports = claimsForName.supports.begin(); itSupports != claimsForName.supports.end(); ++itSupports) { claimSupportMapType::iterator itClaimAndSupports = claimSupportMap.find(itSupports->supportedClaimId); - if (itClaimAndSupports == claimSupportMap.end()) - { - std::pair ret = supportsWithoutClaims.insert(std::pair >(itSupports->supportedClaimId, std::vector())); - ret.first->second.push_back(*itSupports); - } - else - { + if (itClaimAndSupports == claimSupportMap.end()) { + unmatchedSupports.push_back(supportToJSON(*itSupports)); + } else { itClaimAndSupports->second.second.push_back(*itSupports); } } + UniValue ret(UniValue::VOBJ); - UniValue claimObjs(UniValue::VARR); ret.push_back(Pair("nLastTakeoverHeight", claimsForName.nLastTakeoverHeight)); - for (claimSupportMapType::const_iterator itClaimsAndSupports = claimSupportMap.begin(); itClaimsAndSupports != claimSupportMap.end(); ++itClaimsAndSupports) - { - UniValue claimAndSupportsObj = claimsAndSupportsToJSON(itClaimsAndSupports, nCurrentHeight); - claimObjs.push_back(claimAndSupportsObj); + + for (claimSupportMapType::const_iterator itClaimsAndSupports = claimSupportMap.begin(); itClaimsAndSupports != claimSupportMap.end(); ++itClaimsAndSupports) { + CAmount nEffectiveAmount = trieCache.getEffectiveAmountForClaim(claimsForName, itClaimsAndSupports->first); + UniValue claimObj = claimAndSupportsToJSON(nEffectiveAmount, itClaimsAndSupports); + claimObjs.push_back(claimObj); } + ret.push_back(Pair("claims", claimObjs)); - UniValue unmatchedSupports(UniValue::VARR); - for (supportsWithoutClaimsMapType::const_iterator itSupportsWithoutClaims = supportsWithoutClaims.begin(); itSupportsWithoutClaims != supportsWithoutClaims.end(); ++itSupportsWithoutClaims) - { - UniValue supportsObj = supportsWithoutClaimsToJSON(itSupportsWithoutClaims, nCurrentHeight); - unmatchedSupports.push_back(supportsObj); - } - ret.push_back(Pair("supports without claims", unmatchedSupports)); + ret.push_back(Pair("unmatched supports", unmatchedSupports)); return ret; } @@ -403,11 +435,11 @@ UniValue getclaimbyid(const UniValue& params, bool fHelp) if (claimValue.claimId == claimId) { std::vector supports; - CAmount effectiveAmount = pclaimTrie->getEffectiveAmountForClaimWithSupports( - name, claimValue.claimId, supports); + CAmount effectiveAmount = pclaimTrie->getEffectiveAmountForClaim(name, claimValue.claimId, &supports); std::string sValue; - getValueForClaim(claimValue.outPoint, sValue); + CCoinsViewCache coins(pcoinsTip); + getValueForClaim(coins, claimValue.outPoint, sValue); claim.push_back(Pair("name", name)); claim.push_back(Pair("value", sValue)); claim.push_back(Pair("claimId", claimValue.claimId.GetHex())); @@ -448,7 +480,7 @@ UniValue gettotalclaimednames(const UniValue& params, bool fHelp) if (!pclaimTrie) { return -1; - } + } unsigned int num_names = pclaimTrie->getTotalNamesInTrie(); return int(num_names); } @@ -531,7 +563,7 @@ UniValue getclaimsfortx(const UniValue& params, bool fHelp) int op; std::vector > vvchParams; - + CCoinsViewCache view(pcoinsTip); const CCoins* coin = view.AccessCoins(hash); std::vector txouts; @@ -730,7 +762,7 @@ UniValue getnameproof(const UniValue& params, bool fHelp) " this will not\n" " exist whether\n" " the node has a\n" - " value or not\n" + " value or not\n" " ]\n" " \"txhash\" : \"hash\" (string, if exists) the txid of the\n" " claim which controls\n" @@ -749,25 +781,12 @@ UniValue getnameproof(const UniValue& params, bool fHelp) LOCK(cs_main); std::string strName = params[0].get_str(); - uint256 blockHash; - if (params.size() == 2) - { - blockHash = ParseHashV(params[1], "blockhash (optional parameter 2)"); + CBlockIndex* pblockIndex; + if (params.size() == 2) { + pblockIndex = BlockHashIndex(ParseHashV(params[1], "blockhash (optional parameter 2)")); + } else { + pblockIndex = mapBlockIndex[chainActive.Tip()->GetBlockHash()]; } - else - { - blockHash = chainActive.Tip()->GetBlockHash(); - } - - if (mapBlockIndex.count(blockHash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlockIndex* pblockIndex = mapBlockIndex[blockHash]; - if (!chainActive.Contains(pblockIndex)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not in main chain"); - - if (chainActive.Tip()->nHeight > (pblockIndex->nHeight + MAX_RPC_BLOCK_DECREMENTS)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Block too deep to generate proof"); CClaimTrieProof proof; if (!GetProofForName(pblockIndex, strName, proof)) diff --git a/src/test/claimtriebranching_tests.cpp b/src/test/claimtriebranching_tests.cpp index 5e832d629..4caa22c92 100644 --- a/src/test/claimtriebranching_tests.cpp +++ b/src/test/claimtriebranching_tests.cpp @@ -2,21 +2,22 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://opensource.org/licenses/mit-license.php -#include "main.h" -#include "consensus/validation.h" -#include "consensus/merkle.h" -#include "primitives/transaction.h" -#include "miner.h" -#include "txmempool.h" -#include "claimtrie.h" -#include "nameclaim.h" -#include "coins.h" -#include "streams.h" #include "chainparams.h" +#include "claimtrie.h" +#include "coins.h" +#include "consensus/merkle.h" +#include "consensus/validation.h" +#include "main.h" +#include "miner.h" +#include "nameclaim.h" #include "policy/policy.h" +#include "primitives/transaction.h" +#include "rpc/server.h" +#include "streams.h" +#include "test/test_bitcoin.h" +#include "txmempool.h" #include #include -#include "test/test_bitcoin.h" using namespace std; @@ -2931,31 +2932,31 @@ BOOST_AUTO_TEST_CASE(value_proof_test) CClaimTrieProof proof; - proof = cache.getProofForName(sName1); + BOOST_CHECK(cache.getProofForName(sName1, proof)); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName1)); BOOST_CHECK(proof.outPoint == tx1OutPoint); - proof = cache.getProofForName(sName2); + BOOST_CHECK(cache.getProofForName(sName2, proof)); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName2)); BOOST_CHECK(proof.outPoint == tx2OutPoint); - proof = cache.getProofForName(sName3); + BOOST_CHECK(cache.getProofForName(sName3, proof)); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName3)); BOOST_CHECK(proof.outPoint == tx3OutPoint); - proof = cache.getProofForName(sName4); + BOOST_CHECK(cache.getProofForName(sName4, proof)); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName4)); BOOST_CHECK(proof.outPoint == tx4OutPoint); - proof = cache.getProofForName(sName5); + BOOST_CHECK(cache.getProofForName(sName5, proof)); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName5)); BOOST_CHECK(proof.hasValue == false); - proof = cache.getProofForName(sName6); + BOOST_CHECK(cache.getProofForName(sName6, proof)); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName6)); BOOST_CHECK(proof.hasValue == false); - proof = cache.getProofForName(sName7); + BOOST_CHECK(cache.getProofForName(sName7, proof)); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName7)); BOOST_CHECK(proof.hasValue == false); @@ -2969,31 +2970,31 @@ BOOST_AUTO_TEST_CASE(value_proof_test) cache = CClaimTrieCache(pclaimTrie); - proof = cache.getProofForName(sName1); + BOOST_CHECK(cache.getProofForName(sName1, proof)); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName1)); BOOST_CHECK(proof.outPoint == tx1OutPoint); - proof = cache.getProofForName(sName2); + BOOST_CHECK(cache.getProofForName(sName2, proof)); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName2)); BOOST_CHECK(proof.outPoint == tx2OutPoint); - proof = cache.getProofForName(sName3); + BOOST_CHECK(cache.getProofForName(sName3, proof)); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName3)); BOOST_CHECK(proof.outPoint == tx3OutPoint); - proof = cache.getProofForName(sName4); + BOOST_CHECK(cache.getProofForName(sName4, proof)); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName4)); BOOST_CHECK(proof.outPoint == tx4OutPoint); - proof = cache.getProofForName(sName5); + BOOST_CHECK(cache.getProofForName(sName5, proof)); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName5)); BOOST_CHECK(proof.hasValue == false); - proof = cache.getProofForName(sName6); + BOOST_CHECK(cache.getProofForName(sName6, proof)); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName6)); BOOST_CHECK(proof.hasValue == false); - proof = cache.getProofForName(sName7); + BOOST_CHECK(cache.getProofForName(sName7, proof)); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName7)); BOOST_CHECK(proof.outPoint == tx5OutPoint); @@ -3133,4 +3134,222 @@ BOOST_AUTO_TEST_CASE(get_claim_by_id_test_3) BOOST_CHECK(claimValue.claimId == claimId2); } +BOOST_AUTO_TEST_CASE(getclaimsintrie_test) +{ + ClaimTrieChainFixture fixture; + std::string sName1("test"); + std::string sValue1("test"); + std::string sName2("test2"); + std::string sValue2("test2"); + + fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 42); + fixture.IncrementBlocks(1); + + uint256 blockHash = chainActive.Tip()->GetBlockHash(); + + fixture.MakeClaim(fixture.GetCoinbase(), sName2, sValue2, 43); + fixture.IncrementBlocks(1); + + rpcfn_type getclaimsintrie = tableRPC["getclaimsintrie"]->actor; + UniValue params(UniValue::VARR); + + UniValue results = getclaimsintrie(params, false); + BOOST_CHECK(results.size() == 2U); + BOOST_CHECK(results[0]["name"].get_str() == sName1); + BOOST_CHECK(results[1]["name"].get_str() == sName2); + + params.push_back(blockHash.GetHex()); + + results = getclaimsintrie(params, false); + BOOST_CHECK(results.size() == 1U); + BOOST_CHECK(results[0]["name"].get_str() == sName1); +} + +BOOST_AUTO_TEST_CASE(getclaimtrie_test) +{ + ClaimTrieChainFixture fixture; + std::string sName1("test"); + std::string sValue1("test"); + std::string sName2("test2"); + std::string sValue2("test2"); + + int height = chainActive.Height(); + + fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 42); + fixture.IncrementBlocks(1); + + uint256 blockHash = chainActive.Tip()->GetBlockHash(); + + fixture.MakeClaim(fixture.GetCoinbase(), sName2, sValue2, 43); + fixture.IncrementBlocks(1); + + rpcfn_type getclaimtrie = tableRPC["getclaimtrie"]->actor; + UniValue params(UniValue::VARR); + + UniValue results = getclaimtrie(params, false); + BOOST_CHECK(results.size() == 6U); + BOOST_CHECK(results[4]["name"].get_str() == sName1); + BOOST_CHECK(results[5]["name"].get_str() == sName2); + BOOST_CHECK(results[4]["height"].get_int() == height + 1); + BOOST_CHECK(results[5]["height"].get_int() == height + 2); + + params.push_back(blockHash.GetHex()); + + results = getclaimtrie(params, false); + BOOST_CHECK(results.size() == 5U); + BOOST_CHECK(results[4]["name"].get_str() == sName1); + BOOST_CHECK(results[4]["height"].get_int() == height + 1); +} + +BOOST_AUTO_TEST_CASE(getvalueforname_test) +{ + ClaimTrieChainFixture fixture; + std::string sName1("testN"); + std::string sValue1("testV"); + + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 2); + fixture.IncrementBlocks(1); + + uint256 blockHash = chainActive.Tip()->GetBlockHash(); + + fixture.MakeSupport(fixture.GetCoinbase(), tx1, sName1, 3); + fixture.IncrementBlocks(10); + + rpcfn_type getvalueforname = tableRPC["getvalueforname"]->actor; + UniValue params(UniValue::VARR); + params.push_back(UniValue(sName1)); + + UniValue results = getvalueforname(params, false); + BOOST_CHECK(results["value"].get_str() == sValue1); + BOOST_CHECK(results["amount"].get_int() == 2); + BOOST_CHECK(results["effective amount"].get_int() == 5); + + params.push_back(blockHash.GetHex()); + + results = getvalueforname(params, false); + BOOST_CHECK(results["amount"].get_int() == 2); + BOOST_CHECK(results["effective amount"].get_int() == 2); +} + +BOOST_AUTO_TEST_CASE(getclaimsforname_test) +{ + ClaimTrieChainFixture fixture; + std::string sName1("testN"); + std::string sValue1("test1"); + std::string sValue2("test2"); + + int height = chainActive.Height(); + + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 2); + fixture.IncrementBlocks(1); + + uint256 blockHash = chainActive.Tip()->GetBlockHash(); + + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue2, 3); + fixture.IncrementBlocks(1); + + rpcfn_type getclaimsforname = tableRPC["getclaimsforname"]->actor; + UniValue params(UniValue::VARR); + params.push_back(UniValue(sName1)); + + UniValue results = getclaimsforname(params, false); + UniValue claims = results["claims"]; + BOOST_CHECK(claims.size() == 2U); + BOOST_CHECK(results["nLastTakeoverHeight"].get_int() == height + 1); + BOOST_CHECK(claims[0]["nEffectiveAmount"].get_int() == 0); + BOOST_CHECK(claims[1]["nEffectiveAmount"].get_int() == 2); + BOOST_CHECK(claims[0]["supports"].size() == 0U); + BOOST_CHECK(claims[1]["supports"].size() == 0U); + + fixture.IncrementBlocks(1); + + results = getclaimsforname(params, false); + claims = results["claims"]; + BOOST_CHECK(claims.size() == 2U); + BOOST_CHECK(results["nLastTakeoverHeight"].get_int() == height + 3); + BOOST_CHECK(claims[0]["nEffectiveAmount"].get_int() == 3); + BOOST_CHECK(claims[1]["nEffectiveAmount"].get_int() == 2); + BOOST_CHECK(claims[0]["supports"].size() == 0U); + BOOST_CHECK(claims[1]["supports"].size() == 0U); + + params.push_back(blockHash.GetHex()); + + results = getclaimsforname(params, false); + claims = results["claims"]; + BOOST_CHECK(claims.size() == 1U); + BOOST_CHECK(results["nLastTakeoverHeight"].get_int() == height + 1); + BOOST_CHECK(claims[0]["nEffectiveAmount"].get_int() == 2); + BOOST_CHECK(claims[0]["supports"].size() == 0U); +} + +BOOST_AUTO_TEST_CASE(claim_rpcs_rollback2_test) +{ + ClaimTrieChainFixture fixture; + std::string sName1("testN"); + std::string sValue1("test1"); + std::string sValue2("test2"); + + int height = chainActive.Height(); + + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 1); + fixture.IncrementBlocks(2); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue2, 2); + fixture.IncrementBlocks(3); + + uint256 blockHash = chainActive.Tip()->GetBlockHash(); + + CMutableTransaction tx3 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, sValue1, 3); + fixture.IncrementBlocks(1); + + rpcfn_type getclaimsforname = tableRPC["getclaimsforname"]->actor; + rpcfn_type getvalueforname = tableRPC["getvalueforname"]->actor; + + UniValue params(UniValue::VARR); + params.push_back(UniValue(sName1)); + params.push_back(blockHash.GetHex()); + + UniValue claimsResults = getclaimsforname(params, false); + BOOST_CHECK(claimsResults["nLastTakeoverHeight"].get_int() == height + 5); + BOOST_CHECK(claimsResults["claims"][0]["supports"].size() == 0U); + BOOST_CHECK(claimsResults["claims"][1]["supports"].size() == 0U); + + UniValue valueResults = getvalueforname(params, false); + BOOST_CHECK(valueResults["value"].get_str() == sValue2); + BOOST_CHECK(valueResults["amount"].get_int() == 2); +} + +BOOST_AUTO_TEST_CASE(claim_rpcs_rollback3_test) +{ + ClaimTrieChainFixture fixture; + std::string sName1("testN"); + std::string sValue1("test1"); + std::string sValue2("test2"); + + int height = chainActive.Height(); + + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 3); + fixture.IncrementBlocks(1); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue2, 2); + fixture.IncrementBlocks(2); + + uint256 blockHash = chainActive.Tip()->GetBlockHash(); + + CMutableTransaction tx3 = fixture.Spend(tx1); // abandon the claim + fixture.IncrementBlocks(1); + + rpcfn_type getclaimsforname = tableRPC["getclaimsforname"]->actor; + rpcfn_type getvalueforname = tableRPC["getvalueforname"]->actor; + + UniValue params(UniValue::VARR); + params.push_back(UniValue(sName1)); + params.push_back(blockHash.GetHex()); + + UniValue claimsResults = getclaimsforname(params, false); + BOOST_CHECK(claimsResults["nLastTakeoverHeight"].get_int() == height + 1); + + UniValue valueResults = getvalueforname(params, false); + BOOST_CHECK(valueResults["value"].get_str() == sValue1); + BOOST_CHECK(valueResults["amount"].get_int() == 3); +} + BOOST_AUTO_TEST_SUITE_END() -- 2.45.3 From bed577d9cf0568bfe3ed554140b902ae5d23900a Mon Sep 17 00:00:00 2001 From: kay kurokawa Date: Tue, 23 Oct 2018 21:26:50 -0400 Subject: [PATCH 11/25] add some tests for new CClaimTrieCache functions in claimtriecache_tests.cpp --- src/test/claimtriecache_tests.cpp | 49 +++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/test/claimtriecache_tests.cpp b/src/test/claimtriecache_tests.cpp index e94624268..52d0e8fc6 100644 --- a/src/test/claimtriecache_tests.cpp +++ b/src/test/claimtriecache_tests.cpp @@ -1,5 +1,6 @@ #include "claimtrie.h" #include "main.h" +#include "nameclaim.h" #include "uint256.h" #include "test/test_bitcoin.h" @@ -22,6 +23,12 @@ public: { return CClaimTrieCache::recursivePruneName(tnCurrent,nPos,sName, pfNullified); } + + bool insertSupportIntoMap(const std::string& name, CSupportValue support, bool fCheckTakeover) const + { + return CClaimTrieCache::insertSupportIntoMap(name, support, fCheckTakeover); + } + int cacheSize() { return cache.size(); @@ -187,6 +194,48 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test) BOOST_CHECK(pclaimTrie->checkConsistency()); } +BOOST_AUTO_TEST_CASE(basic_insertion_info_test) +{ + // test basic claim insertions and that get methods retreives information properly + BOOST_CHECK(pclaimTrie->empty()); + CClaimTrieCacheTest ctc(pclaimTrie); + + // create and insert claim + CClaimValue unused; + uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); + CMutableTransaction tx1 = BuildTransaction(hash0); + uint160 claimId = ClaimIdHash(tx1.GetHash(), 0); + COutPoint claimOutPoint(tx1.GetHash(), 0); + CAmount amount(10); + int height = 0; + int validHeight = 0; + CClaimValue claimVal(claimOutPoint, claimId, amount, height, validHeight); + ctc.insertClaimIntoTrie("test", claimVal); + + // try getClaimsForName, getEffectiveAmountForClaim, getInfoForName + claimsForNameType res = ctc.getClaimsForName("test"); + BOOST_CHECK(res.claims.size() == 1); + BOOST_CHECK(res.claims[0] == claimVal); + + BOOST_CHECK_EQUAL(10, ctc.getEffectiveAmountForClaim("test", claimId)); + + CClaimValue claim; + BOOST_CHECK(ctc.getInfoForName("test", claim)); + BOOST_CHECK(claim == claimVal); + + // insert a support + CAmount supportAmount(10); + uint256 hash1(uint256S("0000000000000000000000000000000000000000000000000000000000000002")); + CMutableTransaction tx2 = BuildTransaction(hash1); + COutPoint supportOutPoint(tx2.GetHash(), 0); + + CSupportValue support(supportOutPoint, claimId, supportAmount, height, validHeight); + ctc.insertSupportIntoMap("test", support, false); + + // try getEffectiveAmount + BOOST_CHECK_EQUAL(20, ctc.getEffectiveAmountForClaim("test", claimId)); +} + BOOST_AUTO_TEST_CASE(recursive_prune_test) { CClaimTrieCacheTest cc(pclaimTrie); -- 2.45.3 From 0830074e15518d075027ca0c6d84fbd91c21c512 Mon Sep 17 00:00:00 2001 From: Brannon King Date: Wed, 24 Oct 2018 15:27:41 -0600 Subject: [PATCH 12/25] fixed issue with invalid usage of trie's root node in cache --- src/claimtrie.cpp | 35 +++++++-------------------- src/claimtrie.h | 6 +++++ src/rpc/claimtrie.cpp | 2 +- src/test/claimtriebranching_tests.cpp | 26 ++++++++++++++++++++ 4 files changed, 42 insertions(+), 27 deletions(-) diff --git a/src/claimtrie.cpp b/src/claimtrie.cpp index d7fae5fed..f7cefab5c 100644 --- a/src/claimtrie.cpp +++ b/src/claimtrie.cpp @@ -1229,11 +1229,8 @@ uint256 CClaimTrieCache::getMerkleHash() const } if (dirty()) { - nodeCacheType::iterator cachedNode = cache.find(""); - if (cachedNode != cache.end()) - recursiveComputeMerkleHash(cachedNode->second, ""); - else - recursiveComputeMerkleHash(&(base->root), ""); + CClaimTrieNode* root = getRoot(); + recursiveComputeMerkleHash(root, ""); } hashMapType::iterator ithash = cacheHashes.find(""); if (ithash != cacheHashes.end()) @@ -1285,11 +1282,8 @@ bool CClaimTrieCache::getOriginalInfoForName(const std::string& name, CClaimValu bool CClaimTrieCache::insertClaimIntoTrie(const std::string& name, CClaimValue claim, bool fCheckTakeover) const { assert(base); - CClaimTrieNode* currentNode = &(base->root); + CClaimTrieNode* currentNode = getRoot(); nodeCacheType::iterator cachedNode; - cachedNode = cache.find(""); - if (cachedNode != cache.end()) - currentNode = cachedNode->second; for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) { std::string sCurrentSubstring(name.begin(), itCur); @@ -1374,11 +1368,8 @@ bool CClaimTrieCache::insertClaimIntoTrie(const std::string& name, CClaimValue c bool CClaimTrieCache::removeClaimFromTrie(const std::string& name, const COutPoint& outPoint, CClaimValue& claim, bool fCheckTakeover) const { assert(base); - CClaimTrieNode* currentNode = &(base->root); + CClaimTrieNode* currentNode = getRoot(); nodeCacheType::iterator cachedNode; - cachedNode = cache.find(""); - if (cachedNode != cache.end()) - currentNode = cachedNode->second; assert(currentNode != NULL); // If there is no root in either the trie or the cache, how can there be any names to remove? for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) { @@ -1448,10 +1439,7 @@ bool CClaimTrieCache::removeClaimFromTrie(const std::string& name, const COutPoi if (fCheckTakeover) namesToCheckForTakeover.insert(name); } - CClaimTrieNode* rootNode = &(base->root); - cachedNode = cache.find(""); - if (cachedNode != cache.end()) - rootNode = cachedNode->second; + CClaimTrieNode* rootNode = getRoot(); return recursivePruneName(rootNode, 0, name); } @@ -1752,12 +1740,7 @@ bool CClaimTrieCache::reorderTrieNode(const std::string& name, bool fCheckTakeov cachedNode = cache.find(name); if (cachedNode == cache.end()) { - CClaimTrieNode* currentNode; - cachedNode = cache.find(""); - if(cachedNode == cache.end()) - currentNode = &(base->root); - else - currentNode = cachedNode->second; + CClaimTrieNode* currentNode = getRoot(); for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) { std::string sCurrentSubstring(name.begin(), itCur); @@ -2575,7 +2558,7 @@ void CClaimTrieCache::recursiveFlattenTrie(const std::string& name, const CClaim std::vector CClaimTrieCache::flattenTrie() const { std::vector nodes; - recursiveFlattenTrie("", &(base->root), nodes); + recursiveFlattenTrie("", getRoot(), nodes); return nodes; } @@ -2652,7 +2635,7 @@ bool CClaimTrieCache::getInfoForName(const std::string& name, CClaimValue& claim if (dirty()) getMerkleHash(); - CClaimTrieNode* current = &(base->root); + CClaimTrieNode* current = getRoot(); nodeCacheType::const_iterator cachedNode; for (std::string::const_iterator itName = name.begin(); current; ++itName) { @@ -2678,7 +2661,7 @@ bool CClaimTrieCache::getProofForName(const std::string& name, CClaimTrieProof& getMerkleHash(); std::vector nodes; - CClaimTrieNode* current = &(base->root); + CClaimTrieNode* current = getRoot(); nodeCacheType::const_iterator cachedNode; bool fNameHasValue = false; COutPoint outPoint; diff --git a/src/claimtrie.h b/src/claimtrie.h index 14a5c0fe3..ae3c88dac 100644 --- a/src/claimtrie.h +++ b/src/claimtrie.h @@ -476,6 +476,12 @@ public: bool flush(); bool dirty() const { return !dirtyHashes.empty(); } + CClaimTrieNode* getRoot() const + { + nodeCacheType::iterator iter = cache.find(""); + return iter == cache.end() ? &(base->root) : iter->second; + } + bool addClaim(const std::string& name, const COutPoint& outPoint, uint160 claimId, CAmount nAmount, int nHeight) const; bool undoAddClaim(const std::string& name, const COutPoint& outPoint, diff --git a/src/rpc/claimtrie.cpp b/src/rpc/claimtrie.cpp index 53cd4c3ce..1ce579de1 100644 --- a/src/rpc/claimtrie.cpp +++ b/src/rpc/claimtrie.cpp @@ -36,7 +36,7 @@ static CBlockIndex* BlockHashIndex(const uint256& blockHash) throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not in main chain"); if (chainActive.Tip()->nHeight > (pblockIndex->nHeight + MAX_RPC_BLOCK_DECREMENTS)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Block too deep to regenerate it"); + throw JSONRPCError(RPC_INTERNAL_ERROR, "Block is too deep"); return pblockIndex; } diff --git a/src/test/claimtriebranching_tests.cpp b/src/test/claimtriebranching_tests.cpp index 4caa22c92..f02c79371 100644 --- a/src/test/claimtriebranching_tests.cpp +++ b/src/test/claimtriebranching_tests.cpp @@ -3165,6 +3165,32 @@ BOOST_AUTO_TEST_CASE(getclaimsintrie_test) BOOST_CHECK(results[0]["name"].get_str() == sName1); } +BOOST_AUTO_TEST_CASE(getclaimsintrie_test2) +{ + ClaimTrieChainFixture fixture; + std::string sName1("test"); + std::string sValue1("test"); + + uint256 blockHash = chainActive.Tip()->GetBlockHash(); + + rpcfn_type getclaimsintrie = tableRPC["getclaimsintrie"]->actor; + rpcfn_type getclaimtrie = tableRPC["getclaimtrie"]->actor; + UniValue params(UniValue::VARR); + params.push_back(blockHash.GetHex()); + UniValue results = getclaimsintrie(params, false); + BOOST_CHECK(results.size() == 0U); + results = getclaimtrie(params, false); + BOOST_CHECK(results.size() == 1U); + + fixture.IncrementBlocks(10); + fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 42); + fixture.IncrementBlocks(10); + results = getclaimsintrie(params, false); + BOOST_CHECK(results.size() == 0U); + results = getclaimtrie(params, false); + BOOST_CHECK(results.size() == 1U); +} + BOOST_AUTO_TEST_CASE(getclaimtrie_test) { ClaimTrieChainFixture fixture; -- 2.45.3 From cccdce02df1250fe1a1e425a8735834504f30fcc Mon Sep 17 00:00:00 2001 From: Kent <41596906+preserveddarnell@users.noreply.github.com> Date: Sat, 20 Oct 2018 17:24:39 -0400 Subject: [PATCH 13/25] Update README.md --- README.md | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index a9f8d06f7..3aa30cb02 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ LBRYcrd uses a blockchain similar to bitcoin's to implement an index and payment ## Installation -Latest binaries are available from https://github.com/lbryio/lbrycrd/releases. There is no installation procedure, the binaries run as is. +Latest binaries are available from https://github.com/lbryio/lbrycrd/releases. There is no installation procedure, the binaries will be run as-is. ## Usage @@ -18,13 +18,13 @@ the "--help" flag (e.g. `lbrycrd-cli --help`). Run `./lbrycrdd -server -daemon` to start lbrycrdd in the background. -Run `./lbrycrd-cli getinfo` to check for some basic informations about your LBRYcrd node. +Run `./lbrycrd-cli getinfo` to check for some basic information about your LBRYcrd node. Run `./lbrycrd-cli help` to get a list of all commands that you can run. To get help on specific commands run `./lbrycrd-cli [command_name] help` ### Data directory -Lbrycrdd will use the below default data directories +Lbrycrdd will use the below default data directories: Windows < Vista: C:\Documents and Settings\Username\Application Data\lbrycrd @@ -34,9 +34,9 @@ Mac: ~/Library/Application Support/lbrycrd Unix: ~/.lbrycrd -The data directory contains various things such as your default wallet (wallet.dat), debug logs (debug.log), and blockchain data. You can optionally -create a configuration file lbrycrd.conf in the default data directory which will be used by default when running lbrycrdd. -For a list of configuration parameters run `./lbrycrdd --help`. Below is a sample lbrycrd.conf to enable JSON RPC server on lbrycrdd. +The data directory contains various things such as your default wallet (wallet.dat), debug logs (debug.log), and blockchain data. You can optionally create a configuration file lbrycrd.conf in the default data directory which will be used by default when running lbrycrdd. + +For a list of configuration parameters, run `./lbrycrdd --help`. Below is a sample lbrycrd.conf to enable JSON RPC server on lbrycrdd. ```rpcuser=lbry rpcpassword=xyz123456790 @@ -55,12 +55,10 @@ If you encounter any errors, please check `doc/build-*.md` for further instructi Contributions to this project are welcome, encouraged, and compensated. For more details, see [lbry.io/faq/contributing](https://lbry.io/faq/contributing) -The codebase is in C++03, C++11 is currently not supported but we will be migrating to it in the near future. Recommended GCC version is 4.8 or greater. +The codebase is in C++03. C++11 is currently not supported but we will be migrating to it in the near future. Recommended GCC version is 4.8 or greater. We follow the same coding guidelines as documented by Bitcoin Core, see [here](/doc/developer-notes.md). To run an automated code formatting check, try: `git diff -U0 master -- '*.h' '*.cpp' | ./contrib/devtools/clang-format-diff.py -p1`. This will check any commits not on master for proper code formatting. -We try to avoid altering parts of the code that is inherited from Bitcoin Core unless absolutely necessary. This will make it easier to merge changes from -Bitcoin Core. If commits are expected not to be merged upstream (i.e. we broke up a commit from Bitcoin Core in order to use a single feature in it), the commit -message must contain the string "NOT FOR UPSTREAM MERGE". +We try to avoid altering parts of the code that is inherited from Bitcoin Core unless absolutely necessary. This will make it easier to merge changes from Bitcoin Core. If commits are expected not to be merged upstream (i.e. we broke up a commit from Bitcoin Core in order to use a single feature in it), the commit message must contain the string "NOT FOR UPSTREAM MERGE". The `master` branch is regularly built and tested, but is not guaranteed to be completely stable. [Releases](https://github.com/lbryio/lbrycrd/releases) are created @@ -77,7 +75,7 @@ The Travis CI system makes sure that every pull request is built, and that unit ### Testnet -Testnet is maintained for testing purposes and can be accessed using the command `./lbrycrdd -testnet`. If you would like testnet credits, please contact kay@lbry.io or grin@lbry.io. +Testnet is maintained for testing purposes and can be accessed using the command `./lbrycrdd -testnet`. If you would like to obtain testnet credits, please contact kay@lbry.io or grin@lbry.io. ## License -- 2.45.3 From 15be5dacce5db4923c694ae5d2cfd641c9b7840b Mon Sep 17 00:00:00 2001 From: Ariel Rodriguez Date: Thu, 8 Nov 2018 19:29:28 -0300 Subject: [PATCH 14/25] Remove unnecessary height field in removeClaim method --- contrib/devtools/clang-format-diff.py | 3 +- src/claimtrie.cpp | 30 ++--- src/claimtrie.h | 14 +- src/main.cpp | 23 ++-- src/miner.cpp | 11 +- src/test/claimtriebranching_tests.cpp | 180 +++++++++++++++----------- 6 files changed, 138 insertions(+), 123 deletions(-) diff --git a/contrib/devtools/clang-format-diff.py b/contrib/devtools/clang-format-diff.py index 13d2573b9..b0dd9f59a 100755 --- a/contrib/devtools/clang-format-diff.py +++ b/contrib/devtools/clang-format-diff.py @@ -144,7 +144,8 @@ def main(): command.extend(lines) command.extend(['-style=file', '-fallback-style=none']) p = subprocess.Popen(command, stdout=subprocess.PIPE, - stderr=None, stdin=subprocess.PIPE) + stderr=None, + stdin=subprocess.PIPE) stdout, stderr = p.communicate() if p.returncode != 0: sys.exit(p.returncode); diff --git a/src/claimtrie.cpp b/src/claimtrie.cpp index f7cefab5c..172aa35ba 100644 --- a/src/claimtrie.cpp +++ b/src/claimtrie.cpp @@ -151,7 +151,7 @@ template bool CClaimTrie::keyTypeEmpty(char keyType, K& dummy) const { boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); pcursor->SeekToFirst(); - + while (pcursor->Valid()) { std::pair key; @@ -1197,7 +1197,7 @@ bool CClaimTrieCache::recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent, std: vchToHash.insert(vchToHash.end(), it->second->hash.begin(), it->second->hash.end()); } } - + CClaimValue claim; bool hasClaim = tnCurrent->getBestClaim(claim); @@ -1301,7 +1301,7 @@ bool CClaimTrieCache::insertClaimIntoTrie(const std::string& name, CClaimValue c currentNode = childNode->second; continue; } - + // This next substring doesn't exist in the cache and the next // character doesn't exist in current node's children, so check // if the current node is in the cache, and if it's not, copy @@ -1402,7 +1402,7 @@ bool CClaimTrieCache::removeClaimFromTrie(const std::string& name, const COutPoi bool fChanged = false; assert(currentNode != NULL); bool success = false; - + if (currentNode->claims.empty()) { LogPrintf("%s: Asked to remove claim from node without claims\n", __func__); @@ -1478,7 +1478,7 @@ bool CClaimTrieCache::recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int // tnCurrent isn't necessarily in the cache. If it's not, it // has to be added to the cache, so nothing is changed in the // trie. If the current node is added to the cache, however, - // that does not imply that the parent node must be altered to + // that does not imply that the parent node must be altered to // reflect that its child is now in the cache, since it // already has a character in its child map which will be used // when calculating the merkle root. @@ -1653,20 +1653,20 @@ bool CClaimTrieCache::removeClaimFromQueue(const std::string& name, const COutPo return false; } -bool CClaimTrieCache::undoAddClaim(const std::string& name, const COutPoint& outPoint, int nHeight) const +bool CClaimTrieCache::undoAddClaim(const std::string& name, const COutPoint& outPoint) const { int throwaway; - return removeClaim(name, outPoint, nHeight, throwaway, false); + return removeClaim(name, outPoint, throwaway, false); } -bool CClaimTrieCache::spendClaim(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight) const +bool CClaimTrieCache::spendClaim(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const { - return removeClaim(name, outPoint, nHeight, nValidAtHeight, true); + return removeClaim(name, outPoint, nValidAtHeight, true); } -bool CClaimTrieCache::removeClaim(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight, bool fCheckTakeover) const +bool CClaimTrieCache::removeClaim(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight, bool fCheckTakeover) const { - LogPrintf("%s: name: %s, txhash: %s, nOut: %s, nHeight: %s, nCurrentHeight: %s\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nHeight, nCurrentHeight); + LogPrintf("%s: name: %s, txhash: %s, nOut: %s, nCurrentHeight: %s\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nCurrentHeight); bool removed = false; CClaimValue claim; if (removeClaimFromQueue(name, outPoint, claim)) @@ -1680,7 +1680,7 @@ bool CClaimTrieCache::removeClaim(const std::string& name, const COutPoint& outP if (removed == true) { nValidAtHeight = claim.nValidAtHeight; - int expirationHeight = nHeight + base->nExpirationTime; + int expirationHeight = claim.nHeight + base->nExpirationTime; removeFromExpirationQueue(name, outPoint, expirationHeight); claimsToDelete.insert(claim); } @@ -2184,7 +2184,7 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy itSupportExpirationRow->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 + // 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 @@ -2275,7 +2275,7 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy // remove all claims from the queue for that name itQueueNameRow->second.clear(); } - // + // // Then, get all supports in the queue for that name queueNameType::iterator itSupportQueueNameRow = getSupportQueueCacheNameRow(*itNamesToCheck, false); if (itSupportQueueNameRow != supportQueueNameCache.end()) @@ -2390,7 +2390,7 @@ bool CClaimTrieCache::decrementBlock(insertUndoType& insertUndo, claimQueueRowTy assert(removeClaimFromTrie(itInsertUndo->name, itInsertUndo->outPoint, claim, false)); queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(itInsertUndo->name, true); itQueueRow->second.push_back(std::make_pair(itInsertUndo->name, claim)); - itQueueNameRow->second.push_back(outPointHeightType(itInsertUndo->outPoint, itInsertUndo->nHeight)); + itQueueNameRow->second.push_back(outPointHeightType(itInsertUndo->outPoint, itInsertUndo->nHeight)); } for (std::vector >::iterator itTakeoverHeightUndo = takeoverHeightUndo.begin(); itTakeoverHeightUndo != takeoverHeightUndo.end(); ++itTakeoverHeightUndo) diff --git a/src/claimtrie.h b/src/claimtrie.h index ae3c88dac..9d75a5d22 100644 --- a/src/claimtrie.h +++ b/src/claimtrie.h @@ -212,7 +212,6 @@ struct nameOutPointHeightType nameOutPointHeightType(std::string name, COutPoint outPoint, int nHeight) : name(name), outPoint(outPoint), nHeight(nHeight) {} - ADD_SERIALIZE_METHODS; template @@ -323,6 +322,7 @@ public: bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const; claimsForNameType getClaimsForName(const std::string& name) const; + CAmount getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector* supports = NULL) const; CAmount getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector* supports = NULL) const; @@ -484,10 +484,8 @@ public: bool addClaim(const std::string& name, const COutPoint& outPoint, uint160 claimId, CAmount nAmount, int nHeight) const; - bool undoAddClaim(const std::string& name, const COutPoint& outPoint, - int nHeight) const; - bool spendClaim(const std::string& name, const COutPoint& outPoint, - int nHeight, int& nValidAtHeight) const; + bool undoAddClaim(const std::string& name, const COutPoint& outPoint) const; + bool spendClaim(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const; bool undoSpendClaim(const std::string& name, const COutPoint& outPoint, uint160 claimId, CAmount nAmount, int nHeight, int nValidAtHeight) const; @@ -559,7 +557,7 @@ protected: mutable queueNameType supportQueueNameCache; mutable expirationQueueType supportExpirationQueueCache; mutable std::set namesToCheckForTakeover; - mutable std::map cacheTakeoverHeights; + mutable std::map cacheTakeoverHeights; mutable int nCurrentHeight; // Height of the block that is being worked on, which is // one greater than the height of the chain's tip mutable claimIndexElementListType claimsToAdd; @@ -578,9 +576,7 @@ protected: bool clear() const; - bool removeClaim(const std::string& name, const COutPoint& outPoint, - int nHeight, int& nValidAtHeight, bool fCheckTakeover) const; - + bool removeClaim(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight, bool fCheckTakeover) const; bool addClaimToQueues(const std::string& name, CClaimValue& claim) const; bool removeClaimFromQueue(const std::string& name, const COutPoint& outPoint, CClaimValue& claim) const; diff --git a/src/main.cpp b/src/main.cpp index bde0cd1ba..e313a4957 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -963,13 +963,12 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state) if (!MoneyRange(nValueOut)) return state.DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge"); - // check claimtrie transactions + // check claimtrie transactions if (ClaimScriptSize(txout.scriptPubKey) > MAX_CLAIM_SCRIPT_SIZE) return state.DoS(100, false, REJECT_INVALID, "bad-txns-claimscriptsize-toolarge"); - if (ClaimNameSize(txout.scriptPubKey) > MAX_CLAIM_NAME_SIZE) + if (ClaimNameSize(txout.scriptPubKey) > MAX_CLAIM_NAME_SIZE) return state.DoS(100, false, REJECT_INVALID, "bad-txns-claimscriptname-toolarge"); - } // Check for duplicate inputs @@ -2194,8 +2193,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI } std::string name(vvchParams[0].begin(), vvchParams[0].end()); LogPrintf("%s: (txid: %s, nOut: %d) Trying to remove %s from the claim trie due to its block being disconnected\n", __func__, hash.ToString(), i, name.c_str()); - if (!trieCache.undoAddClaim(name, COutPoint(hash, i), pindex->nHeight)) - { + if (!trieCache.undoAddClaim(name, COutPoint(hash, i))) { LogPrintf("%s: Could not find the claim in the trie or the cache\n", __func__); } } @@ -2503,7 +2501,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY; nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE; } - + // v 13 LBRYcrd hard fork to extend expiration time if (pindex->nHeight == Params().GetConsensus().nExtendedClaimExpirationForkHeight) { @@ -2588,7 +2586,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin typedef std::vector > spentClaimsType; spentClaimsType spentClaims; - + for (unsigned int i = 0; i < tx.vin.size(); ++i) { const CTxIn& txin = tx.vin[i]; @@ -2625,8 +2623,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin std::string name(vvchParams[0].begin(), vvchParams[0].end()); int nValidAtHeight; LogPrintf("%s: Removing %s from the claim trie. Tx: %s, nOut: %d\n", __func__, name, txin.prevout.hash.GetHex(), txin.prevout.n); - if (trieCache.spendClaim(name, COutPoint(txin.prevout.hash, txin.prevout.n), coins->nHeight, nValidAtHeight)) - { + if (trieCache.spendClaim(name, COutPoint(txin.prevout.hash, txin.prevout.n), nValidAtHeight)) { mClaimUndoHeights[i] = nValidAtHeight; std::pair entry(name, claimId); spentClaims.push_back(entry); @@ -2649,7 +2646,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } } } - + for (unsigned int i = 0; i < tx.vout.size(); ++i) { const CTxOut& txout = tx.vout[i]; @@ -4218,8 +4215,8 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); // check level 1: verify block validity if (nCheckLevel >= 1 && !CheckBlock(block, state)) - return error("%s: *** found bad block at %d, hash=%s (%s)\n", __func__, - pindex->nHeight, pindex->GetBlockHash().ToString(), FormatStateMessage(state)); + return error("%s: *** found bad block at %d, hash=%s (%s)\n", __func__, + pindex->nHeight, pindex->GetBlockHash().ToString(), FormatStateMessage(state)); // check level 2: verify undo validity if (nCheckLevel >= 2 && pindex) { CBlockUndo undo; @@ -4348,7 +4345,7 @@ bool LoadBlockIndex() return true; } -bool InitBlockIndex(const CChainParams& chainparams) +bool InitBlockIndex(const CChainParams& chainparams) { LOCK(cs_main); diff --git a/src/miner.cpp b/src/miner.cpp index 8136d8e80..bfa5613e1 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -294,8 +294,7 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s } std::string name(vvchParams[0].begin(), vvchParams[0].end()); int throwaway; - if (trieCache.spendClaim(name, COutPoint(txin.prevout.hash, txin.prevout.n), nTxinHeight, throwaway)) - { + if (trieCache.spendClaim(name, COutPoint(txin.prevout.hash, txin.prevout.n), throwaway)) { std::pair entry(name, claimId); spentClaims.push_back(entry); } @@ -316,11 +315,11 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s } } } - + for (unsigned int i = 0; i < tx.vout.size(); ++i) { const CTxOut& txout = tx.vout[i]; - + std::vector > vvchParams; int op; if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams)) @@ -568,7 +567,7 @@ void static BitcoinMiner(const CChainParams& chainparams) while (true) { unsigned int nHashesDone = 0; - + // Check if something found while (true) { @@ -599,7 +598,7 @@ void static BitcoinMiner(const CChainParams& chainparams) } if (found) break; - + // Meter hashes/sec static int64_t nHashCounter; if (nHPSTimerStart == 0) diff --git a/src/test/claimtriebranching_tests.cpp b/src/test/claimtriebranching_tests.cpp index f02c79371..8d7f0f706 100644 --- a/src/test/claimtriebranching_tests.cpp +++ b/src/test/claimtriebranching_tests.cpp @@ -24,37 +24,37 @@ using namespace std; BOOST_FIXTURE_TEST_SUITE(claimtriebranching_tests, RegTestingSetup) -//is a claim in queue +//is a claim in queue boost::test_tools::predicate_result is_claim_in_queue(std::string name, const CTransaction &tx) { COutPoint outPoint(tx.GetHash(), 0); - int validAtHeight; - bool have_claim = pclaimTrie->haveClaimInQueue(name,outPoint,validAtHeight); + int validAtHeight; + bool have_claim = pclaimTrie->haveClaimInQueue(name, outPoint, validAtHeight); if (have_claim){ return true; } else{ boost::test_tools::predicate_result res(false); - res.message()<<"Is not a claim in queue."; + res.message() << "Is not a claim in queue."; return res; } } -// check if tx is best claim based on outpoint +// check if tx is best claim based on outpoint boost::test_tools::predicate_result is_best_claim(std::string name, const CTransaction &tx) { CClaimValue val; COutPoint outPoint(tx.GetHash(), 0); - bool have_claim = pclaimTrie->haveClaim(name,outPoint); + bool have_claim = pclaimTrie->haveClaim(name, outPoint); bool have_info = pclaimTrie->getInfoForName(name, val); if (have_claim && have_info && val.outPoint == outPoint){ return true; } else{ boost::test_tools::predicate_result res(false); - res.message()<<"Is not best claim"; + res.message() << "Is not best claim"; return res; } } @@ -154,13 +154,13 @@ bool CreateCoinbases(unsigned int num_coinbases, std::vector& coin } -// Test Fixtures +// Test Fixtures struct ClaimTrieChainFixture{ std::vector coinbase_txs; std::vector marks; - int coinbase_txs_used; - unsigned int num_txs; - unsigned int num_txs_for_next_block; + int coinbase_txs_used; + unsigned int num_txs; + unsigned int num_txs_for_next_block; // these will take on regtest parameters const int expirationForkHeight; @@ -177,7 +177,7 @@ struct ClaimTrieChainFixture{ ENTER_CRITICAL_SECTION(cs_main); BOOST_CHECK(pclaimTrie->nCurrentHeight == chainActive.Height() + 1); num_txs_for_next_block = 0; - num_txs = 0; + num_txs = 0; coinbase_txs_used = 0; // generate coinbases to spend CreateCoinbases(40, coinbase_txs); @@ -205,30 +205,29 @@ struct ClaimTrieChainFixture{ BOOST_CHECK(AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, &txFeeRate)); } - //spend a bid into some non claimtrie related unspent + //spend a bid into some non claimtrie related unspent CMutableTransaction Spend(const CTransaction &prev){ uint32_t prevout = 0; - CMutableTransaction tx = BuildTransaction(prev,prevout); + CMutableTransaction tx = BuildTransaction(prev, prevout); tx.vout[0].scriptPubKey = CScript() << OP_TRUE; tx.vout[0].nValue = 1; - CommitTx(tx); - return tx; + CommitTx(tx); + return tx; } //make claim at the current block - CMutableTransaction MakeClaim(const CTransaction &prev, std::string name, std::string value, - CAmount quantity) + CMutableTransaction MakeClaim(const CTransaction& prev, std::string name, std::string value, CAmount quantity) { - uint32_t prevout = 0; + uint32_t prevout = 0; CMutableTransaction tx = BuildTransaction(prev,prevout); - tx.vout[0].scriptPubKey = ClaimNameScript(name,value); + tx.vout[0].scriptPubKey = ClaimNameScript(name, value); tx.vout[0].nValue = quantity; - CommitTx(tx); - return tx; + CommitTx(tx); + return tx; } CMutableTransaction MakeClaim(const CTransaction& prev, std::string name, std::string value) @@ -243,10 +242,10 @@ struct ClaimTrieChainFixture{ uint32_t prevout = 0; CMutableTransaction tx = BuildTransaction(prev,prevout); - tx.vout[0].scriptPubKey = SupportClaimScript(name,claimId); + tx.vout[0].scriptPubKey = SupportClaimScript(name, claimId); tx.vout[0].nValue = quantity; - CommitTx(tx); + CommitTx(tx); return tx; } @@ -257,10 +256,10 @@ struct ClaimTrieChainFixture{ uint32_t prevout = 0; CMutableTransaction tx = BuildTransaction(prev,prevout); - tx.vout[0].scriptPubKey = UpdateClaimScript(name,claimId,value); + tx.vout[0].scriptPubKey = UpdateClaimScript(name, claimId, value); tx.vout[0].nValue = quantity; - CommitTx(tx); + CommitTx(tx); return tx; } @@ -280,7 +279,7 @@ struct ClaimTrieChainFixture{ for (int i = 0; i < num_blocks; ++i) { CBlockTemplate *pblocktemplate; - CScript coinbase_scriptpubkey; + CScript coinbase_scriptpubkey; coinbase_scriptpubkey << CScriptNum(chainActive.Height()); BOOST_CHECK(pblocktemplate = CreateNewBlock(Params(), coinbase_scriptpubkey)); BOOST_CHECK(pblocktemplate->block.vtx.size() == num_txs_for_next_block+1); @@ -338,8 +337,8 @@ struct ClaimTrieChainFixture{ there is a competing bid inserted same height check the greater one wins - quantity is same, check outpoint greater wins - there is an existing competing bid - check that rules for delays are observed + there is an existing competing bid + check that rules for delays are observed check that a greater amount wins check that a smaller amount does not win @@ -354,7 +353,7 @@ BOOST_AUTO_TEST_CASE(claim_test) fixture.DecrementBlocks(1); BOOST_CHECK(!is_best_claim("test",tx1)); - + // there is a competing bid inserted same height CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); @@ -362,34 +361,34 @@ BOOST_AUTO_TEST_CASE(claim_test) BOOST_CHECK(is_best_claim("test",tx3)); BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); - fixture.DecrementBlocks(1); + fixture.DecrementBlocks(1); BOOST_CHECK(!is_best_claim("test",tx2)); BOOST_CHECK(!is_best_claim("test",tx3)); BOOST_CHECK_EQUAL(0U, pclaimTrie->getClaimsForName("test").claims.size()); - // make two claims , one older + // make two claims , one older CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - fixture.IncrementBlocks(1); + fixture.IncrementBlocks(1); BOOST_CHECK(is_best_claim("test",tx4)); CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(),"test","two",1); fixture.IncrementBlocks(1); BOOST_CHECK(is_claim_in_queue("test",tx5)); - BOOST_CHECK(is_best_claim("test",tx4)); + BOOST_CHECK(is_best_claim("test", tx4)); fixture.IncrementBlocks(1); BOOST_CHECK(is_best_claim("test",tx4)); BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); - fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx4)); + fixture.DecrementBlocks(1); + BOOST_CHECK(is_best_claim("test", tx4)); BOOST_CHECK(is_claim_in_queue("test",tx5)); - fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx4)); + fixture.DecrementBlocks(1); + BOOST_CHECK(is_best_claim("test", tx4)); fixture.DecrementBlocks(1); // check claim takeover, note that CClaimTrie.nProportionalDelayFactor is set to 1 // instead of 32 in test_bitcoin.cpp CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - fixture.IncrementBlocks(10); + fixture.IncrementBlocks(10); BOOST_CHECK(is_best_claim("test",tx6)); CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(),"test","two",2); fixture.IncrementBlocks(1); @@ -401,7 +400,7 @@ BOOST_AUTO_TEST_CASE(claim_test) fixture.DecrementBlocks(10); BOOST_CHECK(is_claim_in_queue("test",tx7)); - BOOST_CHECK(is_best_claim("test",tx6)); + BOOST_CHECK(is_best_claim("test", tx6)); fixture.DecrementBlocks(1); BOOST_CHECK(is_best_claim("test",tx6)); fixture.DecrementBlocks(10); @@ -409,26 +408,26 @@ BOOST_AUTO_TEST_CASE(claim_test) /* spent claims - spending winning claim will make losing active claim winner + spending winning claim will make losing active claim winner spending winning claim will make inactive claim winner - spending winning claim will empty out claim trie + spending winning claim will empty out claim trie */ BOOST_AUTO_TEST_CASE(spend_claim_test) { ClaimTrieChainFixture fixture; - // spending winning claim will make losing active claim winner + // spending winning claim will make losing active claim winner CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx1)); + BOOST_CHECK(is_best_claim("test", tx1)); fixture.Spend(tx1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx2)); - + BOOST_CHECK(is_best_claim("test", tx2)); + + fixture.DecrementBlocks(1); + BOOST_CHECK(is_best_claim("test", tx1)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx1)); - fixture.DecrementBlocks(1); // spending winning claim will make inactive claim winner @@ -436,7 +435,7 @@ BOOST_AUTO_TEST_CASE(spend_claim_test) fixture.IncrementBlocks(10); BOOST_CHECK(is_best_claim("test",tx3)); CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); - fixture.IncrementBlocks(1); + fixture.IncrementBlocks(1); BOOST_CHECK(is_best_claim("test",tx3)); fixture.Spend(tx3); fixture.IncrementBlocks(1); @@ -449,7 +448,7 @@ BOOST_AUTO_TEST_CASE(spend_claim_test) fixture.DecrementBlocks(10); - //spending winning claim will empty out claim trie + //spending winning claim will empty out claim trie CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); fixture.IncrementBlocks(1); BOOST_CHECK(is_best_claim("test",tx5)); @@ -466,14 +465,14 @@ BOOST_AUTO_TEST_CASE(spend_claim_test) /* supports - check support with wrong name does not work + check support with wrong name does not work check claim with more support wins - check support delay + check support delay */ BOOST_AUTO_TEST_CASE(support_test) { ClaimTrieChainFixture fixture; - // check claim with more support wins + // check claim with more support wins CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx1,"test",1); @@ -483,13 +482,13 @@ BOOST_AUTO_TEST_CASE(support_test) BOOST_CHECK(best_claim_effective_amount_equals("test",11)); fixture.DecrementBlocks(1); - // check support delay + // check support delay CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(),"test","two",2); fixture.IncrementBlocks(10); BOOST_CHECK(is_best_claim("test",tx4)); BOOST_CHECK(best_claim_effective_amount_equals("test",2)); - CMutableTransaction s4 = fixture.MakeSupport(fixture.GetCoinbase(),tx3,"test",10); //10 delay + CMutableTransaction s4 = fixture.MakeSupport(fixture.GetCoinbase(), tx3, "test", 10); //10 delay fixture.IncrementBlocks(10); BOOST_CHECK(is_best_claim("test",tx4)); BOOST_CHECK(best_claim_effective_amount_equals("test",2)); @@ -501,7 +500,7 @@ BOOST_AUTO_TEST_CASE(support_test) BOOST_CHECK(is_best_claim("test",tx4)); BOOST_CHECK(best_claim_effective_amount_equals("test",2)); fixture.DecrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx4)); + BOOST_CHECK(is_best_claim("test", tx4)); BOOST_CHECK(best_claim_effective_amount_equals("test",2)); fixture.DecrementBlocks(10); } @@ -572,7 +571,7 @@ BOOST_AUTO_TEST_CASE(update_on_support_test) support spend spending suport on winning claim will cause it to lose - spending a support on txin[i] where i is not 0 + spending a support on txin[i] where i is not 0 */ BOOST_AUTO_TEST_CASE(support_spend_test) { @@ -582,7 +581,7 @@ BOOST_AUTO_TEST_CASE(support_spend_test) CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx1,"test",2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx1)); + BOOST_CHECK(is_best_claim("test", tx1)); CMutableTransaction sp1 = fixture.Spend(s1); fixture.IncrementBlocks(1); BOOST_CHECK(is_best_claim("test",tx2)); @@ -591,8 +590,8 @@ BOOST_AUTO_TEST_CASE(support_spend_test) BOOST_CHECK(is_best_claim("test",tx1)); fixture.DecrementBlocks(1); - // spend a support on txin[i] where i is not 0 - + // spend a support on txin[i] where i is not 0 + CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"x","one",3); CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(),"test","two",2); CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(),"test","three",1); @@ -601,7 +600,7 @@ BOOST_AUTO_TEST_CASE(support_spend_test) BOOST_CHECK(is_best_claim("test",tx5)); BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); - // build the spend where s2 is sppent on txin[1] and tx3 is spent on txin[0] + // build the spend where s2 is sppent on txin[1] and tx3 is spent on txin[0] uint32_t prevout = 0; CMutableTransaction tx; tx.nVersion = 1; @@ -619,40 +618,40 @@ BOOST_AUTO_TEST_CASE(support_spend_test) tx.vout[0].scriptPubKey = CScript() << OP_TRUE; tx.vout[0].nValue = 1; - fixture.CommitTx(tx); + fixture.CommitTx(tx); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx4)); + BOOST_CHECK(is_best_claim("test", tx4)); fixture.DecrementBlocks(1); BOOST_CHECK(is_best_claim("test",tx5)); } /* update update preserves claim id - update preserves supports + update preserves supports winning update on winning claim happens without delay losing update on winning claim happens without delay update on losing claim happens with delay , and wins - - + + */ BOOST_AUTO_TEST_CASE(claimtrie_update_test) { - //update preserves claim id + //update preserves claim id ClaimTrieChainFixture fixture; CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); - CMutableTransaction u1 = fixture.MakeUpdate(tx1,"test","one",ClaimIdHash(tx1.GetHash(),0),2); + CMutableTransaction u1 = fixture.MakeUpdate(tx1, "test", "one", ClaimIdHash(tx1.GetHash(), 0), 2); fixture.IncrementBlocks(1); - CClaimValue val; + CClaimValue val; pclaimTrie->getInfoForName("test",val); BOOST_CHECK(val.claimId == ClaimIdHash(tx1.GetHash(),0)); BOOST_CHECK(is_best_claim("test",u1)); - fixture.DecrementBlocks(1); - + fixture.DecrementBlocks(1); + // update preserves supports CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx2,"test",1); - CMutableTransaction u2 = fixture.MakeUpdate(tx2,"test","one",ClaimIdHash(tx2.GetHash(),0),1); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx2, "test", 1); + CMutableTransaction u2 = fixture.MakeUpdate(tx2, "test", "one", ClaimIdHash(tx2.GetHash(), 0), 1); fixture.IncrementBlocks(1); BOOST_CHECK(best_claim_effective_amount_equals("test",2)); fixture.DecrementBlocks(1); @@ -661,7 +660,7 @@ BOOST_AUTO_TEST_CASE(claimtrie_update_test) CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); fixture.IncrementBlocks(10); - CMutableTransaction u3 = fixture.MakeUpdate(tx3,"test","one",ClaimIdHash(tx3.GetHash(),0),2); + CMutableTransaction u3 = fixture.MakeUpdate(tx3, "test", "one", ClaimIdHash(tx3.GetHash(), 0), 2); fixture.IncrementBlocks(1); BOOST_CHECK(is_best_claim("test",u3)); BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); @@ -678,14 +677,14 @@ BOOST_AUTO_TEST_CASE(claimtrie_update_test) BOOST_CHECK(is_best_claim("test",tx6)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx5)); + BOOST_CHECK(is_best_claim("test", tx5)); fixture.DecrementBlocks(10); // update on losing claim happens with delay , and wins CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",3); CMutableTransaction tx8 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); fixture.IncrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx7)); + BOOST_CHECK(is_best_claim("test", tx7)); CMutableTransaction tx; tx.nVersion = 1; @@ -702,7 +701,7 @@ BOOST_AUTO_TEST_CASE(claimtrie_update_test) tx.vin[1].nSequence = std::numeric_limits::max(); tx.vout[0].scriptPubKey = UpdateClaimScript("test",ClaimIdHash(tx8.GetHash(),0),"one"); tx.vout[0].nValue = 4; - fixture.CommitTx(tx); + fixture.CommitTx(tx); fixture.IncrementBlocks(1); BOOST_CHECK(is_best_claim("test",tx7)); @@ -718,7 +717,7 @@ BOOST_AUTO_TEST_CASE(claimtrie_update_test) expiration check claims expire and loses claim check claims expire and is not updateable (may be changed in future soft fork) - check supports expire and can cause supported bid to lose claim + check supports expire and can cause supported bid to lose claim */ BOOST_AUTO_TEST_CASE(claimtrie_expire_test) { @@ -977,7 +976,7 @@ BOOST_AUTO_TEST_CASE(hardfork_support_test) ClaimTrieChainFixture fixture; int blocks_before_fork = 10; - fixture.IncrementBlocks(fixture.expirationForkHeight - chainActive.Height() - blocks_before_fork-1); + fixture.IncrementBlocks(fixture.expirationForkHeight - chainActive.Height() - blocks_before_fork - 1); // Create claim and support it before the fork height CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx1,"test",2); @@ -1900,6 +1899,29 @@ BOOST_AUTO_TEST_CASE(claimtrienode_serialize_unserialize) BOOST_CHECK(n1 == n2); } +BOOST_AUTO_TEST_CASE(claimtrienode_remove_invalid_claim) +{ + uint160 hash160; + + CClaimTrieNode n1; + CClaimTrieNode n2; + CClaimValue throwaway; + + CClaimValue v1(COutPoint(uint256S("0000000000000000000000000000000000000000000000000000000000000001"), 0), hash160, 50, 0, 100); + CClaimValue v2(COutPoint(uint256S("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), 1), hash160, 100, 1, 101); + + n1.insertClaim(v1); + + n2.insertClaim(v2); + + bool invalidClaim = n2.removeClaim(v1.outPoint, throwaway); + BOOST_CHECK(invalidClaim == false); + + invalidClaim = n1.removeClaim(v2.outPoint, throwaway); + BOOST_CHECK(invalidClaim == false); +} + + BOOST_AUTO_TEST_CASE(invalid_claimid_test) { ClaimTrieChainFixture fixture; -- 2.45.3 From 10c4254c640ba53be6d261a01ba5a931971db234 Mon Sep 17 00:00:00 2001 From: Anthony Fieroni Date: Tue, 27 Nov 2018 18:23:21 +0200 Subject: [PATCH 15/25] Return the value field to getclaimsforname rpc method Signed-off-by: Anthony Fieroni --- src/rpc/claimtrie.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/rpc/claimtrie.cpp b/src/rpc/claimtrie.cpp index 1ce579de1..9b4d7fe38 100644 --- a/src/rpc/claimtrie.cpp +++ b/src/rpc/claimtrie.cpp @@ -285,7 +285,7 @@ UniValue supportToJSON(const CSupportValue& support) return ret; } -UniValue claimAndSupportsToJSON(CAmount nEffectiveAmount, claimSupportMapType::const_iterator itClaimsAndSupports) +UniValue claimAndSupportsToJSON(const CCoinsViewCache& coinsCache, CAmount nEffectiveAmount, claimSupportMapType::const_iterator itClaimsAndSupports) { UniValue ret(UniValue::VOBJ); const CClaimValue& claim = itClaimsAndSupports->second.first; @@ -300,6 +300,9 @@ UniValue claimAndSupportsToJSON(CAmount nEffectiveAmount, claimSupportMapType::c ret.push_back(Pair("nHeight", claim.nHeight)); ret.push_back(Pair("nValidAtHeight", claim.nValidAtHeight)); ret.push_back(Pair("nAmount", claim.nAmount)); + std::string sValue; + if (getValueForClaim(coinsCache, claim.outPoint, sValue)) + ret.push_back(Pair("value", sValue)); ret.push_back(Pair("nEffectiveAmount", nEffectiveAmount)); ret.push_back(Pair("supports", supportObjs)); return ret; @@ -330,6 +333,7 @@ UniValue getclaimsforname(const UniValue& params, bool fHelp) " \"nHeight\" (numeric) the height at which the claim was included in the blockchain\n" " \"nValidAtHeight\" (numeric) the height at which the claim became/becomes valid\n" " \"nAmount\" (numeric) the amount of the claim\n" + " \"value\" (string) the value of the name, if it exists\n" " \"nEffectiveAmount\" (numeric) the total effective amount of the claim, taking into effect whether the claim or support has reached its nValidAtHeight\n" " \"supports\" : [ (array of object) supports for this claim\n" " \"txid\" (string) the txid of the support\n" @@ -388,7 +392,7 @@ UniValue getclaimsforname(const UniValue& params, bool fHelp) for (claimSupportMapType::const_iterator itClaimsAndSupports = claimSupportMap.begin(); itClaimsAndSupports != claimSupportMap.end(); ++itClaimsAndSupports) { CAmount nEffectiveAmount = trieCache.getEffectiveAmountForClaim(claimsForName, itClaimsAndSupports->first); - UniValue claimObj = claimAndSupportsToJSON(nEffectiveAmount, itClaimsAndSupports); + UniValue claimObj = claimAndSupportsToJSON(coinsCache, nEffectiveAmount, itClaimsAndSupports); claimObjs.push_back(claimObj); } -- 2.45.3 From e89d748b2ff4a846b1493d4ee6a9a98540ea306f Mon Sep 17 00:00:00 2001 From: Anthony Fieroni Date: Fri, 23 Nov 2018 14:41:16 +0200 Subject: [PATCH 16/25] Increase default dbcache size Signed-off-by: Anthony Fieroni --- src/main.cpp | 39 -------------------------- src/main.h | 4 --- src/rpc/claimtrie.cpp | 65 +++++++++++++++++++++++++++++++------------ src/txdb.h | 2 +- 4 files changed, 48 insertions(+), 62 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e313a4957..38f738834 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4264,45 +4264,6 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, return true; } -bool RollBackTo(const CBlockIndex* targetIndex, CCoinsViewCache& coinsCache, CClaimTrieCache& trieCache) -{ - AssertLockHeld(cs_main); - for (CBlockIndex* index = chainActive.Tip(); index && index != targetIndex; index = index->pprev) { - boost::this_thread::interruption_point(); - CBlock block; - - if (!ReadBlockFromDisk(block, index, Params().GetConsensus())) - return false; // return error() instead? - - if (coinsCache.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage() > nCoinCacheUsage) - return false; // don't allow a single query to chew up all our memory? - - if (ShutdownRequested()) - return false; - - CValidationState state; - if (!DisconnectBlock(block, state, index, coinsCache, trieCache)) - return false; - - if (state.IsError()) - return false; - } - return true; -} - -bool GetProofForName(const CBlockIndex* pindexProof, const std::string& name, CClaimTrieProof& proof) -{ - AssertLockHeld(cs_main); - if (!chainActive.Contains(pindexProof)) - return false; - - CCoinsViewCache coinsCache(pcoinsTip); - CClaimTrieCache trieCache(pclaimTrie); - if (RollBackTo(pindexProof, coinsCache, trieCache)) - return trieCache.getProofForName(name, proof); - return false; -} - void UnloadBlockIndex() { LOCK(cs_main); diff --git a/src/main.h b/src/main.h index 3c9f845ee..00bfcb5dd 100644 --- a/src/main.h +++ b/src/main.h @@ -225,10 +225,6 @@ FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false); FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false); /** Translation to a filesystem path */ boost::filesystem::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix); -/** Utility method for going back to a previous state **/ -bool RollBackTo(const CBlockIndex* targetIndex, CCoinsViewCache& coinsCache, CClaimTrieCache& trieCache); -/** Get a cryptographic proof that a name maps to a value **/ -bool GetProofForName(const CBlockIndex* pindexProof, const std::string& name, CClaimTrieProof& proof); /** Import blocks from an external file */ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp = NULL); /** Initialize a new block tree database + block data on disk */ diff --git a/src/rpc/claimtrie.cpp b/src/rpc/claimtrie.cpp index 9b4d7fe38..7e6d17550 100644 --- a/src/rpc/claimtrie.cpp +++ b/src/rpc/claimtrie.cpp @@ -1,13 +1,15 @@ #include "boost/scope_exit.hpp" #include "consensus/validation.h" +#include "init.h" #include "main.h" #include "nameclaim.h" #include "rpc/server.h" #include "txmempool.h" #include "univalue.h" -// Maximum block decrement that is allowed from rpc calls -const int MAX_RPC_BLOCK_DECREMENTS = 50; +#include + +#include uint160 ParseClaimtrieId(const UniValue& v, const std::string& strName) { @@ -35,10 +37,39 @@ static CBlockIndex* BlockHashIndex(const uint256& blockHash) if (!chainActive.Contains(pblockIndex)) throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not in main chain"); - if (chainActive.Tip()->nHeight > (pblockIndex->nHeight + MAX_RPC_BLOCK_DECREMENTS)) + return pblockIndex; +} + +#define MAX_RPC_BLOCK_DECREMENTS 500 + +void RollBackTo(const CBlockIndex* targetIndex, CCoinsViewCache& coinsCache, CClaimTrieCache& trieCache) +{ + AssertLockHeld(cs_main); + + const CBlockIndex* activeIndex = chainActive.Tip(); + + if (activeIndex->nHeight > (targetIndex->nHeight + MAX_RPC_BLOCK_DECREMENTS)) throw JSONRPCError(RPC_INTERNAL_ERROR, "Block is too deep"); - return pblockIndex; + const size_t currentMemoryUsage = pcoinsTip->DynamicMemoryUsage(); + + for (; activeIndex && activeIndex != targetIndex; activeIndex = activeIndex->pprev) { + boost::this_thread::interruption_point(); + + CBlock block; + if (!ReadBlockFromDisk(block, activeIndex, Params().GetConsensus())) + throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("Failed to read %s", activeIndex->ToString())); + + if (coinsCache.DynamicMemoryUsage() + currentMemoryUsage > nCoinCacheUsage) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Out of memory, you may want to increase dbcache size"); + + if (ShutdownRequested()) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Shutdown requested"); + + CValidationState state; + if (!DisconnectBlock(block, state, activeIndex, coinsCache, trieCache)) + throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("Failed to disconnect %s", block.ToString())); + } } UniValue getclaimsintrie(const UniValue& params, bool fHelp) @@ -78,8 +109,7 @@ UniValue getclaimsintrie(const UniValue& params, bool fHelp) if (!params.empty()) { CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[0], "blockhash (optional parameter 1)")); - if (!RollBackTo(blockIndex, coinsCache, trieCache)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Rollback failure"); + RollBackTo(blockIndex, coinsCache, trieCache); } UniValue ret(UniValue::VARR); @@ -155,8 +185,7 @@ UniValue getclaimtrie(const UniValue& params, bool fHelp) if (!params.empty()) { CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[0], "blockhash (optional parameter 1)")); - if (!RollBackTo(blockIndex, coinsCache, trieCache)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Rollback failure"); + RollBackTo(blockIndex, coinsCache, trieCache); } UniValue ret(UniValue::VARR); @@ -245,8 +274,7 @@ UniValue getvalueforname(const UniValue& params, bool fHelp) if (params.size() > 1) { CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[1], "blockhash (optional parameter 2)")); - if (!RollBackTo(blockIndex, coinsCache, trieCache)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Rollback failure"); + RollBackTo(blockIndex, coinsCache, trieCache); } CClaimValue claim; @@ -362,8 +390,7 @@ UniValue getclaimsforname(const UniValue& params, bool fHelp) if (params.size() > 1) { CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[1], "blockhash (optional parameter 2)")); - if (!RollBackTo(blockIndex, coinsCache, trieCache)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Rollback failure"); + RollBackTo(blockIndex, coinsCache, trieCache); } std::string name = params[0].get_str(); @@ -784,16 +811,18 @@ UniValue getnameproof(const UniValue& params, bool fHelp) "}\n"); LOCK(cs_main); - std::string strName = params[0].get_str(); - CBlockIndex* pblockIndex; + + CCoinsViewCache coinsCache(pcoinsTip); + CClaimTrieCache trieCache(pclaimTrie); + if (params.size() == 2) { - pblockIndex = BlockHashIndex(ParseHashV(params[1], "blockhash (optional parameter 2)")); - } else { - pblockIndex = mapBlockIndex[chainActive.Tip()->GetBlockHash()]; + CBlockIndex* pblockIndex = BlockHashIndex(ParseHashV(params[1], "blockhash (optional parameter 2)")); + RollBackTo(pblockIndex, coinsCache, trieCache); } CClaimTrieProof proof; - if (!GetProofForName(pblockIndex, strName, proof)) + std::string name = params[0].get_str(); + if (!trieCache.getProofForName(name, proof)) throw JSONRPCError(RPC_INTERNAL_ERROR, "Failed to generate proof"); return proofToJSON(proof); diff --git a/src/txdb.h b/src/txdb.h index 749802f0e..9186aab61 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -20,7 +20,7 @@ struct CDiskTxPos; class uint256; //! -dbcache default (MiB) -static const int64_t nDefaultDbCache = 100; +static const int64_t nDefaultDbCache = sizeof(void*) > 4 ? 700 : 500; //! max. -dbcache in (MiB) static const int64_t nMaxDbCache = sizeof(void*) > 4 ? 16384 : 1024; //! min. -dbcache in (MiB) -- 2.45.3 From 9f80a4ed342f57629cb4c44cd8241a9a3ba71e95 Mon Sep 17 00:00:00 2001 From: kay kurokawa Date: Wed, 5 Dec 2018 16:47:27 -0500 Subject: [PATCH 17/25] mark getclaimtrie as deprecated, will be removed in next release --- src/rpc/claimtrie.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/claimtrie.cpp b/src/rpc/claimtrie.cpp index 7e6d17550..a2237b2a2 100644 --- a/src/rpc/claimtrie.cpp +++ b/src/rpc/claimtrie.cpp @@ -158,7 +158,7 @@ UniValue getclaimtrie(const UniValue& params, bool fHelp) if (fHelp || params.size() > 1) throw std::runtime_error( "getclaimtrie\n" - "Return the entire name trie.\n" + "DEPRECATED. Return the entire name trie.\n" "Arguments:\n" "1. \"blockhash\" (string, optional) get claim in the trie\n" " at the block specified\n" -- 2.45.3 From 8b3f2e8b0305e6d831259172b20b85c7a603ef45 Mon Sep 17 00:00:00 2001 From: kay kurokawa Date: Wed, 5 Dec 2018 14:47:01 -0500 Subject: [PATCH 18/25] Add tests to trigger https://github.com/lbryio/lbrycrd/issues/243 --- src/test/claimtriebranching_tests.cpp | 60 +++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/test/claimtriebranching_tests.cpp b/src/test/claimtriebranching_tests.cpp index 8d7f0f706..4796a99c4 100644 --- a/src/test/claimtriebranching_tests.cpp +++ b/src/test/claimtriebranching_tests.cpp @@ -176,6 +176,7 @@ struct ClaimTrieChainFixture{ fRequireStandard = false; ENTER_CRITICAL_SECTION(cs_main); BOOST_CHECK(pclaimTrie->nCurrentHeight == chainActive.Height() + 1); + pclaimTrie->setExpirationTime(originalExpiration); // in case it was changed during the test num_txs_for_next_block = 0; num_txs = 0; coinbase_txs_used = 0; @@ -1020,6 +1021,65 @@ BOOST_AUTO_TEST_CASE(hardfork_support_test) } +/* + activation_fall_through and supports_fall_through + Tests for where claims/supports in queues would be undone properly in a decrement. + See https://github.com/lbryio/lbrycrd/issues/243 for more details +*/ + +BOOST_AUTO_TEST_CASE(activations_fall_through) +{ + ClaimTrieChainFixture fixture; + + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1); + fixture.IncrementBlocks(3); + BOOST_CHECK(pclaimTrie->nProportionalDelayFactor == 1); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "2", 3); + fixture.IncrementBlocks(1); + + BOOST_CHECK(is_best_claim("A", tx1)); + fixture.IncrementBlocks(3); + BOOST_CHECK(is_best_claim("A", tx2)); + fixture.DecrementBlocks(3); + fixture.Spend(tx1); // this will trigger early activation on tx2 claim + fixture.IncrementBlocks(1); + BOOST_CHECK(is_best_claim("A", tx2)); + fixture.DecrementBlocks(1); //reorg the early activation + BOOST_CHECK(is_best_claim("A", tx1)); + fixture.Spend(tx1); + fixture.IncrementBlocks(1); // this should not cause tx2 to activate again and crash + BOOST_CHECK(is_best_claim("A", tx2)); +} + +BOOST_AUTO_TEST_CASE(supports_fall_through) +{ + ClaimTrieChainFixture fixture; + + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 3); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "2", 1); + CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "3", 2); + fixture.IncrementBlocks(3); + BOOST_CHECK(pclaimTrie->nProportionalDelayFactor == 1); + CMutableTransaction sx2 = fixture.MakeSupport(fixture.GetCoinbase(), tx2, "A", 3); + fixture.IncrementBlocks(1); + + BOOST_CHECK(is_best_claim("A", tx1)); + fixture.IncrementBlocks(3); + BOOST_CHECK(is_best_claim("A", tx2)); + fixture.DecrementBlocks(3); + fixture.Spend(tx1); // this will trigger early activation + fixture.IncrementBlocks(1); + BOOST_CHECK(is_best_claim("A", tx2)); + fixture.DecrementBlocks(1); // reorg the early activation + BOOST_CHECK(is_best_claim("A", tx1)); + fixture.IncrementBlocks(1); + BOOST_CHECK(is_best_claim("A", tx1)); //tx2 support should not be active + fixture.IncrementBlocks(1); + BOOST_CHECK(is_best_claim("A", tx1)); //tx2 support should not be active + fixture.IncrementBlocks(1); + BOOST_CHECK(is_best_claim("A", tx2)); //tx2 support should be active now +} + /* claim/support expiration for hard fork, but with checks for disk procedures */ -- 2.45.3 From 30a517dcf85a93a09a2750ea978eca9251b40515 Mon Sep 17 00:00:00 2001 From: kay kurokawa Date: Wed, 5 Dec 2018 14:29:32 -0500 Subject: [PATCH 19/25] Fix for https://github.com/lbryio/lbrycrd/issues/243 --- src/claimtrie.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/claimtrie.cpp b/src/claimtrie.cpp index 172aa35ba..334544859 100644 --- a/src/claimtrie.cpp +++ b/src/claimtrie.cpp @@ -2235,7 +2235,7 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy } if (takeoverHappened) { - // Get all claims in the queue for that name + // Get all pending claims for that name and activate them all in the case that our winner is defunct. queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(*itNamesToCheck, false); if (itQueueNameRow != claimQueueNameCache.end()) { @@ -2366,6 +2366,9 @@ bool CClaimTrieCache::decrementBlock(insertUndoType& insertUndo, claimQueueRowTy supportQueueType::iterator itSupportRow = getSupportQueueCacheRow(itSupportUndo->nHeight, true); CSupportValue support; assert(removeSupportFromMap(itSupportUndo->name, itSupportUndo->outPoint, support, false)); + // support.nValidHeight may have been changed if this was inserted before activation height + // due to a triggered takeover, change it back to original nValidAtHeight + support.nValidAtHeight = itSupportUndo->nHeight; queueNameType::iterator itSupportNameRow = getSupportQueueCacheNameRow(itSupportUndo->name, true); itSupportRow->second.push_back(std::make_pair(itSupportUndo->name, support)); itSupportNameRow->second.push_back(outPointHeightType(support.outPoint, support.nValidAtHeight)); @@ -2386,11 +2389,15 @@ bool CClaimTrieCache::decrementBlock(insertUndoType& insertUndo, claimQueueRowTy for (insertUndoType::iterator itInsertUndo = insertUndo.begin(); itInsertUndo != insertUndo.end(); ++itInsertUndo) { claimQueueType::iterator itQueueRow = getQueueCacheRow(itInsertUndo->nHeight, true); + CClaimValue claim; assert(removeClaimFromTrie(itInsertUndo->name, itInsertUndo->outPoint, claim, false)); + // claim.nValidHeight may have been changed if this was inserted before activation height + // due to a triggered takeover, change it back to original nValidAtHeight + claim.nValidAtHeight = itInsertUndo->nHeight; queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(itInsertUndo->name, true); itQueueRow->second.push_back(std::make_pair(itInsertUndo->name, claim)); - itQueueNameRow->second.push_back(outPointHeightType(itInsertUndo->outPoint, itInsertUndo->nHeight)); + itQueueNameRow->second.push_back(outPointHeightType(itInsertUndo->outPoint, claim.nValidAtHeight)); } for (std::vector >::iterator itTakeoverHeightUndo = takeoverHeightUndo.begin(); itTakeoverHeightUndo != takeoverHeightUndo.end(); ++itTakeoverHeightUndo) -- 2.45.3 From 9fbed57043975db8d06455bdbb7acd2781ded2e6 Mon Sep 17 00:00:00 2001 From: kay kurokawa Date: Thu, 6 Dec 2018 09:59:09 -0500 Subject: [PATCH 20/25] bumped release version to 0.12.3.0 --- configure.ac | 4 ++-- src/clientversion.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 6be5a02b9..d86a87965 100644 --- a/configure.ac +++ b/configure.ac @@ -2,8 +2,8 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 12) -define(_CLIENT_VERSION_REVISION, 2) -define(_CLIENT_VERSION_BUILD, 3) +define(_CLIENT_VERSION_REVISION, 3) +define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2016) define(_COPYRIGHT_HOLDERS,[The %s developers]) diff --git a/src/clientversion.h b/src/clientversion.h index 67a55a4a9..95fddfed9 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -16,8 +16,8 @@ //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 12 -#define CLIENT_VERSION_REVISION 2 -#define CLIENT_VERSION_BUILD 3 +#define CLIENT_VERSION_REVISION 3 +#define CLIENT_VERSION_BUILD 0 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true -- 2.45.3 From 3ca72b18ccbd062f72c2000c03a6feba97b1c512 Mon Sep 17 00:00:00 2001 From: kay kurokawa Date: Thu, 6 Dec 2018 21:46:44 -0500 Subject: [PATCH 21/25] Adjust each unit test to use its own reinitialized unique_block_counter, move CreateCoinbase and CreateBlock functions inside of ClaimTrieChainFixture --- src/test/claimtriebranching_tests.cpp | 81 +++++++++++++-------------- 1 file changed, 39 insertions(+), 42 deletions(-) diff --git a/src/test/claimtriebranching_tests.cpp b/src/test/claimtriebranching_tests.cpp index 4796a99c4..bc5bb8e3f 100644 --- a/src/test/claimtriebranching_tests.cpp +++ b/src/test/claimtriebranching_tests.cpp @@ -111,54 +111,13 @@ CMutableTransaction BuildTransaction(const CMutableTransaction& prev, uint32_t p return tx; } -bool CreateBlock(CBlockTemplate* pblocktemplate) -{ - static int unique_block_counter = 0; - CBlock* pblock = &pblocktemplate->block; - pblock->nVersion = 1; - pblock->nTime = chainActive.Tip()->GetBlockTime()+Params().GetConsensus().nPowTargetSpacing; - CMutableTransaction txCoinbase(pblock->vtx[0]); - txCoinbase.vin[0].scriptSig = CScript() << CScriptNum(unique_block_counter++) << CScriptNum(chainActive.Height()); - txCoinbase.vout[0].nValue = GetBlockSubsidy(chainActive.Height() + 1, Params().GetConsensus()); - pblock->vtx[0] = CTransaction(txCoinbase); - pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); - for (uint32_t i = 0;; ++i) { - pblock->nNonce = i; - if (CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, Params().GetConsensus())) - { - break; - } - } - CValidationState state; - bool success = (ProcessNewBlock(state, Params(), NULL, pblock, true, NULL) && state.IsValid() && pblock->GetHash() == chainActive.Tip()->GetBlockHash()); - pblock->hashPrevBlock = pblock->GetHash(); - return success; - -} - -bool CreateCoinbases(unsigned int num_coinbases, std::vector& coinbases) -{ - CBlockTemplate *pblocktemplate; - coinbases.clear(); - BOOST_CHECK(pblocktemplate = CreateNewBlock(Params(), CScript()<block.vtx.size() == 1); - pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash(); - for (unsigned int i = 0; i < 100 + num_coinbases; ++i) - { - BOOST_CHECK(CreateBlock(pblocktemplate)); - if (coinbases.size() < num_coinbases) - coinbases.push_back(CTransaction(pblocktemplate->block.vtx[0])); - } - delete pblocktemplate; - return true; -} - // Test Fixtures struct ClaimTrieChainFixture{ std::vector coinbase_txs; std::vector marks; int coinbase_txs_used; + int unique_block_counter; unsigned int num_txs; unsigned int num_txs_for_next_block; @@ -180,6 +139,7 @@ struct ClaimTrieChainFixture{ num_txs_for_next_block = 0; num_txs = 0; coinbase_txs_used = 0; + unique_block_counter = 0; // generate coinbases to spend CreateCoinbases(40, coinbase_txs); } @@ -190,6 +150,43 @@ struct ClaimTrieChainFixture{ LEAVE_CRITICAL_SECTION(cs_main); } + bool CreateBlock(CBlockTemplate* pblocktemplate) + { + CBlock* pblock = &pblocktemplate->block; + pblock->nVersion = 1; + pblock->nTime = chainActive.Tip()->GetBlockTime() + Params().GetConsensus().nPowTargetSpacing; + CMutableTransaction txCoinbase(pblock->vtx[0]); + txCoinbase.vin[0].scriptSig = CScript() << CScriptNum(unique_block_counter++) << CScriptNum(chainActive.Height()); + txCoinbase.vout[0].nValue = GetBlockSubsidy(chainActive.Height() + 1, Params().GetConsensus()); + pblock->vtx[0] = CTransaction(txCoinbase); + pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); + for (uint32_t i = 0;; ++i) { + pblock->nNonce = i; + if (CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, Params().GetConsensus())) { + break; + } + } + CValidationState state; + bool success = (ProcessNewBlock(state, Params(), NULL, pblock, true, NULL) && state.IsValid() && pblock->GetHash() == chainActive.Tip()->GetBlockHash()); + pblock->hashPrevBlock = pblock->GetHash(); + return success; + } + + bool CreateCoinbases(unsigned int num_coinbases, std::vector& coinbases) + { + CBlockTemplate* pblocktemplate; + coinbases.clear(); + BOOST_CHECK(pblocktemplate = CreateNewBlock(Params(), CScript() << OP_TRUE)); + BOOST_CHECK(pblocktemplate->block.vtx.size() == 1); + pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash(); + for (unsigned int i = 0; i < 100 + num_coinbases; ++i) { + BOOST_CHECK(CreateBlock(pblocktemplate)); + if (coinbases.size() < num_coinbases) + coinbases.push_back(CTransaction(pblocktemplate->block.vtx[0])); + } + delete pblocktemplate; + return true; + } void CommitTx(CMutableTransaction &tx){ num_txs_for_next_block++; -- 2.45.3 From a54f2f4d4859018b33d9e908723bbd50bce5a9b8 Mon Sep 17 00:00:00 2001 From: Anthony Fieroni Date: Wed, 12 Dec 2018 08:49:17 +0200 Subject: [PATCH 22/25] Return correct field "supports without claims" Signed-off-by: Anthony Fieroni --- src/rpc/claimtrie.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rpc/claimtrie.cpp b/src/rpc/claimtrie.cpp index a2237b2a2..8e391d356 100644 --- a/src/rpc/claimtrie.cpp +++ b/src/rpc/claimtrie.cpp @@ -372,7 +372,7 @@ UniValue getclaimsforname(const UniValue& params, bool fHelp) " ]\n" " }\n" " ],\n" - " \"unmatched supports\": [ (array of object) supports that did not match a claim for this name\n" + " \"supports without claims\": [ (array of object) supports that did not match a claim for this name\n" " {\n" " \"txid\" (string) the txid of the support\n" " \"n\" (numeric) the index of the support in the transaction's list of outputs\n" @@ -424,7 +424,7 @@ UniValue getclaimsforname(const UniValue& params, bool fHelp) } ret.push_back(Pair("claims", claimObjs)); - ret.push_back(Pair("unmatched supports", unmatchedSupports)); + ret.push_back(Pair("supports without claims", unmatchedSupports)); return ret; } -- 2.45.3 From b5a0c962d09e5d09a2f4154f8433a2e286c25e08 Mon Sep 17 00:00:00 2001 From: Brannon King Date: Thu, 13 Dec 2018 13:29:22 +0100 Subject: [PATCH 23/25] bumped version number for pending release --- configure.ac | 2 +- src/clientversion.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index d86a87965..d19f0eb32 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 12) define(_CLIENT_VERSION_REVISION, 3) -define(_CLIENT_VERSION_BUILD, 0) +define(_CLIENT_VERSION_BUILD, 1) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2016) define(_COPYRIGHT_HOLDERS,[The %s developers]) diff --git a/src/clientversion.h b/src/clientversion.h index 95fddfed9..dbcf9c627 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -17,7 +17,7 @@ #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 12 #define CLIENT_VERSION_REVISION 3 -#define CLIENT_VERSION_BUILD 0 +#define CLIENT_VERSION_BUILD 1 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true -- 2.45.3 From 02986f766c65257ffd6fbe2710b70bb64b598619 Mon Sep 17 00:00:00 2001 From: Brannon King Date: Thu, 13 Dec 2018 15:48:17 +0100 Subject: [PATCH 24/25] Replace flattenTrie by callback Signed-off-by: Anthony Fieroni Use interruption point instead of boolean condition Signed-off-by: Anthony Fieroni Add ability to earlier exit in rpc methods getclaimtrie and getclaimsintrie Signed-off-by: Anthony Fieroni simplified early exit handling ran formatter --- src/claimtrie.cpp | 49 ++++------- src/claimtrie.h | 31 +++++-- src/rpc/claimtrie.cpp | 138 +++++++++++++++++++----------- src/test/claimtriecache_tests.cpp | 53 ++++++++++++ 4 files changed, 181 insertions(+), 90 deletions(-) diff --git a/src/claimtrie.cpp b/src/claimtrie.cpp index 334544859..f4b1ccd98 100644 --- a/src/claimtrie.cpp +++ b/src/claimtrie.cpp @@ -403,28 +403,6 @@ CAmount CClaimTrie::getTotalValueOfClaimsRecursive(const CClaimTrieNode* current return value_in_subtrie; } -bool CClaimTrie::recursiveFlattenTrie(const std::string& name, const CClaimTrieNode* current, std::vector& nodes) const -{ - namedNodeType node(name, *current); - nodes.push_back(node); - for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) - { - std::stringstream ss; - ss << name << it->first; - if (!recursiveFlattenTrie(ss.str(), it->second, nodes)) - return false; - } - return true; -} - -std::vector CClaimTrie::flattenTrie() const -{ - std::vector nodes; - if (!recursiveFlattenTrie("", &root, nodes)) - LogPrintf("%s: Something went wrong flattening the trie", __func__); - return nodes; -} - const CClaimTrieNode* CClaimTrie::getNodeForName(const std::string& name) const { const CClaimTrieNode* current = &root; @@ -2548,25 +2526,32 @@ uint256 CClaimTrieCache::getLeafHashForProof(const std::string& currentPosition, } } -void CClaimTrieCache::recursiveFlattenTrie(const std::string& name, const CClaimTrieNode* current, std::vector& nodes) const +void CClaimTrieCache::recursiveIterateTrie(std::string& name, const CClaimTrieNode* current, CNodeCallback& callback) const { - nodes.push_back(std::make_pair(name, *current)); + callback.visit(name, current); + nodeCacheType::const_iterator cachedNode; for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) { - const std::string str = name + char(it->first); - cachedNode = cache.find(str); + name.push_back(it->first); + cachedNode = cache.find(name); if (cachedNode != cache.end()) - recursiveFlattenTrie(str, cachedNode->second, nodes); + recursiveIterateTrie(name, cachedNode->second, callback); else - recursiveFlattenTrie(str, it->second, nodes); + recursiveIterateTrie(name, it->second, callback); + name.erase(name.end() - 1); } } -std::vector CClaimTrieCache::flattenTrie() const +bool CClaimTrieCache::iterateTrie(CNodeCallback& callback) const { - std::vector nodes; - recursiveFlattenTrie("", getRoot(), nodes); - return nodes; + try { + std::string name; + recursiveIterateTrie(name, getRoot(), callback); + assert(name.empty()); + } catch (const CNodeCallback::CRecursionInterruptionException& ex) { + return ex.success; + } + return true; } claimsForNameType CClaimTrieCache::getClaimsForName(const std::string& name) const diff --git a/src/claimtrie.h b/src/claimtrie.h index 9d75a5d22..d192cf6f6 100644 --- a/src/claimtrie.h +++ b/src/claimtrie.h @@ -132,8 +132,6 @@ typedef std::vector supportMapEntryType; typedef std::map nodeMapType; -typedef std::pair namedNodeType; - class CClaimTrieNode { public: @@ -317,7 +315,6 @@ public: bool WriteToDisk(); bool ReadFromDisk(bool check = false); - std::vector flattenTrie() const; bool getInfoForName(const std::string& name, CClaimValue& claim) const; bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const; @@ -392,9 +389,6 @@ private: unsigned int getTotalClaimsRecursive(const CClaimTrieNode* current) const; CAmount getTotalValueOfClaimsRecursive(const CClaimTrieNode* current, bool fControllingOnly) const; - bool recursiveFlattenTrie(const std::string& name, - const CClaimTrieNode* current, - std::vector& nodes) const; void markNodeDirty(const std::string& name, CClaimTrieNode* node); void updateQueueRow(int nHeight, claimQueueRowType& row); @@ -459,6 +453,27 @@ public: int nHeightOfLastTakeover; }; +struct CNodeCallback { + struct CRecursionInterruptionException : public std::exception { + const bool success; + explicit CRecursionInterruptionException(bool success) : success(success) {} + }; + + virtual ~CNodeCallback() + { + } + + /** + * Callback to be called on every trie node + * @param[in] name full name of the node + * @param[in] node pointer to node itself + * + * To breakout early throw an exception. + * Throwing CRecursionInterruptionException will allow you to set the return value of iterateTrie. + */ + virtual void visit(const std::string& name, const CClaimTrieNode* node) = 0; +}; + class CClaimTrieCache { public: @@ -533,7 +548,7 @@ public: bool forkForExpirationChange(bool increment) const; - std::vector flattenTrie() const; + bool iterateTrie(CNodeCallback& callback) const; claimsForNameType getClaimsForName(const std::string& name) const; @@ -635,7 +650,7 @@ protected: int getNumBlocksOfContinuousOwnership(const std::string& name) const; - void recursiveFlattenTrie(const std::string& name, const CClaimTrieNode* current, std::vector& nodes) const; + void recursiveIterateTrie(std::string& name, const CClaimTrieNode* current, CNodeCallback& callback) const; const CClaimTrieNode* getNodeForName(const std::string& name) const; }; diff --git a/src/rpc/claimtrie.cpp b/src/rpc/claimtrie.cpp index 8e391d356..dc66cefa2 100644 --- a/src/rpc/claimtrie.cpp +++ b/src/rpc/claimtrie.cpp @@ -112,44 +112,65 @@ UniValue getclaimsintrie(const UniValue& params, bool fHelp) RollBackTo(blockIndex, coinsCache, trieCache); } - UniValue ret(UniValue::VARR); - std::vector nodes = trieCache.flattenTrie(); - for (std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it) { - if (it->second.claims.empty()) continue; - - UniValue claims(UniValue::VARR); - for (std::vector::iterator itClaims = it->second.claims.begin(); itClaims != it->second.claims.end(); ++itClaims) { - UniValue claim(UniValue::VOBJ); - claim.push_back(Pair("claimId", itClaims->claimId.GetHex())); - claim.push_back(Pair("txid", itClaims->outPoint.hash.GetHex())); - claim.push_back(Pair("n", (int)itClaims->outPoint.n)); - claim.push_back(Pair("amount", ValueFromAmount(itClaims->nAmount))); - claim.push_back(Pair("height", itClaims->nHeight)); - const CCoins* coin = coinsCache.AccessCoins(itClaims->outPoint.hash); - if (!coin) { - LogPrintf("%s: %s does not exist in the coins view, despite being associated with a name\n", - __func__, itClaims->outPoint.hash.GetHex()); - claim.push_back(Pair("error", "No value found for claim")); - } else if (!coin->IsAvailable(itClaims->outPoint.n)) { - LogPrintf("%s: the specified txout of %s appears to have been spent\n", __func__, itClaims->outPoint.hash.GetHex()); - claim.push_back(Pair("error", "Txout spent")); - } else { - int op; - std::vector > vvchParams; - if (!DecodeClaimScript(coin->vout[itClaims->outPoint.n].scriptPubKey, op, vvchParams)) { - LogPrintf("%s: the specified txout of %s does not have an claim command\n", __func__, itClaims->outPoint.hash.GetHex()); - } - std::string sValue(vvchParams[1].begin(), vvchParams[1].end()); - claim.push_back(Pair("value", sValue)); - } - claims.push_back(claim); + class CClaimsCallback : public CNodeCallback + { + public: + CClaimsCallback(UniValue& ret, const CCoinsViewCache& coinsCache) : nodes(ret), coinsCache(coinsCache) + { } - UniValue node(UniValue::VOBJ); - node.push_back(Pair("name", it->first)); - node.push_back(Pair("claims", claims)); - ret.push_back(node); - } + void visit(const std::string& name, const CClaimTrieNode* node) + { + if (ShutdownRequested()) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Shutdown requested"); + + boost::this_thread::interruption_point(); + + if (node->claims.empty()) + return; + + UniValue claims(UniValue::VARR); + for (std::vector::const_iterator itClaims = node->claims.begin(); itClaims != node->claims.end(); ++itClaims) { + UniValue claim(UniValue::VOBJ); + claim.push_back(Pair("claimId", itClaims->claimId.GetHex())); + claim.push_back(Pair("txid", itClaims->outPoint.hash.GetHex())); + claim.push_back(Pair("n", (int)itClaims->outPoint.n)); + claim.push_back(Pair("amount", ::ValueFromAmount(itClaims->nAmount))); + claim.push_back(Pair("height", itClaims->nHeight)); + const CCoins* coin = coinsCache.AccessCoins(itClaims->outPoint.hash); + if (!coin) { + LogPrintf("%s: %s does not exist in the coins view, despite being associated with a name\n", + __func__, itClaims->outPoint.hash.GetHex()); + claim.push_back(Pair("error", "No value found for claim")); + } else if (!coin->IsAvailable(itClaims->outPoint.n)) { + LogPrintf("%s: the specified txout of %s appears to have been spent\n", __func__, itClaims->outPoint.hash.GetHex()); + claim.push_back(Pair("error", "Txout spent")); + } else { + int op; + std::vector > vvchParams; + if (!DecodeClaimScript(coin->vout[itClaims->outPoint.n].scriptPubKey, op, vvchParams)) { + LogPrintf("%s: the specified txout of %s does not have an claim command\n", __func__, itClaims->outPoint.hash.GetHex()); + } + std::string sValue(vvchParams[1].begin(), vvchParams[1].end()); + claim.push_back(Pair("value", sValue)); + } + claims.push_back(claim); + } + + UniValue nodeObj(UniValue::VOBJ); + nodeObj.push_back(Pair("name", name)); + nodeObj.push_back(Pair("claims", claims)); + nodes.push_back(nodeObj); + } + + private: + UniValue& nodes; + const CCoinsViewCache& coinsCache; + }; + + UniValue ret(UniValue::VARR); + CClaimsCallback claimsCallback(ret, coinsCache); + trieCache.iterateTrie(claimsCallback); return ret; } @@ -188,23 +209,40 @@ UniValue getclaimtrie(const UniValue& params, bool fHelp) RollBackTo(blockIndex, coinsCache, trieCache); } - UniValue ret(UniValue::VARR); - std::vector nodes = trieCache.flattenTrie(); - for (std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it) + class CClaimCallback : public CNodeCallback { - UniValue node(UniValue::VOBJ); - node.push_back(Pair("name", it->first)); - node.push_back(Pair("hash", it->second.hash.GetHex())); - CClaimValue claim; - if (it->second.getBestClaim(claim)) + public: + CClaimCallback(UniValue& ret) : nodes(ret) { - node.push_back(Pair("txid", claim.outPoint.hash.GetHex())); - node.push_back(Pair("n", (int)claim.outPoint.n)); - node.push_back(Pair("value", ValueFromAmount(claim.nAmount))); - node.push_back(Pair("height", claim.nHeight)); } - ret.push_back(node); - } + + void visit(const std::string& name, const CClaimTrieNode* node) + { + if (ShutdownRequested()) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Shutdown requested"); + + boost::this_thread::interruption_point(); + + UniValue nodeObj(UniValue::VOBJ); + nodeObj.push_back(Pair("name", name)); + nodeObj.push_back(Pair("hash", node->hash.GetHex())); + CClaimValue claim; + if (node->getBestClaim(claim)) { + nodeObj.push_back(Pair("txid", claim.outPoint.hash.GetHex())); + nodeObj.push_back(Pair("n", (int)claim.outPoint.n)); + nodeObj.push_back(Pair("value", ::ValueFromAmount(claim.nAmount))); + nodeObj.push_back(Pair("height", claim.nHeight)); + } + nodes.push_back(nodeObj); + } + + private: + UniValue& nodes; + }; + + UniValue ret(UniValue::VARR); + CClaimCallback claimCallback(ret); + trieCache.iterateTrie(claimCallback); return ret; } diff --git a/src/test/claimtriecache_tests.cpp b/src/test/claimtriecache_tests.cpp index 52d0e8fc6..aa06fd19e 100644 --- a/src/test/claimtriecache_tests.cpp +++ b/src/test/claimtriecache_tests.cpp @@ -274,5 +274,58 @@ BOOST_AUTO_TEST_CASE(recursive_prune_test) BOOST_CHECK_EQUAL(0, it->second->children.size()); } +BOOST_AUTO_TEST_CASE(iteratetrie_test) +{ + BOOST_CHECK(pclaimTrie->empty()); + CClaimTrieCacheTest ctc(pclaimTrie); + + uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); + CMutableTransaction tx1 = BuildTransaction(hash0); + + const uint256 txhash = tx1.GetHash(); + CClaimValue claimVal(COutPoint(txhash, 0), ClaimIdHash(txhash, 0), CAmount(10), 0, 0); + ctc.insertClaimIntoTrie("test", claimVal); + + + int count = 0; + + struct TestCallBack : public CNodeCallback { + TestCallBack(int& count) : count(count) + { + } + + void visit(const std::string& name, const CClaimTrieNode* node) + { + count++; + if (name == "test") { + BOOST_CHECK(node->claims.size() == 1); + } + } + + int& count; + } testCallback(count); + + BOOST_CHECK(ctc.iterateTrie(testCallback)); + BOOST_CHECK(count == 5); + + count = 3; + + struct TestCallBack2 : public CNodeCallback { + TestCallBack2(int& count) : count(count) + { + } + + void visit(const std::string& name, const CClaimTrieNode* node) + { + if (--count <= 0) + throw CRecursionInterruptionException(false); + } + + int& count; + } testCallback2(count); + + BOOST_CHECK(!ctc.iterateTrie(testCallback2)); + BOOST_CHECK(count == 0); +} BOOST_AUTO_TEST_SUITE_END() -- 2.45.3 From a25334c15036fbb2704fb3280a9b23ca5d557493 Mon Sep 17 00:00:00 2001 From: Brannon King Date: Fri, 14 Dec 2018 11:06:10 +0100 Subject: [PATCH 25/25] repair failed format, bump travis images build experiment 2 build experiment 3 build experiment 4 Replace flattenTrie by callback Signed-off-by: Anthony Fieroni Use interruption point instead of boolean condition Signed-off-by: Anthony Fieroni Add ability to earlier exit in rpc methods getclaimtrie and getclaimsintrie Signed-off-by: Anthony Fieroni simplified early exit handling ran formatter check out the whole repo on Travis (for formatter) origin should be there --- .travis.yml | 9 +++++---- reproducible_build.sh | 10 ++++------ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 829422909..f60e6a9a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,17 +2,17 @@ matrix: include: - os: linux sudo: required - dist: trusty + dist: xenial language: c env: TARGET=linux - os: linux sudo: required - dist: trusty + dist: xenial language: c env: TARGET=windows - os: osx language: c - osx_image: xcode7.3 + osx_image: xcode8.3 env: TARGET=osx cache: apt: true @@ -20,11 +20,12 @@ cache: directories: - build - depends/built +git: + depth: false before_install: - date +%s > "${TRAVIS_BUILD_DIR}/start_time" - ls -lh build - du -h -d 2 build -- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update; fi - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install ccache; fi - if [ "$TRAVIS_OS_NAME" == "osx" ]; then export PATH="/usr/local/opt/ccache/libexec:$PATH"; fi install: true diff --git a/reproducible_build.sh b/reproducible_build.sh index 4bd67a034..2a929902f 100755 --- a/reproducible_build.sh +++ b/reproducible_build.sh @@ -237,7 +237,7 @@ function install_apt_packages() { if [ "${CHECK_CODE_FORMAT}" = true ]; then $SUDO apt-get ${QUIET} install -y --no-install-recommends \ - clang-format-3.4 + clang-format-3.9 fi } @@ -327,6 +327,7 @@ function build_libevent() { } function build_dependency() { + pushd . PREFIX=$1 LOG=$2 BUILD=$3 @@ -337,6 +338,7 @@ function build_dependency() { "${BUILD}" "${LOG}" trap - INT TERM EXIT fi + popd } function build_lbrycrd() { @@ -370,11 +372,7 @@ function build_lbrycrd() { function clang_format_diff(){ # run a code formatting check on any commits not in master # requires clang-format - if ! git config remote.origin2.url > /dev/null; then - git remote add origin2 https://github.com/lbryio/lbrycrd.git - fi - git fetch origin2 - git diff -U0 origin2/master -- '*.h' '*.cpp' | ./contrib/devtools/clang-format-diff.py -p1 + git diff -U0 origin/master -- '*.h' '*.cpp' | ./contrib/devtools/clang-format-diff.py -p1 } # these variables are needed in both functions -- 2.45.3