diff --git a/src/claimtrie.cpp b/src/claimtrie.cpp index c3202fb61..7e454b2e1 100644 --- a/src/claimtrie.cpp +++ b/src/claimtrie.cpp @@ -109,7 +109,7 @@ bool CClaimTrie::SyncToDisk() bool CClaimTrie::empty() { int64_t count; - db << "SELECT COUNT(*) FROM claims" >> count; + db << "SELECT COUNT(*) FROM claims WHERE validHeight < ? AND expirationHeight >= ?" << nNextHeight << nNextHeight >> count; return count == 0; } @@ -952,23 +952,24 @@ bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimUndoTy // if somebody activates on this block and they are the new best, then everybody activates on this block CClaimValue value; - if (needsActivate || !getInfoForName(nameWithTakeover, value, 1) || value.nValidAtHeight == nNextHeight) { - activateAllFor(insertUndo, insertSupportUndo, nameWithTakeover); + auto hasCurrent = getInfoForName(nameWithTakeover, value, 1); + // now that they're all in get the winner: + int existingHeight; + std::unique_ptr existingID; + db << "SELECT IFNULL(takeoverHeight, 0), takeoverID FROM nodes WHERE name = ?" + << nameWithTakeover >> std::tie(existingHeight, existingID); - // now that they're all in get the winner: - if (getInfoForName(nameWithTakeover, value, 1)) { - int existingHeight; - std::unique_ptr existingID; - db << "SELECT IFNULL(takeoverHeight, 0), takeoverID FROM nodes WHERE name = ?" - << nameWithTakeover >> std::tie(existingHeight, existingID); - if (existingID == nullptr || *existingID != value.claimId) { - takeoverUndo.emplace_back(nameWithTakeover, - std::make_pair(existingHeight, existingID == nullptr ? uint160() : *existingID)); - db << "UPDATE nodes SET takeoverHeight = ?, takeoverID = ? WHERE name = ?" - << nNextHeight << value.claimId << nameWithTakeover; - assert(db.rows_modified()); - } - } + auto newOwner = needsActivate || existingID == nullptr || !hasCurrent || *existingID != value.claimId; + if (newOwner && activateAllFor(insertUndo, insertSupportUndo, nameWithTakeover)) + getInfoForName(nameWithTakeover, value, 1); + + if (existingID != nullptr) + takeoverUndo.emplace_back(nameWithTakeover, std::make_pair(existingHeight, *existingID)); + + if (newOwner) { + db << "UPDATE nodes SET takeoverHeight = ?, takeoverID = ? WHERE name = ?" + << nNextHeight << value.claimId << nameWithTakeover; + assert(db.rows_modified()); } } @@ -976,9 +977,10 @@ bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimUndoTy return true; } -void CClaimTrieCacheBase::activateAllFor(insertUndoType& insertUndo, insertUndoType& insertSupportUndo, +bool CClaimTrieCacheBase::activateAllFor(insertUndoType& insertUndo, insertUndoType& insertSupportUndo, const std::string& name) { // now that we know a takeover is happening, we bring everybody in: + auto ret = false; { auto query = db << "SELECT txID, txN, validHeight FROM claims WHERE nodeName = ? AND validHeight > ? AND expirationHeight > ?" << name << nNextHeight << nNextHeight; @@ -993,6 +995,7 @@ void CClaimTrieCacheBase::activateAllFor(insertUndoType& insertUndo, insertUndoT // and then update them all to activate now: db << "UPDATE claims SET validHeight = ? WHERE nodeName = ? AND validHeight > ? AND expirationHeight > ?" << nNextHeight << name << nNextHeight << nNextHeight; + ret |= db.rows_modified() > 0; // then do the same for supports: { @@ -1009,6 +1012,8 @@ void CClaimTrieCacheBase::activateAllFor(insertUndoType& insertUndo, insertUndoT // and then update them all to activate now: db << "UPDATE supports SET validHeight = ? WHERE nodeName = ? AND validHeight > ? AND expirationHeight > ?" << nNextHeight << name << nNextHeight << nNextHeight; + ret |= db.rows_modified() > 0; + return ret; } bool CClaimTrieCacheBase::decrementBlock(insertUndoType& insertUndo, claimUndoType& expireUndo, @@ -1021,29 +1026,25 @@ bool CClaimTrieCacheBase::decrementBlock(insertUndoType& insertUndo, claimUndoTy // to actually delete the expired items and then restore them here I would have to look up the metadata in the block // that doesn't sound very fun so we modified the other queries to exclude expired items for (auto it = expireSupportUndo.crbegin(); it != expireSupportUndo.crend(); ++it) { - db << "UPDATE supports SET validHeight = ? WHERE txID = ? AND txN = ?" - << it->second.nValidAtHeight << it->second.outPoint.hash << it->second.outPoint.n; - db << "UPDATE nodes SET hash = NULL WHERE name = ?" << it->first; + db << "INSERT INTO nodes(name) VALUES(?) ON CONFLICT(name) DO UPDATE SET hash = NULL" << it->first; } for (auto it = expireUndo.crbegin(); it != expireUndo.crend(); ++it) { - db << "UPDATE claims SET validHeight = ? WHERE claimID = ?" - << it->second.nValidAtHeight << it->second.claimId; - db << "UPDATE nodes SET hash = NULL WHERE name = ?" << it->first; + db << "INSERT INTO nodes(name) VALUES(?) ON CONFLICT(name) DO UPDATE SET hash = NULL" << it->first; } for (auto it = insertSupportUndo.crbegin(); it != insertSupportUndo.crend(); ++it) { LogPrint(BCLog::CLAIMS, "Resetting support valid height to %d for %s\n", it->nValidHeight, it->name); db << "UPDATE supports SET validHeight = ? WHERE txID = ? AND txN = ?" << it->nValidHeight << it->outPoint.hash << it->outPoint.n; - db << "UPDATE nodes SET hash = NULL WHERE name = ?" << it->name; + db << "INSERT INTO nodes(name) VALUES(?) ON CONFLICT(name) DO UPDATE SET hash = NULL" << it->name; } for (auto it = insertUndo.crbegin(); it != insertUndo.crend(); ++it) { LogPrint(BCLog::CLAIMS, "Resetting valid height to %d for %s\n", it->nValidHeight, it->name); db << "UPDATE claims SET validHeight = ? WHERE nodeName = ? AND txID = ? AND txN = ?" << it->nValidHeight << it->name << it->outPoint.hash << it->outPoint.n; - db << "UPDATE nodes SET hash = NULL WHERE name = ?" << it->name; + db << "INSERT INTO nodes(name) VALUES(?) ON CONFLICT(name) DO UPDATE SET hash = NULL" << it->name; } return true; diff --git a/src/claimtrie.h b/src/claimtrie.h index 5b2469e86..d156e44ac 100644 --- a/src/claimtrie.h +++ b/src/claimtrie.h @@ -400,7 +400,7 @@ private: friend struct ClaimTrieChainFixture; friend class CClaimTrieCacheTest; - void activateAllFor(insertUndoType& insertUndo, insertUndoType& insertSupportUndo, + bool activateAllFor(insertUndoType& insertUndo, insertUndoType& insertSupportUndo, const std::string& takeover); }; diff --git a/src/claimtrieforks.cpp b/src/claimtrieforks.cpp index 8df98dd39..18bd5fb59 100644 --- a/src/claimtrieforks.cpp +++ b/src/claimtrieforks.cpp @@ -74,10 +74,18 @@ bool CClaimTrieCacheExpirationFork::forkForExpirationChange(bool increment) */ auto extension = Params().GetConsensus().nExtendedClaimExpirationTime - Params().GetConsensus().nOriginalClaimExpirationTime; - if (!increment) extension = -extension; - db << "UPDATE claims SET expirationHeight = expirationHeight + ? WHERE expirationHeight >= ?" << extension << nNextHeight; - db << "UPDATE supports SET expirationHeight = expirationHeight + ? WHERE expirationHeight >= ?" << extension << nNextHeight; - db << "UPDATE nodes SET hash = NULL"; // recompute all hashes (as there aren't that many at this point) + if (increment) { + db << "UPDATE claims SET expirationHeight = expirationHeight + ? WHERE expirationHeight >= ?" + << extension << nNextHeight; + db << "UPDATE supports SET expirationHeight = expirationHeight + ? WHERE expirationHeight >= ?" + << extension << nNextHeight; + } + else { + db << "UPDATE claims SET expirationHeight = expirationHeight - ? WHERE expirationHeight >= ?" + << extension << nNextHeight + extension; + db << "UPDATE supports SET expirationHeight = expirationHeight - ? WHERE expirationHeight >= ?" + << extension << nNextHeight + extension; + } return true; } diff --git a/src/test/claimtriebranching_tests.cpp b/src/test/claimtriebranching_tests.cpp index b129fb3c6..a119128a4 100644 --- a/src/test/claimtriebranching_tests.cpp +++ b/src/test/claimtriebranching_tests.cpp @@ -393,27 +393,28 @@ BOOST_AUTO_TEST_CASE(claimtrie_update_takeover_test) fixture.IncrementBlocks(1); uint160 cid2; int takeover; + int height = chainActive.Tip()->nHeight; fixture.getLastTakeoverForName("test", cid2, takeover); - BOOST_CHECK_EQUAL(chainActive.Tip()->nHeight, takeover); + BOOST_CHECK_EQUAL(height, takeover); CMutableTransaction u1 = fixture.MakeUpdate(tx1, "test", "a", cid, 4); fixture.IncrementBlocks(1); fixture.getLastTakeoverForName("test", cid2, takeover); - BOOST_CHECK_EQUAL(chainActive.Tip()->nHeight, takeover); + BOOST_CHECK_EQUAL(height, takeover); CMutableTransaction u2 = fixture.MakeUpdate(u1, "test", "b", cid, 3); fixture.IncrementBlocks(1); fixture.getLastTakeoverForName("test", cid2, takeover); CClaimValue value; BOOST_REQUIRE(fixture.getInfoForName("test", value) && value.nAmount == 3); BOOST_CHECK_EQUAL(cid, cid2); - BOOST_CHECK_EQUAL(chainActive.Tip()->nHeight, takeover); + BOOST_CHECK_EQUAL(height, takeover); fixture.DecrementBlocks(1); fixture.getLastTakeoverForName("test", cid2, takeover); BOOST_CHECK_EQUAL(cid, cid2); - BOOST_CHECK_EQUAL(chainActive.Tip()->nHeight, takeover); + BOOST_CHECK_EQUAL(height, takeover); fixture.DecrementBlocks(1); fixture.getLastTakeoverForName("test", cid2, takeover); BOOST_CHECK_EQUAL(cid, cid2); - BOOST_CHECK_EQUAL(chainActive.Tip()->nHeight, takeover); + BOOST_CHECK_EQUAL(height, takeover); } /* diff --git a/src/test/claimtriefixture.cpp b/src/test/claimtriefixture.cpp index 3c35b5152..1685b8730 100644 --- a/src/test/claimtriefixture.cpp +++ b/src/test/claimtriefixture.cpp @@ -324,7 +324,7 @@ bool ClaimTrieChainFixture::expirationQueueEmpty() const bool ClaimTrieChainFixture::supportEmpty() const { int64_t count; - db << "SELECT COUNT(*) FROM supports" >> count; + db << "SELECT COUNT(*) FROM supports WHERE validHeight < ? AND expirationHeight >= ?" << nNextHeight << nNextHeight >> count; return count == 0; } @@ -392,6 +392,14 @@ boost::test_tools::predicate_result ClaimTrieChainFixture::best_claim_effective_ } bool ClaimTrieChainFixture::getClaimById(const uint160 &claimId, std::string &name, CClaimValue &value) { - std::vector claim(claimId.begin(), claimId.end()); - return findNameForClaim(claim, value, name); + auto query = db << "SELECT nodeName, claimID, txID, txN, amount, validHeight, blockHeight " + "FROM claims WHERE claimID = ?" << claimId; + auto hit = false; + for (auto&& row: query) { + if (hit) return false; + row >> name >> value.claimId >> value.outPoint.hash >> value.outPoint.n + >> value.nAmount >> value.nValidAtHeight >> value.nHeight; + hit = true; + } + return hit; }