separate claim from children storage
This commit is contained in:
parent
c6fd2280aa
commit
1aab6cd3b8
6 changed files with 217 additions and 173 deletions
|
@ -127,7 +127,7 @@ void CClaimTrieData::reorderClaims(const supportEntryType& supports)
|
||||||
CClaimTrie::CClaimTrie(bool fMemory, bool fWipe, int proportionalDelayFactor)
|
CClaimTrie::CClaimTrie(bool fMemory, bool fWipe, int proportionalDelayFactor)
|
||||||
{
|
{
|
||||||
nProportionalDelayFactor = proportionalDelayFactor;
|
nProportionalDelayFactor = proportionalDelayFactor;
|
||||||
db.reset(new CDBWrapper(GetDataDir() / "claimtrie", 200 * 1024 * 1024, fMemory, fWipe, false));
|
db.reset(new CDBWrapper(GetDataDir() / "claimtrie", 400 * 1024 * 1024, fMemory, fWipe, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrie::SyncToDisk()
|
bool CClaimTrie::SyncToDisk()
|
||||||
|
@ -221,9 +221,8 @@ bool CClaimTrieCacheBase::haveClaim(const std::string& name, const COutPoint& ou
|
||||||
return true;
|
return true;
|
||||||
if (it || nodesToDelete.count(name))
|
if (it || nodesToDelete.count(name))
|
||||||
return false;
|
return false;
|
||||||
CClaimTrieDataNode node;
|
CClaimTrieData data;
|
||||||
node.childrenSerialization = false;
|
return base->find(name, data) && data.haveClaim(outPoint);
|
||||||
return base->find(name, node) && node.data.haveClaim(outPoint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrieCacheBase::haveSupport(const std::string& name, const COutPoint& outPoint) const
|
bool CClaimTrieCacheBase::haveSupport(const std::string& name, const COutPoint& outPoint) const
|
||||||
|
@ -276,12 +275,19 @@ bool CClaimTrieCacheBase::haveSupportInQueue(const std::string& name, const COut
|
||||||
return haveInQueue<CSupportValue>(name, outPoint, nValidAtHeight);
|
return haveInQueue<CSupportValue>(name, outPoint, nValidAtHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClaimTrie::recurseAllHashedNodes(const std::string& name, const CClaimTrieDataNode& current, std::function<void(const std::string&, const CClaimTrieDataNode&)> function) const {
|
void CClaimTrie::recurseNodes(const std::string& name, const CClaimTrieDataNode& current, std::function<recurseNodesCB> function) const {
|
||||||
function(name, current);
|
CClaimTrieData data;
|
||||||
|
if (!find(name, data))
|
||||||
|
data = {};
|
||||||
|
|
||||||
|
data.hash = current.hash;
|
||||||
|
data.flags |= current.children.empty() ? 0 : CClaimTrieDataFlags::POTENTIAL_CHILDREN;
|
||||||
|
function(name, data, current.children);
|
||||||
|
|
||||||
for (auto& child: current.children) {
|
for (auto& child: current.children) {
|
||||||
CClaimTrieDataNode node;
|
CClaimTrieDataNode node;
|
||||||
if (find(child.second, node))
|
if (find(name + child, node))
|
||||||
recurseAllHashedNodes(name + child.first, node, function);
|
recurseNodes(name + child, node, function);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,8 +296,8 @@ std::size_t CClaimTrie::getTotalNamesInTrie() const
|
||||||
std::size_t count = 0;
|
std::size_t count = 0;
|
||||||
CClaimTrieDataNode node;
|
CClaimTrieDataNode node;
|
||||||
if (find("", node))
|
if (find("", node))
|
||||||
recurseAllHashedNodes("", node, [&count](const std::string&, const CClaimTrieDataNode& node) {
|
recurseNodes("", node, [&count](const std::string &name, const CClaimTrieData &data, const std::vector<std::string>& children) {
|
||||||
count += !node.data.empty();
|
count += !data.empty();
|
||||||
});
|
});
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -301,8 +307,9 @@ std::size_t CClaimTrie::getTotalClaimsInTrie() const
|
||||||
std::size_t count = 0;
|
std::size_t count = 0;
|
||||||
CClaimTrieDataNode node;
|
CClaimTrieDataNode node;
|
||||||
if (find("", node))
|
if (find("", node))
|
||||||
recurseAllHashedNodes("", node, [&count](const std::string&, const CClaimTrieDataNode& node) {
|
recurseNodes("", node, [&count]
|
||||||
count += node.data.claims.size();
|
(const std::string &name, const CClaimTrieData &data, const std::vector<std::string>& children) {
|
||||||
|
count += data.claims.size();
|
||||||
});
|
});
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -310,11 +317,11 @@ std::size_t CClaimTrie::getTotalClaimsInTrie() const
|
||||||
CAmount CClaimTrie::getTotalValueOfClaimsInTrie(bool fControllingOnly) const
|
CAmount CClaimTrie::getTotalValueOfClaimsInTrie(bool fControllingOnly) const
|
||||||
{
|
{
|
||||||
CAmount value_in_subtrie = 0;
|
CAmount value_in_subtrie = 0;
|
||||||
std::size_t count = 0;
|
|
||||||
CClaimTrieDataNode node;
|
CClaimTrieDataNode node;
|
||||||
if (find("", node))
|
if (find("", node))
|
||||||
recurseAllHashedNodes("", node, [&value_in_subtrie, fControllingOnly](const std::string&, const CClaimTrieDataNode& node) {
|
recurseNodes("", node, [&value_in_subtrie, fControllingOnly]
|
||||||
for (const auto& claim : node.data.claims) {
|
(const std::string &name, const CClaimTrieData &data, const std::vector<std::string>& children) {
|
||||||
|
for (const auto &claim : data.claims) {
|
||||||
value_in_subtrie += claim.nAmount;
|
value_in_subtrie += claim.nAmount;
|
||||||
if (fControllingOnly)
|
if (fControllingOnly)
|
||||||
break;
|
break;
|
||||||
|
@ -330,9 +337,8 @@ bool CClaimTrieCacheBase::getInfoForName(const std::string& name, CClaimValue& c
|
||||||
return true;
|
return true;
|
||||||
if (it || nodesToDelete.count(name))
|
if (it || nodesToDelete.count(name))
|
||||||
return false;
|
return false;
|
||||||
CClaimTrieDataNode node;
|
CClaimTrieData claims;
|
||||||
node.childrenSerialization = false;
|
return base->find(name, claims) && claims.getBestClaim(claim);
|
||||||
return base->find(name, node) && node.data.getBestClaim(claim);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CClaimsForNameType CClaimTrieCacheBase::getClaimsForName(const std::string& name) const
|
CClaimsForNameType CClaimTrieCacheBase::getClaimsForName(const std::string& name) const
|
||||||
|
@ -341,15 +347,14 @@ CClaimsForNameType CClaimTrieCacheBase::getClaimsForName(const std::string& name
|
||||||
int nLastTakeoverHeight = 0;
|
int nLastTakeoverHeight = 0;
|
||||||
auto supports = getSupportsForName(name);
|
auto supports = getSupportsForName(name);
|
||||||
|
|
||||||
CClaimTrieDataNode node;
|
CClaimTrieData data;
|
||||||
node.childrenSerialization = false;
|
|
||||||
if (auto it = nodesToAddOrUpdate.find(name)) {
|
if (auto it = nodesToAddOrUpdate.find(name)) {
|
||||||
claims = it->claims;
|
claims = it->claims;
|
||||||
nLastTakeoverHeight = it->nHeightOfLastTakeover;
|
nLastTakeoverHeight = it->nHeightOfLastTakeover;
|
||||||
}
|
}
|
||||||
else if (!nodesToDelete.count(name) && base->find(name, node)) {
|
else if (!nodesToDelete.count(name) && base->find(name, data)) {
|
||||||
claims = node.data.claims;
|
claims = data.claims;
|
||||||
nLastTakeoverHeight = node.data.nHeightOfLastTakeover;
|
nLastTakeoverHeight = data.nHeightOfLastTakeover;
|
||||||
}
|
}
|
||||||
return {std::move(claims), std::move(supports), nLastTakeoverHeight, name};
|
return {std::move(claims), std::move(supports), nLastTakeoverHeight, name};
|
||||||
}
|
}
|
||||||
|
@ -390,35 +395,10 @@ void completeHash(uint256& partialHash, const std::string& key, std::size_t to)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using iCbType = std::function<void(T&)>;
|
using iCbType = std::function<void(T&)>;
|
||||||
|
|
||||||
template <typename TIterator>
|
|
||||||
uint256 recursiveMerkleHash(TIterator& it, const iCbType<TIterator>& process, const iCbType<TIterator>& verify = {})
|
|
||||||
{
|
|
||||||
std::vector<uint8_t> vchToHash;
|
|
||||||
const auto pos = it.key().size();
|
|
||||||
for (auto& child : it.children()) {
|
|
||||||
process(child);
|
|
||||||
auto& key = child.key();
|
|
||||||
auto hash = child->hash;
|
|
||||||
completeHash(hash, key, pos);
|
|
||||||
vchToHash.push_back(key[pos]);
|
|
||||||
vchToHash.insert(vchToHash.end(), hash.begin(), hash.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
CClaimValue claim;
|
|
||||||
if (it->getBestClaim(claim)) {
|
|
||||||
uint256 valueHash = getValueHash(claim.outPoint, it->nHeightOfLastTakeover);
|
|
||||||
vchToHash.insert(vchToHash.end(), valueHash.begin(), valueHash.end());
|
|
||||||
} else if (verify) {
|
|
||||||
verify(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Hash(vchToHash.begin(), vchToHash.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CClaimTrie::checkConsistency(const uint256& rootHash) const
|
bool CClaimTrie::checkConsistency(const uint256& rootHash) const
|
||||||
{
|
{
|
||||||
CClaimTrieDataNode node;
|
CClaimTrieDataNode node;
|
||||||
if (!find("", node) || node.data.hash != rootHash) {
|
if (!find("", node) || node.hash != rootHash) {
|
||||||
if (rootHash == one)
|
if (rootHash == one)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -426,30 +406,29 @@ bool CClaimTrie::checkConsistency(const uint256& rootHash) const
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
recurseAllHashedNodes("", node, [&success, this](const std::string& name, const CClaimTrieDataNode& node) {
|
recurseNodes("", node, [&success, this](const std::string &name, const CClaimTrieData &data, const std::vector<std::string>& children) {
|
||||||
if (!success) return;
|
if (!success) return;
|
||||||
|
|
||||||
success &= contains(name);
|
|
||||||
|
|
||||||
std::vector<uint8_t> vchToHash;
|
std::vector<uint8_t> vchToHash;
|
||||||
const auto pos = name.size();
|
const auto pos = name.size();
|
||||||
for (auto& child : node.children) {
|
for (auto &child : children) {
|
||||||
auto key = name + child.first;
|
auto key = name + child;
|
||||||
auto hash = child.second;
|
CClaimTrieDataNode node;
|
||||||
|
success &= find(key, node);
|
||||||
|
auto hash = node.hash;
|
||||||
completeHash(hash, key, pos);
|
completeHash(hash, key, pos);
|
||||||
vchToHash.push_back(key[pos]);
|
vchToHash.push_back(key[pos]);
|
||||||
vchToHash.insert(vchToHash.end(), hash.begin(), hash.end());
|
vchToHash.insert(vchToHash.end(), hash.begin(), hash.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
CClaimValue claim;
|
CClaimValue claim;
|
||||||
if (node.data.getBestClaim(claim)) {
|
if (data.getBestClaim(claim)) {
|
||||||
uint256 valueHash = getValueHash(claim.outPoint, node.data.nHeightOfLastTakeover);
|
uint256 valueHash = getValueHash(claim.outPoint, data.nHeightOfLastTakeover);
|
||||||
vchToHash.insert(vchToHash.end(), valueHash.begin(), valueHash.end());
|
vchToHash.insert(vchToHash.end(), valueHash.begin(), valueHash.end());
|
||||||
} else {
|
} else {
|
||||||
success &= !node.children.empty(); // we disallow leaf nodes without claims
|
success &= !children.empty(); // we disallow leaf nodes without claims
|
||||||
}
|
}
|
||||||
|
success &= data.hash == Hash(vchToHash.begin(), vchToHash.end());
|
||||||
success &= node.data.hash == Hash(vchToHash.begin(), vchToHash.end());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
|
@ -467,21 +446,22 @@ std::vector<std::pair<std::string, CClaimTrieDataNode>> CClaimTrie::nodes(const
|
||||||
|
|
||||||
while (!node.children.empty()) {
|
while (!node.children.empty()) {
|
||||||
// auto it = node.children.lower_bound(partialKey); // for using a std::map
|
// auto it = node.children.lower_bound(partialKey); // for using a std::map
|
||||||
auto it = std::lower_bound(node.children.begin(), node.children.end(), std::make_pair(partialKey, uint256()));
|
auto it = std::lower_bound(node.children.begin(), node.children.end(), partialKey);
|
||||||
if (it != node.children.end() && it->first == partialKey) {
|
if (it != node.children.end() && *it == partialKey) {
|
||||||
// we're completely done
|
// we're completely done
|
||||||
if (find(it->second, node))
|
if (find(key, node))
|
||||||
ret.emplace_back(key, node);
|
ret.emplace_back(key, node);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (it != node.children.begin()) --it;
|
if (it != node.children.begin()) --it;
|
||||||
const auto count = match(partialKey, it->first);
|
const auto count = match(partialKey, *it);
|
||||||
|
|
||||||
if (count != it->first.size()) break;
|
if (count != it->size()) break;
|
||||||
if (count == partialKey.size()) break;
|
if (count == partialKey.size()) break;
|
||||||
partialKey = partialKey.substr(count);
|
partialKey = partialKey.substr(count);
|
||||||
if (find(it->second, node))
|
auto frontKey = key.substr(0, key.size() - partialKey.size());
|
||||||
ret.emplace_back(key.substr(0, key.size() - partialKey.size()), node);
|
if (find(frontKey, node))
|
||||||
|
ret.emplace_back(frontKey, node);
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,23 +469,19 @@ std::vector<std::pair<std::string, CClaimTrieDataNode>> CClaimTrie::nodes(const
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrie::contains(const std::string &key) const {
|
bool CClaimTrie::contains(const std::string &key) const {
|
||||||
return db->Exists(std::make_pair(TRIE_NODE_BY_NAME, key));
|
return db->Exists(std::make_pair(TRIE_NODE_CHILDREN, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrie::empty() const {
|
bool CClaimTrie::empty() const {
|
||||||
return !contains("");
|
return !contains("");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrie::find(const std::string &key, CClaimTrieDataNode &node) const {
|
bool CClaimTrie::find(const std::string& key, CClaimTrieDataNode &node) const {
|
||||||
uint256 hash;
|
return db->Read(std::make_pair(TRIE_NODE_CHILDREN, key), node);
|
||||||
if (!db->Read(std::make_pair(TRIE_NODE_BY_NAME, key), hash))
|
|
||||||
return false;
|
|
||||||
auto found = find(hash, node);
|
|
||||||
return found;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrie::find(const uint256 &key, CClaimTrieDataNode &node) const {
|
bool CClaimTrie::find(const std::string& key, CClaimTrieData &data) const {
|
||||||
return db->Read(std::make_pair(TRIE_NODE_BY_HASH, key), node);
|
return db->Read(std::make_pair(TRIE_NODE_CLAIMS, key), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrieCacheBase::getClaimById(const uint160& claimId, std::string& name, CClaimValue& claim) const
|
bool CClaimTrieCacheBase::getClaimById(const uint160& claimId, std::string& name, CClaimValue& claim) const
|
||||||
|
@ -555,7 +531,7 @@ bool CClaimTrieCacheBase::flush()
|
||||||
for (const auto& e : claimsToAddToByIdIndex)
|
for (const auto& e : claimsToAddToByIdIndex)
|
||||||
batch.Write(std::make_pair(CLAIM_BY_ID, e.claim.claimId), e);
|
batch.Write(std::make_pair(CLAIM_BY_ID, e.claim.claimId), e);
|
||||||
|
|
||||||
getMerkleHash();
|
auto rootHash = getMerkleHash();
|
||||||
|
|
||||||
std::set<std::string> forDeletion;
|
std::set<std::string> forDeletion;
|
||||||
for (const auto& nodeName : nodesToDelete) {
|
for (const auto& nodeName : nodesToDelete) {
|
||||||
|
@ -567,21 +543,23 @@ bool CClaimTrieCacheBase::flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto it = nodesToAddOrUpdate.begin(); it != nodesToAddOrUpdate.end(); ++it) {
|
for (auto it = nodesToAddOrUpdate.begin(); it != nodesToAddOrUpdate.end(); ++it) {
|
||||||
forDeletion.erase(it.key());
|
bool removed = forDeletion.erase(it.key());
|
||||||
if (!dirtyNodes.count(it.key()))
|
if (it->flags & CClaimTrieDataFlags::HASH_DIRTY) {
|
||||||
continue;
|
CClaimTrieDataNode node;
|
||||||
|
node.hash = it->hash;
|
||||||
|
for (auto &child: it.children()) // ordering here is important
|
||||||
|
node.children.push_back(child.key().substr(it.key().size()));
|
||||||
|
|
||||||
CClaimTrieDataNode node;
|
batch.Write(std::make_pair(TRIE_NODE_CHILDREN, it.key()), node);
|
||||||
node.data = it.data();
|
|
||||||
for (auto &child: it.children()) // ordering here is important
|
|
||||||
node.children.emplace_back(child.key().substr(it.key().size()), child->hash);
|
|
||||||
|
|
||||||
batch.Write(std::make_pair(TRIE_NODE_BY_HASH, it->hash), node);
|
if (removed || (it->flags & CClaimTrieDataFlags::CLAIMS_DIRTY))
|
||||||
batch.Write(std::make_pair(TRIE_NODE_BY_NAME, it.key()), it->hash);
|
batch.Write(std::make_pair(TRIE_NODE_CLAIMS, it.key()), it.data());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& name: forDeletion) {
|
for (auto& name: forDeletion) {
|
||||||
batch.Erase(std::make_pair(TRIE_NODE_BY_NAME, name));
|
batch.Erase(std::make_pair(TRIE_NODE_CHILDREN, name));
|
||||||
|
batch.Erase(std::make_pair(TRIE_NODE_CLAIMS, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
BatchWriteQueue(batch, SUPPORT, supportCache);
|
BatchWriteQueue(batch, SUPPORT, supportCache);
|
||||||
|
@ -600,6 +578,18 @@ bool CClaimTrieCacheBase::flush()
|
||||||
nodesToAddOrUpdate.height(), nNextHeight, batch.SizeEstimate());
|
nodesToAddOrUpdate.height(), nNextHeight, batch.SizeEstimate());
|
||||||
}
|
}
|
||||||
auto ret = base->db->WriteBatch(batch);
|
auto ret = base->db->WriteBatch(batch);
|
||||||
|
|
||||||
|
// for debugging:
|
||||||
|
// if (nNextHeight >= 235099)
|
||||||
|
// {
|
||||||
|
// g_logger->EnableCategory(BCLog::CLAIMS);
|
||||||
|
// if (!base->checkConsistency(rootHash)) {
|
||||||
|
// LogPrintf("Failure with consistency on block height %d\n", nNextHeight);
|
||||||
|
// dumpToLog(begin());
|
||||||
|
// assert(false);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -623,7 +613,7 @@ bool CClaimTrieCacheBase::ReadFromDisk(const CBlockIndex* tip)
|
||||||
base->nNextHeight = nNextHeight = tip ? tip->nHeight + 1 : 0;
|
base->nNextHeight = nNextHeight = tip ? tip->nHeight + 1 : 0;
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
if (tip && (base->db->Exists(std::make_pair(TRIE_NODE, std::string())) || !base->db->Exists(std::make_pair(TRIE_NODE_BY_HASH, tip->hashClaimTrie)))) {
|
if (tip && base->db->Exists(std::make_pair(TRIE_NODE, std::string()))) {
|
||||||
LogPrintf("The claim trie database contains deprecated data and will need to be rebuilt");
|
LogPrintf("The claim trie database contains deprecated data and will need to be rebuilt");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -643,13 +633,28 @@ int CClaimTrieCacheBase::expirationTime() const
|
||||||
|
|
||||||
uint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(CClaimPrefixTrie::iterator& it)
|
uint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(CClaimPrefixTrie::iterator& it)
|
||||||
{
|
{
|
||||||
using iterator = CClaimPrefixTrie::iterator;
|
if (!it->hash.IsNull())
|
||||||
iCbType<iterator> process = [&process](iterator& it) {
|
return it->hash;
|
||||||
if (it->hash.IsNull())
|
|
||||||
it->hash = recursiveMerkleHash(it, process);
|
std::vector<uint8_t> vchToHash;
|
||||||
};
|
const auto pos = it.key().size();
|
||||||
process(it);
|
for (auto& child : it.children()) {
|
||||||
return it->hash;
|
auto hash = recursiveComputeMerkleHash(child);
|
||||||
|
auto& key = child.key();
|
||||||
|
completeHash(hash, key, pos);
|
||||||
|
vchToHash.push_back(key[pos]);
|
||||||
|
vchToHash.insert(vchToHash.end(), hash.begin(), hash.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
CClaimValue claim;
|
||||||
|
if (it->getBestClaim(claim)) {
|
||||||
|
uint256 valueHash = getValueHash(claim.outPoint, it->nHeightOfLastTakeover);
|
||||||
|
vchToHash.insert(vchToHash.end(), valueHash.begin(), valueHash.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ret = Hash(vchToHash.begin(), vchToHash.end());
|
||||||
|
it->hash = ret;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 CClaimTrieCacheBase::getMerkleHash()
|
uint256 CClaimTrieCacheBase::getMerkleHash()
|
||||||
|
@ -659,9 +664,8 @@ uint256 CClaimTrieCacheBase::getMerkleHash()
|
||||||
return recursiveComputeMerkleHash(it);
|
return recursiveComputeMerkleHash(it);
|
||||||
if (nodesToDelete.empty() && nodesAlreadyCached.empty()) {
|
if (nodesToDelete.empty() && nodesAlreadyCached.empty()) {
|
||||||
CClaimTrieDataNode node;
|
CClaimTrieDataNode node;
|
||||||
node.childrenSerialization = false;
|
|
||||||
if (base->find("", node))
|
if (base->find("", node))
|
||||||
return node.data.hash; // it may be valuable to have base cache its current root hash
|
return node.hash; // it may be valuable to have base cache its current root hash
|
||||||
}
|
}
|
||||||
return one; // we have no data or we deleted everything
|
return one; // we have no data or we deleted everything
|
||||||
}
|
}
|
||||||
|
@ -689,16 +693,25 @@ CClaimPrefixTrie::iterator CClaimTrieCacheBase::cacheData(const std::string& nam
|
||||||
for (auto& node: nodes) {
|
for (auto& node: nodes) {
|
||||||
if (nodesAlreadyCached.insert(node.first).second) {
|
if (nodesAlreadyCached.insert(node.first).second) {
|
||||||
// do not insert nodes that are already present
|
// do not insert nodes that are already present
|
||||||
nodesToAddOrUpdate.insert(node.first, node.second.data);
|
CClaimTrieData data;
|
||||||
|
if (!base->find(node.first, data))
|
||||||
|
data = {};
|
||||||
|
data.hash = node.second.hash;
|
||||||
|
data.flags = node.second.children.empty() ? 0 : CClaimTrieDataFlags::POTENTIAL_CHILDREN;
|
||||||
|
nodesToAddOrUpdate.insert(node.first, data);
|
||||||
}
|
}
|
||||||
for (auto& child : node.second.children) {
|
for (auto& child : node.second.children) {
|
||||||
auto childKey = node.first + child.first;
|
auto childKey = node.first + child;
|
||||||
if (nodesAlreadyCached.insert(childKey).second) {
|
if (nodesAlreadyCached.insert(childKey).second) {
|
||||||
|
CClaimTrieData childData;
|
||||||
|
if (!base->find(childKey, childData))
|
||||||
|
childData = {};
|
||||||
CClaimTrieDataNode childNode;
|
CClaimTrieDataNode childNode;
|
||||||
childNode.childrenSerialization = false;
|
if (base->find(childKey, childNode)) { // TODO: can we eliminate this expensive lookup?
|
||||||
if (base->find(child.second, childNode)) {
|
childData.hash = childNode.hash;
|
||||||
nodesToAddOrUpdate.insert(childKey, childNode.data);
|
childData.flags = childNode.children.empty() ? 0 : CClaimTrieDataFlags::POTENTIAL_CHILDREN;
|
||||||
}
|
}
|
||||||
|
nodesToAddOrUpdate.insert(childKey, childData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -706,6 +719,8 @@ CClaimPrefixTrie::iterator CClaimTrieCacheBase::cacheData(const std::string& nam
|
||||||
auto it = nodesToAddOrUpdate.find(name);
|
auto it = nodesToAddOrUpdate.find(name);
|
||||||
if (!it && create) {
|
if (!it && create) {
|
||||||
it = nodesToAddOrUpdate.insert(name, CClaimTrieData{});
|
it = nodesToAddOrUpdate.insert(name, CClaimTrieData{});
|
||||||
|
// if (it.hasChildren()) any children should be in the trie (not base alone)
|
||||||
|
// it->flags |= CClaimTrieDataFlags::POTENTIAL_CHILDREN;
|
||||||
confirmTakeoverWorkaroundNeeded(name);
|
confirmTakeoverWorkaroundNeeded(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,12 +741,11 @@ bool CClaimTrieCacheBase::getLastTakeoverForName(const std::string& name, uint16
|
||||||
std::tie(claimId, takeoverHeight) = cit->second;
|
std::tie(claimId, takeoverHeight) = cit->second;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
CClaimTrieDataNode data;
|
CClaimTrieData data;
|
||||||
data.childrenSerialization = false;
|
|
||||||
if (base->find(name, data)) {
|
if (base->find(name, data)) {
|
||||||
takeoverHeight = data.data.nHeightOfLastTakeover;
|
takeoverHeight = data.nHeightOfLastTakeover;
|
||||||
CClaimValue claim;
|
CClaimValue claim;
|
||||||
if (data.data.getBestClaim(claim)) {
|
if (data.getBestClaim(claim)) {
|
||||||
claimId = claim.claimId;
|
claimId = claim.claimId;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -742,8 +756,10 @@ bool CClaimTrieCacheBase::getLastTakeoverForName(const std::string& name, uint16
|
||||||
void CClaimTrieCacheBase::markAsDirty(const std::string& name, bool fCheckTakeover)
|
void CClaimTrieCacheBase::markAsDirty(const std::string& name, bool fCheckTakeover)
|
||||||
{
|
{
|
||||||
for (auto& node : nodesToAddOrUpdate.nodes(name)) {
|
for (auto& node : nodesToAddOrUpdate.nodes(name)) {
|
||||||
dirtyNodes.insert(node.key());
|
node->flags |= CClaimTrieDataFlags::HASH_DIRTY;
|
||||||
node->hash.SetNull();
|
node->hash.SetNull();
|
||||||
|
if (node.key() == name)
|
||||||
|
node->flags |= CClaimTrieDataFlags::CLAIMS_DIRTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fCheckTakeover)
|
if (fCheckTakeover)
|
||||||
|
@ -1022,8 +1038,7 @@ void CClaimTrieCacheBase::dumpToLog(CClaimPrefixTrie::const_iterator it, bool di
|
||||||
|
|
||||||
if (diffFromBase) {
|
if (diffFromBase) {
|
||||||
CClaimTrieDataNode node;
|
CClaimTrieDataNode node;
|
||||||
node.childrenSerialization = false;
|
if (base->find(it.key(), node) && node.hash == it->hash)
|
||||||
if (base->find(it.key(), node) && node.data.hash == it->hash)
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1342,10 +1357,9 @@ int CClaimTrieCacheBase::getNumBlocksOfContinuousOwnership(const std::string& na
|
||||||
return nNextHeight - it->nHeightOfLastTakeover;
|
return nNextHeight - it->nHeightOfLastTakeover;
|
||||||
if (it) // we specifically ignore deleted nodes here to allow this to fall into the base lookup in that scenario
|
if (it) // we specifically ignore deleted nodes here to allow this to fall into the base lookup in that scenario
|
||||||
return 0;
|
return 0;
|
||||||
CClaimTrieDataNode node;
|
CClaimTrieData data;
|
||||||
node.childrenSerialization = false;
|
if (base->find(name, data) && !data.empty())
|
||||||
if (base->find(name, node) && !node.data.empty())
|
return nNextHeight - data.nHeightOfLastTakeover;
|
||||||
return nNextHeight - node.data.nHeightOfLastTakeover;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1375,7 +1389,6 @@ bool CClaimTrieCacheBase::clear()
|
||||||
{
|
{
|
||||||
nodesToAddOrUpdate.clear();
|
nodesToAddOrUpdate.clear();
|
||||||
claimsToAddToByIdIndex.clear();
|
claimsToAddToByIdIndex.clear();
|
||||||
dirtyNodes.clear();
|
|
||||||
supportCache.clear();
|
supportCache.clear();
|
||||||
nodesToDelete.clear();
|
nodesToDelete.clear();
|
||||||
claimsToDeleteFromByIdIndex.clear();
|
claimsToDeleteFromByIdIndex.clear();
|
||||||
|
@ -1442,3 +1455,34 @@ bool CClaimTrieCacheBase::getProofForName(const std::string& name, CClaimTriePro
|
||||||
proof = CClaimTrieProof(std::move(nodes), fNameHasValue, outPoint, nHeightOfLastTakeover);
|
proof = CClaimTrieProof(std::move(nodes), fNameHasValue, outPoint, nHeightOfLastTakeover);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CClaimTrieCacheBase::recurseNodes(const std::string &name,
|
||||||
|
std::function<void(const std::string &, const CClaimTrieData &)> function) const {
|
||||||
|
|
||||||
|
std::function<CClaimTrie::recurseNodesCB> baseFunction = [this, &function]
|
||||||
|
(const std::string& name, const CClaimTrieData& data, const std::vector<std::string>&) {
|
||||||
|
if (nodesToDelete.find(name) == nodesToDelete.end())
|
||||||
|
function(name, data);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (empty()) {
|
||||||
|
CClaimTrieDataNode node;
|
||||||
|
if (base->find(name, node))
|
||||||
|
base->recurseNodes(name, node, baseFunction);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (auto it = begin(); it != end(); ++it) {
|
||||||
|
function(it.key(), it.data());
|
||||||
|
if ((it->flags & CClaimTrieDataFlags::POTENTIAL_CHILDREN) && !it.hasChildren()) {
|
||||||
|
CClaimTrieDataNode node;
|
||||||
|
if (base->find(it.key(), node))
|
||||||
|
for (auto& partialKey: node.children) {
|
||||||
|
auto childKey = it.key() + partialKey;
|
||||||
|
CClaimTrieDataNode childNode;
|
||||||
|
if (base->find(childKey, childNode))
|
||||||
|
base->recurseNodes(childKey, childNode, baseFunction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
|
|
||||||
// leveldb keys
|
// leveldb keys
|
||||||
#define TRIE_NODE 'n' // deprecated
|
#define TRIE_NODE 'n' // deprecated
|
||||||
#define TRIE_NODE_BY_HASH 'h'
|
#define TRIE_NODE_CHILDREN 'b'
|
||||||
#define TRIE_NODE_BY_NAME 'g'
|
#define TRIE_NODE_CLAIMS 'c'
|
||||||
#define CLAIM_BY_ID 'i'
|
#define CLAIM_BY_ID 'i'
|
||||||
#define CLAIM_QUEUE_ROW 'r'
|
#define CLAIM_QUEUE_ROW 'r'
|
||||||
#define CLAIM_QUEUE_NAME_ROW 'm'
|
#define CLAIM_QUEUE_NAME_ROW 'm'
|
||||||
|
@ -136,12 +136,21 @@ struct CSupportValue
|
||||||
typedef std::vector<CClaimValue> claimEntryType;
|
typedef std::vector<CClaimValue> claimEntryType;
|
||||||
typedef std::vector<CSupportValue> supportEntryType;
|
typedef std::vector<CSupportValue> supportEntryType;
|
||||||
|
|
||||||
|
enum CClaimTrieDataFlags: uint32_t {
|
||||||
|
HASH_DIRTY = 1U,
|
||||||
|
CLAIMS_DIRTY = 2U,
|
||||||
|
POTENTIAL_CHILDREN = 4U, // existing on disk
|
||||||
|
};
|
||||||
|
|
||||||
struct CClaimTrieData
|
struct CClaimTrieData
|
||||||
{
|
{
|
||||||
uint256 hash;
|
|
||||||
claimEntryType claims;
|
claimEntryType claims;
|
||||||
int nHeightOfLastTakeover = 0;
|
int nHeightOfLastTakeover = 0;
|
||||||
|
|
||||||
|
// non-serialized data:
|
||||||
|
uint256 hash;
|
||||||
|
uint32_t flags = 0;
|
||||||
|
|
||||||
CClaimTrieData() = default;
|
CClaimTrieData() = default;
|
||||||
CClaimTrieData(CClaimTrieData&&) = default;
|
CClaimTrieData(CClaimTrieData&&) = default;
|
||||||
CClaimTrieData(const CClaimTrieData&) = default;
|
CClaimTrieData(const CClaimTrieData&) = default;
|
||||||
|
@ -159,14 +168,13 @@ struct CClaimTrieData
|
||||||
template <typename Stream, typename Operation>
|
template <typename Stream, typename Operation>
|
||||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
inline void SerializationOp(Stream& s, Operation ser_action)
|
||||||
{
|
{
|
||||||
READWRITE(hash);
|
|
||||||
READWRITE(claims);
|
READWRITE(claims);
|
||||||
READWRITE(nHeightOfLastTakeover);
|
READWRITE(nHeightOfLastTakeover);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const CClaimTrieData& other) const
|
bool operator==(const CClaimTrieData& other) const
|
||||||
{
|
{
|
||||||
return hash == other.hash && nHeightOfLastTakeover == other.nHeightOfLastTakeover && claims == other.claims;
|
return nHeightOfLastTakeover == other.nHeightOfLastTakeover && claims == other.claims;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const CClaimTrieData& other) const
|
bool operator!=(const CClaimTrieData& other) const
|
||||||
|
@ -181,11 +189,10 @@ struct CClaimTrieData
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CClaimTrieDataNode {
|
struct CClaimTrieDataNode {
|
||||||
CClaimTrieData data;
|
uint256 hash;
|
||||||
// we're using a vector to avoid RAM thrashing and for faster serialization ops.
|
// we're using a vector to avoid RAM thrashing and for faster serialization ops.
|
||||||
// We're assuming its data is inserted in order and never modified.
|
// We're assuming its data is inserted in order and never modified.
|
||||||
std::vector<std::pair<std::string, uint256>> children;
|
std::vector<std::string> children;
|
||||||
bool childrenSerialization = true;
|
|
||||||
|
|
||||||
CClaimTrieDataNode() = default;
|
CClaimTrieDataNode() = default;
|
||||||
CClaimTrieDataNode(CClaimTrieDataNode&&) = default;
|
CClaimTrieDataNode(CClaimTrieDataNode&&) = default;
|
||||||
|
@ -198,9 +205,8 @@ struct CClaimTrieDataNode {
|
||||||
template <typename Stream, typename Operation>
|
template <typename Stream, typename Operation>
|
||||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
inline void SerializationOp(Stream& s, Operation ser_action)
|
||||||
{
|
{
|
||||||
READWRITE(data);
|
READWRITE(hash);
|
||||||
if (childrenSerialization) // wanting constexpr but hoping the compiler is smart enough anyway
|
READWRITE(children);
|
||||||
READWRITE(children);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -346,11 +352,13 @@ public:
|
||||||
|
|
||||||
bool contains(const std::string& key) const;
|
bool contains(const std::string& key) const;
|
||||||
bool empty() const;
|
bool empty() const;
|
||||||
bool find(const uint256& key, CClaimTrieDataNode& node) const;
|
|
||||||
bool find(const std::string& key, CClaimTrieDataNode& node) const;
|
bool find(const std::string& key, CClaimTrieDataNode& node) const;
|
||||||
|
bool find(const std::string& key, CClaimTrieData& claims) const;
|
||||||
|
|
||||||
std::vector<std::pair<std::string, CClaimTrieDataNode>> nodes(const std::string& key) const;
|
std::vector<std::pair<std::string, CClaimTrieDataNode>> nodes(const std::string& key) const;
|
||||||
void recurseAllHashedNodes(const std::string& name, const CClaimTrieDataNode& current, std::function<void(const std::string&, const CClaimTrieDataNode&)> function) const;
|
|
||||||
|
using recurseNodesCB = void(const std::string&, const CClaimTrieData&, const std::vector<std::string>&);
|
||||||
|
void recurseNodes(const std::string& name, const CClaimTrieDataNode& current, std::function<recurseNodesCB> function) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CClaimTrieProofNode
|
struct CClaimTrieProofNode
|
||||||
|
@ -473,7 +481,9 @@ public:
|
||||||
void dumpToLog(CClaimPrefixTrie::const_iterator it, bool diffFromBase = true) const;
|
void dumpToLog(CClaimPrefixTrie::const_iterator it, bool diffFromBase = true) const;
|
||||||
virtual std::string adjustNameForValidHeight(const std::string& name, int validHeight) const;
|
virtual std::string adjustNameForValidHeight(const std::string& name, int validHeight) const;
|
||||||
|
|
||||||
protected:
|
void recurseNodes(const std::string& name, std::function<void(const std::string&, const CClaimTrieData&)> function) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
CClaimTrie* base;
|
CClaimTrie* base;
|
||||||
CClaimPrefixTrie nodesToAddOrUpdate; // nodes pulled in from base (and possibly modified thereafter), written to base on flush
|
CClaimPrefixTrie nodesToAddOrUpdate; // nodes pulled in from base (and possibly modified thereafter), written to base on flush
|
||||||
std::unordered_set<std::string> namesToCheckForTakeover; // takeover numbers are updated on increment
|
std::unordered_set<std::string> namesToCheckForTakeover; // takeover numbers are updated on increment
|
||||||
|
@ -523,7 +533,6 @@ private:
|
||||||
std::unordered_set<std::string> nodesAlreadyCached; // set of nodes already pulled into cache from base
|
std::unordered_set<std::string> nodesAlreadyCached; // set of nodes already pulled into cache from base
|
||||||
std::unordered_map<std::string, bool> takeoverWorkaround;
|
std::unordered_map<std::string, bool> takeoverWorkaround;
|
||||||
std::unordered_set<std::string> removalWorkaround;
|
std::unordered_set<std::string> removalWorkaround;
|
||||||
std::unordered_set<std::string> dirtyNodes;
|
|
||||||
|
|
||||||
bool shouldUseTakeoverWorkaround(const std::string& key) const;
|
bool shouldUseTakeoverWorkaround(const std::string& key) const;
|
||||||
void addTakeoverWorkaroundPotential(const std::string& key);
|
void addTakeoverWorkaroundPotential(const std::string& key);
|
||||||
|
|
|
@ -164,7 +164,7 @@ bool CClaimTrieCacheNormalizationFork::normalizeAllNamesInTrieIfNecessary(insert
|
||||||
boost::scoped_ptr<CDBIterator> pcursor(base->db->NewIterator());
|
boost::scoped_ptr<CDBIterator> pcursor(base->db->NewIterator());
|
||||||
for (pcursor->SeekToFirst(); pcursor->Valid(); pcursor->Next()) {
|
for (pcursor->SeekToFirst(); pcursor->Valid(); pcursor->Next()) {
|
||||||
std::pair<uint8_t, std::string> key;
|
std::pair<uint8_t, std::string> key;
|
||||||
if (!pcursor->GetKey(key) || key.first != TRIE_NODE_BY_NAME)
|
if (!pcursor->GetKey(key) || key.first != TRIE_NODE_CHILDREN)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto& name = key.second;
|
const auto& name = key.second;
|
||||||
|
|
|
@ -76,6 +76,7 @@ void RollBackTo(const CBlockIndex* targetIndex, CCoinsViewCache& coinsCache, CCl
|
||||||
if (g_chainstate.DisconnectBlock(block, activeIndex, coinsCache, trieCache) != DisconnectResult::DISCONNECT_OK)
|
if (g_chainstate.DisconnectBlock(block, activeIndex, coinsCache, trieCache) != DisconnectResult::DISCONNECT_OK)
|
||||||
throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("Failed to disconnect %s", block.ToString()));
|
throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("Failed to disconnect %s", block.ToString()));
|
||||||
}
|
}
|
||||||
|
trieCache.getMerkleHash(); // update the hash tree
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string escapeNonUtf8(const std::string& name)
|
std::string escapeNonUtf8(const std::string& name)
|
||||||
|
@ -175,7 +176,6 @@ static UniValue getclaimsintrie(const JSONRPCRequest& request)
|
||||||
}
|
}
|
||||||
|
|
||||||
UniValue ret(UniValue::VARR);
|
UniValue ret(UniValue::VARR);
|
||||||
uint256 rootHash;
|
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
CCoinsViewCache coinsCache(pcoinsTip.get());
|
CCoinsViewCache coinsCache(pcoinsTip.get());
|
||||||
|
@ -185,24 +185,18 @@ static UniValue getclaimsintrie(const JSONRPCRequest& request)
|
||||||
CBlockIndex *blockIndex = BlockHashIndex(ParseHashV(request.params[0], "blockhash (optional parameter 1)"));
|
CBlockIndex *blockIndex = BlockHashIndex(ParseHashV(request.params[0], "blockhash (optional parameter 1)"));
|
||||||
RollBackTo(blockIndex, coinsCache, trieCache);
|
RollBackTo(blockIndex, coinsCache, trieCache);
|
||||||
}
|
}
|
||||||
rootHash = trieCache.getMerkleHash();
|
|
||||||
|
|
||||||
CClaimTrieDataNode rootNode;
|
trieCache.recurseNodes("", [&ret, &trieCache, &coinsCache] (const std::string& name, const CClaimTrieData& data) {
|
||||||
if (!pclaimTrie->find(rootHash, rootNode))
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
pclaimTrie->recurseAllHashedNodes("", rootNode, [&ret, &trieCache, &coinsCache](const std::string &name,
|
|
||||||
const CClaimTrieDataNode &node) {
|
|
||||||
if (ShutdownRequested())
|
if (ShutdownRequested())
|
||||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Shutdown requested");
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Shutdown requested");
|
||||||
|
|
||||||
boost::this_thread::interruption_point();
|
boost::this_thread::interruption_point();
|
||||||
|
|
||||||
if (node.data.empty())
|
if (data.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UniValue claims(UniValue::VARR);
|
UniValue claims(UniValue::VARR);
|
||||||
for (auto itClaims = node.data.claims.cbegin(); itClaims != node.data.claims.cend(); ++itClaims) {
|
for (auto itClaims = data.claims.cbegin(); itClaims != data.claims.cend(); ++itClaims) {
|
||||||
UniValue claim(UniValue::VOBJ);
|
UniValue claim(UniValue::VOBJ);
|
||||||
claim.pushKV("claimId", itClaims->claimId.GetHex());
|
claim.pushKV("claimId", itClaims->claimId.GetHex());
|
||||||
claim.pushKV("txid", itClaims->outPoint.hash.GetHex());
|
claim.pushKV("txid", itClaims->outPoint.hash.GetHex());
|
||||||
|
@ -261,27 +255,19 @@ static UniValue getnamesintrie(const JSONRPCRequest& request)
|
||||||
"Result: \n"
|
"Result: \n"
|
||||||
"\"names\" (array) all names in the trie that have claims\n");
|
"\"names\" (array) all names in the trie that have claims\n");
|
||||||
|
|
||||||
uint256 rootHash;
|
LOCK(cs_main);
|
||||||
{
|
|
||||||
LOCK(cs_main);
|
|
||||||
|
|
||||||
CCoinsViewCache coinsCache(pcoinsTip.get());
|
CCoinsViewCache coinsCache(pcoinsTip.get());
|
||||||
CClaimTrieCache trieCache(pclaimTrie);
|
CClaimTrieCache trieCache(pclaimTrie);
|
||||||
|
|
||||||
if (!request.params.empty()) {
|
if (!request.params.empty()) {
|
||||||
CBlockIndex *blockIndex = BlockHashIndex(ParseHashV(request.params[0], "blockhash (optional parameter 1)"));
|
CBlockIndex *blockIndex = BlockHashIndex(ParseHashV(request.params[0], "blockhash (optional parameter 1)"));
|
||||||
RollBackTo(blockIndex, coinsCache, trieCache);
|
RollBackTo(blockIndex, coinsCache, trieCache);
|
||||||
}
|
|
||||||
rootHash = trieCache.getMerkleHash();
|
|
||||||
}
|
}
|
||||||
UniValue ret(UniValue::VARR);
|
UniValue ret(UniValue::VARR);
|
||||||
|
|
||||||
CClaimTrieDataNode rootNode;
|
trieCache.recurseNodes("", [&ret](const std::string &name, const CClaimTrieData &data) {
|
||||||
if (!pclaimTrie->find(rootHash, rootNode))
|
if (!data.empty())
|
||||||
return ret;
|
|
||||||
|
|
||||||
pclaimTrie->recurseAllHashedNodes("", rootNode, [&ret](const std::string& name, const CClaimTrieDataNode& node) {
|
|
||||||
if (!node.data.empty())
|
|
||||||
ret.push_back(escapeNonUtf8(name));
|
ret.push_back(escapeNonUtf8(name));
|
||||||
if (ShutdownRequested())
|
if (ShutdownRequested())
|
||||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Shutdown requested");
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Shutdown requested");
|
||||||
|
|
|
@ -509,6 +509,22 @@ BOOST_AUTO_TEST_CASE(triehash_fuzzer_test)
|
||||||
std::cerr << "Hash: " << fixture.getMerkleHash().GetHex() << std::endl;
|
std::cerr << "Hash: " << fixture.getMerkleHash().GetHex() << std::endl;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(claim_replace_test) {
|
||||||
|
// no competing bids
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "bass", "one", 1);
|
||||||
|
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "basso", "two", 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("bass", tx1));
|
||||||
|
fixture.Spend(tx1);
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "bassfisher", "one", 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(pclaimTrie->checkConsistency(fixture.getMerkleHash()));
|
||||||
|
BOOST_CHECK(!fixture.is_best_claim("bass", tx1));
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("bassfisher", tx2));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
claims
|
claims
|
||||||
no competing bids
|
no competing bids
|
||||||
|
@ -2617,18 +2633,6 @@ BOOST_AUTO_TEST_CASE(claimtrienode_serialize_unserialize)
|
||||||
ss >> n2;
|
ss >> n2;
|
||||||
BOOST_CHECK_EQUAL(n1, n2);
|
BOOST_CHECK_EQUAL(n1, n2);
|
||||||
|
|
||||||
n1.hash.SetHex("0000000000000000000000000000000000000000000000000000000000000001");
|
|
||||||
BOOST_CHECK(n1 != n2);
|
|
||||||
ss << n1;
|
|
||||||
ss >> n2;
|
|
||||||
BOOST_CHECK_EQUAL(n1, n2);
|
|
||||||
|
|
||||||
n1.hash.SetHex("a79e8a5b28f7fa5e8836a4b48da9988bdf56ce749f81f413cb754f963a516200");
|
|
||||||
BOOST_CHECK(n1 != n2);
|
|
||||||
ss << n1;
|
|
||||||
ss >> n2;
|
|
||||||
BOOST_CHECK_EQUAL(n1, n2);
|
|
||||||
|
|
||||||
CClaimValue v1(COutPoint(uint256S("0000000000000000000000000000000000000000000000000000000000000001"), 0), hash160, 50, 0, 100);
|
CClaimValue v1(COutPoint(uint256S("0000000000000000000000000000000000000000000000000000000000000001"), 0), hash160, 50, 0, 100);
|
||||||
CClaimValue v2(COutPoint(uint256S("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), 1), hash160, 100, 1, 101);
|
CClaimValue v2(COutPoint(uint256S("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), 1), hash160, 100, 1, 101);
|
||||||
|
|
||||||
|
@ -4101,9 +4105,9 @@ BOOST_AUTO_TEST_CASE(update_on_support2_test)
|
||||||
CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, name, 1);
|
CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, name, 1);
|
||||||
fixture.IncrementBlocks(1);
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
CClaimTrieDataNode node;
|
CClaimTrieData node;
|
||||||
BOOST_CHECK(pclaimTrie->find(name, node));
|
BOOST_CHECK(pclaimTrie->find(name, node));
|
||||||
BOOST_CHECK_EQUAL(node.data.nHeightOfLastTakeover, height + 1);
|
BOOST_CHECK_EQUAL(node.nHeightOfLastTakeover, height + 1);
|
||||||
|
|
||||||
fixture.Spend(s1);
|
fixture.Spend(s1);
|
||||||
fixture.Spend(s2);
|
fixture.Spend(s2);
|
||||||
|
@ -4111,7 +4115,7 @@ BOOST_AUTO_TEST_CASE(update_on_support2_test)
|
||||||
fixture.IncrementBlocks(1);
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
BOOST_CHECK(pclaimTrie->find(name, node));
|
BOOST_CHECK(pclaimTrie->find(name, node));
|
||||||
BOOST_CHECK_EQUAL(node.data.nHeightOfLastTakeover, height + 1);
|
BOOST_CHECK_EQUAL(node.nHeightOfLastTakeover, height + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
|
@ -200,7 +200,6 @@ BOOST_AUTO_TEST_CASE(basic_insertion_info_test)
|
||||||
CClaimTrieCacheTest ctc(pclaimTrie);
|
CClaimTrieCacheTest ctc(pclaimTrie);
|
||||||
|
|
||||||
// create and insert claim
|
// create and insert claim
|
||||||
CClaimValue unused;
|
|
||||||
uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
|
uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
|
||||||
CMutableTransaction tx1 = BuildTransaction(hash0);
|
CMutableTransaction tx1 = BuildTransaction(hash0);
|
||||||
uint160 claimId = ClaimIdHash(tx1.GetHash(), 0);
|
uint160 claimId = ClaimIdHash(tx1.GetHash(), 0);
|
||||||
|
@ -304,7 +303,9 @@ BOOST_AUTO_TEST_CASE(iteratetrie_test)
|
||||||
BOOST_CHECK_EQUAL(node.children.size(), 1U);
|
BOOST_CHECK_EQUAL(node.children.size(), 1U);
|
||||||
BOOST_CHECK(pclaimTrie->find("test", node));
|
BOOST_CHECK(pclaimTrie->find("test", node));
|
||||||
BOOST_CHECK_EQUAL(node.children.size(), 0U);
|
BOOST_CHECK_EQUAL(node.children.size(), 0U);
|
||||||
BOOST_CHECK_EQUAL(node.data.claims.size(), 1);
|
CClaimTrieData data;
|
||||||
|
BOOST_CHECK(pclaimTrie->find("test", data));
|
||||||
|
BOOST_CHECK_EQUAL(data.claims.size(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(trie_stays_consistent_test)
|
BOOST_AUTO_TEST_CASE(trie_stays_consistent_test)
|
||||||
|
|
Loading…
Reference in a new issue