From 97f2067c6621eada1df24b74824a1a818b78f5ca Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak Date: Tue, 29 Dec 2015 13:50:11 -0500 Subject: [PATCH] make supports expire --- src/claimtrie.cpp | 91 ++++++++++--- src/claimtrie.h | 13 +- src/main.cpp | 4 +- src/miner.cpp | 3 +- src/test/claimtrie_tests.cpp | 240 +++++++++++++++++++++++++++++++++++ src/undo.h | 4 +- 6 files changed, 328 insertions(+), 27 deletions(-) diff --git a/src/claimtrie.cpp b/src/claimtrie.cpp index 7ff1721d4..5f4cd9755 100644 --- a/src/claimtrie.cpp +++ b/src/claimtrie.cpp @@ -605,6 +605,20 @@ void CClaimTrie::updateSupportNameQueue(const std::string& name, std::vectorsecond.swap(row); } +void CClaimTrie::updateSupportExpirationQueue(int nHeight, supportQueueRowType& row) +{ + supportQueueType::iterator itQueueRow = dirtySupportExpirationQueueRows.find(nHeight); + if (itQueueRow == dirtySupportExpirationQueueRows.end()) + { + supportQueueRowType newRow; + std::pair ret; + ret = dirtySupportExpirationQueueRows.insert(std::pair(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); @@ -638,7 +652,18 @@ bool CClaimTrie::getSupportQueueNameRow(const std::string& name, std::vector& takeoverHeights, const uint256& hashBlockIn, claimQueueType& queueCache, claimQueueNamesType& queueNameCache, claimQueueType& expirationQueueCache, int nNewHeight, supportMapType& supportCache, supportQueueType& supportQueueCache, supportQueueNamesType& supportQueueNameCache) +bool CClaimTrie::getSupportExpirationQueueRow(int nHeight, supportQueueRowType& row) const +{ + supportQueueType::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& takeoverHeights, const uint256& hashBlockIn, claimQueueType& queueCache, claimQueueNamesType& queueNameCache, claimQueueType& expirationQueueCache, int nNewHeight, supportMapType& supportCache, supportQueueType& supportQueueCache, supportQueueNamesType& supportQueueNameCache, supportQueueType& supportExpirationQueueCache) { for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache) { @@ -679,6 +704,10 @@ bool CClaimTrie::update(nodeCacheType& cache, hashMapType& hashes, std::mapfirst, itSupportNameQueue->second); } + for (supportQueueType::iterator itSupportExpirationQueue = supportExpirationQueueCache.begin(); itSupportExpirationQueue != supportExpirationQueueCache.end(); ++itSupportExpirationQueue) + { + updateSupportExpirationQueue(itSupportExpirationQueue->first, itSupportExpirationQueue->second); + } hashBlock = hashBlockIn; nCurrentHeight = nNewHeight; return true; @@ -888,6 +917,21 @@ void CClaimTrie::BatchWriteSupportQueueNameRows(CLevelDBBatch& batch) } } +void CClaimTrie::BatchWriteSupportExpirationQueueRows(CLevelDBBatch& batch) +{ + for (supportQueueType::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() { CLevelDBBatch batch(&db.GetObfuscateKey()); @@ -1711,7 +1755,7 @@ bool CClaimTrieCache::addSupportToQueues(const std::string& name, CSupportValue& supportQueueNamesType::iterator itQueueNameRow = getSupportQueueCacheNameRow(name, true); itQueueRow->second.push_back(entry); itQueueNameRow->second.push_back(support); - //addSupportToExpirationQueue(entry); + addSupportToExpirationQueue(entry); return true; } @@ -1784,7 +1828,7 @@ bool CClaimTrieCache::undoSpendSupport(const std::string& name, const COutPoint& if (nValidAtHeight < nCurrentHeight) { supportQueueEntryType entry(name, support); - //addSupportToExpirationQueue(entry); + addSupportToExpirationQueue(entry); return insertSupportIntoMap(name, support, false); } else @@ -1802,18 +1846,21 @@ bool CClaimTrieCache::removeSupport(const std::string& name, const COutPoint& ou if (removed == false && removeSupportFromMap(name, outPoint, support, fCheckTakeover)) removed = true; if (removed) + { + removeSupportFromExpirationQueue(name, outPoint, nHeight); nValidAtHeight = support.nValidAtHeight; + } return removed; } -/*void CClaimTrieCache::addSupportToExpirationQueue(supportQueueEntryType& entry) const +void CClaimTrieCache::addSupportToExpirationQueue(supportQueueEntryType& entry) const { int expirationHeight = entry.second.nHeight + base->nExpirationTime; supportQueueType::iterator itQueueRow = getSupportExpirationQueueCacheRow(expirationHeight, true); 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 nHeight) const { int expirationHeight = nHeight + base->nExpirationTime; supportQueueType::iterator itQueueRow = getSupportExpirationQueueCacheRow(expirationHeight, false); @@ -1831,9 +1878,9 @@ bool CClaimTrieCache::removeSupport(const std::string& name, const COutPoint& ou { itQueueRow->second.erase(itQueue); } -}*/ +} -/*supportQueueType::iterator CClaimTrieCache::getSupportExpirationQueueCacheRow(int nHeight, bool createIfNotExists) const +supportQueueType::iterator CClaimTrieCache::getSupportExpirationQueueCacheRow(int nHeight, bool createIfNotExists) const { supportQueueType::iterator itQueueRow = supportExpirationQueueCache.find(nHeight); if (itQueueRow == supportExpirationQueueCache.end()) @@ -1852,7 +1899,7 @@ bool CClaimTrieCache::removeSupport(const std::string& name, const COutPoint& ou itQueueRow = ret.first; } return itQueueRow; -}*/ +} bool CClaimTrieCache::undoAddSupport(const std::string& name, const COutPoint& outPoint, int nHeight) const { @@ -1867,7 +1914,7 @@ bool CClaimTrieCache::spendSupport(const std::string& name, const COutPoint& out return removeSupport(name, outPoint, nHeight, nValidAtHeight, true); } -bool CClaimTrieCache::incrementBlock(claimQueueRowType& insertUndo, claimQueueRowType& expireUndo, supportQueueRowType& insertSupportUndo,/* supportQueueRowType& expireSupportUndo,*/ std::vector >& takeoverHeightUndo) const +bool CClaimTrieCache::incrementBlock(claimQueueRowType& insertUndo, claimQueueRowType& expireUndo, supportQueueRowType& insertSupportUndo, supportQueueRowType& expireSupportUndo, std::vector >& takeoverHeightUndo) const { LogPrintf("%s: nCurrentHeight (before increment): %d\n", __func__, nCurrentHeight); claimQueueType::iterator itQueueRow = getQueueCacheRow(nCurrentHeight, false); @@ -1961,16 +2008,17 @@ bool CClaimTrieCache::incrementBlock(claimQueueRowType& insertUndo, claimQueueRo } itSupportRow->second.clear(); } - /*supportQueueType::iterator itSupportExpirationRow = getSupportExpirationQueueCacheRow(nCurrentHeight, false); + supportQueueType::iterator itSupportExpirationRow = getSupportExpirationQueueCacheRow(nCurrentHeight, false); if (itSupportExpirationRow != supportExpirationQueueCache.end()) { for (supportQueueRowType::iterator itEntry = itSupportExpirationRow->second.begin(); itEntry != itSupportExpirationRow->second.end(); ++itEntry) { - int nValidAtHeight; - assert(removeSupportFromMap(itEntry->first, itEntry->second.outPoint, nValidAtHeight, true)); - supportExpireUndo.push_back(*itEntry); + CSupportValue support; + assert(removeSupportFromMap(itEntry->first, itEntry->second.outPoint, support, true)); + expireSupportUndo.push_back(std::make_pair(itEntry->first, support)); } - }*/ + itSupportExpirationRow->second.clear(); + } // check each potentially taken over name to see if a takeover occurred. // if it did, then check the claim and support insertion queues for // the names that have been taken over, immediately insert all claim and @@ -2126,7 +2174,7 @@ bool CClaimTrieCache::incrementBlock(claimQueueRowType& insertUndo, claimQueueRo return true; } -bool CClaimTrieCache::decrementBlock(claimQueueRowType& insertUndo, claimQueueRowType& expireUndo, supportQueueRowType& insertSupportUndo, std::vector >& takeoverHeightUndo) const +bool CClaimTrieCache::decrementBlock(claimQueueRowType& insertUndo, claimQueueRowType& expireUndo, supportQueueRowType& insertSupportUndo, supportQueueRowType& expireSupportUndo, std::vector >& takeoverHeightUndo) const { LogPrintf("%s: nCurrentHeight (before decrement): %d\n", __func__, nCurrentHeight); nCurrentHeight--; @@ -2157,6 +2205,15 @@ bool CClaimTrieCache::decrementBlock(claimQueueRowType& insertUndo, claimQueueRo itSupportRow->second.push_back(*itSupportUndo); itSupportNameRow->second.push_back(itSupportUndo->second); } + if (expireSupportUndo.begin() != expireSupportUndo.end()) + { + supportQueueType::iterator itSupportExpireRow = getSupportExpirationQueueCacheRow(nCurrentHeight, true); + for (supportQueueRowType::iterator itSupportExpireUndo = expireSupportUndo.begin(); itSupportExpireUndo != expireSupportUndo.end(); ++itSupportExpireUndo) + { + insertSupportIntoMap(itSupportExpireUndo->first, itSupportExpireUndo->second, false); + itSupportExpireRow->second.push_back(*itSupportExpireUndo); + } + } for (std::vector >::iterator itTakeoverHeightUndo = takeoverHeightUndo.begin(); itTakeoverHeightUndo != takeoverHeightUndo.end(); ++itTakeoverHeightUndo) { @@ -2241,7 +2298,7 @@ bool CClaimTrieCache::flush() { if (dirty()) getMerkleHash(); - bool success = base->update(cache, cacheHashes, cacheTakeoverHeights, getBestBlock(), claimQueueCache, claimQueueNameCache, expirationQueueCache, nCurrentHeight, supportCache, supportQueueCache, supportQueueNameCache); + bool success = base->update(cache, cacheHashes, cacheTakeoverHeights, getBestBlock(), claimQueueCache, claimQueueNameCache, expirationQueueCache, nCurrentHeight, supportCache, supportQueueCache, supportQueueNameCache, supportExpirationQueueCache); if (success) { success = clear(); diff --git a/src/claimtrie.h b/src/claimtrie.h index 4b4f78f7c..54bdd344d 100644 --- a/src/claimtrie.h +++ b/src/claimtrie.h @@ -20,7 +20,8 @@ #define EXP_QUEUE_ROW 'e' #define SUPPORT 's' #define SUPPORT_QUEUE_ROW 'u' -#define SUPPORT_QUEUE_NAME_ROW 'p' +#define SUPPORT_QUEUE_NAME_ROW 'p' +#define SUPPORT_EXP_QUEUE_ROW 'x' class CClaimValue { @@ -267,8 +268,8 @@ private: claimQueueType& expirationQueueCache, int nNewHeight, supportMapType& supportCache, supportQueueType& supportQueueCache, - supportQueueNamesType& supportQueueNameCache);//, - //supportQueueType& supportExpirationQueueCache); + supportQueueNamesType& supportQueueNameCache, + supportQueueType& supportExpirationQueueCache); bool updateName(const std::string& name, CClaimTrieNode* updatedNode); bool updateHash(const std::string& name, uint256& hash); bool updateTakeoverHeight(const std::string& name, int nTakeoverHeight); @@ -295,7 +296,7 @@ private: void updateSupportQueue(int nHeight, supportQueueRowType& row); void updateSupportNameQueue(const std::string& name, std::vector& row); - void updateSupportExpirationRow(int nHeight, supportQueueRowType& row); + void updateSupportExpirationQueue(int nHeight, supportQueueRowType& row); void BatchWriteNode(CLevelDBBatch& batch, const std::string& name, const CClaimTrieNode* pNode) const; @@ -368,12 +369,12 @@ public: bool incrementBlock(claimQueueRowType& insertUndo, claimQueueRowType& expireUndo, supportQueueRowType& insertSupportUndo, -// supportQueueRowType& expireSupportUndo, + supportQueueRowType& expireSupportUndo, std::vector >& takeoverHeightUndo) const; bool decrementBlock(claimQueueRowType& insertUndo, claimQueueRowType& expireUndo, supportQueueRowType& insertSupportUndo, -// supportQueueRowType& expireSupportUndo, + supportQueueRowType& expireSupportUndo, std::vector >& takeoverHeightUndo) const; ~CClaimTrieCache() { clear(); } diff --git a/src/main.cpp b/src/main.cpp index 12c0c3947..71fbf24e0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1611,7 +1611,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI if (blockUndo.vtxundo.size() + 1 != block.vtx.size()) return error("DisconnectBlock(): block and undo data inconsistent"); - assert(trieCache.decrementBlock(blockUndo.insertUndo, blockUndo.expireUndo, blockUndo.insertSupportUndo, blockUndo.takeoverHeightUndo)); + assert(trieCache.decrementBlock(blockUndo.insertUndo, blockUndo.expireUndo, blockUndo.insertSupportUndo, blockUndo.expireSupportUndo, blockUndo.takeoverHeightUndo)); // undo transactions in reverse order for (int i = block.vtx.size() - 1; i >= 0; i--) { @@ -2067,7 +2067,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); } - assert(trieCache.incrementBlock(blockundo.insertUndo, blockundo.expireUndo, blockundo.insertSupportUndo, blockundo.takeoverHeightUndo)); + assert(trieCache.incrementBlock(blockundo.insertUndo, blockundo.expireUndo, blockundo.insertSupportUndo, blockundo.expireSupportUndo, blockundo.takeoverHeightUndo)); if (trieCache.getMerkleHash() != block.hashClaimTrie) return state.DoS(100, diff --git a/src/miner.cpp b/src/miner.cpp index 917334b4d..25f9da817 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -467,8 +467,9 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) claimQueueRowType dummyInsertUndo; claimQueueRowType dummyExpireUndo; supportQueueRowType dummyInsertSupportUndo; + supportQueueRowType dummyExpireSupportUndo; std::vector > dummyTakeoverHeightUndo; - trieCache.incrementBlock(dummyInsertUndo, dummyExpireUndo, dummyInsertSupportUndo, dummyTakeoverHeightUndo); + trieCache.incrementBlock(dummyInsertUndo, dummyExpireUndo, dummyInsertSupportUndo, dummyExpireSupportUndo, dummyTakeoverHeightUndo); pblock->hashClaimTrie = trieCache.getMerkleHash(); CValidationState state; diff --git a/src/test/claimtrie_tests.cpp b/src/test/claimtrie_tests.cpp index 07a499c54..60f720e04 100644 --- a/src/test/claimtrie_tests.cpp +++ b/src/test/claimtrie_tests.cpp @@ -2029,6 +2029,246 @@ BOOST_AUTO_TEST_CASE(claimtrie_supporting_claims2) BOOST_CHECK(pclaimTrie->supportQueueEmpty()); } +BOOST_AUTO_TEST_CASE(claimtrie_expiring_supports) +{ + BOOST_CHECK(pclaimTrie->nCurrentHeight = chainActive.Height() + 1); + + LOCK(cs_main); + + std::string sName("atest"); + std::string sValue1("testa"); + std::string sValue2("testb"); + + std::vector vchName(sName.begin(), sName.end()); + std::vector vchValue1(sValue1.begin(), sValue1.end()); + std::vector vchValue2(sValue2.begin(), sValue2.end()); + + std::vector coinbases; + + BOOST_CHECK(CreateCoinbases(3, coinbases)); + + CMutableTransaction tx1 = BuildTransaction(coinbases[0]); + tx1.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName << vchValue1 << OP_2DROP << OP_DROP << OP_TRUE; + tx1.vout[0].nValue = 100000000; + COutPoint tx1OutPoint(tx1.GetHash(), 0); + + CMutableTransaction tx2 = BuildTransaction(coinbases[1]); + tx2.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName << vchValue2 << OP_2DROP << OP_DROP << OP_TRUE; + tx2.vout[0].nValue = 500000000; + COutPoint tx2OutPoint(tx2.GetHash(), 0); + + CMutableTransaction tx3 = BuildTransaction(coinbases[2]); + uint160 tx1ClaimId = ClaimIdHash(tx1.GetHash(), 0); + std::vector vchTx1ClaimId(tx1ClaimId.begin(), tx1ClaimId.end()); + tx3.vout[0].scriptPubKey = CScript() << OP_SUPPORT_CLAIM << vchName << vchTx1ClaimId << OP_2DROP << OP_DROP << OP_TRUE; + tx3.vout[0].nValue = 500000000; + COutPoint tx3OutPoint(tx3.GetHash(), 0); + + CMutableTransaction tx4 = BuildTransaction(tx1); + tx4.vout[0].scriptPubKey = CScript() << OP_UPDATE_CLAIM << vchName << vchTx1ClaimId << vchValue1 << OP_2DROP << OP_2DROP << OP_TRUE; + COutPoint tx4OutPoint(tx4.GetHash(), 0); + + CMutableTransaction tx5 = BuildTransaction(tx3); + tx5.vout[0].scriptPubKey = CScript() << OP_TRUE; + COutPoint tx5OutPoint(tx5.GetHash(), 0); + + CClaimValue val; + std::vector blocks_to_invalidate; + + pclaimTrie->setExpirationTime(200); + + // Verify that supports expire + + // Create a 1 LBC claim (tx1) + + AddToMempool(tx1); + + BOOST_CHECK(CreateBlocks(1, 2)); + blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); + + BOOST_CHECK(pcoinsTip->HaveCoins(tx1.GetHash())); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + // Create a 5 LBC support (tx3) + + AddToMempool(tx3); + + BOOST_CHECK(CreateBlocks(1, 2)); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + // Advance some, then insert 5 LBC claim (tx2) + + BOOST_CHECK(CreateBlocks(49, 1)); + + AddToMempool(tx2); + + BOOST_CHECK(CreateBlocks(1, 2)); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + // Advance until tx2 is valid + + BOOST_CHECK(CreateBlocks(50, 1)); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + BOOST_CHECK(CreateBlocks(1, 1)); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint == tx1OutPoint); + + // Update tx1 so that it expires after tx3 expires + + AddToMempool(tx4); + + BOOST_CHECK(CreateBlocks(1, 2)); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint == tx4OutPoint); + + // Advance until the support expires + + BOOST_CHECK(CreateBlocks(50, 1)); + + blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); + + BOOST_CHECK(CreateBlocks(47, 1)); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + BOOST_CHECK(CreateBlocks(1, 1)); + blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint == tx2OutPoint); + + // undo the block, make sure control goes back + + BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); + blocks_to_invalidate.pop_back(); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint == tx4OutPoint); + + // redo the block, make sure it expires again + + BOOST_CHECK(CreateBlocks(1, 1)); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint == tx2OutPoint); + + // roll back some, spend the support, and make sure nothing unexpected + // happens at the time the support should have expired + + BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); + blocks_to_invalidate.pop_back(); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint == tx4OutPoint); + + AddToMempool(tx5); + + BOOST_CHECK(CreateBlocks(1, 2)); + + blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint == tx2OutPoint); + + BOOST_CHECK(CreateBlocks(50, 1)); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint == tx2OutPoint); + + //undo the spend, and make sure it still expires on time + + BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); + blocks_to_invalidate.pop_back(); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint == tx4OutPoint); + + BOOST_CHECK(CreateBlocks(48, 1)); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint == tx4OutPoint); + + BOOST_CHECK(CreateBlocks(1, 1)); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint == tx2OutPoint); + + // roll all the way back + + BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); + blocks_to_invalidate.pop_back(); + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); +} + BOOST_AUTO_TEST_CASE(claimtrienode_serialize_unserialize) { CDataStream ss(SER_DISK, 0); diff --git a/src/undo.h b/src/undo.h index 313671d1c..923cd223e 100644 --- a/src/undo.h +++ b/src/undo.h @@ -86,7 +86,8 @@ public: std::vector vtxundo; // for all but the coinbase claimQueueRowType insertUndo; // any claims that went from the queue to the trie claimQueueRowType expireUndo; // any claims that expired - supportQueueRowType insertSupportUndo; // any claims that went from the support queue to the support map + supportQueueRowType insertSupportUndo; // any supports that went from the support queue to the support map + supportQueueRowType expireSupportUndo; // any supports that expired std::vector > takeoverHeightUndo; // for any name that was taken over, the previous time that name was taken over ADD_SERIALIZE_METHODS; @@ -97,6 +98,7 @@ public: READWRITE(insertUndo); READWRITE(expireUndo); READWRITE(insertSupportUndo); + READWRITE(expireSupportUndo); READWRITE(takeoverHeightUndo); } };