fixed issue with untouched child nodes needing a parent update

This commit is contained in:
Brannon King 2019-11-07 16:42:37 -07:00
parent dfc5ebf3f6
commit 75c4c7ab0d
5 changed files with 72 additions and 15 deletions

View file

@ -15,7 +15,7 @@ bool CClaimScriptAddOp::claimName(CClaimTrieCache& trieCache, const std::string&
const std::vector<unsigned char>& metadata) const std::vector<unsigned char>& metadata)
{ {
auto claimId = ClaimIdHash(point.hash, point.n); auto claimId = ClaimIdHash(point.hash, point.n);
LogPrint(BCLog::CLAIMS, "+++ Claim added: %s, c: %.6s, t: %.6s:%d, h: %.6d, a: %du\n", LogPrint(BCLog::CLAIMS, "+++ Claim added: %s, c: %.6s, t: %.6s:%d, h: %.6d, a: %d\n",
name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValue); name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValue);
return addClaim(trieCache, name, claimId, -1, metadata); return addClaim(trieCache, name, claimId, -1, metadata);
} }
@ -23,7 +23,7 @@ bool CClaimScriptAddOp::claimName(CClaimTrieCache& trieCache, const std::string&
bool CClaimScriptAddOp::updateClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId, bool CClaimScriptAddOp::updateClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId,
const std::vector<unsigned char>& metadata) const std::vector<unsigned char>& metadata)
{ {
LogPrint(BCLog::CLAIMS, "+++ Claim updated: %s, c: %.6s, t: %.6s:%d, h: %.6d, a: %du\n", LogPrint(BCLog::CLAIMS, "+++ Claim updated: %s, c: %.6s, t: %.6s:%d, h: %.6d, a: %d\n",
name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValue); name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValue);
return addClaim(trieCache, name, claimId, -1, metadata); return addClaim(trieCache, name, claimId, -1, metadata);
} }
@ -37,7 +37,7 @@ bool CClaimScriptAddOp::addClaim(CClaimTrieCache& trieCache, const std::string&
bool CClaimScriptAddOp::supportClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId, bool CClaimScriptAddOp::supportClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId,
const std::vector<unsigned char>& metadata) const std::vector<unsigned char>& metadata)
{ {
LogPrint(BCLog::CLAIMS, "+++ Support added: %s, c: %.6s, t: %.6s:%d, h: %.6d, a: %du\n", LogPrint(BCLog::CLAIMS, "+++ Support added: %s, c: %.6s, t: %.6s:%d, h: %.6d, a: %d\n",
name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValue); name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValue);
return trieCache.addSupport(name, point, nValue, claimId, nHeight, -1, metadata); return trieCache.addSupport(name, point, nValue, claimId, nHeight, -1, metadata);
} }

View file

