diff --git a/src/claimtrie.cpp b/src/claimtrie.cpp index b439d8d3f..83eb64da8 100644 --- a/src/claimtrie.cpp +++ b/src/claimtrie.cpp @@ -340,19 +340,19 @@ bool CClaimTrieCacheBase::getInfoForName(const std::string& name, CClaimValue& c CClaimSupportToName CClaimTrieCacheBase::getClaimsForName(const std::string& name) const { - claimEntryType claims; int nLastTakeoverHeight = 0; + db << "SELECT IFNULL(takeoverHeight,0) FROM nodes WHERE name = ?" << name >> nLastTakeoverHeight; + auto supports = getSupportsForName(name); auto query = db << "SELECT claimID, txID, txN, blockHeight, validHeight, amount " "FROM claims WHERE nodeName = ? AND expirationHeight >= ?" << name << nNextHeight; + claimEntryType claims; for (auto&& row: query) { CClaimValue claim; row >> claim.claimId >> claim.outPoint.hash >> claim.outPoint.n >> claim.nHeight >> claim.nValidAtHeight >> claim.nAmount; - if (nLastTakeoverHeight == 0 && claim.nValidAtHeight < nNextHeight) - nLastTakeoverHeight = claim.nValidAtHeight; claims.push_back(claim); } @@ -1253,18 +1253,19 @@ bool CClaimTrieCacheBase::getProofForName(const std::string& name, const uint160 // cache the parent nodes getMerkleHash(); proof = CClaimTrieProof(); - auto nodeQuery = db << "SELECT name FROM nodes WHERE " + auto nodeQuery = db << "SELECT name, IFNULL(takeoverHeight, 0) FROM nodes WHERE " "name IN (WITH RECURSIVE prefix(p) AS (VALUES(?) UNION ALL " "SELECT SUBSTR(p, 1, LENGTH(p)-1) FROM prefix WHERE p != '') SELECT p FROM prefix) " "ORDER BY LENGTH(name)" << name; for (auto&& row: nodeQuery) { CClaimValue claim; std::string key; - row >> key; + int takeoverHeight; + row >> key >> takeoverHeight; bool fNodeHasValue = getInfoForName(key, claim); uint256 valueHash; if (fNodeHasValue) - valueHash = getValueHash(claim.outPoint, claim.nValidAtHeight); + valueHash = getValueHash(claim.outPoint, takeoverHeight); const auto pos = key.size(); std::vector> children; @@ -1291,7 +1292,7 @@ bool CClaimTrieCacheBase::getProofForName(const std::string& name, const uint160 proof.hasValue = fNodeHasValue && claim.claimId == finalClaim; if (proof.hasValue) { proof.outPoint = claim.outPoint; - proof.nHeightOfLastTakeover = claim.nValidAtHeight; + proof.nHeightOfLastTakeover = takeoverHeight; } valueHash.SetNull(); } diff --git a/src/claimtrieforks.cpp b/src/claimtrieforks.cpp index e4bf17361..1926e7975 100644 --- a/src/claimtrieforks.cpp +++ b/src/claimtrieforks.cpp @@ -261,10 +261,11 @@ uint256 CClaimTrieCacheHashFork::recursiveComputeMerkleHash(const std::string& n } auto claimQuery = db << "SELECT c.txID, c.txN, " - "(SELECT TOTAL(s.amount)+c.amount FROM supports s WHERE s.supportedClaimID = c.claimID " - "AND s.validHeight < ? AND s.expirationHeight >= ?) as effectiveAmount" - "FROM claims c WHERE c.nodeName = ? AND c.validHeight < ? AND c.expirationHeight >= ? " - "ORDER BY effectiveAmount DESC, c.blockHeight, c.txID, c.txN" << nNextHeight << nNextHeight << name << nNextHeight << nNextHeight; + "(SELECT TOTAL(s.amount)+c.amount FROM supports s WHERE s.supportedClaimID = c.claimID " + "AND s.validHeight < ? AND s.expirationHeight >= ?) as effectiveAmount " + "FROM claims c WHERE c.nodeName = ? AND c.validHeight < ? AND c.expirationHeight >= ? " + "ORDER BY effectiveAmount DESC, c.blockHeight, c.txID, c.txN" + << nNextHeight << nNextHeight << name << nNextHeight << nNextHeight; std::vector claimHashes; for (auto&& row: claimQuery) { @@ -355,7 +356,7 @@ bool CClaimTrieCacheHashFork::getProofForName(const std::string& name, const uin auto nodeQuery = db << "SELECT name, IFNULL(takeoverHeight, 0) FROM nodes WHERE " "name IN (WITH RECURSIVE prefix(p) AS (VALUES(?) UNION ALL " "SELECT SUBSTR(p, 1, LENGTH(p)-1) FROM prefix WHERE p != '') SELECT p FROM prefix) " - "ORDER BY LENGTH(name)" << name; + "ORDER BY name" << name; for (auto&& row: nodeQuery) { std::string key;; int takeoverHeight; @@ -372,26 +373,32 @@ bool CClaimTrieCacheHashFork::getProofForName(const std::string& name, const uin childHashes.push_back(childHash); } - auto cns = getClaimsForName(key); + auto claimQuery = db << "SELECT c.txID, c.txN, c.claimID, " + "(SELECT TOTAL(s.amount)+c.amount FROM supports s WHERE s.supportedClaimID = c.claimID " + "AND s.validHeight < ? AND s.expirationHeight >= ?) as effectiveAmount " + "FROM claims c WHERE c.nodeName = ? AND c.validHeight < ? AND c.expirationHeight >= ? " + "ORDER BY effectiveAmount DESC, c.blockHeight, c.txID, c.txN" + << nNextHeight << nNextHeight << name << nNextHeight << nNextHeight; + std::vector claimHashes; uint32_t finalClaimIdx = 0; - COutPoint finalOutPoint; - for (uint32_t i = 0; i < cns.claimsNsupports.size(); ++i) { - auto& child = cns.claimsNsupports[i].claim; - claimHashes.push_back(getValueHash(child.outPoint, takeoverHeight)); - if (child.claimId == finalClaim) { - finalClaimIdx = i; - finalOutPoint = child.outPoint; + for (auto&& child: claimQuery) { + COutPoint childOutPoint; + uint160 childClaimID; + child >> childOutPoint.hash >> childOutPoint.n >> childClaimID; + if (childClaimID == finalClaim && key == name) { + finalClaimIdx = uint32_t(claimHashes.size()); + proof.outPoint = childOutPoint; + proof.hasValue = true; } + claimHashes.push_back(getValueHash(childOutPoint, takeoverHeight)); } // I am on a node; I need a hash(children, claims) // if I am the last node on the list, it will be hash(children, x) // else it will be hash(x, claims) if (key == name) { - proof.outPoint = finalOutPoint; - proof.nHeightOfLastTakeover = cns.nLastTakeoverHeight; - proof.hasValue = true; + proof.nHeightOfLastTakeover = takeoverHeight; auto hash = childHashes.empty() ? leafHash : ComputeMerkleRoot(childHashes); proof.pairs.emplace_back(true, hash); if (!claimHashes.empty()) @@ -411,15 +418,19 @@ void CClaimTrieCacheHashFork::initializeIncrement() { CClaimTrieCacheNormalizationFork::initializeIncrement(); // we could do this in the constructor, but that would not allow for multiple increments in a row (as done in unit tests) - if (nNextHeight == Params().GetConsensus().nAllClaimsInMerkleForkHeight - 1) + if (nNextHeight == Params().GetConsensus().nAllClaimsInMerkleForkHeight - 1) { + if (!transacting) { transacting = true; db << "begin"; } db << "UPDATE nodes SET hash = NULL"; + } } bool CClaimTrieCacheHashFork::finalizeDecrement(takeoverUndoType& takeoverUndo) { auto ret = CClaimTrieCacheNormalizationFork::finalizeDecrement(takeoverUndo); - if (ret && nNextHeight == Params().GetConsensus().nAllClaimsInMerkleForkHeight - 1) + if (ret && nNextHeight == Params().GetConsensus().nAllClaimsInMerkleForkHeight - 1) { + if (!transacting) { transacting = true; db << "begin"; } db << "UPDATE nodes SET hash = NULL"; + } return ret; } diff --git a/src/test/claimtriehashfork_tests.cpp b/src/test/claimtriehashfork_tests.cpp index dabc937f0..3ce8749d2 100644 --- a/src/test/claimtriehashfork_tests.cpp +++ b/src/test/claimtriehashfork_tests.cpp @@ -74,12 +74,14 @@ BOOST_AUTO_TEST_CASE(hash_includes_all_claims_triple_test) fixture.IncrementBlocks(1); for (const auto& name : names) { - for (auto& claimSupports : fixture.getClaimsForName(name).claimsNsupports) { + auto cfn = fixture.getClaimsForName(name); + for (auto& claimSupports : cfn.claimsNsupports) { CClaimTrieProof proof; auto& claim = claimSupports.claim; BOOST_CHECK(fixture.getProofForName(name, claim.claimId, proof)); BOOST_CHECK(proof.hasValue); BOOST_CHECK_EQUAL(proof.outPoint, claim.outPoint); + BOOST_CHECK_EQUAL(proof.nHeightOfLastTakeover, cfn.nLastTakeoverHeight); uint256 claimHash = getValueHash(claim.outPoint, proof.nHeightOfLastTakeover); ValidatePairs(fixture, proof.pairs, claimHash); }