diff --git a/.travis.yml b/.travis.yml index f60e6a9a7..829422909 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,17 +2,17 @@ matrix: include: - os: linux sudo: required - dist: xenial + dist: trusty language: c env: TARGET=linux - os: linux sudo: required - dist: xenial + dist: trusty language: c env: TARGET=windows - os: osx language: c - osx_image: xcode8.3 + osx_image: xcode7.3 env: TARGET=osx cache: apt: true @@ -20,12 +20,11 @@ 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/README.md b/README.md index 3aa30cb02..a9f8d06f7 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 will be run as-is. +Latest binaries are available from https://github.com/lbryio/lbrycrd/releases. There is no installation procedure, the binaries 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 information about your LBRYcrd node. +Run `./lbrycrd-cli getinfo` to check for some basic informations 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,10 +55,12 @@ 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 @@ -75,7 +77,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 to obtain 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 testnet credits, please contact kay@lbry.io or grin@lbry.io. ## License diff --git a/configure.ac b/configure.ac index d19f0eb32..6be5a02b9 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, 3) -define(_CLIENT_VERSION_BUILD, 1) +define(_CLIENT_VERSION_REVISION, 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/contrib/devtools/clang-format-diff.py b/contrib/devtools/clang-format-diff.py index b0dd9f59a..13d2573b9 100755 --- a/contrib/devtools/clang-format-diff.py +++ b/contrib/devtools/clang-format-diff.py @@ -144,8 +144,7 @@ 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/reproducible_build.sh b/reproducible_build.sh index 2a929902f..4bd67a034 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.9 + clang-format-3.4 fi } @@ -327,7 +327,6 @@ function build_libevent() { } function build_dependency() { - pushd . PREFIX=$1 LOG=$2 BUILD=$3 @@ -338,7 +337,6 @@ function build_dependency() { "${BUILD}" "${LOG}" trap - INT TERM EXIT fi - popd } function build_lbrycrd() { @@ -372,7 +370,11 @@ function build_lbrycrd() { function clang_format_diff(){ # run a code formatting check on any commits not in master # requires clang-format - git diff -U0 origin/master -- '*.h' '*.cpp' | ./contrib/devtools/clang-format-diff.py -p1 + 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 } # these variables are needed in both functions diff --git a/src/claimtrie.cpp b/src/claimtrie.cpp index f4b1ccd98..ff72ccb43 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; @@ -403,6 +403,28 @@ 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; @@ -505,26 +527,39 @@ 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, const uint160& claimId, std::vector* supports) const +CAmount CClaimTrie::getEffectiveAmountForClaim(const std::string& name, uint160 claimId) const { - return getEffectiveAmountForClaim(getClaimsForName(name), claimId, supports); + std::vector supports; + return getEffectiveAmountForClaimWithSupports(name, claimId, supports); } -CAmount CClaimTrie::getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector* supports) const +//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 { + claimsForNameType claims = getClaimsForName(name); CAmount effectiveAmount = 0; - for (std::vector::const_iterator it = claims.claims.begin(); it != claims.claims.end(); ++it) { - if (it->claimId == claimId && it->nValidAtHeight < nCurrentHeight) { + bool claim_found = false; + for (std::vector::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); - } - } + 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) + { + effectiveAmount += it->nAmount; + supports.push_back(*it); + } + } return effectiveAmount; } @@ -1175,7 +1210,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); @@ -1207,8 +1242,11 @@ uint256 CClaimTrieCache::getMerkleHash() const } if (dirty()) { - CClaimTrieNode* root = getRoot(); - recursiveComputeMerkleHash(root, ""); + nodeCacheType::iterator cachedNode = cache.find(""); + if (cachedNode != cache.end()) + recursiveComputeMerkleHash(cachedNode->second, ""); + else + recursiveComputeMerkleHash(&(base->root), ""); } hashMapType::iterator ithash = cacheHashes.find(""); if (ithash != cacheHashes.end()) @@ -1260,8 +1298,11 @@ bool CClaimTrieCache::getOriginalInfoForName(const std::string& name, CClaimValu bool CClaimTrieCache::insertClaimIntoTrie(const std::string& name, CClaimValue claim, bool fCheckTakeover) const { assert(base); - CClaimTrieNode* currentNode = getRoot(); + CClaimTrieNode* currentNode = &(base->root); 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); @@ -1279,7 +1320,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 @@ -1346,8 +1387,11 @@ 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 = getRoot(); + CClaimTrieNode* currentNode = &(base->root); 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) { @@ -1380,7 +1424,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__); @@ -1417,7 +1461,10 @@ bool CClaimTrieCache::removeClaimFromTrie(const std::string& name, const COutPoi if (fCheckTakeover) namesToCheckForTakeover.insert(name); } - CClaimTrieNode* rootNode = getRoot(); + CClaimTrieNode* rootNode = &(base->root); + cachedNode = cache.find(""); + if (cachedNode != cache.end()) + rootNode = cachedNode->second; return recursivePruneName(rootNode, 0, name); } @@ -1456,7 +1503,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. @@ -1631,20 +1678,20 @@ bool CClaimTrieCache::removeClaimFromQueue(const std::string& name, const COutPo return false; } -bool CClaimTrieCache::undoAddClaim(const std::string& name, const COutPoint& outPoint) const +bool CClaimTrieCache::undoAddClaim(const std::string& name, const COutPoint& outPoint, int nHeight) const { int throwaway; - return removeClaim(name, outPoint, throwaway, false); + return removeClaim(name, outPoint, nHeight, throwaway, false); } -bool CClaimTrieCache::spendClaim(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const +bool CClaimTrieCache::spendClaim(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight) const { - return removeClaim(name, outPoint, nValidAtHeight, true); + return removeClaim(name, outPoint, nHeight, nValidAtHeight, true); } -bool CClaimTrieCache::removeClaim(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight, bool fCheckTakeover) const +bool CClaimTrieCache::removeClaim(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight, bool fCheckTakeover) const { - LogPrintf("%s: name: %s, txhash: %s, nOut: %s, nCurrentHeight: %s\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nCurrentHeight); + 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)) @@ -1658,7 +1705,7 @@ bool CClaimTrieCache::removeClaim(const std::string& name, const COutPoint& outP if (removed == true) { nValidAtHeight = claim.nValidAtHeight; - int expirationHeight = claim.nHeight + base->nExpirationTime; + int expirationHeight = nHeight + base->nExpirationTime; removeFromExpirationQueue(name, outPoint, expirationHeight); claimsToDelete.insert(claim); } @@ -1718,7 +1765,12 @@ bool CClaimTrieCache::reorderTrieNode(const std::string& name, bool fCheckTakeov cachedNode = cache.find(name); if (cachedNode == cache.end()) { - CClaimTrieNode* currentNode = getRoot(); + CClaimTrieNode* currentNode; + cachedNode = cache.find(""); + if(cachedNode == cache.end()) + currentNode = &(base->root); + else + currentNode = cachedNode->second; for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) { std::string sCurrentSubstring(name.begin(), itCur); @@ -2162,7 +2214,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 @@ -2213,7 +2265,7 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy } if (takeoverHappened) { - // Get all pending claims for that name and activate them all in the case that our winner is defunct. + // Get all claims in the queue for that name queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(*itNamesToCheck, false); if (itQueueNameRow != claimQueueNameCache.end()) { @@ -2253,7 +2305,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()) @@ -2344,9 +2396,6 @@ 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)); @@ -2367,15 +2416,11 @@ 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, claim.nValidAtHeight)); + itQueueNameRow->second.push_back(outPointHeightType(itInsertUndo->outPoint, itInsertUndo->nHeight)); } for (std::vector >::iterator itTakeoverHeightUndo = takeoverHeightUndo.begin(); itTakeoverHeightUndo != takeoverHeightUndo.end(); ++itTakeoverHeightUndo) @@ -2418,26 +2463,25 @@ bool CClaimTrieCache::getLastTakeoverForName(const std::string& name, int& nLast int CClaimTrieCache::getNumBlocksOfContinuousOwnership(const std::string& name) const { - const CClaimTrieNode* node = getNodeForName(name); - if (!node || node->claims.empty()) return 0; + 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; + } 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) @@ -2526,134 +2570,12 @@ uint256 CClaimTrieCache::getLeafHashForProof(const std::string& currentPosition, } } -void CClaimTrieCache::recursiveIterateTrie(std::string& name, const CClaimTrieNode* current, CNodeCallback& callback) const -{ - callback.visit(name, current); - - nodeCacheType::const_iterator cachedNode; - for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) { - name.push_back(it->first); - cachedNode = cache.find(name); - if (cachedNode != cache.end()) - recursiveIterateTrie(name, cachedNode->second, callback); - else - recursiveIterateTrie(name, it->second, callback); - name.erase(name.end() - 1); - } -} - -bool CClaimTrieCache::iterateTrie(CNodeCallback& callback) const -{ - 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 -{ - 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 +CClaimTrieProof CClaimTrieCache::getProofForName(const std::string& name) const { if (dirty()) getMerkleHash(); - - CClaimTrieNode* current = getRoot(); - 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 = getRoot(); + CClaimTrieNode* current = &(base->root); nodeCacheType::const_iterator cachedNode; bool fNameHasValue = false; COutPoint outPoint; @@ -2670,8 +2592,7 @@ bool CClaimTrieCache::getProofForName(const std::string& name, CClaimTrieProof& if (fNodeHasValue) { int nHeightOfLastTakeover; - if (!getLastTakeoverForName(currentPosition, nHeightOfLastTakeover)) - return false; + assert(getLastTakeoverForName(currentPosition, nHeightOfLastTakeover)); valueHash = getValueHash(claim.outPoint, nHeightOfLastTakeover); } std::vector > children; @@ -2696,8 +2617,7 @@ bool CClaimTrieCache::getProofForName(const std::string& name, CClaimTrieProof& if (fNameHasValue) { outPoint = claim.outPoint; - if (!getLastTakeoverForName(name, nHeightOfLastTakeover)) - return false; + assert(getLastTakeoverForName(name, nHeightOfLastTakeover)); } valueHash.SetNull(); } @@ -2705,8 +2625,8 @@ bool CClaimTrieCache::getProofForName(const std::string& name, CClaimTrieProof& nodes.push_back(node); current = nextCurrent; } - proof = CClaimTrieProof(nodes, fNameHasValue, outPoint, nHeightOfLastTakeover); - return true; + return CClaimTrieProof(nodes, fNameHasValue, outPoint, + nHeightOfLastTakeover); } diff --git a/src/claimtrie.h b/src/claimtrie.h index d192cf6f6..12ef5c4ad 100644 --- a/src/claimtrie.h +++ b/src/claimtrie.h @@ -56,6 +56,7 @@ public: READWRITE(nAmount); READWRITE(nHeight); READWRITE(nValidAtHeight); + READWRITE(nEffectiveAmount); } bool operator<(const CClaimValue& other) const @@ -132,6 +133,8 @@ typedef std::vector supportMapEntryType; typedef std::map nodeMapType; +typedef std::pair namedNodeType; + class CClaimTrieNode { public: @@ -210,6 +213,7 @@ struct nameOutPointHeightType nameOutPointHeightType(std::string name, COutPoint outPoint, int nHeight) : name(name), outPoint(outPoint), nHeight(nHeight) {} + ADD_SERIALIZE_METHODS; template @@ -315,13 +319,14 @@ 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; 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; + CAmount getEffectiveAmountForClaim(const std::string& name, uint160 claimId) const; + CAmount getEffectiveAmountForClaimWithSupports(const std::string& name, uint160 claimId, + std::vector& supports) const; bool queueEmpty() const; bool supportEmpty() const; @@ -389,6 +394,9 @@ 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); @@ -453,27 +461,6 @@ 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: @@ -491,16 +478,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) const; - bool spendClaim(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) 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; @@ -537,9 +520,7 @@ public: bool removeClaimFromTrie(const std::string& name, const COutPoint& outPoint, CClaimValue& claim, bool fCheckTakeover = false) const; - - bool getProofForName(const std::string& name, CClaimTrieProof& proof) const; - bool getInfoForName(const std::string& name, CClaimValue& claim) const; + CClaimTrieProof getProofForName(const std::string& name) const; bool finalizeDecrement() const; @@ -548,12 +529,6 @@ public: bool forkForExpirationChange(bool increment) const; - bool iterateTrie(CNodeCallback& callback) 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; @@ -572,7 +547,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; @@ -591,7 +566,9 @@ protected: bool clear() const; - bool removeClaim(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight, bool fCheckTakeover) const; + bool removeClaim(const std::string& name, const COutPoint& outPoint, + int nHeight, 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; @@ -649,10 +626,6 @@ protected: bool getOriginalInfoForName(const std::string& name, CClaimValue& claim) const; int getNumBlocksOfContinuousOwnership(const std::string& name) const; - - void recursiveIterateTrie(std::string& name, const CClaimTrieNode* current, CNodeCallback& callback) const; - - const CClaimTrieNode* getNodeForName(const std::string& name) const; }; #endif // BITCOIN_CLAIMTRIE_H diff --git a/src/clientversion.h b/src/clientversion.h index dbcf9c627..67a55a4a9 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 3 -#define CLIENT_VERSION_BUILD 1 +#define CLIENT_VERSION_REVISION 2 +#define CLIENT_VERSION_BUILD 3 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/main.cpp b/src/main.cpp index 38f738834..d910d8da8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -963,12 +963,13 @@ 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 @@ -2193,7 +2194,8 @@ 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))) { + if (!trieCache.undoAddClaim(name, COutPoint(hash, i), pindex->nHeight)) + { LogPrintf("%s: Could not find the claim in the trie or the cache\n", __func__); } } @@ -2501,7 +2503,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) { @@ -2586,7 +2588,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]; @@ -2623,7 +2625,8 @@ 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), nValidAtHeight)) { + if (trieCache.spendClaim(name, COutPoint(txin.prevout.hash, txin.prevout.n), coins->nHeight, nValidAtHeight)) + { mClaimUndoHeights[i] = nValidAtHeight; std::pair entry(name, claimId); spentClaims.push_back(entry); @@ -2646,7 +2649,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]; @@ -4215,8 +4218,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; @@ -4264,6 +4267,42 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, 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); + 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; +} + void UnloadBlockIndex() { LOCK(cs_main); @@ -4306,7 +4345,7 @@ bool LoadBlockIndex() return true; } -bool InitBlockIndex(const CChainParams& chainparams) +bool InitBlockIndex(const CChainParams& chainparams) { LOCK(cs_main); diff --git a/src/main.h b/src/main.h index 00bfcb5dd..4dfc5b2ca 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); +/** 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/miner.cpp b/src/miner.cpp index bfa5613e1..8136d8e80 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -294,7 +294,8 @@ 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), throwaway)) { + if (trieCache.spendClaim(name, COutPoint(txin.prevout.hash, txin.prevout.n), nTxinHeight, throwaway)) + { std::pair entry(name, claimId); spentClaims.push_back(entry); } @@ -315,11 +316,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)) @@ -567,7 +568,7 @@ void static BitcoinMiner(const CChainParams& chainparams) while (true) { unsigned int nHashesDone = 0; - + // Check if something found while (true) { @@ -598,7 +599,7 @@ void static BitcoinMiner(const CChainParams& chainparams) } if (found) break; - + // Meter hashes/sec static int64_t nHashCounter; if (nHPSTimerStart == 0) diff --git a/src/rpc/claimtrie.cpp b/src/rpc/claimtrie.cpp index dc66cefa2..b0b3d0d49 100644 --- a/src/rpc/claimtrie.cpp +++ b/src/rpc/claimtrie.cpp @@ -1,15 +1,11 @@ -#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" +#include "txmempool.h" -#include - -#include +// Maximum block decrement that is allowed from rpc calls +const int MAX_RPC_BLOCK_DECREMENTS = 50; uint160 ParseClaimtrieId(const UniValue& v, const std::string& strName) { @@ -26,129 +22,72 @@ 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"); - - 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"); - - 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) { - if (fHelp || params.size() > 1) + if (fHelp || params.size() > 0) throw std::runtime_error( "getclaimsintrie\n" "Return all claims in the name trie.\n" "Arguments:\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" + "None\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); + UniValue ret(UniValue::VARR); - CCoinsViewCache coinsCache(pcoinsTip); - CClaimTrieCache trieCache(pclaimTrie); + CCoinsViewCache view(pcoinsTip); + std::vector nodes = pclaimTrie->flattenTrie(); - if (!params.empty()) { - CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[0], "blockhash (optional parameter 1)")); - RollBackTo(blockIndex, coinsCache, trieCache); - } - - class CClaimsCallback : public CNodeCallback + for (std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it) { - public: - CClaimsCallback(UniValue& ret, const CCoinsViewCache& coinsCache) : nodes(ret), coinsCache(coinsCache) + if (!it->second.claims.empty()) { - } - - 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 node(UniValue::VOBJ); + node.push_back(Pair("name", it->first)); UniValue claims(UniValue::VARR); - for (std::vector::const_iterator itClaims = node->claims.begin(); itClaims != node->claims.end(); ++itClaims) { + 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("amount", ValueFromAmount(itClaims->nAmount))); claim.push_back(Pair("height", itClaims->nHeight)); - const CCoins* coin = coinsCache.AccessCoins(itClaims->outPoint.hash); - if (!coin) { + 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()); + __func__, itClaims->outPoint.hash.GetHex()); claim.push_back(Pair("error", "No value found for claim")); - } else if (!coin->IsAvailable(itClaims->outPoint.n)) { + } + 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 { + } + else + { int op; std::vector > vvchParams; - if (!DecodeClaimScript(coin->vout[itClaims->outPoint.n].scriptPubKey, op, 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()); @@ -156,112 +95,70 @@ UniValue getclaimsintrie(const UniValue& params, bool fHelp) } claims.push_back(claim); } - - UniValue nodeObj(UniValue::VOBJ); - nodeObj.push_back(Pair("name", name)); - nodeObj.push_back(Pair("claims", claims)); - nodes.push_back(nodeObj); + node.push_back(Pair("claims", claims)); + ret.push_back(node); } - - private: - UniValue& nodes; - const CCoinsViewCache& coinsCache; - }; - - UniValue ret(UniValue::VARR); - CClaimsCallback claimsCallback(ret, coinsCache); - trieCache.iterateTrie(claimsCallback); + } return ret; } UniValue getclaimtrie(const UniValue& params, bool fHelp) { - if (fHelp || params.size() > 1) + if (fHelp || params.size() > 0) throw std::runtime_error( "getclaimtrie\n" - "DEPRECATED. Return the entire name trie.\n" + "Return the entire name trie.\n" "Arguments:\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" + "None\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); - - CCoinsViewCache coinsCache(pcoinsTip); - CClaimTrieCache trieCache(pclaimTrie); - - if (!params.empty()) { - CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[0], "blockhash (optional parameter 1)")); - RollBackTo(blockIndex, coinsCache, trieCache); - } - - class CClaimCallback : public CNodeCallback - { - public: - CClaimCallback(UniValue& ret) : nodes(ret) - { - } - - 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); + + std::vector nodes = pclaimTrie->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("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)); + } + ret.push_back(node); + } return ret; } -bool getValueForClaim(const CCoinsViewCache& coinsCache, const COutPoint& out, std::string& sValue) +bool getValueForClaim(const COutPoint& out, std::string& sValue) { - const CCoins* coin = coinsCache.AccessCoins(out.hash); + CCoinsViewCache view(pcoinsTip); + const CCoins* coin = view.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)) @@ -283,115 +180,118 @@ bool getValueForClaim(const CCoinsViewCache& coinsCache, const COutPoint& out, s UniValue getvalueforname(const UniValue& params, bool fHelp) { - if (fHelp || params.size() > 2) + if (fHelp || params.size() != 1) 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" - "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" + "1. \"name\" (string) the name to look up\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); - - CCoinsViewCache coinsCache(pcoinsTip); - CClaimTrieCache trieCache(pclaimTrie); - - if (params.size() > 1) { - CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[1], "blockhash (optional parameter 2)")); - RollBackTo(blockIndex, coinsCache, trieCache); - } - + std::string name = params[0].get_str(); CClaimValue claim; UniValue ret(UniValue::VOBJ); - 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(coinsCache, claim.outPoint, sValue)) + if (!pclaimTrie->getInfoForName(name, claim)) + return ret; + std::string sValue; + if (!getValueForClaim(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", nEffectiveAmount)); + ret.push_back(Pair("effective amount", pclaimTrie->getEffectiveAmountForClaim(name, claim.claimId))); ret.push_back(Pair("height", claim.nHeight)); return ret; } typedef std::pair > claimAndSupportsType; typedef std::map claimSupportMapType; +typedef std::map > supportsWithoutClaimsMapType; -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(const CCoinsViewCache& coinsCache, CAmount nEffectiveAmount, claimSupportMapType::const_iterator itClaimsAndSupports) +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; + CAmount nEffectiveAmount = 0; UniValue supportObjs(UniValue::VARR); - for (std::vector::const_iterator itSupports = supports.begin(); itSupports != supports.end(); ++itSupports) { - supportObjs.push_back(supportToJSON(*itSupports)); + 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); } 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(coinsCache, claim.outPoint, 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() > 2) + if (fHelp || params.size() != 1) 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" - "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" + "1. \"name\" (string) the name for which to get claims and supports\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" @@ -399,7 +299,6 @@ 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" @@ -410,7 +309,7 @@ UniValue getclaimsforname(const UniValue& params, bool fHelp) " ]\n" " }\n" " ],\n" - " \"supports without claims\": [ (array of object) supports that did not match a claim for this name\n" + " \"unmatched supports\": [ (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" @@ -419,49 +318,49 @@ UniValue getclaimsforname(const UniValue& params, bool fHelp) " \"nAmount\" (numeric) the amount of the support\n" " }\n" " ]\n" - "}\n"); + "}\n" + ); LOCK(cs_main); - - CCoinsViewCache coinsCache(pcoinsTip); - CClaimTrieCache trieCache(pclaimTrie); - - if (params.size() > 1) { - CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[1], "blockhash (optional parameter 2)")); - RollBackTo(blockIndex, coinsCache, trieCache); - } - std::string name = params[0].get_str(); - claimsForNameType claimsForName = trieCache.getClaimsForName(name); + claimsForNameType claimsForName = pclaimTrie->getClaimsForName(name); + int nCurrentHeight = chainActive.Height(); - UniValue claimObjs(UniValue::VARR); claimSupportMapType claimSupportMap; - UniValue unmatchedSupports(UniValue::VARR); - - for (std::vector::const_iterator itClaims = claimsForName.claims.begin(); itClaims != claimsForName.claims.end(); ++itClaims) { + supportsWithoutClaimsMapType supportsWithoutClaims; + 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()) { - unmatchedSupports.push_back(supportToJSON(*itSupports)); - } else { + if (itClaimAndSupports == claimSupportMap.end()) + { + std::pair ret = supportsWithoutClaims.insert(std::pair >(itSupports->supportedClaimId, std::vector())); + ret.first->second.push_back(*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) { - CAmount nEffectiveAmount = trieCache.getEffectiveAmountForClaim(claimsForName, itClaimsAndSupports->first); - UniValue claimObj = claimAndSupportsToJSON(coinsCache, nEffectiveAmount, itClaimsAndSupports); - claimObjs.push_back(claimObj); + for (claimSupportMapType::const_iterator itClaimsAndSupports = claimSupportMap.begin(); itClaimsAndSupports != claimSupportMap.end(); ++itClaimsAndSupports) + { + UniValue claimAndSupportsObj = claimsAndSupportsToJSON(itClaimsAndSupports, nCurrentHeight); + claimObjs.push_back(claimAndSupportsObj); } - 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)); return ret; } @@ -504,11 +403,11 @@ UniValue getclaimbyid(const UniValue& params, bool fHelp) if (claimValue.claimId == claimId) { std::vector supports; - CAmount effectiveAmount = pclaimTrie->getEffectiveAmountForClaim(name, claimValue.claimId, &supports); + CAmount effectiveAmount = pclaimTrie->getEffectiveAmountForClaimWithSupports( + name, claimValue.claimId, supports); std::string sValue; - CCoinsViewCache coins(pcoinsTip); - getValueForClaim(coins, claimValue.outPoint, sValue); + getValueForClaim(claimValue.outPoint, sValue); claim.push_back(Pair("name", name)); claim.push_back(Pair("value", sValue)); claim.push_back(Pair("claimId", claimValue.claimId.GetHex())); @@ -549,7 +448,7 @@ UniValue gettotalclaimednames(const UniValue& params, bool fHelp) if (!pclaimTrie) { return -1; - } + } unsigned int num_names = pclaimTrie->getTotalNamesInTrie(); return int(num_names); } @@ -632,7 +531,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; @@ -831,7 +730,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" @@ -849,18 +748,29 @@ UniValue getnameproof(const UniValue& params, bool fHelp) "}\n"); LOCK(cs_main); - - CCoinsViewCache coinsCache(pcoinsTip); - CClaimTrieCache trieCache(pclaimTrie); - - if (params.size() == 2) { - CBlockIndex* pblockIndex = BlockHashIndex(ParseHashV(params[1], "blockhash (optional parameter 2)")); - RollBackTo(pblockIndex, coinsCache, trieCache); + std::string strName = params[0].get_str(); + uint256 blockHash; + if (params.size() == 2) + { + blockHash = ParseHashV(params[1], "blockhash (optional parameter 2)"); + } + 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; - std::string name = params[0].get_str(); - if (!trieCache.getProofForName(name, proof)) + if (!GetProofForName(pblockIndex, strName, proof)) throw JSONRPCError(RPC_INTERNAL_ERROR, "Failed to generate proof"); return proofToJSON(proof); diff --git a/src/test/claimtriebranching_tests.cpp b/src/test/claimtriebranching_tests.cpp index bc5bb8e3f..5e832d629 100644 --- a/src/test/claimtriebranching_tests.cpp +++ b/src/test/claimtriebranching_tests.cpp @@ -2,59 +2,58 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://opensource.org/licenses/mit-license.php -#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 "consensus/validation.h" +#include "consensus/merkle.h" #include "primitives/transaction.h" -#include "rpc/server.h" -#include "streams.h" -#include "test/test_bitcoin.h" +#include "miner.h" #include "txmempool.h" +#include "claimtrie.h" +#include "nameclaim.h" +#include "coins.h" +#include "streams.h" +#include "chainparams.h" +#include "policy/policy.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) { 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; } } @@ -111,15 +110,56 @@ 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; -// Test Fixtures +} + +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; + int coinbase_txs_used; + unsigned int num_txs; + unsigned int num_txs_for_next_block; // these will take on regtest parameters const int expirationForkHeight; @@ -135,11 +175,9 @@ 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; + num_txs = 0; coinbase_txs_used = 0; - unique_block_counter = 0; // generate coinbases to spend CreateCoinbases(40, coinbase_txs); } @@ -150,43 +188,6 @@ 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++; @@ -203,29 +204,30 @@ 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) @@ -240,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; } @@ -254,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; } @@ -277,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); @@ -335,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 @@ -351,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); @@ -359,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); @@ -398,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); @@ -406,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)); - - fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test", tx1)); + BOOST_CHECK(is_best_claim("test",tx2)); + fixture.DecrementBlocks(1); + BOOST_CHECK(is_best_claim("test",tx1)); + fixture.DecrementBlocks(1); // spending winning claim will make inactive claim winner @@ -433,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); @@ -446,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)); @@ -463,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); @@ -480,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)); @@ -498,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); } @@ -569,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) { @@ -579,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)); @@ -588,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); @@ -598,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; @@ -616,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); @@ -658,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()); @@ -675,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; @@ -699,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)); @@ -715,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) { @@ -974,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); @@ -1018,65 +1020,6 @@ 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 */ @@ -1956,29 +1899,6 @@ 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; @@ -3011,31 +2931,31 @@ BOOST_AUTO_TEST_CASE(value_proof_test) CClaimTrieProof proof; - BOOST_CHECK(cache.getProofForName(sName1, proof)); + proof = cache.getProofForName(sName1); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName1)); BOOST_CHECK(proof.outPoint == tx1OutPoint); - BOOST_CHECK(cache.getProofForName(sName2, proof)); + proof = cache.getProofForName(sName2); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName2)); BOOST_CHECK(proof.outPoint == tx2OutPoint); - BOOST_CHECK(cache.getProofForName(sName3, proof)); + proof = cache.getProofForName(sName3); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName3)); BOOST_CHECK(proof.outPoint == tx3OutPoint); - BOOST_CHECK(cache.getProofForName(sName4, proof)); + proof = cache.getProofForName(sName4); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName4)); BOOST_CHECK(proof.outPoint == tx4OutPoint); - BOOST_CHECK(cache.getProofForName(sName5, proof)); + proof = cache.getProofForName(sName5); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName5)); BOOST_CHECK(proof.hasValue == false); - BOOST_CHECK(cache.getProofForName(sName6, proof)); + proof = cache.getProofForName(sName6); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName6)); BOOST_CHECK(proof.hasValue == false); - BOOST_CHECK(cache.getProofForName(sName7, proof)); + proof = cache.getProofForName(sName7); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName7)); BOOST_CHECK(proof.hasValue == false); @@ -3049,31 +2969,31 @@ BOOST_AUTO_TEST_CASE(value_proof_test) cache = CClaimTrieCache(pclaimTrie); - BOOST_CHECK(cache.getProofForName(sName1, proof)); + proof = cache.getProofForName(sName1); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName1)); BOOST_CHECK(proof.outPoint == tx1OutPoint); - BOOST_CHECK(cache.getProofForName(sName2, proof)); + proof = cache.getProofForName(sName2); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName2)); BOOST_CHECK(proof.outPoint == tx2OutPoint); - BOOST_CHECK(cache.getProofForName(sName3, proof)); + proof = cache.getProofForName(sName3); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName3)); BOOST_CHECK(proof.outPoint == tx3OutPoint); - BOOST_CHECK(cache.getProofForName(sName4, proof)); + proof = cache.getProofForName(sName4); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName4)); BOOST_CHECK(proof.outPoint == tx4OutPoint); - BOOST_CHECK(cache.getProofForName(sName5, proof)); + proof = cache.getProofForName(sName5); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName5)); BOOST_CHECK(proof.hasValue == false); - BOOST_CHECK(cache.getProofForName(sName6, proof)); + proof = cache.getProofForName(sName6); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName6)); BOOST_CHECK(proof.hasValue == false); - BOOST_CHECK(cache.getProofForName(sName7, proof)); + proof = cache.getProofForName(sName7); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName7)); BOOST_CHECK(proof.outPoint == tx5OutPoint); @@ -3213,248 +3133,4 @@ 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(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; - 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() diff --git a/src/test/claimtriecache_tests.cpp b/src/test/claimtriecache_tests.cpp index aa06fd19e..e94624268 100644 --- a/src/test/claimtriecache_tests.cpp +++ b/src/test/claimtriecache_tests.cpp @@ -1,6 +1,5 @@ #include "claimtrie.h" #include "main.h" -#include "nameclaim.h" #include "uint256.h" #include "test/test_bitcoin.h" @@ -23,12 +22,6 @@ 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(); @@ -194,48 +187,6 @@ 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); @@ -274,58 +225,5 @@ 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() diff --git a/src/txdb.h b/src/txdb.h index 9186aab61..749802f0e 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 = sizeof(void*) > 4 ? 700 : 500; +static const int64_t nDefaultDbCache = 100; //! max. -dbcache in (MiB) static const int64_t nMaxDbCache = sizeof(void*) > 4 ? 16384 : 1024; //! min. -dbcache in (MiB)