@ -99,6 +99,8 @@ CClaimTrieCacheBase::~CClaimTrieCacheBase() {
db << "rollback"; db << "rollback";
transacting = false; transacting = false;
} }
claimHashQuery.used(true);
childHashQuery.used(true);
} }
bool CClaimTrie::SyncToDisk() bool CClaimTrie::SyncToDisk()
@ -234,6 +236,12 @@ void CClaimTrieCacheBase::ensureTreeStructureIsUpToDate() {
"SELECT SUBSTR(p, 1, LENGTH(p)-1) FROM prefix WHERE p != '') SELECT p FROM prefix) " "SELECT SUBSTR(p, 1, LENGTH(p)-1) FROM prefix WHERE p != '') SELECT p FROM prefix) "
"ORDER BY name DESC LIMIT 1"; "ORDER BY name DESC LIMIT 1";
auto insertQuery = db << "INSERT INTO nodes(name, parent, hash) VALUES(?, ?, NULL) "
"ON CONFLICT(name) DO UPDATE SET parent = excluded.parent, hash = NULL";
auto updateUnaffectedsQuery = db << "UPDATE nodes SET parent = ? WHERE name LIKE ? AND LENGTH(parent) < ?";
for (auto& name: names) { for (auto& name: names) {
std::vector<std::string> claims; std::vector<std::string> claims;
std::string parent; std::string parent;
@ -273,26 +281,43 @@ void CClaimTrieCacheBase::ensureTreeStructureIsUpToDate() {
break; break;
} }
// insert the split node: // insert the split node:
LogPrint(BCLog::CLAIMS, "Inserting split node %s, parent %s\n", newNodeName, parent); LogPrint(BCLog::CLAIMS, "Inserting split node %s near %s, parent %s\n", newNodeName, sibling, parent);
db << "INSERT INTO nodes(name, parent, hash) VALUES(?, ?, NULL) " insertQuery << newNodeName << parent;
"ON CONFLICT(name) DO UPDATE SET parent = excluded.parent, hash = NULL" insertQuery++;
<< newNodeName << parent;
if (newNodeName.find('_') == std::string::npos && newNodeName.find('%') == std::string::npos) {
updateUnaffectedsQuery << newNodeName << newNodeName + "_%" << newNodeName.size();
updateUnaffectedsQuery++;
}
else
db << "UPDATE nodes SET parent = ?1 WHERE SUBSTR(name, 1, ?2) = ?1 AND LENGTH(parent) < ?2 AND name != ?1"
<< newNodeName << newNodeName.size();
parent = std::move(newNodeName); parent = std::move(newNodeName);
break; break;
} }
} }
LogPrint(BCLog::CLAIMS, "Inserting or updating node %s, parent %s\n", name, parent); LogPrint(BCLog::CLAIMS, "Inserting or updating node %s, parent %s\n", name, parent);
db << "INSERT INTO nodes(name, parent, hash) VALUES(?, ?, NULL) " insertQuery << name << parent;
"ON CONFLICT(name) DO UPDATE SET parent = excluded.parent, hash = NULL" insertQuery++;
<< name << parent;
if (splitPos == 0) if (splitPos == 0)
db << "UPDATE nodes SET hash = NULL WHERE name = ?" << parent; db << "UPDATE nodes SET hash = NULL WHERE name = ?" << parent;
if (name.find('_') == std::string::npos && name.find('%') == std::string::npos) {
updateUnaffectedsQuery << name << name + "_%" << name.size();
updateUnaffectedsQuery++;
}
else
db << "UPDATE nodes SET parent = ?1 WHERE SUBSTR(name, 1, ?2) = ?1 AND LENGTH(parent) < ?2 AND name != ?1" db << "UPDATE nodes SET parent = ?1 WHERE SUBSTR(name, 1, ?2) = ?1 AND LENGTH(parent) < ?2 AND name != ?1"
<< name << name.size(); << name << name.size();
} }
parentQuery.used(true);
insertQuery.used(true);
updateUnaffectedsQuery.used(true);
// now we need to percolate the nulls up the tree // now we need to percolate the nulls up the tree
// parents should all be set right // parents should all be set right
db << "UPDATE nodes SET hash = NULL WHERE name IN (WITH RECURSIVE prefix(p) AS " db << "UPDATE nodes SET hash = NULL WHERE name IN (WITH RECURSIVE prefix(p) AS "
@ -320,7 +345,7 @@ std::size_t CClaimTrieCacheBase::getTotalClaimsInTrie() const
CAmount CClaimTrieCacheBase::getTotalValueOfClaimsInTrie(bool fControllingOnly) const CAmount CClaimTrieCacheBase::getTotalValueOfClaimsInTrie(bool fControllingOnly) const
{ {
CAmount ret = 0; CAmount ret = 0;
std::string query("SELECT (SELECT TOTAL(s.amount)+c.amount FROM supports s " std::string query("SELECT TOTAL(SELECT TOTAL(s.amount)+c.amount FROM supports s "
"WHERE s.supportedClaimID = c.claimID AND s.validHeight < ?1 AND s.expirationHeight >= ?1) " "WHERE s.supportedClaimID = c.claimID AND s.validHeight < ?1 AND s.expirationHeight >= ?1) "
"FROM claims c WHERE c.validHeight < ?1 AND s.expirationHeight >= ?1"); "FROM claims c WHERE c.validHeight < ?1 AND s.expirationHeight >= ?1");
if (fControllingOnly) if (fControllingOnly)
@ -417,6 +442,7 @@ uint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(const std::string& name,
if (child.hash->IsNull()) { if (child.hash->IsNull()) {
*child.hash = recursiveComputeMerkleHash(child.name, child.takeoverHeight, checkOnly); *child.hash = recursiveComputeMerkleHash(child.name, child.takeoverHeight, checkOnly);
} }
LogPrint(BCLog::CLAIMS, "Hash of %s: %s, takeover: %d\n", child.name, (*child.hash).GetHex(), child.takeoverHeight);
completeHash(*child.hash, child.name, pos); completeHash(*child.hash, child.name, pos);
vchToHash.push_back(child.name[pos]); vchToHash.push_back(child.name[pos]);
vchToHash.insert(vchToHash.end(), child.hash->begin(), child.hash->end()); vchToHash.insert(vchToHash.end(), child.hash->begin(), child.hash->end());
@ -1003,6 +1029,10 @@ bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimUndoTy
} }
} }
getTakeoverQuery.used(true);
hasCandidateQuery.used(true);
noCandidateQuery.used(true);
nNextHeight++; nNextHeight++;
return true; return true;
} }
@ -1302,8 +1332,7 @@ bool CClaimTrieCacheBase::getProofForName(const std::string& name, const uint160
const auto pos = key.size(); const auto pos = key.size();
std::vector<std::pair<unsigned char, uint256>> children; std::vector<std::pair<unsigned char, uint256>> children;
auto childQuery = db << "SELECT name, hash FROM nodes WHERE parent = ?" << key; for (auto&& child : childHashQuery << key) {
for (auto&& child : childQuery) {
std::string childKey; std::string childKey;
uint256 hash; uint256 hash;
child >> childKey >> hash; child >> childKey >> hash;
@ -1321,6 +1350,7 @@ bool CClaimTrieCacheBase::getProofForName(const std::string& name, const uint160
completeHash(hash, childKey, pos); completeHash(hash, childKey, pos);
children.emplace_back(childKey[pos], hash); children.emplace_back(childKey[pos], hash);
} }
childHashQuery++;
if (key == name) { if (key == name) {
proof.hasValue = fNodeHasValue && claim.claimId == finalClaim; proof.hasValue = fNodeHasValue && claim.claimId == finalClaim;
if (proof.hasValue) { if (proof.hasValue) {

View file

@ -42,6 +42,22 @@ BOOST_AUTO_TEST_CASE(takeover_stability_test) {
BOOST_CHECK_EQUAL(takeover, height); BOOST_CHECK_EQUAL(takeover, height);
} }
BOOST_AUTO_TEST_CASE(unaffected_children_get_new_parents_test) {
// this happens first on block 193976
ClaimTrieChainFixture fixture;
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "longest123", "one", 1);
fixture.IncrementBlocks(1);
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "longest", "two", 2);
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "longest1", "three", 3);
CMutableTransaction tx4 = fixture.MakeClaim(tx3, "longest1", "three1234", 2);
fixture.IncrementBlocks(1);
auto n1 = fixture.getNodeChildren("longest");
auto n2 = fixture.getNodeChildren("longest1");
BOOST_CHECK_EQUAL(n1[0], "longest1");
BOOST_CHECK_EQUAL(n2[0], "longest123");
// TODO: this test at present fails to cover the split node case of the same thing (which occurs on block 202577)
}
/* /*
claims claims
no competing bids no competing bids

View file

@ -403,3 +403,12 @@ bool ClaimTrieChainFixture::getClaimById(const uint160 &claimId, std::string &na
} }
return hit; return hit;
} }
std::vector<std::string> ClaimTrieChainFixture::getNodeChildren(const std::string &name) {
std::vector<std::string> ret;
for (auto&& row: db << "SELECT name FROM nodes WHERE parent = ?" << name) {
ret.emplace_back();
row >> ret.back();
}
return ret;
}

View file

@ -113,6 +113,8 @@ struct ClaimTrieChainFixture: public CClaimTrieCache
// check effective quantity of best claim // check effective quantity of best claim
boost::test_tools::predicate_result best_claim_effective_amount_equals(const std::string& name, CAmount amount); boost::test_tools::predicate_result best_claim_effective_amount_equals(const std::string& name, CAmount amount);
std::vector<std::string> getNodeChildren(const std::string& name);
}; };
#endif // _CLAIMTRIEFIXTURE_H_ #endif // _CLAIMTRIEFIXTURE_H_