Separate disk related functions in CClaimTrieDb

Signed-off-by: Anthony Fieroni <bvbfan@abv.bg>
This commit is contained in:
Anthony Fieroni 2018-05-19 23:55:32 +03:00
parent 7930840005
commit 7d321ec0ea
14 changed files with 802 additions and 579 deletions

View file

@ -2,8 +2,8 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
AC_PREREQ([2.60]) AC_PREREQ([2.60])
define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MAJOR, 0)
define(_CLIENT_VERSION_MINOR, 12) define(_CLIENT_VERSION_MINOR, 12)
define(_CLIENT_VERSION_REVISION, 1) define(_CLIENT_VERSION_REVISION, 2)
define(_CLIENT_VERSION_BUILD, 2) define(_CLIENT_VERSION_BUILD, 0)
define(_CLIENT_VERSION_IS_RELEASE, true) define(_CLIENT_VERSION_IS_RELEASE, true)
define(_COPYRIGHT_YEAR, 2016) define(_COPYRIGHT_YEAR, 2016)
define(_COPYRIGHT_HOLDERS,[The %s developers]) define(_COPYRIGHT_HOLDERS,[The %s developers])

View file

@ -277,8 +277,9 @@ function build_openssl() {
-fPIC darwin64-x86_64-cc \ -fPIC darwin64-x86_64-cc \
no-shared no-dso no-engines > "${OPENSSL_LOG}" no-shared no-dso no-engines > "${OPENSSL_LOG}"
else else
[[ $(uname -m) = 'i686' ]] && OS_ARCH="linux-generic32" || OS_ARCH="linux-x86_64"
./Configure --prefix="${OPENSSL_PREFIX}" --openssldir="${OPENSSL_PREFIX}/ssl" \ ./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 fi
background make "${OPENSSL_LOG}" "Waiting for openssl to finish building" background make "${OPENSSL_LOG}" "Waiting for openssl to finish building"
make install >> "${OPENSSL_LOG}" 2>&1 make install >> "${OPENSSL_LOG}" 2>&1

View file

@ -119,6 +119,7 @@ BITCOIN_CORE_H = \
miner.h \ miner.h \
nameclaim.h \ nameclaim.h \
claimtrie.h \ claimtrie.h \
claimtriedb.h \
lbry.h \ lbry.h \
net.h \ net.h \
netbase.h \ netbase.h \
@ -191,6 +192,7 @@ libbitcoin_server_a_SOURCES = \
merkleblock.cpp \ merkleblock.cpp \
miner.cpp \ miner.cpp \
claimtrie.cpp \ claimtrie.cpp \
claimtriedb.cpp \
net.cpp \ net.cpp \
noui.cpp \ noui.cpp \
policy/fees.cpp \ policy/fees.cpp \

View file

@ -131,6 +131,9 @@ public:
consensus.powLimit = uint256S("0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.powLimit = uint256S("0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
consensus.nPowTargetTimespan = 150; //retarget every block consensus.nPowTargetTimespan = 150; //retarget every block
consensus.nPowTargetSpacing = 150; consensus.nPowTargetSpacing = 150;
consensus.nOriginalClaimExpirationTime = 262974;
consensus.nExtendedClaimExpirationTime = 2102400;
consensus.nExtendedClaimExpirationForkHeight = 400155;
consensus.fPowAllowMinDifficultyBlocks = false; consensus.fPowAllowMinDifficultyBlocks = false;
consensus.fPowNoRetargeting = false; consensus.fPowNoRetargeting = false;
consensus.nRuleChangeActivationThreshold = 1916; // 95% of 2016 consensus.nRuleChangeActivationThreshold = 1916; // 95% of 2016
@ -215,6 +218,9 @@ public:
consensus.powLimit = uint256S("0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.powLimit = uint256S("0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
consensus.nPowTargetTimespan = 150; consensus.nPowTargetTimespan = 150;
consensus.nPowTargetSpacing = 150; consensus.nPowTargetSpacing = 150;
consensus.nOriginalClaimExpirationTime = 262974;
consensus.nExtendedClaimExpirationTime = 2102400;
consensus.nExtendedClaimExpirationForkHeight = 278160;
consensus.fPowAllowMinDifficultyBlocks = true; consensus.fPowAllowMinDifficultyBlocks = true;
consensus.fPowNoRetargeting = false; consensus.fPowNoRetargeting = false;
consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains
@ -292,6 +298,9 @@ public:
consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
consensus.nPowTargetTimespan = 1;//14 * 24 * 60 * 60; // two weeks consensus.nPowTargetTimespan = 1;//14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 1; consensus.nPowTargetSpacing = 1;
consensus.nOriginalClaimExpirationTime = 500;
consensus.nExtendedClaimExpirationTime = 600;
consensus.nExtendedClaimExpirationForkHeight = 800;
consensus.fPowAllowMinDifficultyBlocks = false; consensus.fPowAllowMinDifficultyBlocks = false;
consensus.fPowNoRetargeting = false; consensus.fPowNoRetargeting = false;
consensus.nRuleChangeActivationThreshold = 108; // 75% for testchains consensus.nRuleChangeActivationThreshold = 108; // 75% for testchains

View file

@ -2,10 +2,14 @@
#include "coins.h" #include "coins.h"
#include "hash.h" #include "hash.h"
#include <boost/scoped_ptr.hpp>
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
#define HASH_BLOCK 'h'
#define CURRENT_HEIGHT 't'
#include "claimtriedb.cpp" // avoid linker problems
std::vector<unsigned char> heightToVch(int n) std::vector<unsigned char> heightToVch(int n)
{ {
std::vector<unsigned char> vchHeight; std::vector<unsigned char> vchHeight;
@ -147,77 +151,30 @@ bool CClaimTrie::empty() const
return root.empty(); return root.empty();
} }
template<typename K> bool CClaimTrie::keyTypeEmpty(char keyType, K& dummy) const
{
boost::scoped_ptr<CDBIterator> pcursor(const_cast<CDBWrapper*>(&db)->NewIterator());
pcursor->SeekToFirst();
while (pcursor->Valid())
{
std::pair<char, K> key;
if (pcursor->GetKey(key))
{
if (key.first == keyType)
{
return false;
}
}
else
{
break;
}
pcursor->Next();
}
return true;
}
bool CClaimTrie::queueEmpty() const bool CClaimTrie::queueEmpty() const
{ {
for (claimQueueType::const_iterator itRow = dirtyQueueRows.begin(); itRow != dirtyQueueRows.end(); ++itRow) return db.keyTypeEmpty<int, claimQueueRowType>();
{
if (!itRow->second.empty())
return false;
}
int dummy;
return keyTypeEmpty(CLAIM_QUEUE_ROW, dummy);
} }
bool CClaimTrie::expirationQueueEmpty() const bool CClaimTrie::expirationQueueEmpty() const
{ {
for (expirationQueueType::const_iterator itRow = dirtyExpirationQueueRows.begin(); itRow != dirtyExpirationQueueRows.end(); ++itRow) return db.keyTypeEmpty<int, expirationQueueRowType>();
{
if (!itRow->second.empty())
return false;
}
int dummy;
return keyTypeEmpty(EXP_QUEUE_ROW, dummy);
} }
bool CClaimTrie::supportEmpty() const bool CClaimTrie::supportEmpty() const
{ {
for (supportMapType::const_iterator itNode = dirtySupportNodes.begin(); itNode != dirtySupportNodes.end(); ++itNode) return db.keyTypeEmpty<std::string, supportMapEntryType>();
{
if (!itNode->second.empty())
return false;
}
std::string dummy;
return keyTypeEmpty(SUPPORT, dummy);
} }
bool CClaimTrie::supportQueueEmpty() const bool CClaimTrie::supportQueueEmpty() const
{ {
for (supportQueueType::const_iterator itRow = dirtySupportQueueRows.begin(); itRow != dirtySupportQueueRows.end(); ++itRow) return db.keyTypeEmpty<int, supportQueueRowType>();
{
if (!itRow->second.empty())
return false;
}
int dummy;
return keyTypeEmpty(SUPPORT_QUEUE_ROW, dummy);
} }
void CClaimTrie::setExpirationTime(int t) void CClaimTrie::setExpirationTime(int t)
{ {
nExpirationTime = t; nExpirationTime = t;
LogPrintf("%s: Expiration time is now %d\n", __func__, nExpirationTime);
} }
void CClaimTrie::clear() 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 bool CClaimTrie::haveSupport(const std::string& name, const COutPoint& outPoint) const
{ {
supportMapEntryType node; supportMapEntryType node;
if (!getSupportNode(name, node)) if (!db.getQueueRow(name, node))
{ {
return false; 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 bool CClaimTrie::haveClaimInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const
{ {
queueNameRowType nameRow; queueNameRowType nameRow;
if (!getQueueNameRow(name, nameRow)) if (!db.getQueueRow(name, nameRow))
{ {
return false; return false;
} }
@ -283,7 +240,7 @@ bool CClaimTrie::haveClaimInQueue(const std::string& name, const COutPoint& outP
return false; return false;
} }
claimQueueRowType row; claimQueueRowType row;
if (getQueueRow(nValidAtHeight, row)) if (db.getQueueRow(nValidAtHeight, row))
{ {
for (claimQueueRowType::const_iterator itRow = row.begin(); itRow != row.end(); ++itRow) 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 bool CClaimTrie::haveSupportInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const
{ {
queueNameRowType nameRow; supportQueueNameRowType nameRow;
if (!getSupportQueueNameRow(name, nameRow)) if (!db.getQueueRow(name, nameRow))
{ {
return false; return false;
} }
queueNameRowType::const_iterator itNameRow; supportQueueNameRowType::const_iterator itNameRow;
for (itNameRow = nameRow.begin(); itNameRow != nameRow.end(); ++itNameRow) for (itNameRow = nameRow.begin(); itNameRow != nameRow.end(); ++itNameRow)
{ {
if (itNameRow->outPoint == outPoint) if (itNameRow->outPoint == outPoint)
@ -322,7 +279,7 @@ bool CClaimTrie::haveSupportInQueue(const std::string& name, const COutPoint& ou
return false; return false;
} }
supportQueueRowType row; supportQueueRowType row;
if (getSupportQueueRow(nValidAtHeight, row)) if (db.getQueueRow(nValidAtHeight, row))
{ {
for (supportQueueRowType::const_iterator itRow = row.begin(); itRow != row.end(); ++itRow) 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; supportMapEntryType supportNode;
if (getSupportNode(name, supportNode)) if (db.getQueueRow(name, supportNode))
{ {
for (std::vector<CSupportValue>::const_iterator itSupports = supportNode.begin(); itSupports != supportNode.end(); ++itSupports) for (std::vector<CSupportValue>::const_iterator itSupports = supportNode.begin(); itSupports != supportNode.end(); ++itSupports)
{ {
@ -484,12 +441,12 @@ claimsForNameType CClaimTrie::getClaimsForName(const std::string& name) const
} }
} }
queueNameRowType namedClaimRow; queueNameRowType namedClaimRow;
if (getQueueNameRow(name, namedClaimRow)) if (db.getQueueRow(name, namedClaimRow))
{ {
for (queueNameRowType::const_iterator itClaimsForName = namedClaimRow.begin(); itClaimsForName != namedClaimRow.end(); ++itClaimsForName) for (queueNameRowType::const_iterator itClaimsForName = namedClaimRow.begin(); itClaimsForName != namedClaimRow.end(); ++itClaimsForName)
{ {
claimQueueRowType claimRow; claimQueueRowType claimRow;
if (getQueueRow(itClaimsForName->nHeight, claimRow)) if (db.getQueueRow(itClaimsForName->nHeight, claimRow))
{ {
for (claimQueueRowType::const_iterator itClaimRow = claimRow.begin(); itClaimRow != claimRow.end(); ++itClaimRow) 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; supportQueueNameRowType namedSupportRow;
if (getSupportQueueNameRow(name, 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; supportQueueRowType supportRow;
if (getSupportQueueRow(itSupportsForName->nHeight, supportRow)) if (db.getQueueRow(itSupportsForName->nHeight, supportRow))
{ {
for (supportQueueRowType::const_iterator itSupportRow = supportRow.begin(); itSupportRow != supportRow.end(); ++itSupportRow) 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 }; CClaimIndexElement element = { name, claim };
LogPrintf("%s: ClaimIndex[%s] updated %s\n", __func__, claim.claimId.GetHex(), name); 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) 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 bool CClaimTrie::getClaimById(const uint160 claimId, std::string& name, CClaimValue& claim) const
{ {
CClaimIndexElement element; CClaimIndexElement element;
if (db.Read(std::make_pair(CLAIM_BY_ID, claimId), element)) if (db.getQueueRow(claimId, element))
{ {
name = element.name; name = element.name;
claim = element.claim; claim = element.claim;
@ -616,182 +574,7 @@ bool CClaimTrie::getClaimById(const uint160 claimId, std::string& name, CClaimVa
return false; return false;
} }
bool CClaimTrie::getQueueRow(int nHeight, claimQueueRowType& row) const bool CClaimTrie::update(nodeCacheType& cache, hashMapType& hashes, std::map<std::string, int>& takeoverHeights, const uint256& hashBlockIn, claimQueueType& queueCache, queueNameType& queueNameCache, expirationQueueType& expirationQueueCache, int nNewHeight, supportMapType& supportCache, supportQueueType& supportQueueCache, supportQueueNameType& supportQueueNameCache, supportExpirationQueueType& supportExpirationQueueCache)
{
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<claimQueueType::iterator, bool> ret;
ret = dirtyQueueRows.insert(std::pair<int, claimQueueRowType >(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<queueNameType::iterator, bool> ret;
ret = dirtyQueueNameRows.insert(std::pair<std::string, queueNameRowType>(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<expirationQueueType::iterator, bool> ret;
ret = dirtyExpirationQueueRows.insert(std::pair<int, expirationQueueRowType >(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<supportMapType::iterator, bool> ret;
ret = dirtySupportNodes.insert(std::pair<std::string, supportMapEntryType>(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<supportQueueType::iterator, bool> ret;
ret = dirtySupportQueueRows.insert(std::pair<int, supportQueueRowType >(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<queueNameType::iterator, bool> ret;
ret = dirtySupportQueueNameRows.insert(std::pair<std::string, queueNameRowType>(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<expirationQueueType::iterator, bool> ret;
ret = dirtySupportExpirationQueueRows.insert(std::pair<int, expirationQueueRowType >(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<std::string, int>& takeoverHeights, const uint256& hashBlockIn, claimQueueType& queueCache, queueNameType& queueNameCache, expirationQueueType& expirationQueueCache, int nNewHeight, supportMapType& supportCache, supportQueueType& supportQueueCache, queueNameType& supportQueueNameCache, expirationQueueType& supportExpirationQueueCache)
{ {
for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache) for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache)
{ {
@ -819,31 +602,31 @@ bool CClaimTrie::update(nodeCacheType& cache, hashMapType& hashes, std::map<std:
} }
for (claimQueueType::iterator itQueueCacheRow = queueCache.begin(); itQueueCacheRow != queueCache.end(); ++itQueueCacheRow) for (claimQueueType::iterator itQueueCacheRow = queueCache.begin(); itQueueCacheRow != queueCache.end(); ++itQueueCacheRow)
{ {
updateQueueRow(itQueueCacheRow->first, itQueueCacheRow->second); db.updateQueueRow(itQueueCacheRow->first, itQueueCacheRow->second);
} }
for (queueNameType::iterator itQueueNameCacheRow = queueNameCache.begin(); itQueueNameCacheRow != queueNameCache.end(); ++itQueueNameCacheRow) 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) 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) 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) 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; hashBlock = hashBlockIn;
nCurrentHeight = nNewHeight; nCurrentHeight = nNewHeight;
@ -952,146 +735,16 @@ bool CClaimTrie::updateTakeoverHeight(const std::string& name, int nTakeoverHeig
return true; 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() bool CClaimTrie::WriteToDisk()
{ {
CDBBatch batch(&db.GetObfuscateKey());
for (nodeCacheType::iterator itcache = dirtyNodes.begin(); itcache != dirtyNodes.end(); ++itcache) for (nodeCacheType::iterator itcache = dirtyNodes.begin(); itcache != dirtyNodes.end(); ++itcache)
BatchWriteNode(batch, itcache->first, itcache->second); db.updateQueueRow(itcache->first, *(itcache->second));
dirtyNodes.clear(); dirtyNodes.clear();
BatchWriteQueueRows(batch); db.writeQueues();
dirtyQueueRows.clear(); db.Write(HASH_BLOCK, hashBlock);
BatchWriteQueueNameRows(batch); db.Write(CURRENT_HEIGHT, nCurrentHeight);
dirtyQueueNameRows.clear(); return db.Sync();
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);
} }
bool CClaimTrie::InsertFromDisk(const std::string& name, CClaimTrieNode* node) bool CClaimTrie::InsertFromDisk(const std::string& name, CClaimTrieNode* node)
@ -1109,7 +762,7 @@ bool CClaimTrie::InsertFromDisk(const std::string& name, CClaimTrieNode* node)
return false; return false;
current = itchild->second; current = itchild->second;
} }
current->children[name[name.size()-1]] = node; current->children[name[name.size()-1]] = new CClaimTrieNode(*node);
return true; return true;
} }
@ -1119,31 +772,19 @@ bool CClaimTrie::ReadFromDisk(bool check)
LogPrintf("%s: Couldn't read the best block's hash\n", __func__); LogPrintf("%s: Couldn't read the best block's hash\n", __func__);
if (!db.Read(CURRENT_HEIGHT, nCurrentHeight)) if (!db.Read(CURRENT_HEIGHT, nCurrentHeight))
LogPrintf("%s: Couldn't read the current height\n", __func__); LogPrintf("%s: Couldn't read the current height\n", __func__);
boost::scoped_ptr<CDBIterator> pcursor(const_cast<CDBWrapper*>(&db)->NewIterator());
pcursor->SeekToFirst(); setExpirationTime(Params().GetConsensus().GetExpirationTime(nCurrentHeight-1));
while (pcursor->Valid())
std::string name;
CClaimTrieNode node;
if(!db.SeekFirstKey(name, node))
{ {
std::pair<char, std::string> key; return error("%s(): error reading claim trie from disk", __func__);
if (pcursor->GetKey(key)) }
{
if (key.first == TRIE_NODE) if (!InsertFromDisk(name, &node))
{ {
CClaimTrieNode* node = new CClaimTrieNode(); return error("%s(): error restoring claim trie from disk", __func__);
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();
} }
if (check) if (check)
@ -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 // Have to make a new row it put in the cache, if createIfNotExists is true
claimQueueRowType queueRow; claimQueueRowType queueRow;
// If the row exists in the base, copy its claims into the new row. // 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 (!exists)
if (!createIfNotExists) if (!createIfNotExists)
return itQueueRow; 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 // Have to make a new name row and put it in the cache, if createIfNotExists is true
queueNameRowType queueNameRow; queueNameRowType queueNameRow;
// If the row exists in the base, copy its claims into the new row. // 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 (!exists)
if (!createIfNotExists) if (!createIfNotExists)
return itQueueNameRow; return itQueueNameRow;
@ -1653,7 +1294,8 @@ bool CClaimTrieCache::removeClaimFromQueue(const std::string& name, const COutPo
} }
if (itQueue != itQueueRow->second.end()) if (itQueue != itQueueRow->second.end())
{ {
std::swap(claim, itQueue->second); swap(claim, itQueue->second);
claim = itQueue->second;
itQueueNameRow->second.erase(itQueueName); itQueueNameRow->second.erase(itQueueName);
itQueueRow->second.erase(itQueue); itQueueRow->second.erase(itQueue);
@ -1692,7 +1334,8 @@ bool CClaimTrieCache::removeClaim(const std::string& name, const COutPoint& outP
if (removed == true) if (removed == true)
{ {
nValidAtHeight = claim.nValidAtHeight; nValidAtHeight = claim.nValidAtHeight;
removeFromExpirationQueue(name, outPoint, nHeight); int expirationHeight = nHeight + base->nExpirationTime;
removeFromExpirationQueue(name, outPoint, expirationHeight);
} }
return removed; return removed;
} }
@ -1703,9 +1346,8 @@ void CClaimTrieCache::addToExpirationQueue(int nExpirationHeight, nameOutPointTy
itQueueRow->second.push_back(entry); 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); expirationQueueType::iterator itQueueRow = getExpirationQueueCacheRow(expirationHeight, false);
expirationQueueRowType::iterator itQueue; expirationQueueRowType::iterator itQueue;
if (itQueueRow != expirationQueueCache.end()) if (itQueueRow != expirationQueueCache.end())
@ -1715,10 +1357,11 @@ void CClaimTrieCache::removeFromExpirationQueue(const std::string& name, const C
if (name == itQueue->name && outPoint == itQueue->outPoint) if (name == itQueue->name && outPoint == itQueue->outPoint)
break; break;
} }
}
if (itQueue != itQueueRow->second.end()) if (itQueue != itQueueRow->second.end())
{ {
itQueueRow->second.erase(itQueue); 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 // Have to make a new row it put in the cache, if createIfNotExists is true
expirationQueueRowType queueRow; expirationQueueRowType queueRow;
// If the row exists in the base, copy its claims into the new row. // 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 (!exists)
if (!createIfNotExists) if (!createIfNotExists)
return itQueueRow; return itQueueRow;
@ -1822,7 +1465,7 @@ bool CClaimTrieCache::getSupportsForName(const std::string& name, supportMapEntr
} }
else 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()) if (cachedNode == supportCache.end())
{ {
supportMapEntryType node; supportMapEntryType node;
base->getSupportNode(name, node); base->db.getQueueRow(name, node);
std::pair<supportMapType::iterator, bool> ret; std::pair<supportMapType::iterator, bool> ret;
ret = supportCache.insert(std::pair<std::string, supportMapEntryType>(name, node)); ret = supportCache.insert(std::pair<std::string, supportMapEntryType>(name, node));
assert(ret.second); assert(ret.second);
@ -1853,7 +1496,7 @@ bool CClaimTrieCache::removeSupportFromMap(const std::string& name, const COutPo
if (cachedNode == supportCache.end()) if (cachedNode == supportCache.end())
{ {
supportMapEntryType node; supportMapEntryType node;
if (!base->getSupportNode(name, node)) if (!base->db.getQueueRow(name, node))
{ {
// clearly, this support does not exist // clearly, this support does not exist
return false; return false;
@ -1890,7 +1533,7 @@ supportQueueType::iterator CClaimTrieCache::getSupportQueueCacheRow(int nHeight,
if (itQueueRow == supportQueueCache.end()) if (itQueueRow == supportQueueCache.end())
{ {
supportQueueRowType queueRow; supportQueueRowType queueRow;
bool exists = base->getSupportQueueRow(nHeight, queueRow); bool exists = base->db.getQueueRow(nHeight, queueRow);
if (!exists) if (!exists)
if (!createIfNotExists) if (!createIfNotExists)
return itQueueRow; return itQueueRow;
@ -1903,19 +1546,19 @@ supportQueueType::iterator CClaimTrieCache::getSupportQueueCacheRow(int nHeight,
return itQueueRow; 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()) if (itQueueNameRow == supportQueueNameCache.end())
{ {
queueNameRowType queueNameRow; supportQueueNameRowType queueNameRow;
bool exists = base->getSupportQueueNameRow(name, queueNameRow); bool exists = base->db.getQueueRow(name, queueNameRow);
if (!exists) if (!exists)
if (!createIfNotExists) if (!createIfNotExists)
return itQueueNameRow; return itQueueNameRow;
// Stick the new row in the name cache // Stick the new row in the name cache
std::pair<queueNameType::iterator, bool> ret; std::pair<supportQueueNameType::iterator, bool> ret;
ret = supportQueueNameCache.insert(std::pair<std::string, queueNameRowType>(name, queueNameRow)); ret = supportQueueNameCache.insert(std::make_pair(name, queueNameRow));
assert(ret.second); assert(ret.second);
itQueueNameRow = ret.first; itQueueNameRow = ret.first;
} }
@ -1927,7 +1570,7 @@ bool CClaimTrieCache::addSupportToQueues(const std::string& name, CSupportValue&
LogPrintf("%s: nValidAtHeight: %d\n", __func__, support.nValidAtHeight); LogPrintf("%s: nValidAtHeight: %d\n", __func__, support.nValidAtHeight);
supportQueueEntryType entry(name, support); supportQueueEntryType entry(name, support);
supportQueueType::iterator itQueueRow = getSupportQueueCacheRow(support.nValidAtHeight, true); supportQueueType::iterator itQueueRow = getSupportQueueCacheRow(support.nValidAtHeight, true);
queueNameType::iterator itQueueNameRow = getSupportQueueCacheNameRow(name, true); supportQueueNameType::iterator itQueueNameRow = getSupportQueueCacheNameRow(name, true);
itQueueRow->second.push_back(entry); itQueueRow->second.push_back(entry);
itQueueNameRow->second.push_back(outPointHeightType(support.outPoint, support.nValidAtHeight)); itQueueNameRow->second.push_back(outPointHeightType(support.outPoint, support.nValidAtHeight));
nameOutPointType expireEntry(name, support.outPoint); 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 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()) if (itQueueNameRow == supportQueueNameCache.end())
{ {
return false; return false;
} }
queueNameRowType::iterator itQueueName; supportQueueNameRowType::iterator itQueueName;
for (itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) for (itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName)
{ {
if (itQueueName->outPoint == outPoint) if (itQueueName->outPoint == outPoint)
@ -1968,7 +1611,7 @@ bool CClaimTrieCache::removeSupportFromQueue(const std::string& name, const COut
} }
if (itQueue != itQueueRow->second.end()) if (itQueue != itQueueRow->second.end())
{ {
std::swap(support, itQueue->second); swap(support, itQueue->second);
itQueueNameRow->second.erase(itQueueName); itQueueNameRow->second.erase(itQueueName);
itQueueRow->second.erase(itQueue); itQueueRow->second.erase(itQueue);
return true; return true;
@ -2023,7 +1666,8 @@ bool CClaimTrieCache::removeSupport(const std::string& name, const COutPoint& ou
removed = true; removed = true;
if (removed) if (removed)
{ {
removeSupportFromExpirationQueue(name, outPoint, nHeight); int expirationHeight = nHeight + base->nExpirationTime;
removeSupportFromExpirationQueue(name, outPoint, expirationHeight);
nValidAtHeight = support.nValidAtHeight; nValidAtHeight = support.nValidAtHeight;
} }
return removed; return removed;
@ -2031,15 +1675,14 @@ bool CClaimTrieCache::removeSupport(const std::string& name, const COutPoint& ou
void CClaimTrieCache::addSupportToExpirationQueue(int nExpirationHeight, nameOutPointType& entry) const 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); 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; supportExpirationQueueType::iterator itQueueRow = getSupportExpirationQueueCacheRow(expirationHeight, false);
expirationQueueType::iterator itQueueRow = getSupportExpirationQueueCacheRow(expirationHeight, false); supportExpirationQueueRowType::iterator itQueue;
expirationQueueRowType::iterator itQueue;
if (itQueueRow != supportExpirationQueueCache.end()) if (itQueueRow != supportExpirationQueueCache.end())
{ {
for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) 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()) if (itQueueRow == supportExpirationQueueCache.end())
{ {
// Have to make a new row it put in the cache, if createIfNotExists is true // 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. // 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 (!exists)
if (!createIfNotExists) if (!createIfNotExists)
return itQueueRow; return itQueueRow;
// Stick the new row in the cache // Stick the new row in the cache
std::pair<expirationQueueType::iterator, bool> ret; std::pair<supportExpirationQueueType::iterator, bool> ret;
ret = supportExpirationQueueCache.insert(std::pair<int, expirationQueueRowType >(nHeight, queueRow)); ret = supportExpirationQueueCache.insert(std::make_pair(nHeight, queueRow));
assert(ret.second); assert(ret.second);
itQueueRow = ret.first; 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<std::pair<std::string, int> >& takeoverHeightUndo) const bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowType& expireUndo, insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo, std::vector<std::pair<std::string, int> >& takeoverHeightUndo) const
{ {
LogPrintf("%s: nCurrentHeight (before increment): %d\n", __func__, nCurrentHeight); LogPrintf("%s: nCurrentHeight (before increment): %d\n", __func__, nCurrentHeight);
claimQueueType::iterator itQueueRow = getQueueCacheRow(nCurrentHeight, false); claimQueueType::iterator itQueueRow = getQueueCacheRow(nCurrentHeight, false);
if (itQueueRow != claimQueueCache.end()) if (itQueueRow != claimQueueCache.end())
{ {
@ -2140,6 +1784,7 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy
CClaimValue claim; CClaimValue claim;
assert(removeClaimFromTrie(itEntry->name, itEntry->outPoint, claim, true)); assert(removeClaimFromTrie(itEntry->name, itEntry->outPoint, claim, true));
expireUndo.push_back(std::make_pair(itEntry->name, claim)); expireUndo.push_back(std::make_pair(itEntry->name, claim));
LogPrintf("Expiring claim %s: %s, nHeight: %d, nValidAtHeight: %d\n", claim.claimId.GetHex(), itEntry->name, claim.nHeight, claim.nValidAtHeight);
} }
itExpirationRow->second.clear(); 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) for (supportQueueRowType::iterator itSupport = itSupportRow->second.begin(); itSupport != itSupportRow->second.end(); ++itSupport)
{ {
bool found = false; bool found = false;
queueNameType::iterator itSupportNameRow = getSupportQueueCacheNameRow(itSupport->first, false); supportQueueNameType::iterator itSupportNameRow = getSupportQueueCacheNameRow(itSupport->first, false);
if (itSupportNameRow != supportQueueNameCache.end()) 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) 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()) if (itSupportNameRow != supportQueueNameCache.end())
{ {
LogPrintf("Supports found for that name:\n"); 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); LogPrintf("\ttxid: %s, nOut: %d, nValidAtHeight: %d\n", itSupportName->outPoint.hash.GetHex(), itSupportName->outPoint.n, itSupportName->nHeight);
} }
@ -2183,14 +1828,15 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy
} }
itSupportRow->second.clear(); itSupportRow->second.clear();
} }
expirationQueueType::iterator itSupportExpirationRow = getSupportExpirationQueueCacheRow(nCurrentHeight, false); supportExpirationQueueType::iterator itSupportExpirationRow = getSupportExpirationQueueCacheRow(nCurrentHeight, false);
if (itSupportExpirationRow != supportExpirationQueueCache.end()) 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; CSupportValue support;
assert(removeSupportFromMap(itEntry->name, itEntry->outPoint, support, true)); assert(removeSupportFromMap(itEntry->name, itEntry->outPoint, support, true));
expireSupportUndo.push_back(std::make_pair(itEntry->name, support)); 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(); itSupportExpirationRow->second.clear();
} }
@ -2288,10 +1934,10 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy
} }
// //
// Then, get all supports in the queue for that name // 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()) 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 // Pull those supports out of the height-based queue
supportQueueType::iterator itSupportQueueRow = getSupportQueueCacheRow(itSupportQueueName->nHeight, false); supportQueueType::iterator itSupportQueueRow = getSupportQueueCacheRow(itSupportQueueName->nHeight, false);
@ -2364,7 +2010,7 @@ bool CClaimTrieCache::decrementBlock(insertUndoType& insertUndo, claimQueueRowTy
if (expireSupportUndo.begin() != expireSupportUndo.end()) 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) for (supportQueueRowType::iterator itSupportExpireUndo = expireSupportUndo.begin(); itSupportExpireUndo != expireSupportUndo.end(); ++itSupportExpireUndo)
{ {
insertSupportIntoMap(itSupportExpireUndo->first, itSupportExpireUndo->second, false); insertSupportIntoMap(itSupportExpireUndo->first, itSupportExpireUndo->second, false);
@ -2377,7 +2023,7 @@ bool CClaimTrieCache::decrementBlock(insertUndoType& insertUndo, claimQueueRowTy
supportQueueType::iterator itSupportRow = getSupportQueueCacheRow(itSupportUndo->nHeight, true); supportQueueType::iterator itSupportRow = getSupportQueueCacheRow(itSupportUndo->nHeight, true);
CSupportValue support; CSupportValue support;
assert(removeSupportFromMap(itSupportUndo->name, itSupportUndo->outPoint, support, false)); 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)); itSupportRow->second.push_back(std::make_pair(itSupportUndo->name, support));
itSupportNameRow->second.push_back(outPointHeightType(support.outPoint, support.nValidAtHeight)); itSupportNameRow->second.push_back(outPointHeightType(support.outPoint, support.nValidAtHeight));
} }
@ -2406,6 +2052,7 @@ bool CClaimTrieCache::decrementBlock(insertUndoType& insertUndo, claimQueueRowTy
{ {
cacheTakeoverHeights[itTakeoverHeightUndo->first] = itTakeoverHeightUndo->second; cacheTakeoverHeights[itTakeoverHeightUndo->first] = itTakeoverHeightUndo->second;
} }
return true; return true;
} }
@ -2594,3 +2241,70 @@ CClaimTrieProof CClaimTrieCache::getProofForName(const std::string& name) const
return CClaimTrieProof(nodes, fNameHasValue, outPoint, return CClaimTrieProof(nodes, fNameHasValue, outPoint,
nHeightOfLastTakeover); 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;
}

View file

@ -5,25 +5,12 @@
#include "serialize.h" #include "serialize.h"
#include "uint256.h" #include "uint256.h"
#include "util.h" #include "util.h"
#include "dbwrapper.h" #include "claimtriedb.h"
#include "chainparams.h"
#include "primitives/transaction.h" #include "primitives/transaction.h"
#include <string> #include <string>
#include <vector> #include <vector>
#include <map>
// leveldb keys
#define HASH_BLOCK 'h'
#define CURRENT_HEIGHT 't'
#define TRIE_NODE 'n'
#define CLAIM_BY_ID 'i'
#define CLAIM_QUEUE_ROW 'r'
#define CLAIM_QUEUE_NAME_ROW 'm'
#define EXP_QUEUE_ROW 'e'
#define SUPPORT 's'
#define SUPPORT_QUEUE_ROW 'u'
#define SUPPORT_QUEUE_NAME_ROW 'p'
#define SUPPORT_EXP_QUEUE_ROW 'x'
uint256 getValueHash(COutPoint outPoint, int nHeightOfLastTakeover); uint256 getValueHash(COutPoint outPoint, int nHeightOfLastTakeover);
@ -254,24 +241,75 @@ class CClaimIndexElement
READWRITE(claim); READWRITE(claim);
} }
bool empty() const
{
return name.empty() && claim.claimId.IsNull();
}
std::string name; std::string name;
CClaimValue claim; CClaimValue claim;
}; };
typedef std::pair<std::string, CClaimValue> claimQueueEntryType; struct claimQueueEntryHelper;
struct supportQueueEntryHelper;
typedef std::pair<std::string, CSupportValue> supportQueueEntryType; struct queueNameRowHelper;
struct supportQueueNameRowHelper;
struct expirationQueueRowHelper;
struct supportExpirationQueueRowHelper;
template <typename Base, typename Form>
struct Generic : public Base
{
Generic() : Base() {}
Generic(const Base &base) : Base(base) {}
Generic(const Generic &generic) : Base(generic) {}
};
template <typename Base, typename Form> inline
void swap(Generic<Base, Form> &generic, Base &base)
{
Base base1 = generic;
generic = base;
base = base1;
}
template <typename Base, typename Form> inline
void swap(Base &base, Generic<Base, Form> &generic)
{
swap(generic, base);
}
typedef Generic<CClaimValue, claimQueueEntryHelper> claimQueueValueType;
typedef Generic<CSupportValue, supportQueueEntryHelper> supportQueueValueType;
typedef Generic<outPointHeightType, queueNameRowHelper> queueNameRowValueType;
typedef Generic<outPointHeightType, supportQueueNameRowHelper> supportQueueNameRowValueType;
typedef Generic<nameOutPointType, expirationQueueRowHelper> expirationQueueRowValueType;
typedef Generic<nameOutPointType, supportExpirationQueueRowHelper> supportExpirationQueueRowValueType;
typedef std::pair<std::string, claimQueueValueType> claimQueueEntryType;
typedef std::pair<std::string, supportQueueValueType> supportQueueEntryType;
typedef std::map<std::string, supportMapEntryType> supportMapType; typedef std::map<std::string, supportMapEntryType> supportMapType;
typedef std::vector<outPointHeightType> queueNameRowType; typedef std::vector<queueNameRowValueType> queueNameRowType;
typedef std::map<std::string, queueNameRowType> queueNameType; typedef std::map<std::string, queueNameRowType> queueNameType;
typedef std::vector<supportQueueNameRowValueType> supportQueueNameRowType;
typedef std::map<std::string, supportQueueNameRowType> supportQueueNameType;
typedef std::vector<nameOutPointHeightType> insertUndoType; typedef std::vector<nameOutPointHeightType> insertUndoType;
typedef std::vector<nameOutPointType> expirationQueueRowType; typedef std::vector<expirationQueueRowValueType> expirationQueueRowType;
typedef std::map<int, expirationQueueRowType> expirationQueueType; typedef std::map<int, expirationQueueRowType> expirationQueueType;
typedef std::vector<supportExpirationQueueRowValueType> supportExpirationQueueRowType;
typedef std::map<int, supportExpirationQueueRowType> supportExpirationQueueType;
typedef std::vector<claimQueueEntryType> claimQueueRowType; typedef std::vector<claimQueueEntryType> claimQueueRowType;
typedef std::map<int, claimQueueRowType> claimQueueType; typedef std::map<int, claimQueueRowType> claimQueueType;
@ -298,9 +336,9 @@ class CClaimTrie
{ {
public: public:
CClaimTrie(bool fMemory = false, bool fWipe = false, int nProportionalDelayFactor = 32) CClaimTrie(bool fMemory = false, bool fWipe = false, int nProportionalDelayFactor = 32)
: db(GetDataDir() / "claimtrie", 100, fMemory, fWipe, false) : nCurrentHeight(0), nExpirationTime(Params().GetConsensus().nOriginalClaimExpirationTime)
, nCurrentHeight(0), nExpirationTime(262974)
, nProportionalDelayFactor(nProportionalDelayFactor) , nProportionalDelayFactor(nProportionalDelayFactor)
, db(fMemory, fWipe)
, root(uint256S("0000000000000000000000000000000000000000000000000000000000000001")) , root(uint256S("0000000000000000000000000000000000000000000000000000000000000001"))
{} {}
@ -333,13 +371,6 @@ public:
void removeFromClaimIndex(const CClaimValue& claim); void removeFromClaimIndex(const CClaimValue& claim);
bool getClaimById(const uint160 claimId, std::string& name, CClaimValue& claim) const; 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; bool haveClaim(const std::string& name, const COutPoint& outPoint) const;
@ -356,11 +387,11 @@ public:
friend class CClaimTrieCache; friend class CClaimTrieCache;
CDBWrapper db;
int nCurrentHeight; int nCurrentHeight;
int nExpirationTime; int nExpirationTime;
int nProportionalDelayFactor; int nProportionalDelayFactor;
private: private:
CClaimTrieDb db;
void clear(CClaimTrieNode* current); void clear(CClaimTrieNode* current);
const CClaimTrieNode* getNodeForName(const std::string& name) const; const CClaimTrieNode* getNodeForName(const std::string& name) const;
@ -372,8 +403,8 @@ private:
expirationQueueType& expirationQueueCache, int nNewHeight, expirationQueueType& expirationQueueCache, int nNewHeight,
supportMapType& supportCache, supportMapType& supportCache,
supportQueueType& supportQueueCache, supportQueueType& supportQueueCache,
queueNameType& supportQueueNameCache, supportQueueNameType& supportQueueNameCache,
expirationQueueType& supportExpirationQueueCache); supportExpirationQueueType& supportExpirationQueueCache);
bool updateName(const std::string& name, CClaimTrieNode* updatedNode); bool updateName(const std::string& name, CClaimTrieNode* updatedNode);
bool updateHash(const std::string& name, uint256& hash); bool updateHash(const std::string& name, uint256& hash);
bool updateTakeoverHeight(const std::string& name, int nTakeoverHeight); bool updateTakeoverHeight(const std::string& name, int nTakeoverHeight);
@ -392,42 +423,11 @@ private:
std::vector<namedNodeType>& nodes) const; std::vector<namedNodeType>& nodes) const;
void markNodeDirty(const std::string& name, CClaimTrieNode* node); 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<typename K> bool keyTypeEmpty(char key, K& dummy) const;
CClaimTrieNode root; CClaimTrieNode root;
uint256 hashBlock; uint256 hashBlock;
claimQueueType dirtyQueueRows;
queueNameType dirtyQueueNameRows;
expirationQueueType dirtyExpirationQueueRows;
supportQueueType dirtySupportQueueRows;
queueNameType dirtySupportQueueNameRows;
expirationQueueType dirtySupportExpirationQueueRows;
nodeCacheType dirtyNodes; nodeCacheType dirtyNodes;
supportMapType dirtySupportNodes;
}; };
class CClaimTrieProofNode class CClaimTrieProofNode
@ -516,6 +516,12 @@ public:
CClaimTrieProof getProofForName(const std::string& name) const; CClaimTrieProof getProofForName(const std::string& name) const;
bool finalizeDecrement() 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: protected:
CClaimTrie* base; CClaimTrie* base;
@ -530,8 +536,8 @@ protected:
mutable expirationQueueType expirationQueueCache; mutable expirationQueueType expirationQueueCache;
mutable supportMapType supportCache; mutable supportMapType supportCache;
mutable supportQueueType supportQueueCache; mutable supportQueueType supportQueueCache;
mutable queueNameType supportQueueNameCache; mutable supportQueueNameType supportQueueNameCache;
mutable expirationQueueType supportExpirationQueueCache; mutable supportExpirationQueueType supportExpirationQueueCache;
mutable std::set<std::string> namesToCheckForTakeover; mutable std::set<std::string> namesToCheckForTakeover;
mutable std::map<std::string, int> cacheTakeoverHeights; mutable std::map<std::string, int> cacheTakeoverHeights;
mutable int nCurrentHeight; // Height of the block that is being worked on, which is mutable int nCurrentHeight; // Height of the block that is being worked on, which is
@ -580,10 +586,10 @@ protected:
supportQueueType::iterator getSupportQueueCacheRow(int nHeight, supportQueueType::iterator getSupportQueueCacheRow(int nHeight,
bool createIfNotExists) const; bool createIfNotExists) const;
queueNameType::iterator getSupportQueueCacheNameRow(const std::string& name, supportQueueNameType::iterator getSupportQueueCacheNameRow(const std::string& name,
bool createIfNotExists) const; bool createIfNotExists) const;
expirationQueueType::iterator getSupportExpirationQueueCacheRow(int nHeight, supportExpirationQueueType::iterator getSupportExpirationQueueCacheRow(int nHeight,
bool createIfNotExists) const; bool createIfNotExists) const;
bool addSupportToQueues(const std::string& name, CSupportValue& support) const; bool addSupportToQueues(const std::string& name, CSupportValue& support) const;
bool removeSupportFromQueue(const std::string& name, const COutPoint& outPoint, bool removeSupportFromQueue(const std::string& name, const COutPoint& outPoint,

188
src/claimtriedb.cpp Normal file
View file

@ -0,0 +1,188 @@
#include "claimtriedb.h"
#include <boost/scoped_ptr.hpp>
template <typename K, typename V>
class CCMap : public CCBase
{
std::map<K, V> data;
public:
CCMap() : data() {}
std::map<K, V>& 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<size_t, CCBase*>::iterator itQueue = queues.begin(); itQueue != queues.end(); ++itQueue)
{
delete itQueue->second;
}
}
void CClaimTrieDb::writeQueues()
{
for (std::map<size_t, CCBase*>::iterator itQueue = queues.begin(); itQueue != queues.end(); ++itQueue)
{
itQueue->second->write(itQueue->first, this);
}
}
template <typename K, typename V> bool CClaimTrieDb::getQueueRow(const K &key, V &row) const
{
const size_t hash = boost::typeindex::type_id<std::map<K, V> >().hash_code();
std::map<size_t, CCBase*>::const_iterator itQueue = queues.find(hash);
if (itQueue != queues.end())
{
std::map<K, V> &map = (static_cast<CCMap<K, V>*>(itQueue->second))->data_map();
typename std::map<K, V>::iterator itMap = map.find(key);
if (itMap != map.end())
{
row = itMap->second;
return true;
}
}
return Read(std::make_pair(hash, key), row);
}
template <typename K, typename V> void CClaimTrieDb::updateQueueRow(const K &key, V &row)
{
const size_t hash = boost::typeindex::type_id<std::map<K, V> >().hash_code();
std::map<size_t, CCBase*>::iterator itQueue = queues.find(hash);
if (itQueue == queues.end())
{
itQueue = queues.insert(itQueue, std::pair<size_t, CCBase*>(hash, new CCMap<K, V>));
}
std::map<K, V> &map = (static_cast<CCMap<K, V>*>(itQueue->second))->data_map();
typename std::map<K, V>::iterator itMap = map.find(key);
if (itMap == map.end())
{
itMap = map.insert(itMap, std::make_pair(key, row));
}
std::swap(itMap->second, row);
}
template <typename K, typename V> bool CClaimTrieDb::keyTypeEmpty() const
{
const size_t hash = boost::typeindex::type_id<std::map<K, V> >().hash_code();
std::map<size_t, CCBase*>::const_iterator itQueue = queues.find(hash);
if (itQueue != queues.end())
{
std::map<K, V> &map = (static_cast<CCMap<K, V>*>(itQueue->second))->data_map();
for (typename std::map<K, V>::iterator itMap = map.begin(); itMap != map.end(); ++itMap)
{
if (!itMap->second.empty())
{
return false;
}
}
}
boost::scoped_ptr<CDBIterator> pcursor(const_cast<CClaimTrieDb*>(this)->NewIterator());
pcursor->SeekToFirst();
while (pcursor->Valid())
{
std::pair<size_t, K> key;
if (pcursor->GetKey(key))
{
if (key.first == hash)
{
return false;
}
}
else
{
break;
}
pcursor->Next();
}
return true;
}
template <typename K, typename V> bool CClaimTrieDb::SeekFirstKey(K &keyOut, V &value) const
{
const size_t hash = boost::typeindex::type_id<std::map<K, V> >().hash_code();
boost::scoped_ptr<CDBIterator> pcursor(const_cast<CClaimTrieDb*>(this)->NewIterator());
pcursor->SeekToFirst();
while (pcursor->Valid())
{
std::pair<size_t, K> 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 <typename K, typename V> bool CClaimTrieDb::getQueueMap(std::map<K,V> &map) const
{
const size_t hash = boost::typeindex::type_id<std::map<K, V> >().hash_code();
std::map<size_t, CCBase*>::const_iterator itQueue = queues.find(hash);
if (itQueue != queues.end())
{
map = (static_cast<CCMap<K, V>*>(itQueue->second))->data_map();
}
boost::scoped_ptr<CDBIterator> pcursor(const_cast<CClaimTrieDb*>(this)->NewIterator());
pcursor->SeekToFirst();
while (pcursor->Valid())
{
std::pair<size_t, K> key;
if (pcursor->GetKey(key))
{
if (key.first == hash)
{
typename std::map<K, V>::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;
}

40
src/claimtriedb.h Normal file
View file

@ -0,0 +1,40 @@
#ifndef BITCOIN_CLAIMTRIE_DB_H
#define BITCOIN_CLAIMTRIE_DB_H
#include "dbwrapper.h"
#include <utility>
#include <map>
#include <boost/type_index.hpp>
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 <typename K, typename V> bool getQueueMap(std::map<K,V> &map) const;
template <typename K, typename V> bool getQueueRow(const K &key, V &row) const;
template <typename K, typename V> void updateQueueRow(const K &key, V &row);
template <typename K, typename V> bool keyTypeEmpty() const;
template <typename K, typename V> bool SeekFirstKey(K &key, V &value) const;
private:
std::map<size_t, CCBase*> queues;
};
#endif // BITCOIN_CLAIMTRIE_DB_H

View file

@ -16,8 +16,8 @@
//! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it //! 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_MAJOR 0
#define CLIENT_VERSION_MINOR 12 #define CLIENT_VERSION_MINOR 12
#define CLIENT_VERSION_REVISION 1 #define CLIENT_VERSION_REVISION 2
#define CLIENT_VERSION_BUILD 2 #define CLIENT_VERSION_BUILD 0
//! Set to true for release, false for prerelease or test build //! Set to true for release, false for prerelease or test build
#define CLIENT_VERSION_IS_RELEASE true #define CLIENT_VERSION_IS_RELEASE true

View file

@ -58,6 +58,14 @@ struct Params {
bool fPowNoRetargeting; bool fPowNoRetargeting;
int64_t nPowTargetSpacing; int64_t nPowTargetSpacing;
int64_t nPowTargetTimespan; 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; } int64_t DifficultyAdjustmentInterval() const { return nPowTargetTimespan / nPowTargetSpacing; }
}; };
} // namespace Consensus } // namespace Consensus

View file

@ -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 chain state database\n", nCoinDBCache * (1.0 / 1024 / 1024));
LogPrintf("* Using %.1fMiB for in-memory UTXO set\n", nCoinCacheUsage * (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; bool fLoaded = false;
while (!fLoaded) { while (!fLoaded) {
bool fReset = fReindex; 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 // If the loaded chain has a wrong genesis, bail out immediately
// (we're likely using a testnet datadir, or the other way around). // (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?")); 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) // 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(); RandAddSeedPerfmon();
pclaimTrie->setExpirationTime(consensusParams.GetExpirationTime(chainActive.Height()));
//// debug print //// debug print
LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size()); LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size());
LogPrintf("nBestHeight = %d\n", chainActive.Height()); LogPrintf("nBestHeight = %d\n", chainActive.Height());
@ -1437,7 +1441,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
StartNode(threadGroup, scheduler); StartNode(threadGroup, scheduler);
// Monitor the chain, and alert if we get blocks much quicker or slower than expected // 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, CScheduler::Function f = boost::bind(&PartitionCheck, &IsInitialBlockDownload,
boost::ref(cs_main), boost::cref(pindexBestHeader), nPowTargetSpacing); boost::ref(cs_main), boost::cref(pindexBestHeader), nPowTargetSpacing);
scheduler.scheduleEvery(f, nPowTargetSpacing); scheduler.scheduleEvery(f, nPowTargetSpacing);

View file

@ -2171,12 +2171,22 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
if (op == OP_CLAIM_NAME) if (op == OP_CLAIM_NAME)
{ {
assert(vvchParams.size() == 2); 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); 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) else if (op == OP_UPDATE_CLAIM)
{ {
assert(vvchParams.size() == 3); 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]); 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()); 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()); 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); assert(vvchParams.size() == 2);
std::string name(vvchParams[0].begin(), vvchParams[0].end()); std::string name(vvchParams[0].begin(), vvchParams[0].end());
uint160 supportedClaimId(vvchParams[1]); 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()); 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)) 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()); 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()); assert(trieCache.finalizeDecrement());
trieCache.setBestBlock(pindex->pprev->GetBlockHash()); trieCache.setBestBlock(pindex->pprev->GetBlockHash());
assert(trieCache.getMerkleHash() == pindex->pprev->hashClaimTrie); 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) { if (pfClean) {
*pfClean = fClean; *pfClean = fClean;
@ -2481,6 +2500,15 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE; 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; int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1;
LogPrint("bench", " - Fork checks: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeForks * 0.000001); 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) if (op == OP_CLAIM_NAME)
{ {
assert(vvchParams.size() == 2); 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); 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) else if (op == OP_UPDATE_CLAIM)
{ {
assert(vvchParams.size() == 3); 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]); 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()); std::string name(vvchParams[0].begin(), vvchParams[0].end());
int nValidAtHeight; int nValidAtHeight;
@ -2595,6 +2633,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
assert(vvchParams.size() == 2); assert(vvchParams.size() == 2);
std::string name(vvchParams[0].begin(), vvchParams[0].end()); std::string name(vvchParams[0].begin(), vvchParams[0].end());
uint160 supportedClaimId(vvchParams[1]); 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; 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()); 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)) if (trieCache.spendSupport(name, COutPoint(txin.prevout.hash, txin.prevout.n), coins->nHeight, nValidAtHeight))

View file

@ -14,31 +14,21 @@
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{ {
unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact(); unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();
// Genesis block // Genesis block
if (pindexLast == NULL) if (pindexLast == NULL)
return nProofOfWorkLimit; return nProofOfWorkLimit;
// Only change once per difficulty adjustment interval if (params.fPowAllowMinDifficultyBlocks && pindexLast->nHeight >= 277299)
if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0)
{ {
if (params.fPowAllowMinDifficultyBlocks) // Special difficulty rule for testnet:
{ // If the new block's timestamp is twice the target block time
// Special difficulty rule for testnet: // then allow mining of a min-difficulty block.
// If the new block's timestamp is more than 2* 10 minutes // This is to prevent the testnet from gettig stuck when a large amount
// then allow mining of a min-difficulty block. // of hashrate drops off the network.
if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2) // This rule was not implemented properly until testnet block 277299.
return nProofOfWorkLimit; if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2){
else return nProofOfWorkLimit;
{
// 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;
}
} }
return pindexLast->nBits;
} }
// Go back the full period unless it's the first retarget after genesis. // Go back the full period unless it's the first retarget after genesis.

View file

@ -23,7 +23,6 @@ using namespace std;
BOOST_FIXTURE_TEST_SUITE(claimtriebranching_tests, RegTestingSetup) BOOST_FIXTURE_TEST_SUITE(claimtriebranching_tests, RegTestingSetup)
//is a claim in queue //is a claim in queue
boost::test_tools::predicate_result boost::test_tools::predicate_result
is_claim_in_queue(std::string name, const CTransaction &tx) is_claim_in_queue(std::string name, const CTransaction &tx)
@ -164,7 +163,16 @@ struct ClaimTrieChainFixture{
unsigned int num_txs; unsigned int num_txs;
unsigned int num_txs_for_next_block; 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; fRequireStandard = false;
BOOST_CHECK(pclaimTrie->nCurrentHeight == chainActive.Height() + 1); BOOST_CHECK(pclaimTrie->nCurrentHeight == chainActive.Height() + 1);
@ -300,6 +308,17 @@ struct ClaimTrieChainFixture{
num_txs_for_next_block = 0; 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); fixture.DecrementBlocks(11);
} }
/* /*
expiration expiration
check claims expire and loses claim check claims expire and loses claim
@ -844,4 +864,204 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_get_claim_by_id)
BOOST_CHECK(claimValue2.claimId != claimId); 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() BOOST_AUTO_TEST_SUITE_END()