From 7d321ec0eac0a9cb14a3ef078f134a87f6aed956 Mon Sep 17 00:00:00 2001 From: Anthony Fieroni Date: Sat, 19 May 2018 23:55:32 +0300 Subject: [PATCH] Separate disk related functions in CClaimTrieDb Signed-off-by: Anthony Fieroni --- configure.ac | 4 +- reproducible_build.sh | 7 +- src/Makefile.am | 2 + src/chainparams.cpp | 9 + src/claimtrie.cpp | 670 ++++++++------------------ src/claimtrie.h | 148 +++--- src/claimtriedb.cpp | 188 ++++++++ src/claimtriedb.h | 40 ++ src/clientversion.h | 4 +- src/consensus/params.h | 8 + src/init.cpp | 8 +- src/main.cpp | 41 ++ src/pow.cpp | 28 +- src/test/claimtriebranching_tests.cpp | 224 ++++++++- 14 files changed, 802 insertions(+), 579 deletions(-) create mode 100644 src/claimtriedb.cpp create mode 100644 src/claimtriedb.h diff --git a/configure.ac b/configure.ac index a419b9249..7445545d5 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, 1) -define(_CLIENT_VERSION_BUILD, 2) +define(_CLIENT_VERSION_REVISION, 2) +define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2016) define(_COPYRIGHT_HOLDERS,[The %s developers]) diff --git a/reproducible_build.sh b/reproducible_build.sh index 3b6df6a09..95cffb032 100755 --- a/reproducible_build.sh +++ b/reproducible_build.sh @@ -232,7 +232,7 @@ function build_dependencies() { else install_apt_packages fi - + if [ "$CLEAN" = true ]; then rm -rf "${LBRYCRD_DEPENDENCIES}" rm -rf "${OUTPUT_DIR}" @@ -246,7 +246,7 @@ function build_dependencies() { build_dependency "${BDB_PREFIX}" "${LOG_DIR}/bdb_build.log" build_bdb build_dependency "${OPENSSL_PREFIX}" "${LOG_DIR}/openssl_build.log" build_openssl - + set +u export PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:${OPENSSL_PREFIX}/lib/pkgconfig/" set -u @@ -277,8 +277,9 @@ function build_openssl() { -fPIC darwin64-x86_64-cc \ no-shared no-dso no-engines > "${OPENSSL_LOG}" else + [[ $(uname -m) = 'i686' ]] && OS_ARCH="linux-generic32" || OS_ARCH="linux-x86_64" ./Configure --prefix="${OPENSSL_PREFIX}" --openssldir="${OPENSSL_PREFIX}/ssl" \ - linux-x86_64 -fPIC -static no-shared no-dso > "${OPENSSL_LOG}" + ${OS_ARCH} -fPIC -static no-shared no-dso > "${OPENSSL_LOG}" fi background make "${OPENSSL_LOG}" "Waiting for openssl to finish building" make install >> "${OPENSSL_LOG}" 2>&1 diff --git a/src/Makefile.am b/src/Makefile.am index a9f0a949c..0352c3df7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -119,6 +119,7 @@ BITCOIN_CORE_H = \ miner.h \ nameclaim.h \ claimtrie.h \ + claimtriedb.h \ lbry.h \ net.h \ netbase.h \ @@ -191,6 +192,7 @@ libbitcoin_server_a_SOURCES = \ merkleblock.cpp \ miner.cpp \ claimtrie.cpp \ + claimtriedb.cpp \ net.cpp \ noui.cpp \ policy/fees.cpp \ diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 91923ea70..2f7d71c1b 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -131,6 +131,9 @@ public: consensus.powLimit = uint256S("0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.nPowTargetTimespan = 150; //retarget every block consensus.nPowTargetSpacing = 150; + consensus.nOriginalClaimExpirationTime = 262974; + consensus.nExtendedClaimExpirationTime = 2102400; + consensus.nExtendedClaimExpirationForkHeight = 400155; consensus.fPowAllowMinDifficultyBlocks = false; consensus.fPowNoRetargeting = false; consensus.nRuleChangeActivationThreshold = 1916; // 95% of 2016 @@ -215,6 +218,9 @@ public: consensus.powLimit = uint256S("0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.nPowTargetTimespan = 150; consensus.nPowTargetSpacing = 150; + consensus.nOriginalClaimExpirationTime = 262974; + consensus.nExtendedClaimExpirationTime = 2102400; + consensus.nExtendedClaimExpirationForkHeight = 278160; consensus.fPowAllowMinDifficultyBlocks = true; consensus.fPowNoRetargeting = false; consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains @@ -292,6 +298,9 @@ public: consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.nPowTargetTimespan = 1;//14 * 24 * 60 * 60; // two weeks consensus.nPowTargetSpacing = 1; + consensus.nOriginalClaimExpirationTime = 500; + consensus.nExtendedClaimExpirationTime = 600; + consensus.nExtendedClaimExpirationForkHeight = 800; consensus.fPowAllowMinDifficultyBlocks = false; consensus.fPowNoRetargeting = false; consensus.nRuleChangeActivationThreshold = 108; // 75% for testchains diff --git a/src/claimtrie.cpp b/src/claimtrie.cpp index f5e97444c..aef95cc3f 100644 --- a/src/claimtrie.cpp +++ b/src/claimtrie.cpp @@ -2,10 +2,14 @@ #include "coins.h" #include "hash.h" -#include #include #include +#define HASH_BLOCK 'h' +#define CURRENT_HEIGHT 't' + +#include "claimtriedb.cpp" // avoid linker problems + std::vector heightToVch(int n) { std::vector vchHeight; @@ -27,7 +31,7 @@ uint256 getValueHash(COutPoint outPoint, int nHeightOfLastTakeover) txHasher.Write(outPoint.hash.begin(), outPoint.hash.size()); std::vector vchtxHash(txHasher.OUTPUT_SIZE); txHasher.Finalize(&(vchtxHash[0])); - + CHash256 nOutHasher; std::stringstream ss; ss << outPoint.n; @@ -48,7 +52,7 @@ uint256 getValueHash(COutPoint outPoint, int nHeightOfLastTakeover) hasher.Write(vchTakeoverHash.data(), vchTakeoverHash.size()); std::vector vchHash(hasher.OUTPUT_SIZE); hasher.Finalize(&(vchHash[0])); - + uint256 valueHash(vchHash); return valueHash; } @@ -116,7 +120,7 @@ bool CClaimTrieNode::haveClaim(const COutPoint& outPoint) const void CClaimTrieNode::reorderClaims(supportMapEntryType& supports) { std::vector::iterator itclaim; - + for (itclaim = claims.begin(); itclaim != claims.end(); ++itclaim) { itclaim->nEffectiveAmount = itclaim->nAmount; @@ -133,7 +137,7 @@ void CClaimTrieNode::reorderClaims(supportMapEntryType& supports) } } } - + std::make_heap(claims.begin(), claims.end()); } @@ -147,77 +151,30 @@ bool CClaimTrie::empty() const return root.empty(); } -template bool CClaimTrie::keyTypeEmpty(char keyType, K& dummy) const -{ - boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); - pcursor->SeekToFirst(); - - while (pcursor->Valid()) - { - std::pair key; - if (pcursor->GetKey(key)) - { - if (key.first == keyType) - { - return false; - } - } - else - { - break; - } - pcursor->Next(); - } - return true; -} - bool CClaimTrie::queueEmpty() const { - for (claimQueueType::const_iterator itRow = dirtyQueueRows.begin(); itRow != dirtyQueueRows.end(); ++itRow) - { - if (!itRow->second.empty()) - return false; - } - int dummy; - return keyTypeEmpty(CLAIM_QUEUE_ROW, dummy); + return db.keyTypeEmpty(); } bool CClaimTrie::expirationQueueEmpty() const { - for (expirationQueueType::const_iterator itRow = dirtyExpirationQueueRows.begin(); itRow != dirtyExpirationQueueRows.end(); ++itRow) - { - if (!itRow->second.empty()) - return false; - } - int dummy; - return keyTypeEmpty(EXP_QUEUE_ROW, dummy); + return db.keyTypeEmpty(); } bool CClaimTrie::supportEmpty() const { - for (supportMapType::const_iterator itNode = dirtySupportNodes.begin(); itNode != dirtySupportNodes.end(); ++itNode) - { - if (!itNode->second.empty()) - return false; - } - std::string dummy; - return keyTypeEmpty(SUPPORT, dummy); + return db.keyTypeEmpty(); } bool CClaimTrie::supportQueueEmpty() const { - for (supportQueueType::const_iterator itRow = dirtySupportQueueRows.begin(); itRow != dirtySupportQueueRows.end(); ++itRow) - { - if (!itRow->second.empty()) - return false; - } - int dummy; - return keyTypeEmpty(SUPPORT_QUEUE_ROW, dummy); + return db.keyTypeEmpty(); } void CClaimTrie::setExpirationTime(int t) { nExpirationTime = t; + LogPrintf("%s: Expiration time is now %d\n", __func__, nExpirationTime); } void CClaimTrie::clear() @@ -250,7 +207,7 @@ bool CClaimTrie::haveClaim(const std::string& name, const COutPoint& outPoint) c bool CClaimTrie::haveSupport(const std::string& name, const COutPoint& outPoint) const { supportMapEntryType node; - if (!getSupportNode(name, node)) + if (!db.getQueueRow(name, node)) { return false; } @@ -265,7 +222,7 @@ bool CClaimTrie::haveSupport(const std::string& name, const COutPoint& outPoint) bool CClaimTrie::haveClaimInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const { queueNameRowType nameRow; - if (!getQueueNameRow(name, nameRow)) + if (!db.getQueueRow(name, nameRow)) { return false; } @@ -283,7 +240,7 @@ bool CClaimTrie::haveClaimInQueue(const std::string& name, const COutPoint& outP return false; } claimQueueRowType row; - if (getQueueRow(nValidAtHeight, row)) + if (db.getQueueRow(nValidAtHeight, row)) { for (claimQueueRowType::const_iterator itRow = row.begin(); itRow != row.end(); ++itRow) { @@ -303,12 +260,12 @@ bool CClaimTrie::haveClaimInQueue(const std::string& name, const COutPoint& outP bool CClaimTrie::haveSupportInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const { - queueNameRowType nameRow; - if (!getSupportQueueNameRow(name, nameRow)) + supportQueueNameRowType nameRow; + if (!db.getQueueRow(name, nameRow)) { return false; } - queueNameRowType::const_iterator itNameRow; + supportQueueNameRowType::const_iterator itNameRow; for (itNameRow = nameRow.begin(); itNameRow != nameRow.end(); ++itNameRow) { if (itNameRow->outPoint == outPoint) @@ -322,7 +279,7 @@ bool CClaimTrie::haveSupportInQueue(const std::string& name, const COutPoint& ou return false; } supportQueueRowType row; - if (getSupportQueueRow(nValidAtHeight, row)) + if (db.getQueueRow(nValidAtHeight, row)) { for (supportQueueRowType::const_iterator itRow = row.begin(); itRow != row.end(); ++itRow) { @@ -476,7 +433,7 @@ claimsForNameType CClaimTrie::getClaimsForName(const std::string& name) const } } supportMapEntryType supportNode; - if (getSupportNode(name, supportNode)) + if (db.getQueueRow(name, supportNode)) { for (std::vector::const_iterator itSupports = supportNode.begin(); itSupports != supportNode.end(); ++itSupports) { @@ -484,12 +441,12 @@ claimsForNameType CClaimTrie::getClaimsForName(const std::string& name) const } } queueNameRowType namedClaimRow; - if (getQueueNameRow(name, namedClaimRow)) + if (db.getQueueRow(name, namedClaimRow)) { for (queueNameRowType::const_iterator itClaimsForName = namedClaimRow.begin(); itClaimsForName != namedClaimRow.end(); ++itClaimsForName) { claimQueueRowType claimRow; - if (getQueueRow(itClaimsForName->nHeight, claimRow)) + if (db.getQueueRow(itClaimsForName->nHeight, claimRow)) { for (claimQueueRowType::const_iterator itClaimRow = claimRow.begin(); itClaimRow != claimRow.end(); ++itClaimRow) { @@ -502,13 +459,13 @@ claimsForNameType CClaimTrie::getClaimsForName(const std::string& name) const } } } - queueNameRowType namedSupportRow; - if (getSupportQueueNameRow(name, namedSupportRow)) + supportQueueNameRowType namedSupportRow; + if (db.getQueueRow(name, namedSupportRow)) { - for (queueNameRowType::const_iterator itSupportsForName = namedSupportRow.begin(); itSupportsForName != namedSupportRow.end(); ++itSupportsForName) + for (supportQueueNameRowType::const_iterator itSupportsForName = namedSupportRow.begin(); itSupportsForName != namedSupportRow.end(); ++itSupportsForName) { supportQueueRowType supportRow; - if (getSupportQueueRow(itSupportsForName->nHeight, supportRow)) + if (db.getQueueRow(itSupportsForName->nHeight, supportRow)) { for (supportQueueRowType::const_iterator itSupportRow = supportRow.begin(); itSupportRow != supportRow.end(); ++itSupportRow) { @@ -596,18 +553,19 @@ void CClaimTrie::addToClaimIndex(const std::string& name, const CClaimValue& cla CClaimIndexElement element = { name, claim }; LogPrintf("%s: ClaimIndex[%s] updated %s\n", __func__, claim.claimId.GetHex(), name); - db.Write(std::make_pair(CLAIM_BY_ID, claim.claimId), element); + db.updateQueueRow(claim.claimId, element); } void CClaimTrie::removeFromClaimIndex(const CClaimValue& claim) { - db.Erase(std::make_pair(CLAIM_BY_ID, claim.claimId)); + CClaimIndexElement element; + db.updateQueueRow(claim.claimId, element); } bool CClaimTrie::getClaimById(const uint160 claimId, std::string& name, CClaimValue& claim) const { CClaimIndexElement element; - if (db.Read(std::make_pair(CLAIM_BY_ID, claimId), element)) + if (db.getQueueRow(claimId, element)) { name = element.name; claim = element.claim; @@ -616,182 +574,7 @@ bool CClaimTrie::getClaimById(const uint160 claimId, std::string& name, CClaimVa return false; } -bool CClaimTrie::getQueueRow(int nHeight, claimQueueRowType& row) const -{ - claimQueueType::const_iterator itQueueRow = dirtyQueueRows.find(nHeight); - if (itQueueRow != dirtyQueueRows.end()) - { - row = itQueueRow->second; - return true; - } - return db.Read(std::make_pair(CLAIM_QUEUE_ROW, nHeight), row); -} - -bool CClaimTrie::getQueueNameRow(const std::string& name, queueNameRowType& row) const -{ - queueNameType::const_iterator itQueueNameRow = dirtyQueueNameRows.find(name); - if (itQueueNameRow != dirtyQueueNameRows.end()) - { - row = itQueueNameRow->second; - return true; - } - return db.Read(std::make_pair(CLAIM_QUEUE_NAME_ROW, name), row); -} - -bool CClaimTrie::getExpirationQueueRow(int nHeight, expirationQueueRowType& row) const -{ - expirationQueueType::const_iterator itQueueRow = dirtyExpirationQueueRows.find(nHeight); - if (itQueueRow != dirtyExpirationQueueRows.end()) - { - row = itQueueRow->second; - return true; - } - return db.Read(std::make_pair(EXP_QUEUE_ROW, nHeight), row); -} - -void CClaimTrie::updateQueueRow(int nHeight, claimQueueRowType& row) -{ - claimQueueType::iterator itQueueRow = dirtyQueueRows.find(nHeight); - if (itQueueRow == dirtyQueueRows.end()) - { - claimQueueRowType newRow; - std::pair ret; - ret = dirtyQueueRows.insert(std::pair(nHeight, newRow)); - assert(ret.second); - itQueueRow = ret.first; - } - itQueueRow->second.swap(row); -} - -void CClaimTrie::updateQueueNameRow(const std::string& name, queueNameRowType& row) -{ - queueNameType::iterator itQueueRow = dirtyQueueNameRows.find(name); - if (itQueueRow == dirtyQueueNameRows.end()) - { - queueNameRowType newRow; - std::pair ret; - ret = dirtyQueueNameRows.insert(std::pair(name, newRow)); - assert(ret.second); - itQueueRow = ret.first; - } - itQueueRow->second.swap(row); -} - -void CClaimTrie::updateExpirationRow(int nHeight, expirationQueueRowType& row) -{ - expirationQueueType::iterator itQueueRow = dirtyExpirationQueueRows.find(nHeight); - if (itQueueRow == dirtyExpirationQueueRows.end()) - { - expirationQueueRowType newRow; - std::pair ret; - ret = dirtyExpirationQueueRows.insert(std::pair(nHeight, newRow)); - assert(ret.second); - itQueueRow = ret.first; - } - itQueueRow->second.swap(row); -} - -void CClaimTrie::updateSupportMap(const std::string& name, supportMapEntryType& node) -{ - supportMapType::iterator itNode = dirtySupportNodes.find(name); - if (itNode == dirtySupportNodes.end()) - { - supportMapEntryType newNode; - std::pair ret; - ret = dirtySupportNodes.insert(std::pair(name, newNode)); - assert(ret.second); - itNode = ret.first; - } - itNode->second.swap(node); -} - -void CClaimTrie::updateSupportQueue(int nHeight, supportQueueRowType& row) -{ - supportQueueType::iterator itQueueRow = dirtySupportQueueRows.find(nHeight); - if (itQueueRow == dirtySupportQueueRows.end()) - { - supportQueueRowType newRow; - std::pair ret; - ret = dirtySupportQueueRows.insert(std::pair(nHeight, newRow)); - assert(ret.second); - itQueueRow = ret.first; - } - itQueueRow->second.swap(row); -} - -void CClaimTrie::updateSupportNameQueue(const std::string& name, queueNameRowType& row) -{ - queueNameType::iterator itQueueRow = dirtySupportQueueNameRows.find(name); - if (itQueueRow == dirtySupportQueueNameRows.end()) - { - queueNameRowType newRow; - std::pair ret; - ret = dirtySupportQueueNameRows.insert(std::pair(name, newRow)); - assert(ret.second); - itQueueRow = ret.first; - } - itQueueRow->second.swap(row); -} - -void CClaimTrie::updateSupportExpirationQueue(int nHeight, expirationQueueRowType& row) -{ - expirationQueueType::iterator itQueueRow = dirtySupportExpirationQueueRows.find(nHeight); - if (itQueueRow == dirtySupportExpirationQueueRows.end()) - { - expirationQueueRowType newRow; - std::pair ret; - ret = dirtySupportExpirationQueueRows.insert(std::pair(nHeight, newRow)); - assert(ret.second); - itQueueRow = ret.first; - } - itQueueRow->second.swap(row); -} - -bool CClaimTrie::getSupportNode(std::string name, supportMapEntryType& node) const -{ - supportMapType::const_iterator itNode = dirtySupportNodes.find(name); - if (itNode != dirtySupportNodes.end()) - { - node = itNode->second; - return true; - } - return db.Read(std::make_pair(SUPPORT, name), node); -} - -bool CClaimTrie::getSupportQueueRow(int nHeight, supportQueueRowType& row) const -{ - supportQueueType::const_iterator itQueueRow = dirtySupportQueueRows.find(nHeight); - if (itQueueRow != dirtySupportQueueRows.end()) - { - row = itQueueRow->second; - return true; - } - return db.Read(std::make_pair(SUPPORT_QUEUE_ROW, nHeight), row); -} - -bool CClaimTrie::getSupportQueueNameRow(const std::string& name, queueNameRowType& row) const -{ - queueNameType::const_iterator itQueueNameRow = dirtySupportQueueNameRows.find(name); - if (itQueueNameRow != dirtySupportQueueNameRows.end()) - { - row = itQueueNameRow->second; - return true; - } - return db.Read(std::make_pair(SUPPORT_QUEUE_NAME_ROW, name), row); -} - -bool CClaimTrie::getSupportExpirationQueueRow(int nHeight, expirationQueueRowType& row) const -{ - expirationQueueType::const_iterator itQueueRow = dirtySupportExpirationQueueRows.find(nHeight); - if (itQueueRow != dirtySupportExpirationQueueRows.end()) - { - row = itQueueRow->second; - return true; - } - return db.Read(std::make_pair(SUPPORT_EXP_QUEUE_ROW, nHeight), row); -} - -bool CClaimTrie::update(nodeCacheType& cache, hashMapType& hashes, std::map& takeoverHeights, const uint256& hashBlockIn, claimQueueType& queueCache, queueNameType& queueNameCache, expirationQueueType& expirationQueueCache, int nNewHeight, supportMapType& supportCache, supportQueueType& supportQueueCache, queueNameType& supportQueueNameCache, expirationQueueType& supportExpirationQueueCache) +bool CClaimTrie::update(nodeCacheType& cache, hashMapType& hashes, std::map& takeoverHeights, const uint256& hashBlockIn, claimQueueType& queueCache, queueNameType& queueNameCache, expirationQueueType& expirationQueueCache, int nNewHeight, supportMapType& supportCache, supportQueueType& supportQueueCache, supportQueueNameType& supportQueueNameCache, supportExpirationQueueType& supportExpirationQueueCache) { for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache) { @@ -819,31 +602,31 @@ bool CClaimTrie::update(nodeCacheType& cache, hashMapType& hashes, std::mapfirst, itQueueCacheRow->second); + db.updateQueueRow(itQueueCacheRow->first, itQueueCacheRow->second); } for (queueNameType::iterator itQueueNameCacheRow = queueNameCache.begin(); itQueueNameCacheRow != queueNameCache.end(); ++itQueueNameCacheRow) { - updateQueueNameRow(itQueueNameCacheRow->first, itQueueNameCacheRow->second); + db.updateQueueRow(itQueueNameCacheRow->first, itQueueNameCacheRow->second); } for (expirationQueueType::iterator itExpirationRow = expirationQueueCache.begin(); itExpirationRow != expirationQueueCache.end(); ++itExpirationRow) { - updateExpirationRow(itExpirationRow->first, itExpirationRow->second); + db.updateQueueRow(itExpirationRow->first, itExpirationRow->second); } for (supportMapType::iterator itSupportCache = supportCache.begin(); itSupportCache != supportCache.end(); ++itSupportCache) { - updateSupportMap(itSupportCache->first, itSupportCache->second); + db.updateQueueRow(itSupportCache->first, itSupportCache->second); } for (supportQueueType::iterator itSupportQueue = supportQueueCache.begin(); itSupportQueue != supportQueueCache.end(); ++itSupportQueue) { - updateSupportQueue(itSupportQueue->first, itSupportQueue->second); + db.updateQueueRow(itSupportQueue->first, itSupportQueue->second); } - for (queueNameType::iterator itSupportNameQueue = supportQueueNameCache.begin(); itSupportNameQueue != supportQueueNameCache.end(); ++itSupportNameQueue) + for (supportQueueNameType::iterator itSupportNameQueue = supportQueueNameCache.begin(); itSupportNameQueue != supportQueueNameCache.end(); ++itSupportNameQueue) { - updateSupportNameQueue(itSupportNameQueue->first, itSupportNameQueue->second); + db.updateQueueRow(itSupportNameQueue->first, itSupportNameQueue->second); } - for (expirationQueueType::iterator itSupportExpirationQueue = supportExpirationQueueCache.begin(); itSupportExpirationQueue != supportExpirationQueueCache.end(); ++itSupportExpirationQueue) + for (supportExpirationQueueType::iterator itSupportExpirationQueue = supportExpirationQueueCache.begin(); itSupportExpirationQueue != supportExpirationQueueCache.end(); ++itSupportExpirationQueue) { - updateSupportExpirationQueue(itSupportExpirationQueue->first, itSupportExpirationQueue->second); + db.updateQueueRow(itSupportExpirationQueue->first, itSupportExpirationQueue->second); } hashBlock = hashBlockIn; nCurrentHeight = nNewHeight; @@ -952,146 +735,16 @@ bool CClaimTrie::updateTakeoverHeight(const std::string& name, int nTakeoverHeig return true; } -void CClaimTrie::BatchWriteNode(CDBBatch& batch, const std::string& name, const CClaimTrieNode* pNode) const -{ - uint32_t num_claims = 0; - if (pNode) - num_claims = pNode->claims.size(); - LogPrintf("%s: Writing %s to disk with %d claims\n", __func__, name, num_claims); - if (pNode) - batch.Write(std::make_pair(TRIE_NODE, name), *pNode); - else - batch.Erase(std::make_pair(TRIE_NODE, name)); -} - -void CClaimTrie::BatchWriteQueueRows(CDBBatch& batch) -{ - for (claimQueueType::iterator itQueue = dirtyQueueRows.begin(); itQueue != dirtyQueueRows.end(); ++itQueue) - { - if (itQueue->second.empty()) - { - batch.Erase(std::make_pair(CLAIM_QUEUE_ROW, itQueue->first)); - } - else - { - batch.Write(std::make_pair(CLAIM_QUEUE_ROW, itQueue->first), itQueue->second); - } - } -} - -void CClaimTrie::BatchWriteQueueNameRows(CDBBatch& batch) -{ - for (queueNameType::iterator itQueue = dirtyQueueNameRows.begin(); itQueue != dirtyQueueNameRows.end(); ++itQueue) - { - if (itQueue->second.empty()) - { - batch.Erase(std::make_pair(CLAIM_QUEUE_NAME_ROW, itQueue->first)); - } - else - { - batch.Write(std::make_pair(CLAIM_QUEUE_NAME_ROW, itQueue->first), itQueue->second); - } - } -} - -void CClaimTrie::BatchWriteExpirationQueueRows(CDBBatch& batch) -{ - for (expirationQueueType::iterator itQueue = dirtyExpirationQueueRows.begin(); itQueue != dirtyExpirationQueueRows.end(); ++itQueue) - { - if (itQueue->second.empty()) - { - batch.Erase(std::make_pair(EXP_QUEUE_ROW, itQueue->first)); - } - else - { - batch.Write(std::make_pair(EXP_QUEUE_ROW, itQueue->first), itQueue->second); - } - } -} - -void CClaimTrie::BatchWriteSupportNodes(CDBBatch& batch) -{ - for (supportMapType::iterator itSupport = dirtySupportNodes.begin(); itSupport != dirtySupportNodes.end(); ++itSupport) - { - if (itSupport->second.empty()) - { - batch.Erase(std::make_pair(SUPPORT, itSupport->first)); - } - else - { - batch.Write(std::make_pair(SUPPORT, itSupport->first), itSupport->second); - } - } -} - -void CClaimTrie::BatchWriteSupportQueueRows(CDBBatch& batch) -{ - for (supportQueueType::iterator itQueue = dirtySupportQueueRows.begin(); itQueue != dirtySupportQueueRows.end(); ++itQueue) - { - if (itQueue->second.empty()) - { - batch.Erase(std::make_pair(SUPPORT_QUEUE_ROW, itQueue->first)); - } - else - { - batch.Write(std::make_pair(SUPPORT_QUEUE_ROW, itQueue->first), itQueue->second); - } - } -} - -void CClaimTrie::BatchWriteSupportQueueNameRows(CDBBatch& batch) -{ - for (queueNameType::iterator itQueue = dirtySupportQueueNameRows.begin(); itQueue != dirtySupportQueueNameRows.end(); ++itQueue) - { - if (itQueue->second.empty()) - { - batch.Erase(std::make_pair(SUPPORT_QUEUE_NAME_ROW, itQueue->first)); - } - else - { - batch.Write(std::make_pair(SUPPORT_QUEUE_NAME_ROW, itQueue->first), itQueue->second); - } - } -} - -void CClaimTrie::BatchWriteSupportExpirationQueueRows(CDBBatch& batch) -{ - for (expirationQueueType::iterator itQueue = dirtySupportExpirationQueueRows.begin(); itQueue != dirtySupportExpirationQueueRows.end(); ++itQueue) - { - if (itQueue->second.empty()) - { - batch.Erase(std::make_pair(SUPPORT_EXP_QUEUE_ROW, itQueue->first)); - } - else - { - batch.Write(std::make_pair(SUPPORT_EXP_QUEUE_ROW, itQueue->first), itQueue->second); - } - } -} - bool CClaimTrie::WriteToDisk() { - CDBBatch batch(&db.GetObfuscateKey()); for (nodeCacheType::iterator itcache = dirtyNodes.begin(); itcache != dirtyNodes.end(); ++itcache) - BatchWriteNode(batch, itcache->first, itcache->second); + db.updateQueueRow(itcache->first, *(itcache->second)); + dirtyNodes.clear(); - BatchWriteQueueRows(batch); - dirtyQueueRows.clear(); - BatchWriteQueueNameRows(batch); - dirtyQueueNameRows.clear(); - BatchWriteExpirationQueueRows(batch); - dirtyExpirationQueueRows.clear(); - BatchWriteSupportNodes(batch); - dirtySupportNodes.clear(); - BatchWriteSupportQueueRows(batch); - dirtySupportQueueRows.clear(); - BatchWriteSupportQueueNameRows(batch); - dirtySupportQueueNameRows.clear(); - BatchWriteSupportExpirationQueueRows(batch); - dirtySupportExpirationQueueRows.clear(); - batch.Write(HASH_BLOCK, hashBlock); - batch.Write(CURRENT_HEIGHT, nCurrentHeight); - return db.WriteBatch(batch); + db.writeQueues(); + db.Write(HASH_BLOCK, hashBlock); + db.Write(CURRENT_HEIGHT, nCurrentHeight); + return db.Sync(); } bool CClaimTrie::InsertFromDisk(const std::string& name, CClaimTrieNode* node) @@ -1109,7 +762,7 @@ bool CClaimTrie::InsertFromDisk(const std::string& name, CClaimTrieNode* node) return false; current = itchild->second; } - current->children[name[name.size()-1]] = node; + current->children[name[name.size()-1]] = new CClaimTrieNode(*node); return true; } @@ -1119,31 +772,19 @@ bool CClaimTrie::ReadFromDisk(bool check) LogPrintf("%s: Couldn't read the best block's hash\n", __func__); if (!db.Read(CURRENT_HEIGHT, nCurrentHeight)) LogPrintf("%s: Couldn't read the current height\n", __func__); - boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); - pcursor->SeekToFirst(); - while (pcursor->Valid()) + setExpirationTime(Params().GetConsensus().GetExpirationTime(nCurrentHeight-1)); + + std::string name; + CClaimTrieNode node; + if(!db.SeekFirstKey(name, node)) { - std::pair key; - if (pcursor->GetKey(key)) - { - if (key.first == TRIE_NODE) - { - CClaimTrieNode* node = new CClaimTrieNode(); - if (pcursor->GetValue(*node)) - { - if (!InsertFromDisk(key.second, node)) - { - return error("%s(): error restoring claim trie from disk", __func__); - } - } - else - { - return error("%s(): error reading claim trie from disk", __func__); - } - } - } - pcursor->Next(); + return error("%s(): error reading claim trie from disk", __func__); + } + + if (!InsertFromDisk(name, &node)) + { + return error("%s(): error restoring claim trie from disk", __func__); } if (check) @@ -1196,7 +837,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); @@ -1306,7 +947,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 @@ -1410,7 +1051,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__); @@ -1431,7 +1072,7 @@ bool CClaimTrieCache::removeClaimFromTrie(const std::string& name, const COutPoi } else fChanged = true; - + if (!success) { LogPrintf("%s: Removing a claim was unsuccessful. name = %s, txhash = %s, nOut = %d", __func__, name.c_str(), outPoint.hash.GetHex(), outPoint.n); @@ -1491,7 +1132,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. @@ -1538,7 +1179,7 @@ claimQueueType::iterator CClaimTrieCache::getQueueCacheRow(int nHeight, bool cre // Have to make a new row it put in the cache, if createIfNotExists is true claimQueueRowType queueRow; // If the row exists in the base, copy its claims into the new row. - bool exists = base->getQueueRow(nHeight, queueRow); + bool exists = base->db.getQueueRow(nHeight, queueRow); if (!exists) if (!createIfNotExists) return itQueueRow; @@ -1559,7 +1200,7 @@ queueNameType::iterator CClaimTrieCache::getQueueCacheNameRow(const std::string& // Have to make a new name row and put it in the cache, if createIfNotExists is true queueNameRowType queueNameRow; // If the row exists in the base, copy its claims into the new row. - bool exists = base->getQueueNameRow(name, queueNameRow); + bool exists = base->db.getQueueRow(name, queueNameRow); if (!exists) if (!createIfNotExists) return itQueueNameRow; @@ -1653,7 +1294,8 @@ bool CClaimTrieCache::removeClaimFromQueue(const std::string& name, const COutPo } if (itQueue != itQueueRow->second.end()) { - std::swap(claim, itQueue->second); + swap(claim, itQueue->second); + claim = itQueue->second; itQueueNameRow->second.erase(itQueueName); itQueueRow->second.erase(itQueue); @@ -1692,7 +1334,8 @@ bool CClaimTrieCache::removeClaim(const std::string& name, const COutPoint& outP if (removed == true) { nValidAtHeight = claim.nValidAtHeight; - removeFromExpirationQueue(name, outPoint, nHeight); + int expirationHeight = nHeight + base->nExpirationTime; + removeFromExpirationQueue(name, outPoint, expirationHeight); } return removed; } @@ -1703,9 +1346,8 @@ void CClaimTrieCache::addToExpirationQueue(int nExpirationHeight, nameOutPointTy itQueueRow->second.push_back(entry); } -void CClaimTrieCache::removeFromExpirationQueue(const std::string& name, const COutPoint& outPoint, int nHeight) const +void CClaimTrieCache::removeFromExpirationQueue(const std::string& name, const COutPoint& outPoint, int expirationHeight) const { - int expirationHeight = nHeight + base->nExpirationTime; expirationQueueType::iterator itQueueRow = getExpirationQueueCacheRow(expirationHeight, false); expirationQueueRowType::iterator itQueue; if (itQueueRow != expirationQueueCache.end()) @@ -1715,10 +1357,11 @@ void CClaimTrieCache::removeFromExpirationQueue(const std::string& name, const C if (name == itQueue->name && outPoint == itQueue->outPoint) break; } - } - if (itQueue != itQueueRow->second.end()) - { - itQueueRow->second.erase(itQueue); + + if (itQueue != itQueueRow->second.end()) + { + itQueueRow->second.erase(itQueue); + } } } @@ -1730,7 +1373,7 @@ expirationQueueType::iterator CClaimTrieCache::getExpirationQueueCacheRow(int nH // Have to make a new row it put in the cache, if createIfNotExists is true expirationQueueRowType queueRow; // If the row exists in the base, copy its claims into the new row. - bool exists = base->getExpirationQueueRow(nHeight, queueRow); + bool exists = base->db.getQueueRow(nHeight, queueRow); if (!exists) if (!createIfNotExists) return itQueueRow; @@ -1822,7 +1465,7 @@ bool CClaimTrieCache::getSupportsForName(const std::string& name, supportMapEntr } else { - return base->getSupportNode(name, node); + return base->db.getQueueRow(name, node); } } @@ -1835,7 +1478,7 @@ bool CClaimTrieCache::insertSupportIntoMap(const std::string& name, CSupportValu if (cachedNode == supportCache.end()) { supportMapEntryType node; - base->getSupportNode(name, node); + base->db.getQueueRow(name, node); std::pair ret; ret = supportCache.insert(std::pair(name, node)); assert(ret.second); @@ -1853,7 +1496,7 @@ bool CClaimTrieCache::removeSupportFromMap(const std::string& name, const COutPo if (cachedNode == supportCache.end()) { supportMapEntryType node; - if (!base->getSupportNode(name, node)) + if (!base->db.getQueueRow(name, node)) { // clearly, this support does not exist return false; @@ -1890,7 +1533,7 @@ supportQueueType::iterator CClaimTrieCache::getSupportQueueCacheRow(int nHeight, if (itQueueRow == supportQueueCache.end()) { supportQueueRowType queueRow; - bool exists = base->getSupportQueueRow(nHeight, queueRow); + bool exists = base->db.getQueueRow(nHeight, queueRow); if (!exists) if (!createIfNotExists) return itQueueRow; @@ -1903,19 +1546,19 @@ supportQueueType::iterator CClaimTrieCache::getSupportQueueCacheRow(int nHeight, return itQueueRow; } -queueNameType::iterator CClaimTrieCache::getSupportQueueCacheNameRow(const std::string& name, bool createIfNotExists) const +supportQueueNameType::iterator CClaimTrieCache::getSupportQueueCacheNameRow(const std::string& name, bool createIfNotExists) const { - queueNameType::iterator itQueueNameRow = supportQueueNameCache.find(name); + supportQueueNameType::iterator itQueueNameRow = supportQueueNameCache.find(name); if (itQueueNameRow == supportQueueNameCache.end()) { - queueNameRowType queueNameRow; - bool exists = base->getSupportQueueNameRow(name, queueNameRow); + supportQueueNameRowType queueNameRow; + bool exists = base->db.getQueueRow(name, queueNameRow); if (!exists) if (!createIfNotExists) return itQueueNameRow; // Stick the new row in the name cache - std::pair ret; - ret = supportQueueNameCache.insert(std::pair(name, queueNameRow)); + std::pair ret; + ret = supportQueueNameCache.insert(std::make_pair(name, queueNameRow)); assert(ret.second); itQueueNameRow = ret.first; } @@ -1927,7 +1570,7 @@ bool CClaimTrieCache::addSupportToQueues(const std::string& name, CSupportValue& LogPrintf("%s: nValidAtHeight: %d\n", __func__, support.nValidAtHeight); supportQueueEntryType entry(name, support); supportQueueType::iterator itQueueRow = getSupportQueueCacheRow(support.nValidAtHeight, true); - queueNameType::iterator itQueueNameRow = getSupportQueueCacheNameRow(name, true); + supportQueueNameType::iterator itQueueNameRow = getSupportQueueCacheNameRow(name, true); itQueueRow->second.push_back(entry); itQueueNameRow->second.push_back(outPointHeightType(support.outPoint, support.nValidAtHeight)); nameOutPointType expireEntry(name, support.outPoint); @@ -1937,12 +1580,12 @@ bool CClaimTrieCache::addSupportToQueues(const std::string& name, CSupportValue& bool CClaimTrieCache::removeSupportFromQueue(const std::string& name, const COutPoint& outPoint, CSupportValue& support) const { - queueNameType::iterator itQueueNameRow = getSupportQueueCacheNameRow(name, false); + supportQueueNameType::iterator itQueueNameRow = getSupportQueueCacheNameRow(name, false); if (itQueueNameRow == supportQueueNameCache.end()) { return false; } - queueNameRowType::iterator itQueueName; + supportQueueNameRowType::iterator itQueueName; for (itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) { if (itQueueName->outPoint == outPoint) @@ -1968,7 +1611,7 @@ bool CClaimTrieCache::removeSupportFromQueue(const std::string& name, const COut } if (itQueue != itQueueRow->second.end()) { - std::swap(support, itQueue->second); + swap(support, itQueue->second); itQueueNameRow->second.erase(itQueueName); itQueueRow->second.erase(itQueue); return true; @@ -2023,7 +1666,8 @@ bool CClaimTrieCache::removeSupport(const std::string& name, const COutPoint& ou removed = true; if (removed) { - removeSupportFromExpirationQueue(name, outPoint, nHeight); + int expirationHeight = nHeight + base->nExpirationTime; + removeSupportFromExpirationQueue(name, outPoint, expirationHeight); nValidAtHeight = support.nValidAtHeight; } return removed; @@ -2031,15 +1675,14 @@ bool CClaimTrieCache::removeSupport(const std::string& name, const COutPoint& ou void CClaimTrieCache::addSupportToExpirationQueue(int nExpirationHeight, nameOutPointType& entry) const { - expirationQueueType::iterator itQueueRow = getSupportExpirationQueueCacheRow(nExpirationHeight, true); + supportExpirationQueueType::iterator itQueueRow = getSupportExpirationQueueCacheRow(nExpirationHeight, true); itQueueRow->second.push_back(entry); } -void CClaimTrieCache::removeSupportFromExpirationQueue(const std::string& name, const COutPoint& outPoint, int nHeight) const +void CClaimTrieCache::removeSupportFromExpirationQueue(const std::string& name, const COutPoint& outPoint, int expirationHeight) const { - int expirationHeight = nHeight + base->nExpirationTime; - expirationQueueType::iterator itQueueRow = getSupportExpirationQueueCacheRow(expirationHeight, false); - expirationQueueRowType::iterator itQueue; + supportExpirationQueueType::iterator itQueueRow = getSupportExpirationQueueCacheRow(expirationHeight, false); + supportExpirationQueueRowType::iterator itQueue; if (itQueueRow != supportExpirationQueueCache.end()) { for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) @@ -2054,21 +1697,21 @@ void CClaimTrieCache::removeSupportFromExpirationQueue(const std::string& name, } } -expirationQueueType::iterator CClaimTrieCache::getSupportExpirationQueueCacheRow(int nHeight, bool createIfNotExists) const +supportExpirationQueueType::iterator CClaimTrieCache::getSupportExpirationQueueCacheRow(int nHeight, bool createIfNotExists) const { - expirationQueueType::iterator itQueueRow = supportExpirationQueueCache.find(nHeight); + supportExpirationQueueType::iterator itQueueRow = supportExpirationQueueCache.find(nHeight); if (itQueueRow == supportExpirationQueueCache.end()) { // Have to make a new row it put in the cache, if createIfNotExists is true - expirationQueueRowType queueRow; + supportExpirationQueueRowType queueRow; // If the row exists in the base, copy its claims into the new row. - bool exists = base->getSupportExpirationQueueRow(nHeight, queueRow); + bool exists = base->db.getQueueRow(nHeight, queueRow); if (!exists) if (!createIfNotExists) return itQueueRow; // Stick the new row in the cache - std::pair ret; - ret = supportExpirationQueueCache.insert(std::pair(nHeight, queueRow)); + std::pair ret; + ret = supportExpirationQueueCache.insert(std::make_pair(nHeight, queueRow)); assert(ret.second); itQueueRow = ret.first; } @@ -2091,6 +1734,7 @@ bool CClaimTrieCache::spendSupport(const std::string& name, const COutPoint& out bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowType& expireUndo, insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo, std::vector >& takeoverHeightUndo) const { LogPrintf("%s: nCurrentHeight (before increment): %d\n", __func__, nCurrentHeight); + claimQueueType::iterator itQueueRow = getQueueCacheRow(nCurrentHeight, false); if (itQueueRow != claimQueueCache.end()) { @@ -2140,6 +1784,7 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy CClaimValue claim; assert(removeClaimFromTrie(itEntry->name, itEntry->outPoint, claim, true)); expireUndo.push_back(std::make_pair(itEntry->name, claim)); + LogPrintf("Expiring claim %s: %s, nHeight: %d, nValidAtHeight: %d\n", claim.claimId.GetHex(), itEntry->name, claim.nHeight, claim.nValidAtHeight); } itExpirationRow->second.clear(); } @@ -2149,10 +1794,10 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy for (supportQueueRowType::iterator itSupport = itSupportRow->second.begin(); itSupport != itSupportRow->second.end(); ++itSupport) { bool found = false; - queueNameType::iterator itSupportNameRow = getSupportQueueCacheNameRow(itSupport->first, false); + supportQueueNameType::iterator itSupportNameRow = getSupportQueueCacheNameRow(itSupport->first, false); if (itSupportNameRow != supportQueueNameCache.end()) { - for (queueNameRowType::iterator itSupportName = itSupportNameRow->second.begin(); itSupportName != itSupportNameRow->second.end(); ++itSupportName) + for (supportQueueNameRowType::iterator itSupportName = itSupportNameRow->second.begin(); itSupportName != itSupportNameRow->second.end(); ++itSupportName) { if (itSupportName->outPoint == itSupport->second.outPoint && itSupportName->nHeight == itSupport->second.nValidAtHeight) { @@ -2168,7 +1813,7 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy if (itSupportNameRow != supportQueueNameCache.end()) { LogPrintf("Supports found for that name:\n"); - for (queueNameRowType::iterator itSupportName = itSupportNameRow->second.begin(); itSupportName != itSupportNameRow->second.end(); ++itSupportName) + for (supportQueueNameRowType::iterator itSupportName = itSupportNameRow->second.begin(); itSupportName != itSupportNameRow->second.end(); ++itSupportName) { LogPrintf("\ttxid: %s, nOut: %d, nValidAtHeight: %d\n", itSupportName->outPoint.hash.GetHex(), itSupportName->outPoint.n, itSupportName->nHeight); } @@ -2183,19 +1828,20 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy } itSupportRow->second.clear(); } - expirationQueueType::iterator itSupportExpirationRow = getSupportExpirationQueueCacheRow(nCurrentHeight, false); + supportExpirationQueueType::iterator itSupportExpirationRow = getSupportExpirationQueueCacheRow(nCurrentHeight, false); if (itSupportExpirationRow != supportExpirationQueueCache.end()) { - for (expirationQueueRowType::iterator itEntry = itSupportExpirationRow->second.begin(); itEntry != itSupportExpirationRow->second.end(); ++itEntry) + for (supportExpirationQueueRowType::iterator itEntry = itSupportExpirationRow->second.begin(); itEntry != itSupportExpirationRow->second.end(); ++itEntry) { CSupportValue support; assert(removeSupportFromMap(itEntry->name, itEntry->outPoint, support, true)); expireSupportUndo.push_back(std::make_pair(itEntry->name, support)); + LogPrintf("Expiring support %s: %s, nHeight: %d, nValidAtHeight: %d\n", support.supportedClaimId.GetHex(), itEntry->name, support.nHeight, support.nValidAtHeight); } 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 @@ -2286,12 +1932,12 @@ 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); + supportQueueNameType::iterator itSupportQueueNameRow = getSupportQueueCacheNameRow(*itNamesToCheck, false); if (itSupportQueueNameRow != supportQueueNameCache.end()) { - for (queueNameRowType::iterator itSupportQueueName = itSupportQueueNameRow->second.begin(); itSupportQueueName != itSupportQueueNameRow->second.end(); ++itSupportQueueName) + for (supportQueueNameRowType::iterator itSupportQueueName = itSupportQueueNameRow->second.begin(); itSupportQueueName != itSupportQueueNameRow->second.end(); ++itSupportQueueName) { // Pull those supports out of the height-based queue supportQueueType::iterator itSupportQueueRow = getSupportQueueCacheRow(itSupportQueueName->nHeight, false); @@ -2328,7 +1974,7 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy // remove all supports from the queue for that name itSupportQueueNameRow->second.clear(); } - + // save the old last height so that it can be restored if the block is undone if (haveClaimInTrie) { @@ -2361,27 +2007,27 @@ bool CClaimTrieCache::decrementBlock(insertUndoType& insertUndo, claimQueueRowTy { LogPrintf("%s: nCurrentHeight (before decrement): %d\n", __func__, nCurrentHeight); nCurrentHeight--; - + if (expireSupportUndo.begin() != expireSupportUndo.end()) { - expirationQueueType::iterator itSupportExpireRow = getSupportExpirationQueueCacheRow(nCurrentHeight, true); + supportExpirationQueueType::iterator itSupportExpireRow = getSupportExpirationQueueCacheRow(nCurrentHeight, true); for (supportQueueRowType::iterator itSupportExpireUndo = expireSupportUndo.begin(); itSupportExpireUndo != expireSupportUndo.end(); ++itSupportExpireUndo) { insertSupportIntoMap(itSupportExpireUndo->first, itSupportExpireUndo->second, false); itSupportExpireRow->second.push_back(nameOutPointType(itSupportExpireUndo->first, itSupportExpireUndo->second.outPoint)); } } - + for (insertUndoType::iterator itSupportUndo = insertSupportUndo.begin(); itSupportUndo != insertSupportUndo.end(); ++itSupportUndo) { supportQueueType::iterator itSupportRow = getSupportQueueCacheRow(itSupportUndo->nHeight, true); CSupportValue support; assert(removeSupportFromMap(itSupportUndo->name, itSupportUndo->outPoint, support, false)); - queueNameType::iterator itSupportNameRow = getSupportQueueCacheNameRow(itSupportUndo->name, true); + supportQueueNameType::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)); } - + if (expireUndo.begin() != expireUndo.end()) { expirationQueueType::iterator itExpireRow = getExpirationQueueCacheRow(nCurrentHeight, true); @@ -2399,13 +2045,14 @@ bool CClaimTrieCache::decrementBlock(insertUndoType& insertUndo, claimQueueRowTy assert(removeClaimFromTrie(itInsertUndo->name, itInsertUndo->outPoint, claim, false)); queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(itInsertUndo->name, true); itQueueRow->second.push_back(std::make_pair(itInsertUndo->name, claim)); - itQueueNameRow->second.push_back(outPointHeightType(itInsertUndo->outPoint, itInsertUndo->nHeight)); + itQueueNameRow->second.push_back(outPointHeightType(itInsertUndo->outPoint, itInsertUndo->nHeight)); } - + for (std::vector >::iterator itTakeoverHeightUndo = takeoverHeightUndo.begin(); itTakeoverHeightUndo != takeoverHeightUndo.end(); ++itTakeoverHeightUndo) { cacheTakeoverHeights[itTakeoverHeightUndo->first] = itTakeoverHeightUndo->second; } + return true; } @@ -2594,3 +2241,70 @@ CClaimTrieProof CClaimTrieCache::getProofForName(const std::string& name) const return CClaimTrieProof(nodes, fNameHasValue, outPoint, nHeightOfLastTakeover); } + +void CClaimTrieCache::removeAndAddToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const +{ + for (expirationQueueRowType::iterator e = row.begin(); e != row.end(); ++e) + { + // remove and insert with new expiration time + removeFromExpirationQueue(e->name, e->outPoint, height); + int extend_expiration = Params().GetConsensus().nExtendedClaimExpirationTime - Params().GetConsensus().nOriginalClaimExpirationTime; + int new_expiration_height = increment ? height + extend_expiration : height - extend_expiration; + nameOutPointType entry(e->name, e->outPoint); + addToExpirationQueue(new_expiration_height, entry); + } + +} + +void CClaimTrieCache::removeAndAddSupportToExpirationQueue(supportExpirationQueueRowType &row, int height, bool increment) const +{ + for (supportExpirationQueueRowType::iterator e = row.begin(); e != row.end(); ++e) + { + // remove and insert with new expiration time + removeSupportFromExpirationQueue(e->name, e->outPoint, height); + int extend_expiration = Params().GetConsensus().nExtendedClaimExpirationTime - Params().GetConsensus().nOriginalClaimExpirationTime; + int new_expiration_height = increment ? height + extend_expiration : height - extend_expiration; + nameOutPointType entry(e->name, e->outPoint); + addSupportToExpirationQueue(new_expiration_height, entry); + } + +} + +bool CClaimTrieCache::forkForExpirationChange(bool increment) const +{ + /* + If increment is True, we have forked to extend the expiration time, thus items in the expiration queue + will have their expiration extended by "new expiration time - original expiration time" + + If increment is False, we are decremented a block to reverse the fork. Thus items in the expiration queue + will have their expiration extension removed. + */ + + expirationQueueType dirtyExpirationQueueRows; + if (!base->db.getQueueMap(dirtyExpirationQueueRows)) + { + return error("%s(): error reading expiration queue rows from disk", __func__); + } + + supportExpirationQueueType dirtySupportExpirationQueueRows; + if (!base->db.getQueueMap(dirtySupportExpirationQueueRows)) + { + return error("%s(): error reading support expiration queue rows from disk", __func__); + } + + for (expirationQueueType::const_iterator i = dirtyExpirationQueueRows.begin(); i != dirtyExpirationQueueRows.end(); ++i) + { + int height = i->first; + expirationQueueRowType row = i->second; + removeAndAddToExpirationQueue(row, height, increment); + } + + for (supportExpirationQueueType::const_iterator i = dirtySupportExpirationQueueRows.begin(); i != dirtySupportExpirationQueueRows.end(); ++i) + { + int height = i->first; + supportExpirationQueueRowType row = i->second; + removeAndAddSupportToExpirationQueue(row, height, increment); + } + + return true; +} diff --git a/src/claimtrie.h b/src/claimtrie.h index bef40f51f..3baf49240 100644 --- a/src/claimtrie.h +++ b/src/claimtrie.h @@ -5,25 +5,12 @@ #include "serialize.h" #include "uint256.h" #include "util.h" -#include "dbwrapper.h" +#include "claimtriedb.h" +#include "chainparams.h" #include "primitives/transaction.h" #include #include -#include - -// leveldb keys -#define HASH_BLOCK 'h' -#define CURRENT_HEIGHT 't' -#define TRIE_NODE 'n' -#define CLAIM_BY_ID 'i' -#define CLAIM_QUEUE_ROW 'r' -#define CLAIM_QUEUE_NAME_ROW 'm' -#define EXP_QUEUE_ROW 'e' -#define SUPPORT 's' -#define SUPPORT_QUEUE_ROW 'u' -#define SUPPORT_QUEUE_NAME_ROW 'p' -#define SUPPORT_EXP_QUEUE_ROW 'x' uint256 getValueHash(COutPoint outPoint, int nHeightOfLastTakeover); @@ -211,7 +198,7 @@ struct nameOutPointHeightType nameOutPointHeightType(std::string name, COutPoint outPoint, int nHeight) : name(name), outPoint(outPoint), nHeight(nHeight) {} - + ADD_SERIALIZE_METHODS; template @@ -254,24 +241,75 @@ class CClaimIndexElement READWRITE(claim); } + bool empty() const + { + return name.empty() && claim.claimId.IsNull(); + } + std::string name; CClaimValue claim; }; -typedef std::pair claimQueueEntryType; +struct claimQueueEntryHelper; +struct supportQueueEntryHelper; -typedef std::pair supportQueueEntryType; +struct queueNameRowHelper; +struct supportQueueNameRowHelper; + +struct expirationQueueRowHelper; +struct supportExpirationQueueRowHelper; + +template +struct Generic : public Base +{ + Generic() : Base() {} + Generic(const Base &base) : Base(base) {} + Generic(const Generic &generic) : Base(generic) {} +}; + +template inline +void swap(Generic &generic, Base &base) +{ + Base base1 = generic; + generic = base; + base = base1; +} + +template inline +void swap(Base &base, Generic &generic) +{ + swap(generic, base); +} + +typedef Generic claimQueueValueType; +typedef Generic supportQueueValueType; + +typedef Generic queueNameRowValueType; +typedef Generic supportQueueNameRowValueType; + +typedef Generic expirationQueueRowValueType; +typedef Generic supportExpirationQueueRowValueType; + +typedef std::pair claimQueueEntryType; + +typedef std::pair supportQueueEntryType; typedef std::map supportMapType; -typedef std::vector queueNameRowType; +typedef std::vector queueNameRowType; typedef std::map queueNameType; +typedef std::vector supportQueueNameRowType; +typedef std::map supportQueueNameType; + typedef std::vector insertUndoType; -typedef std::vector expirationQueueRowType; +typedef std::vector expirationQueueRowType; typedef std::map expirationQueueType; +typedef std::vector supportExpirationQueueRowType; +typedef std::map supportExpirationQueueType; + typedef std::vector claimQueueRowType; typedef std::map claimQueueType; @@ -298,9 +336,9 @@ class CClaimTrie { public: CClaimTrie(bool fMemory = false, bool fWipe = false, int nProportionalDelayFactor = 32) - : db(GetDataDir() / "claimtrie", 100, fMemory, fWipe, false) - , nCurrentHeight(0), nExpirationTime(262974) + : nCurrentHeight(0), nExpirationTime(Params().GetConsensus().nOriginalClaimExpirationTime) , nProportionalDelayFactor(nProportionalDelayFactor) + , db(fMemory, fWipe) , root(uint256S("0000000000000000000000000000000000000000000000000000000000000001")) {} @@ -319,7 +357,7 @@ public: bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const; claimsForNameType getClaimsForName(const std::string& name) const; - CAmount getEffectiveAmountForClaim(const std::string& name, uint160 claimId) const; + CAmount getEffectiveAmountForClaim(const std::string& name, uint160 claimId) const; bool queueEmpty() const; bool supportEmpty() const; @@ -333,13 +371,6 @@ public: void removeFromClaimIndex(const CClaimValue& claim); bool getClaimById(const uint160 claimId, std::string& name, CClaimValue& claim) const; - bool getQueueRow(int nHeight, claimQueueRowType& row) const; - bool getQueueNameRow(const std::string& name, queueNameRowType& row) const; - bool getExpirationQueueRow(int nHeight, expirationQueueRowType& row) const; - bool getSupportNode(std::string name, supportMapEntryType& node) const; - bool getSupportQueueRow(int nHeight, supportQueueRowType& row) const; - bool getSupportQueueNameRow(const std::string& name, queueNameRowType& row) const; - bool getSupportExpirationQueueRow(int nHeight, expirationQueueRowType& row) const; bool haveClaim(const std::string& name, const COutPoint& outPoint) const; @@ -356,11 +387,11 @@ public: friend class CClaimTrieCache; - CDBWrapper db; int nCurrentHeight; int nExpirationTime; int nProportionalDelayFactor; private: + CClaimTrieDb db; void clear(CClaimTrieNode* current); const CClaimTrieNode* getNodeForName(const std::string& name) const; @@ -372,8 +403,8 @@ private: expirationQueueType& expirationQueueCache, int nNewHeight, supportMapType& supportCache, supportQueueType& supportQueueCache, - queueNameType& supportQueueNameCache, - expirationQueueType& supportExpirationQueueCache); + supportQueueNameType& supportQueueNameCache, + supportExpirationQueueType& supportExpirationQueueCache); bool updateName(const std::string& name, CClaimTrieNode* updatedNode); bool updateHash(const std::string& name, uint256& hash); bool updateTakeoverHeight(const std::string& name, int nTakeoverHeight); @@ -392,42 +423,11 @@ private: std::vector& nodes) const; void markNodeDirty(const std::string& name, CClaimTrieNode* node); - void updateQueueRow(int nHeight, claimQueueRowType& row); - void updateQueueNameRow(const std::string& name, - queueNameRowType& row); - void updateExpirationRow(int nHeight, expirationQueueRowType& row); - void updateSupportMap(const std::string& name, supportMapEntryType& node); - void updateSupportQueue(int nHeight, supportQueueRowType& row); - void updateSupportNameQueue(const std::string& name, - queueNameRowType& row); - void updateSupportExpirationQueue(int nHeight, expirationQueueRowType& row); - - void BatchWriteNode(CDBBatch& batch, const std::string& name, - const CClaimTrieNode* pNode) const; - void BatchEraseNode(CDBBatch& batch, const std::string& nome) const; - void BatchWriteClaimIndex(CDBBatch& batch) const; - void BatchWriteQueueRows(CDBBatch& batch); - void BatchWriteQueueNameRows(CDBBatch& batch); - void BatchWriteExpirationQueueRows(CDBBatch& batch); - void BatchWriteSupportNodes(CDBBatch& batch); - void BatchWriteSupportQueueRows(CDBBatch& batch); - void BatchWriteSupportQueueNameRows(CDBBatch& batch); - void BatchWriteSupportExpirationQueueRows(CDBBatch& batch); - template bool keyTypeEmpty(char key, K& dummy) const; CClaimTrieNode root; uint256 hashBlock; - claimQueueType dirtyQueueRows; - queueNameType dirtyQueueNameRows; - expirationQueueType dirtyExpirationQueueRows; - - supportQueueType dirtySupportQueueRows; - queueNameType dirtySupportQueueNameRows; - expirationQueueType dirtySupportExpirationQueueRows; - nodeCacheType dirtyNodes; - supportMapType dirtySupportNodes; }; class CClaimTrieProofNode @@ -516,6 +516,12 @@ public: CClaimTrieProof getProofForName(const std::string& name) const; bool finalizeDecrement() const; + + void removeAndAddSupportToExpirationQueue(supportExpirationQueueRowType &row, int height, bool increment) const; + void removeAndAddToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const; + + bool forkForExpirationChange(bool increment) const; + protected: CClaimTrie* base; @@ -530,10 +536,10 @@ protected: mutable expirationQueueType expirationQueueCache; mutable supportMapType supportCache; mutable supportQueueType supportQueueCache; - mutable queueNameType supportQueueNameCache; - mutable expirationQueueType supportExpirationQueueCache; + mutable supportQueueNameType supportQueueNameCache; + mutable supportExpirationQueueType 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 @@ -580,10 +586,10 @@ protected: supportQueueType::iterator getSupportQueueCacheRow(int nHeight, bool createIfNotExists) const; - queueNameType::iterator getSupportQueueCacheNameRow(const std::string& name, - bool createIfNotExists) const; - expirationQueueType::iterator getSupportExpirationQueueCacheRow(int nHeight, - bool createIfNotExists) const; + supportQueueNameType::iterator getSupportQueueCacheNameRow(const std::string& name, + bool createIfNotExists) const; + supportExpirationQueueType::iterator getSupportExpirationQueueCacheRow(int nHeight, + bool createIfNotExists) const; bool addSupportToQueues(const std::string& name, CSupportValue& support) const; bool removeSupportFromQueue(const std::string& name, const COutPoint& outPoint, diff --git a/src/claimtriedb.cpp b/src/claimtriedb.cpp new file mode 100644 index 000000000..49ab8205f --- /dev/null +++ b/src/claimtriedb.cpp @@ -0,0 +1,188 @@ + +#include "claimtriedb.h" +#include + +template +class CCMap : public CCBase +{ + std::map data; +public: + CCMap() : data() {} + std::map& data_map() { return data; } + void write(size_t key, CClaimTrieDb *db) + { + for (auto &it : data) + { + if (it.second.empty()) + { + db->Erase(std::make_pair(key, it.first)); + } + else + { + db->Write(std::make_pair(key, it.first), it.second); + } + } + data.clear(); + } +}; + +CClaimTrieDb::CClaimTrieDb(bool fMemory, bool fWipe) + : CDBWrapper(GetDataDir() / "claimtrie", 100, fMemory, fWipe, false) +{} + +CClaimTrieDb::~CClaimTrieDb() +{ + for (std::map::iterator itQueue = queues.begin(); itQueue != queues.end(); ++itQueue) + { + delete itQueue->second; + } +} + +void CClaimTrieDb::writeQueues() +{ + for (std::map::iterator itQueue = queues.begin(); itQueue != queues.end(); ++itQueue) + { + itQueue->second->write(itQueue->first, this); + } +} + +template bool CClaimTrieDb::getQueueRow(const K &key, V &row) const +{ + const size_t hash = boost::typeindex::type_id >().hash_code(); + std::map::const_iterator itQueue = queues.find(hash); + if (itQueue != queues.end()) + { + std::map &map = (static_cast*>(itQueue->second))->data_map(); + typename std::map::iterator itMap = map.find(key); + if (itMap != map.end()) + { + row = itMap->second; + return true; + } + } + return Read(std::make_pair(hash, key), row); +} + +template void CClaimTrieDb::updateQueueRow(const K &key, V &row) +{ + const size_t hash = boost::typeindex::type_id >().hash_code(); + std::map::iterator itQueue = queues.find(hash); + if (itQueue == queues.end()) + { + itQueue = queues.insert(itQueue, std::pair(hash, new CCMap)); + } + std::map &map = (static_cast*>(itQueue->second))->data_map(); + typename std::map::iterator itMap = map.find(key); + if (itMap == map.end()) + { + itMap = map.insert(itMap, std::make_pair(key, row)); + } + std::swap(itMap->second, row); +} + +template bool CClaimTrieDb::keyTypeEmpty() const +{ + const size_t hash = boost::typeindex::type_id >().hash_code(); + std::map::const_iterator itQueue = queues.find(hash); + if (itQueue != queues.end()) + { + std::map &map = (static_cast*>(itQueue->second))->data_map(); + for (typename std::map::iterator itMap = map.begin(); itMap != map.end(); ++itMap) + { + if (!itMap->second.empty()) + { + return false; + } + } + } + + boost::scoped_ptr pcursor(const_cast(this)->NewIterator()); + pcursor->SeekToFirst(); + + while (pcursor->Valid()) + { + std::pair key; + if (pcursor->GetKey(key)) + { + if (key.first == hash) + { + return false; + } + } + else + { + break; + } + pcursor->Next(); + } + return true; +} + +template bool CClaimTrieDb::SeekFirstKey(K &keyOut, V &value) const +{ + const size_t hash = boost::typeindex::type_id >().hash_code(); + boost::scoped_ptr pcursor(const_cast(this)->NewIterator()); + pcursor->SeekToFirst(); + + while (pcursor->Valid()) + { + std::pair key; + if (pcursor->GetKey(key)) + { + if (key.first == hash) + { + if (pcursor->GetValue(value)) + { + keyOut = key.second; + return true; + } + else + { + return false; + } + } + } + pcursor->Next(); + } + return false; +} + +template bool CClaimTrieDb::getQueueMap(std::map &map) const +{ + const size_t hash = boost::typeindex::type_id >().hash_code(); + std::map::const_iterator itQueue = queues.find(hash); + if (itQueue != queues.end()) + { + map = (static_cast*>(itQueue->second))->data_map(); + } + + boost::scoped_ptr pcursor(const_cast(this)->NewIterator()); + pcursor->SeekToFirst(); + + while (pcursor->Valid()) + { + std::pair key; + if (pcursor->GetKey(key)) + { + if (key.first == hash) + { + typename std::map::iterator itMap = map.find(key.second); + if (itMap != map.end()) + { + continue; + } + V value; + if (pcursor->GetValue(value)) + { + map.insert(itMap, std::make_pair(key.second, value)); + } + else + { + return false; + } + } + } + pcursor->Next(); + } + return true; +} diff --git a/src/claimtriedb.h b/src/claimtriedb.h new file mode 100644 index 000000000..a0df53b5d --- /dev/null +++ b/src/claimtriedb.h @@ -0,0 +1,40 @@ +#ifndef BITCOIN_CLAIMTRIE_DB_H +#define BITCOIN_CLAIMTRIE_DB_H + +#include "dbwrapper.h" + +#include + +#include +#include + +class CClaimTrieDb; + +class CCBase +{ +public: + virtual ~CCBase() {} + virtual void write(size_t key, CClaimTrieDb *db) = 0; +}; + +class CClaimTrieDb : public CDBWrapper +{ +public: + CClaimTrieDb(bool fMemory = false, bool fWipe = false); + ~CClaimTrieDb(); + + void writeQueues(); + + template bool getQueueMap(std::map &map) const; + + template bool getQueueRow(const K &key, V &row) const; + template void updateQueueRow(const K &key, V &row); + + template bool keyTypeEmpty() const; + template bool SeekFirstKey(K &key, V &value) const; + +private: + std::map queues; +}; + +#endif // BITCOIN_CLAIMTRIE_DB_H diff --git a/src/clientversion.h b/src/clientversion.h index 2f0507d1b..e8e8417ca 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 1 -#define CLIENT_VERSION_BUILD 2 +#define CLIENT_VERSION_REVISION 2 +#define CLIENT_VERSION_BUILD 0 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/consensus/params.h b/src/consensus/params.h index f1be85e9c..5356cd515 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -58,6 +58,14 @@ struct Params { bool fPowNoRetargeting; int64_t nPowTargetSpacing; int64_t nPowTargetTimespan; + int64_t nOriginalClaimExpirationTime; + int64_t nExtendedClaimExpirationTime; + int64_t nExtendedClaimExpirationForkHeight; + int64_t GetExpirationTime(int64_t nHeight) const { + return nHeight < nExtendedClaimExpirationForkHeight ? + nOriginalClaimExpirationTime : + nExtendedClaimExpirationTime; + } int64_t DifficultyAdjustmentInterval() const { return nPowTargetTimespan / nPowTargetSpacing; } }; } // namespace Consensus diff --git a/src/init.cpp b/src/init.cpp index c064dd334..299d86b6b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1229,6 +1229,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("* Using %.1fMiB for chain state database\n", nCoinDBCache * (1.0 / 1024 / 1024)); LogPrintf("* Using %.1fMiB for in-memory UTXO set\n", nCoinCacheUsage * (1.0 / 1024 / 1024)); + const Consensus::Params& consensusParams = Params().GetConsensus(); + bool fLoaded = false; while (!fLoaded) { bool fReset = fReindex; @@ -1266,7 +1268,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // If the loaded chain has a wrong genesis, bail out immediately // (we're likely using a testnet datadir, or the other way around). - if (!mapBlockIndex.empty() && mapBlockIndex.count(chainparams.GetConsensus().hashGenesisBlock) == 0) + if (!mapBlockIndex.empty() && mapBlockIndex.count(consensusParams.hashGenesisBlock) == 0) return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?")); // Initialize the block index (no-op if non-empty database was already loaded) @@ -1422,6 +1424,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) RandAddSeedPerfmon(); + pclaimTrie->setExpirationTime(consensusParams.GetExpirationTime(chainActive.Height())); + //// debug print LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size()); LogPrintf("nBestHeight = %d\n", chainActive.Height()); @@ -1437,7 +1441,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) StartNode(threadGroup, scheduler); // Monitor the chain, and alert if we get blocks much quicker or slower than expected - int64_t nPowTargetSpacing = Params().GetConsensus().nPowTargetSpacing; + int64_t nPowTargetSpacing = consensusParams.nPowTargetSpacing; CScheduler::Function f = boost::bind(&PartitionCheck, &IsInitialBlockDownload, boost::ref(cs_main), boost::cref(pindexBestHeader), nPowTargetSpacing); scheduler.scheduleEvery(f, nPowTargetSpacing); diff --git a/src/main.cpp b/src/main.cpp index 84a8fe226..a894999b6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2171,12 +2171,22 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI if (op == OP_CLAIM_NAME) { assert(vvchParams.size() == 2); + std::string name(vvchParams[0].begin(), vvchParams[0].end()); + std::string value(vvchParams[1].begin(), vvchParams[1].end()); claimId = ClaimIdHash(hash, i); + LogPrintf("--- %s[%lu]: OP_CLAIM_NAME \"%s\" = \"%s\" with claimId %s and tx prevout %s at index %d\n", + __func__, pindex->nHeight, name, SanitizeString(value), + claimId.GetHex(), hash.ToString(), i); } else if (op == OP_UPDATE_CLAIM) { assert(vvchParams.size() == 3); + std::string name(vvchParams[0].begin(), vvchParams[0].end()); + std::string value(vvchParams[1].begin(), vvchParams[1].end()); claimId = uint160(vvchParams[1]); + LogPrintf("--- %s[%lu]: OP_UPDATE_CLAIM \"%s\" = \"%s\" with claimId %s and tx prevout %s at index %d\n", + __func__, pindex->nHeight, name, SanitizeString(value), + claimId.GetHex(), hash.ToString(), i); } 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()); @@ -2190,6 +2200,8 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI assert(vvchParams.size() == 2); std::string name(vvchParams[0].begin(), vvchParams[0].end()); uint160 supportedClaimId(vvchParams[1]); + LogPrintf("--- %s[%lu]: OP_SUPPORT_CLAIM \"%s\" with claimId %s and tx prevout %s at index %d\n", + __func__, pindex->nHeight, name, supportedClaimId.GetHex(), hash.ToString(), i); LogPrintf("%s: (txid: %s, nOut: %d) Removing support for claim id %s on %s due to its block being disconnected\n", __func__, hash.ToString(), i, supportedClaimId.ToString(), name.c_str()); if (!trieCache.undoAddSupport(name, COutPoint(hash, i), pindex->nHeight)) LogPrintf("%s: Something went wrong removing support for name %s in hash %s\n", __func__, name.c_str(), hash.ToString()); @@ -2220,6 +2232,13 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI assert(trieCache.finalizeDecrement()); trieCache.setBestBlock(pindex->pprev->GetBlockHash()); assert(trieCache.getMerkleHash() == pindex->pprev->hashClaimTrie); + if (pindex->nHeight == Params().GetConsensus().nExtendedClaimExpirationForkHeight) + { + LogPrintf("Decremented past the extended claim expiration hard fork height"); + pclaimTrie->setExpirationTime(Params().GetConsensus().GetExpirationTime(pindex->nHeight-1)); + trieCache.forkForExpirationChange(false); + } + if (pfClean) { *pfClean = fClean; @@ -2480,6 +2499,15 @@ 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) + { + LogPrintf("Incremented past the extended claim expiration hard fork height"); + pclaimTrie->setExpirationTime(chainparams.GetConsensus().GetExpirationTime(pindex->nHeight)); + trieCache.forkForExpirationChange(true); + } + int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1; LogPrint("bench", " - Fork checks: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeForks * 0.000001); @@ -2573,12 +2601,22 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (op == OP_CLAIM_NAME) { assert(vvchParams.size() == 2); + std::string name(vvchParams[0].begin(), vvchParams[0].end()); + std::string value(vvchParams[1].begin(), vvchParams[1].end()); claimId = ClaimIdHash(txin.prevout.hash, txin.prevout.n); + LogPrintf("+++ %s[%lu]: OP_CLAIM_NAME \"%s\" = \"%s\" with claimId %s and tx prevout %s at index %d\n", + __func__, pindex->nHeight, name, SanitizeString(value), + claimId.GetHex(), txin.prevout.hash.GetHex(), txin.prevout.n); } else if (op == OP_UPDATE_CLAIM) { assert(vvchParams.size() == 3); + std::string name(vvchParams[0].begin(), vvchParams[0].end()); + std::string value(vvchParams[1].begin(), vvchParams[1].end()); claimId = uint160(vvchParams[1]); + LogPrintf("+++ %s[%lu]: OP_UPDATE_CLAIM \"%s\" = \"%s\" with claimId %s and tx prevout %s at index %d\n", + __func__, pindex->nHeight, name, SanitizeString(value), + claimId.GetHex(), txin.prevout.hash.GetHex(), txin.prevout.n); } std::string name(vvchParams[0].begin(), vvchParams[0].end()); int nValidAtHeight; @@ -2595,6 +2633,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin assert(vvchParams.size() == 2); std::string name(vvchParams[0].begin(), vvchParams[0].end()); uint160 supportedClaimId(vvchParams[1]); + LogPrintf("+++ %s[%lu]: OP_SUPPORT_CLAIM \"%s\" with claimId %s and tx prevout %s at index %d\n", + __func__, pindex->nHeight, name, + supportedClaimId.GetHex(), txin.prevout.hash.GetHex(), txin.prevout.n); int nValidAtHeight; LogPrintf("%s: Removing support for %s in %s. Tx: %s, nOut: %d, removed txid: %s\n", __func__, supportedClaimId.ToString(), name, txin.prevout.hash.ToString(), txin.prevout.n,tx.GetHash().ToString()); if (trieCache.spendSupport(name, COutPoint(txin.prevout.hash, txin.prevout.n), coins->nHeight, nValidAtHeight)) diff --git a/src/pow.cpp b/src/pow.cpp index 39adfa9d7..328c19f60 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -14,31 +14,21 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) { unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact(); - // Genesis block if (pindexLast == NULL) return nProofOfWorkLimit; - // Only change once per difficulty adjustment interval - if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0) + if (params.fPowAllowMinDifficultyBlocks && pindexLast->nHeight >= 277299) { - if (params.fPowAllowMinDifficultyBlocks) - { - // Special difficulty rule for testnet: - // If the new block's timestamp is more than 2* 10 minutes - // then allow mining of a min-difficulty block. - if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2) - return nProofOfWorkLimit; - else - { - // Return the last non-special-min-difficulty-rules-block - const CBlockIndex* pindex = pindexLast; - while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) - pindex = pindex->pprev; - return pindex->nBits; - } + // Special difficulty rule for testnet: + // If the new block's timestamp is twice the target block time + // then allow mining of a min-difficulty block. + // This is to prevent the testnet from gettig stuck when a large amount + // of hashrate drops off the network. + // This rule was not implemented properly until testnet block 277299. + if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2){ + return nProofOfWorkLimit; } - return pindexLast->nBits; } // Go back the full period unless it's the first retarget after genesis. diff --git a/src/test/claimtriebranching_tests.cpp b/src/test/claimtriebranching_tests.cpp index 3ec47301e..2ccdaa0f0 100644 --- a/src/test/claimtriebranching_tests.cpp +++ b/src/test/claimtriebranching_tests.cpp @@ -23,7 +23,6 @@ using namespace std; BOOST_FIXTURE_TEST_SUITE(claimtriebranching_tests, RegTestingSetup) - //is a claim in queue boost::test_tools::predicate_result is_claim_in_queue(std::string name, const CTransaction &tx) @@ -164,7 +163,16 @@ struct ClaimTrieChainFixture{ unsigned int num_txs; unsigned int num_txs_for_next_block; - ClaimTrieChainFixture() + // these will take on regtest parameters + const int expirationForkHeight; + const int originalExpiration; + const int extendedExpiration; + + + ClaimTrieChainFixture(): + expirationForkHeight(Params(CBaseChainParams::REGTEST).GetConsensus().nExtendedClaimExpirationForkHeight), + originalExpiration(Params(CBaseChainParams::REGTEST).GetConsensus().nOriginalClaimExpirationTime), + extendedExpiration(Params(CBaseChainParams::REGTEST).GetConsensus().nExtendedClaimExpirationTime) { fRequireStandard = false; BOOST_CHECK(pclaimTrie->nCurrentHeight == chainActive.Height() + 1); @@ -300,6 +308,17 @@ struct ClaimTrieChainFixture{ num_txs_for_next_block = 0; } + + void WriteClearReadClaimTrie() + { + // this will simulate restart of lbrycrdd by writing the claimtrie to disk, + // clearing the-in memory claimtrie, and then reading the saved claimtrie + // from disk + pclaimTrie->WriteToDisk(); + pclaimTrie->clear(); + pclaimTrie->ReadFromDisk(true); + } + }; @@ -683,6 +702,7 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_update) fixture.DecrementBlocks(11); } + /* expiration check claims expire and loses claim @@ -844,4 +864,204 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_get_claim_by_id) BOOST_CHECK(claimValue2.claimId != claimId); } +/* + claim expiration for hard fork + check claims do not expire post ExpirationForkHeight + check supports work post ExpirationForkHeight +*/ +BOOST_AUTO_TEST_CASE(claimtriebranching_hardfork_claim) +{ + ClaimTrieChainFixture fixture; + + BOOST_CHECK_EQUAL(pclaimTrie->nExpirationTime, fixture.originalExpiration); + // First create a claim and make sure it expires pre-fork + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",3); + fixture.IncrementBlocks(fixture.originalExpiration+1); + BOOST_CHECK(!is_best_claim("test",tx1)); + fixture.DecrementBlocks(fixture.originalExpiration); + BOOST_CHECK(is_best_claim("test",tx1)); + fixture.IncrementBlocks(fixture.originalExpiration); + BOOST_CHECK(!is_best_claim("test",tx1)); + + // Create a claim 1 block before the fork height that will expire after the fork height + fixture.IncrementBlocks(fixture.expirationForkHeight - chainActive.Height() -2); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test2","one",3); + fixture.IncrementBlocks(1); + BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight -1); + + // Disable future expirations and fast-forward past the fork height + fixture.IncrementBlocks(1); + BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight); + BOOST_CHECK_EQUAL(pclaimTrie->nExpirationTime, fixture.extendedExpiration); + // make sure decrementing to before the fork height will apppropriately set back the + // expiration time to the original expiraiton time + fixture.DecrementBlocks(1); + BOOST_CHECK_EQUAL(pclaimTrie->nExpirationTime, fixture.originalExpiration); + fixture.IncrementBlocks(1); + + // make sure that claim created 1 block before the fork expires as expected + // at the extended expiration times + BOOST_CHECK(is_best_claim("test2", tx2)); + fixture.IncrementBlocks(fixture.extendedExpiration-1); + BOOST_CHECK(!is_best_claim("test2", tx2)); + fixture.DecrementBlocks(fixture.extendedExpiration-1); + + // This first claim is still expired since it's pre-fork, even + // after fork activation + BOOST_CHECK(!is_best_claim("test",tx1)); + + // This new claim created at the fork height cannot expire at original expiration + BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight); + CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); + fixture.IncrementBlocks(1); + fixture.IncrementBlocks(fixture.originalExpiration); + BOOST_CHECK(is_best_claim("test",tx3)); + BOOST_CHECK(!is_best_claim("test",tx1)); + fixture.DecrementBlocks(fixture.originalExpiration); + + // but it expires at the extended expiration, and not a single block below + fixture.IncrementBlocks(fixture.extendedExpiration); + BOOST_CHECK(!is_best_claim("test",tx3)); + fixture.DecrementBlocks(fixture.extendedExpiration); + fixture.IncrementBlocks(fixture.extendedExpiration-1); + BOOST_CHECK(is_best_claim("test",tx3)); + fixture.DecrementBlocks(fixture.extendedExpiration-1); + + + // Ensure that we cannot update the original pre-fork expired claim + CMutableTransaction u1 = fixture.MakeUpdate(tx1,"test","two",ClaimIdHash(tx1.GetHash(),0), 3); + fixture.IncrementBlocks(1); + BOOST_CHECK(!is_best_claim("test",u1)); + + // Ensure that supports for the expired claim don't support it + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),u1,"test",10); + BOOST_CHECK(!is_best_claim("test",u1)); + + // Ensure that we can update the new post-fork claim + CMutableTransaction u2 = fixture.MakeUpdate(tx3,"test","two",ClaimIdHash(tx3.GetHash(),0), 1); + fixture.IncrementBlocks(1); + BOOST_CHECK(is_best_claim("test",u2)); + + // Ensure that supports for the new post-fork claim + CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(),u2,"test",3); + BOOST_CHECK(is_best_claim("test",u2)); +} + +/* + support expiration for hard fork +*/ +BOOST_AUTO_TEST_CASE(claimtriebranching_hardfork_support) +{ + ClaimTrieChainFixture fixture; + + int blocks_before_fork = 10; + 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); + // this claim will win without the support + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + fixture.IncrementBlocks(1); + fixture.IncrementBlocks(blocks_before_fork); + + // check that the claim expires as expected at the extended time, as does the support + fixture.IncrementBlocks(fixture.originalExpiration - blocks_before_fork); + BOOST_CHECK(is_best_claim("test",tx1)); + BOOST_CHECK(best_claim_effective_amount_equals("test",3)); + fixture.DecrementBlocks(fixture.originalExpiration - blocks_before_fork); + fixture.IncrementBlocks(fixture.extendedExpiration - blocks_before_fork); + BOOST_CHECK(!is_best_claim("test",tx1)); + fixture.DecrementBlocks(fixture.extendedExpiration - blocks_before_fork); + fixture.IncrementBlocks(fixture.extendedExpiration - blocks_before_fork - 1); + BOOST_CHECK(is_best_claim("test",tx1)); + BOOST_CHECK(best_claim_effective_amount_equals("test",3)); + fixture.DecrementBlocks(fixture.extendedExpiration - blocks_before_fork - 1); + + // update the claims at fork + fixture.DecrementBlocks(1); + CMutableTransaction u1 = fixture.MakeUpdate(tx1,"test","two",ClaimIdHash(tx1.GetHash(),0),1); + CMutableTransaction u2 = fixture.MakeUpdate(tx2,"test","two",ClaimIdHash(tx2.GetHash(),0),2); + fixture.IncrementBlocks(1); + BOOST_CHECK_EQUAL(fixture.expirationForkHeight, chainActive.Height()); + + BOOST_CHECK(is_best_claim("test", u1)); + BOOST_CHECK(best_claim_effective_amount_equals("test",3)); + BOOST_CHECK(!is_claim_in_queue("test",tx1)); + BOOST_CHECK(!is_claim_in_queue("test",tx2)); + + // check that the support expires as expected + fixture.IncrementBlocks(fixture.extendedExpiration - blocks_before_fork); + BOOST_CHECK(is_best_claim("test",u2)); + fixture.DecrementBlocks(fixture.extendedExpiration - blocks_before_fork); + fixture.IncrementBlocks(fixture.extendedExpiration - blocks_before_fork - 1); + BOOST_CHECK(is_best_claim("test",u1)); + BOOST_CHECK(best_claim_effective_amount_equals("test",3)); + +} + +/* + claim/support expiration for hard fork, but with checks for disk procedures +*/ +BOOST_AUTO_TEST_CASE(claimtriebranching_hardfork_disktest) +{ + ClaimTrieChainFixture fixture; + + // Check that incrementing to fork height, reseting to disk will get proper expiration time + BOOST_CHECK_EQUAL(pclaimTrie->nExpirationTime, fixture.originalExpiration); + fixture.IncrementBlocks(fixture.expirationForkHeight - chainActive.Height()); + BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight); + BOOST_CHECK_EQUAL(pclaimTrie->nExpirationTime, fixture.extendedExpiration); + fixture.WriteClearReadClaimTrie(); + BOOST_CHECK_EQUAL(pclaimTrie->nExpirationTime, fixture.extendedExpiration); + + // Create a claim and support 1 block before the fork height that will expire after the fork height. + // Reset to disk, increment past the fork height and make sure we get + // proper behavior + fixture.DecrementBlocks(2); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx1,"test",1); + fixture.IncrementBlocks(1); + BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight -1); + + fixture.WriteClearReadClaimTrie(); + BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight-1); + BOOST_CHECK_EQUAL(pclaimTrie->nExpirationTime, fixture.originalExpiration); + fixture.IncrementBlocks(1); + BOOST_CHECK_EQUAL(pclaimTrie->nExpirationTime, fixture.extendedExpiration); + BOOST_CHECK(is_best_claim("test", tx1)); + BOOST_CHECK(best_claim_effective_amount_equals("test",2)); + fixture.IncrementBlocks(fixture.originalExpiration-1); + BOOST_CHECK(is_best_claim("test", tx1)); + BOOST_CHECK(best_claim_effective_amount_equals("test",2)); + fixture.DecrementBlocks(fixture.originalExpiration-1); + fixture.IncrementBlocks(fixture.extendedExpiration-1); + BOOST_CHECK(!is_best_claim("test", tx1)); + + // Create a claim and support before the fork height, reset to disk, update the claim + // increment past the fork height and make sure we get proper behavior + int height_of_update_before_expiration = 50; + fixture.DecrementBlocks(chainActive.Height() - fixture.expirationForkHeight + height_of_update_before_expiration+2); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test2","one",1); + CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(),tx2,"test2",1); + fixture.IncrementBlocks(1); + fixture.WriteClearReadClaimTrie(); + CMutableTransaction u2 = fixture.MakeUpdate(tx2,"test2","two",ClaimIdHash(tx2.GetHash(),0),1); + // increment to fork + fixture.IncrementBlocks(fixture.expirationForkHeight - chainActive.Height()); + BOOST_CHECK(is_best_claim("test2", u2)); + BOOST_CHECK(best_claim_effective_amount_equals("test2",2)); + // increment to original expiration, should not be expired + fixture.IncrementBlocks(fixture.originalExpiration - height_of_update_before_expiration); + BOOST_CHECK(is_best_claim("test2", u2)); + BOOST_CHECK(best_claim_effective_amount_equals("test2",2)); + fixture.DecrementBlocks(fixture.originalExpiration - height_of_update_before_expiration); + // increment to extended expiration, should be expired and not one block before + fixture.IncrementBlocks(fixture.extendedExpiration - height_of_update_before_expiration); + BOOST_CHECK(!is_best_claim("test2", u2)); + fixture.DecrementBlocks(fixture.extendedExpiration - height_of_update_before_expiration); + fixture.IncrementBlocks(fixture.extendedExpiration - height_of_update_before_expiration-1); + BOOST_CHECK(is_best_claim("test2", u2)); + BOOST_CHECK(best_claim_effective_amount_equals("test2",1)); // the support expires one block before +} + BOOST_AUTO_TEST_SUITE_END()