From 966e7386d99bf6c3d3867468bcfa4659bad62321 Mon Sep 17 00:00:00 2001 From: Anthony Fieroni Date: Tue, 9 Jul 2019 18:02:54 +0300 Subject: [PATCH] Fix expiration fork usage Signed-off-by: Anthony Fieroni --- src/claimscriptop.cpp | 87 ++++++++++++++++---------- src/claimscriptop.h | 25 +++----- src/claimtrie.cpp | 30 ++++----- src/claimtrie.h | 29 ++++++--- src/claimtrieforks.cpp | 48 +++++++++++++- src/init.cpp | 3 - src/miner.cpp | 90 +++++++++++---------------- src/miner.h | 2 +- src/test/claimtriebranching_tests.cpp | 20 +++--- src/validation.cpp | 53 +++------------- 10 files changed, 196 insertions(+), 191 deletions(-) diff --git a/src/claimscriptop.cpp b/src/claimscriptop.cpp index 3af804fe2..837ea23f3 100644 --- a/src/claimscriptop.cpp +++ b/src/claimscriptop.cpp @@ -2,8 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "claimscriptop.h" -#include "nameclaim.h" +#include +#include +#include CClaimScriptAddOp::CClaimScriptAddOp(const COutPoint& point, CAmount nValue, int nHeight) : point(point), nValue(nValue), nHeight(nHeight) @@ -153,59 +154,81 @@ bool ProcessClaim(CClaimScriptOp& claimOp, CClaimTrieCache& trieCache, const CSc throw std::runtime_error("Unimplemented OP handler."); } -bool SpendClaim(CClaimTrieCache& trieCache, const CScript& scriptPubKey, const COutPoint& point, int nHeight, int& nValidHeight, spentClaimsType& spentClaims) +void UpdateCache(const CTransaction& tx, CClaimTrieCache& trieCache, const CCoinsViewCache& view, int nHeight, const CUpdateCacheCallbacks& callbacks) { class CSpendClaimHistory : public CClaimScriptSpendOp { public: - CSpendClaimHistory(spentClaimsType& spentClaims, const COutPoint& point, int nHeight, int& nValidHeight) - : CClaimScriptSpendOp(point, nHeight, nValidHeight), spentClaims(spentClaims) - { - } + using CClaimScriptSpendOp::CClaimScriptSpendOp; bool spendClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId) override { if (CClaimScriptSpendOp::spendClaim(trieCache, name, claimId)) { - spentClaims.emplace_back(name, claimId); + callback(name, claimId); return true; } return false; } - - private: - spentClaimsType& spentClaims; + std::function callback; }; - CSpendClaimHistory spendClaim(spentClaims, point, nHeight, nValidHeight); - return ProcessClaim(spendClaim, trieCache, scriptPubKey); -} + spentClaimsType spentClaims; + + for (std::size_t j = 0; j < tx.vin.size(); j++) { + const CTxIn& txin = tx.vin[j]; + const Coin& coin = view.AccessCoin(txin.prevout); + + CScript scriptPubKey; + int scriptHeight = nHeight; + if (coin.out.IsNull() && callbacks.findScriptKey) { + scriptPubKey = callbacks.findScriptKey(txin.prevout); + } else { + scriptHeight = coin.nHeight; + scriptPubKey = coin.out.scriptPubKey; + } + + if (scriptPubKey.empty()) + continue; + + int nValidAtHeight; + CSpendClaimHistory spendClaim(COutPoint(txin.prevout.hash, txin.prevout.n), scriptHeight, nValidAtHeight); + spendClaim.callback = [&spentClaims](const std::string& name, const uint160& claimId) { + spentClaims.emplace_back(name, claimId); + }; + if (ProcessClaim(spendClaim, trieCache, scriptPubKey) && callbacks.claimUndoHeights) + callbacks.claimUndoHeights(j, nValidAtHeight); + } -bool AddSpendClaim(CClaimTrieCache& trieCache, const CScript& scriptPubKey, const COutPoint& point, CAmount nValue, int nHeight, spentClaimsType& spentClaims) -{ class CAddSpendClaim : public CClaimScriptAddOp { public: - CAddSpendClaim(spentClaimsType& spentClaims, const COutPoint& point, CAmount nValue, int nHeight) - : CClaimScriptAddOp(point, nValue, nHeight), spentClaims(spentClaims) - { - } + using CClaimScriptAddOp::CClaimScriptAddOp; bool updateClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId) override { - spentClaimsType::iterator itSpent = spentClaims.begin(); - for (; itSpent != spentClaims.end(); ++itSpent) { + if (callback(name, claimId)) + return CClaimScriptAddOp::updateClaim(trieCache, name, claimId); + return false; + } + std::function callback; + }; + + for (std::size_t j = 0; j < tx.vout.size(); j++) { + const CTxOut& txout = tx.vout[j]; + + if (txout.scriptPubKey.empty()) + continue; + + CAddSpendClaim addClaim(COutPoint(tx.GetHash(), j), txout.nValue, nHeight); + addClaim.callback = [&trieCache, &spentClaims](const std::string& name, const uint160& claimId) -> bool { + for (auto itSpent = spentClaims.begin(); itSpent != spentClaims.end(); ++itSpent) { if (itSpent->second == claimId && trieCache.normalizeClaimName(name) == trieCache.normalizeClaimName(itSpent->first)) { spentClaims.erase(itSpent); - return CClaimScriptAddOp::updateClaim(trieCache, name, claimId); + return true; } } return false; - } - - private: - spentClaimsType& spentClaims; - }; - - CAddSpendClaim addClaim(spentClaims, point, nValue, nHeight); - return ProcessClaim(addClaim, trieCache, scriptPubKey); -} \ No newline at end of file + }; + ProcessClaim(addClaim, trieCache, txout.scriptPubKey); + } +} diff --git a/src/claimscriptop.h b/src/claimscriptop.h index 0502093dc..7fc93048a 100644 --- a/src/claimscriptop.h +++ b/src/claimscriptop.h @@ -225,26 +225,21 @@ typedef std::pair spentClaimType; typedef std::vector spentClaimsType; +struct CUpdateCacheCallbacks +{ + std::function findScriptKey; + std::function claimUndoHeights; +}; + /** * Function to spend claim from tie, keeping the successful list on + * @param[in] tx transaction inputs/outputs * @param[in] trieCache trie to operate on - * @param[in] scriptPubKey claim script to be decoded + * @param[in] view coins cache * @param[in] point pair of transaction hash and its index * @param[in] nHeight entry height of the claim - * @param[out] nValidHeight valid height of the claim - * @param[out] spentClaims inserts successfully spent claim + * @param[out] fallback optional callbacks */ -bool SpendClaim(CClaimTrieCache& trieCache, const CScript& scriptPubKey, const COutPoint& point, int nHeight, int& nValidHeight, spentClaimsType& spentClaims); - -/** - * Function to add / update (that present in spent list) claim in trie - * @param[in] trieCache trie to operate on - * @param[in] scriptPubKey claim script to be decoded - * @param[in] point pair of transaction hash and its index - * @param[in] nValue ` value of the claim - * @param[in] nHeight entry height of the claim - * @param[out] spentClaims erases successfully added claim - */ -bool AddSpendClaim(CClaimTrieCache& trieCache, const CScript& scriptPubKey, const COutPoint& point, CAmount nValue, int nHeight, spentClaimsType& spentClaims); +void UpdateCache(const CTransaction& tx, CClaimTrieCache& trieCache, const CCoinsViewCache& view, int nHeight, const CUpdateCacheCallbacks& callbacks = {}); #endif // CLAIMSCRIPTOP_H diff --git a/src/claimtrie.cpp b/src/claimtrie.cpp index db6c53377..dc072c6c1 100644 --- a/src/claimtrie.cpp +++ b/src/claimtrie.cpp @@ -92,7 +92,6 @@ void CClaimTrieData::reorderClaims(const supportEntryType& supports) CClaimTrie::CClaimTrie(bool fMemory, bool fWipe, int proportionalDelayFactor) { nProportionalDelayFactor = proportionalDelayFactor; - nExpirationTime = Params().GetConsensus().nOriginalClaimExpirationTime; db.reset(new CDBWrapper(GetDataDir() / "claimtrie", 100 * 1024 * 1024, fMemory, fWipe, false)); } @@ -469,9 +468,7 @@ bool CClaimTrieCacheBase::ReadFromDisk(const CBlockIndex* tip) { LogPrintf("Loading the claim trie from disk...\n"); - nNextHeight = tip ? tip->nHeight + 1 : 0; - base->nNextHeight = nNextHeight; - base->nExpirationTime = Params().GetConsensus().GetExpirationTime(nNextHeight - 1); // -1 okay + base->nNextHeight = nNextHeight = tip ? tip->nHeight + 1 : 0; clear(); base->clear(); @@ -532,14 +529,9 @@ CClaimTrieCacheBase::CClaimTrieCacheBase(CClaimTrie* base, bool fRequireTakeover nNextHeight = base->nNextHeight; } -void CClaimTrieCacheBase::setExpirationTime(int time) +int CClaimTrieCacheBase::expirationTime() const { - base->nExpirationTime = time; -} - -int CClaimTrieCacheBase::expirationTime() -{ - return base->nExpirationTime; + return Params().GetConsensus().nOriginalClaimExpirationTime; } uint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(CClaimTrie::iterator& it) @@ -726,7 +718,7 @@ bool CClaimTrieCacheBase::undoSpendClaim(const std::string& name, const COutPoin CClaimValue claim(outPoint, claimId, nAmount, nHeight, nValidAtHeight); if (nValidAtHeight < nNextHeight) { CNameOutPointType entry(adjustNameForValidHeight(name, nValidAtHeight), claim.outPoint); - addToExpirationQueue(claim.nHeight + base->nExpirationTime, entry); + addToExpirationQueue(claim.nHeight + expirationTime(), entry); CClaimIndexElement element = {name, claim}; claimsToAdd.push_back(element); return insertClaimIntoTrie(name, claim, false); @@ -745,7 +737,7 @@ bool CClaimTrieCacheBase::addClaimToQueues(const std::string& name, const CClaim itQueueRow->second.push_back(entry); itQueueNameRow->second.emplace_back(claim.outPoint, claim.nValidAtHeight); CNameOutPointType expireEntry(name, claim.outPoint); - addToExpirationQueue(claim.nHeight + base->nExpirationTime, expireEntry); + addToExpirationQueue(claim.nHeight + expirationTime(), expireEntry); return true; } @@ -798,7 +790,7 @@ bool CClaimTrieCacheBase::removeClaim(const std::string& name, const COutPoint& std::string adjusted = adjustNameForValidHeight(name, nValidAtHeight); if (removeClaimFromQueue(adjusted, outPoint, claim) || removeClaimFromTrie(name, outPoint, claim, fCheckTakeover)) { - int expirationHeight = claim.nHeight + base->nExpirationTime; + int expirationHeight = claim.nHeight + expirationTime(); removeFromExpirationQueue(adjusted, outPoint, expirationHeight); claimsToDelete.insert(claim); nValidAtHeight = claim.nValidAtHeight; @@ -880,7 +872,7 @@ bool CClaimTrieCacheBase::addSupportToQueues(const std::string& name, const CSup itQueueRow->second.push_back(entry); itQueueNameRow->second.emplace_back(support.outPoint, support.nValidAtHeight); CNameOutPointType expireEntry(name, support.outPoint); - addSupportToExpirationQueue(support.nHeight + base->nExpirationTime, expireEntry); + addSupportToExpirationQueue(support.nHeight + expirationTime(), expireEntry); return true; } @@ -929,7 +921,7 @@ bool CClaimTrieCacheBase::undoSpendSupport(const std::string& name, const COutPo CSupportValue support(outPoint, supportedClaimId, nAmount, nHeight, nValidAtHeight); if (nValidAtHeight < nNextHeight) { CNameOutPointType entry(adjustNameForValidHeight(name, nValidAtHeight), support.outPoint); - addSupportToExpirationQueue(support.nHeight + base->nExpirationTime, entry); + addSupportToExpirationQueue(support.nHeight + expirationTime(), entry); return insertSupportIntoMap(name, support, false); } else { return addSupportToQueues(name, support); @@ -943,7 +935,7 @@ bool CClaimTrieCacheBase::removeSupport(const std::string& name, const COutPoint std::string adjusted = adjustNameForValidHeight(name, nValidAtHeight); if (removeSupportFromQueue(adjusted, outPoint, support) || removeSupportFromMap(name, outPoint, support, fCheckTakeover)) { - int expirationHeight = support.nHeight + base->nExpirationTime; + int expirationHeight = support.nHeight + expirationTime(); removeSupportFromExpirationQueue(adjusted, outPoint, expirationHeight); nValidAtHeight = support.nValidAtHeight; return true; @@ -1244,7 +1236,7 @@ bool CClaimTrieCacheBase::decrementBlock(insertUndoType& insertUndo, claimQueueR if (!expireSupportUndo.empty()) { for (auto itSupportExpireUndo = expireSupportUndo.crbegin(); itSupportExpireUndo != expireSupportUndo.crend(); ++itSupportExpireUndo) { insertSupportIntoMap(itSupportExpireUndo->first, itSupportExpireUndo->second, false); - if (nNextHeight == itSupportExpireUndo->second.nHeight + base->nExpirationTime) { + if (nNextHeight == itSupportExpireUndo->second.nHeight + expirationTime()) { auto itSupportExpireRow = getSupportExpirationQueueCacheRow(nNextHeight, true); itSupportExpireRow->second.emplace_back(itSupportExpireUndo->first, itSupportExpireUndo->second.outPoint); } @@ -1270,7 +1262,7 @@ bool CClaimTrieCacheBase::decrementBlock(insertUndoType& insertUndo, claimQueueR insertClaimIntoTrie(itExpireUndo->first, itExpireUndo->second, false); CClaimIndexElement element = {itExpireUndo->first, itExpireUndo->second}; claimsToAdd.push_back(element); - if (nNextHeight == itExpireUndo->second.nHeight + base->nExpirationTime) { + if (nNextHeight == itExpireUndo->second.nHeight + expirationTime()) { auto itExpireRow = getExpirationQueueCacheRow(nNextHeight, true); itExpireRow->second.emplace_back(itExpireUndo->first, itExpireUndo->second.outPoint); } diff --git a/src/claimtrie.h b/src/claimtrie.h index 5c5af60fd..8805d1db9 100644 --- a/src/claimtrie.h +++ b/src/claimtrie.h @@ -302,7 +302,6 @@ struct CClaimsForNameType class CClaimTrie : public CPrefixTrie { int nNextHeight = 0; - int nExpirationTime = 0; int nProportionalDelayFactor = 0; std::unique_ptr db; @@ -434,6 +433,8 @@ public: virtual bool getProofForName(const std::string& name, CClaimTrieProof& proof); virtual bool getInfoForName(const std::string& name, CClaimValue& claim) const; + virtual int expirationTime() const; + bool finalizeDecrement(std::vector>& takeoverHeightUndo); virtual CClaimsForNameType getClaimsForName(const std::string& name) const; @@ -441,9 +442,6 @@ public: CAmount getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector* supports = nullptr) const; CAmount getEffectiveAmountForClaim(const CClaimsForNameType& claims, const uint160& claimId, std::vector* supports = nullptr) const; - void setExpirationTime(int time); - int expirationTime(); - CClaimTrie::const_iterator begin() const; CClaimTrie::const_iterator end() const; CClaimTrie::const_iterator find(const std::string& name) const; @@ -539,16 +537,27 @@ private: class CClaimTrieCacheExpirationFork : public CClaimTrieCacheBase { public: - explicit CClaimTrieCacheExpirationFork(CClaimTrie* base, bool fRequireTakeoverHeights = true) - : CClaimTrieCacheBase(base, fRequireTakeoverHeights) - { - } + explicit CClaimTrieCacheExpirationFork(CClaimTrie* base, bool fRequireTakeoverHeights = true); - bool forkForExpirationChange(bool increment); + void setExpirationTime(int time); + int expirationTime() const override; - // TODO: move the expiration fork code from main.cpp to overrides of increment/decrement block + void expirationForkActive(int height, bool increment); + + bool incrementBlock(insertUndoType& insertUndo, + claimQueueRowType& expireUndo, + insertUndoType& insertSupportUndo, + supportQueueRowType& expireSupportUndo, + std::vector>& takeoverHeightUndo) override; + + bool decrementBlock(insertUndoType& insertUndo, + claimQueueRowType& expireUndo, + insertUndoType& insertSupportUndo, + supportQueueRowType& expireSupportUndo) override; private: + int nExpirationTime; + bool forkForExpirationChange(bool increment); void removeAndAddSupportToExpirationQueue(expirationQueueRowType& row, int height, bool increment); void removeAndAddToExpirationQueue(expirationQueueRowType& row, int height, bool increment); }; diff --git a/src/claimtrieforks.cpp b/src/claimtrieforks.cpp index d8cec6198..b3d4cb58b 100644 --- a/src/claimtrieforks.cpp +++ b/src/claimtrieforks.cpp @@ -1,4 +1,6 @@ -#include "claimtrie.h" + +#include +#include #include #include @@ -7,6 +9,46 @@ #include #include +CClaimTrieCacheExpirationFork::CClaimTrieCacheExpirationFork(CClaimTrie* base, bool fRequireTakeoverHeights) + : CClaimTrieCacheBase(base, fRequireTakeoverHeights) +{ + setExpirationTime(Params().GetConsensus().GetExpirationTime(nNextHeight)); +} + +void CClaimTrieCacheExpirationFork::setExpirationTime(int time) +{ + nExpirationTime = time; +} + +int CClaimTrieCacheExpirationFork::expirationTime() const +{ + return nExpirationTime; +} + +bool CClaimTrieCacheExpirationFork::incrementBlock(insertUndoType& insertUndo, claimQueueRowType& expireUndo, insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo, std::vector>& takeoverHeightUndo) +{ + if (CClaimTrieCacheBase::incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverHeightUndo)) { + setExpirationTime(Params().GetConsensus().GetExpirationTime(nNextHeight)); + return true; + } + return false; +} + +bool CClaimTrieCacheExpirationFork::decrementBlock(insertUndoType& insertUndo, claimQueueRowType& expireUndo, insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo) +{ + if (CClaimTrieCacheBase::decrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo)) { + setExpirationTime(Params().GetConsensus().GetExpirationTime(nNextHeight)); + return true; + } + return false; +} + +void CClaimTrieCacheExpirationFork::expirationForkActive(int nHeight, bool increment) +{ + if (nHeight == Params().GetConsensus().nExtendedClaimExpirationForkHeight) + forkForExpirationChange(increment); +} + void CClaimTrieCacheExpirationFork::removeAndAddToExpirationQueue(expirationQueueRowType& row, int height, bool increment) { for (auto e = row.begin(); e != row.end(); ++e) { @@ -150,7 +192,7 @@ bool CClaimTrieCacheNormalizationFork::normalizeAllNamesInTrieIfNecessary(insert auto supports = getSupportsForName(it.key()); for (auto& support : supports) { // if it's already going to expire just skip it - if (support.nHeight + base->nExpirationTime <= nNextHeight) + if (support.nHeight + expirationTime() <= nNextHeight) continue; CSupportValue removed; @@ -167,7 +209,7 @@ bool CClaimTrieCacheNormalizationFork::normalizeAllNamesInTrieIfNecessary(insert continue; for (auto& claim : it->claims) { - if (claim.nHeight + base->nExpirationTime <= nNextHeight) + if (claim.nHeight + expirationTime() <= nNextHeight) continue; CClaimValue removed; diff --git a/src/init.cpp b/src/init.cpp index 069cd1fae..26408bd79 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1702,9 +1702,6 @@ bool AppInitMain() } LogPrintf("nBestHeight = %d\n", chain_active_height); - const Consensus::Params& consensusParams = Params().GetConsensus(); - CClaimTrieCache(pclaimTrie).setExpirationTime(consensusParams.GetExpirationTime(chain_active_height)); - if (gArgs.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) StartTorControl(); diff --git a/src/miner.cpp b/src/miner.cpp index 7a6f392a1..dcfd3c6b8 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -53,6 +53,35 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam return nNewTime - nOldTime; } +void blockToCache(const CBlock* pblock, CClaimTrieCache& trieCache, int nHeight) +{ + insertUndoType dummyInsertUndo; + claimQueueRowType dummyExpireUndo; + insertUndoType dummyInsertSupportUndo; + supportQueueRowType dummyExpireSupportUndo; + std::vector > dummyTakeoverHeightUndo; + + CUpdateCacheCallbacks callbacks = { + .findScriptKey = [&pblock](const COutPoint& point) { + for (auto& tx : pblock->vtx) + if (tx->GetHash() == point.hash && point.n < tx->vout.size()) + return tx->vout[point.n].scriptPubKey; + return CScript{}; + }, + .claimUndoHeights = {} + }; + + trieCache.expirationForkActive(nHeight, true); + + CCoinsViewCache view(pcoinsTip.get()); + + for (auto& tx : pblock->vtx) + if (!tx->IsCoinBase()) + UpdateCache(*tx, trieCache, view, nHeight, callbacks); + + trieCache.incrementBlock(dummyInsertUndo, dummyExpireUndo, dummyInsertSupportUndo, dummyExpireSupportUndo, dummyTakeoverHeightUndo); +} + BlockAssembler::Options::Options() { blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE); nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT; @@ -118,12 +147,6 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc CBlockIndex* pindexPrev = chainActive.Tip(); assert(pindexPrev != nullptr); nHeight = pindexPrev->nHeight + 1; - if (!pclaimTrie) - { - LogPrintf("CreateNewBlock(): pclaimTrie is invalid"); - return NULL; - } - CClaimTrieCache trieCache(pclaimTrie); pblock->nVersion = ComputeBlockVersion(pindexPrev, chainparams.GetConsensus()); // -regtest only: allow overriding block.nVersion with // -blockversion=N to test forking scenarios @@ -150,7 +173,7 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc int nPackagesSelected = 0; int nDescendantsUpdated = 0; - addPackageTxs(nPackagesSelected, nDescendantsUpdated, trieCache); + addPackageTxs(nPackagesSelected, nDescendantsUpdated); int64_t nTime1 = GetTimeMicros(); @@ -178,20 +201,14 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc pblock->nNonce = 0; pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]); - insertUndoType dummyInsertUndo; - claimQueueRowType dummyExpireUndo; - insertUndoType dummyInsertSupportUndo; - supportQueueRowType dummyExpireSupportUndo; - std::vector > dummyTakeoverHeightUndo; - - trieCache.incrementBlock(dummyInsertUndo, dummyExpireUndo, dummyInsertSupportUndo, dummyExpireSupportUndo, dummyTakeoverHeightUndo); - + CClaimTrieCache trieCache(pclaimTrie); + blockToCache(pblock, trieCache, nHeight); pblock->hashClaimTrie = trieCache.getMerkleHash(); CValidationState state; if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) { - // if (trieCache.checkConsistency()) // TODO: bring back after prefixtrie merge - // trieCache.dumpToLog(trieCache.begin()); + if (!trieCache.empty() && trieCache.checkConsistency()) + trieCache.dumpToLog(trieCache.begin()); throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state))); } int64_t nTime2 = GetTimeMicros(); @@ -311,42 +328,6 @@ void BlockAssembler::SortForBlock(const CTxMemPool::setEntries& package, std::ve std::sort(sortedEntries.begin(), sortedEntries.end(), CompareTxIterByAncestorCount()); } -void iterToTrieCache(CTxMemPool::txiter iter, CClaimTrieCache& trieCache, const CTxMemPool::setEntries& entries, int nHeight) -{ - spentClaimsType spentClaims; - auto& tx = iter->GetTx(); - - CCoinsViewCache view(pcoinsTip.get()); - for (const CTxIn& txin: tx.vin) { - const Coin& coin = view.AccessCoin(txin.prevout); - CScript scriptPubKey; - int scriptHeight = nHeight; - if (coin.out.IsNull()) { - for (auto entry : entries) { - auto& e = entry->GetTx(); - if (e.GetHash() != txin.prevout.hash || txin.prevout.n >= e.vout.size()) - continue; - scriptPubKey = e.vout[txin.prevout.n].scriptPubKey; - break; - } - } else { - scriptPubKey = coin.out.scriptPubKey; - scriptHeight = coin.nHeight; - } - - if (!scriptPubKey.empty()) { - int throwaway; - SpendClaim(trieCache, scriptPubKey, COutPoint(txin.prevout.hash, txin.prevout.n), scriptHeight, throwaway, spentClaims); - } - } - - for (unsigned int i = 0; i < tx.vout.size(); ++i) { - const CTxOut& txout = tx.vout[i]; - if (!txout.scriptPubKey.empty()) - AddSpendClaim(trieCache, txout.scriptPubKey, COutPoint(tx.GetHash(), i), txout.nValue, nHeight, spentClaims); - } -} - // This transaction selection algorithm orders the mempool based // on feerate of a transaction including all unconfirmed ancestors. // Since we don't remove transactions from the mempool as we select them @@ -357,7 +338,7 @@ void iterToTrieCache(CTxMemPool::txiter iter, CClaimTrieCache& trieCache, const // Each time through the loop, we compare the best transaction in // mapModifiedTxs with the next transaction in the mempool to decide what // transaction package to work on next. -void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated, CClaimTrieCache& trieCache) +void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated) { // mapModifiedTx will store sorted packages after they are modified // because some of their txs are already in the block @@ -474,7 +455,6 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda SortForBlock(ancestors, sortedEntries); for (size_t i=0; i coinbase_txs; std::vector marks; @@ -86,9 +86,9 @@ struct ClaimTrieChainFixture: public CClaimTrieCacheBase int64_t originalExpiration; int64_t extendedExpiration; - using CClaimTrieCacheBase::getSupportsForName; + using CClaimTrieCacheExpirationFork::getSupportsForName; - ClaimTrieChainFixture(): CClaimTrieCacheBase(pclaimTrie), + ClaimTrieChainFixture(): CClaimTrieCacheExpirationFork(pclaimTrie), unique_block_counter(0), normalization_original(-1), expirationForkHeight(-1) { fRequireStandard = false; @@ -114,14 +114,12 @@ struct ClaimTrieChainFixture: public CClaimTrieCacheBase DecrementBlocks(chainActive.Height()); auto& consensus = const_cast(Params().GetConsensus()); if (normalization_original >= 0) - { consensus.nNormalizedNameForkHeight = normalization_original; - } + if (expirationForkHeight >= 0) { consensus.nExtendedClaimExpirationForkHeight = expirationForkHeight; consensus.nExtendedClaimExpirationTime = extendedExpiration; consensus.nOriginalClaimExpirationTime = originalExpiration; - base->nExpirationTime = originalExpiration; } } @@ -136,7 +134,7 @@ struct ClaimTrieChainFixture: public CClaimTrieCacheBase consensus.nExtendedClaimExpirationForkHeight = target; consensus.nExtendedClaimExpirationTime = postForkExpirationTime; consensus.nOriginalClaimExpirationTime = preForkExpirationTime; - base->nExpirationTime = targetMinusCurrent >= 0 ? preForkExpirationTime : postForkExpirationTime; + setExpirationTime(targetMinusCurrent >= 0 ? preForkExpirationTime : postForkExpirationTime); } void setNormalizationForkHeight(int targetMinusCurrent) { @@ -292,6 +290,7 @@ struct ClaimTrieChainFixture: public CClaimTrieCacheBase num_txs_for_next_block = 0; nNextHeight = chainActive.Height() + 1; } + setExpirationTime(Params().GetConsensus().GetExpirationTime(nNextHeight - 1)); } //disconnect i blocks from tip @@ -306,9 +305,10 @@ struct ClaimTrieChainFixture: public CClaimTrieCacheBase } BOOST_CHECK_EQUAL(state.IsValid(), true); BOOST_CHECK_EQUAL(ActivateBestChain(state, Params()), true); - nNextHeight = chainActive.Height() + 1; mempool.clear(); num_txs_for_next_block = 0; + nNextHeight = chainActive.Height() + 1; + setExpirationTime(Params().GetConsensus().GetExpirationTime(nNextHeight - 1)); } // decrement back to last mark @@ -1157,7 +1157,7 @@ BOOST_AUTO_TEST_CASE(hardfork_claim_test) // make sure decrementing to before the fork height will apppropriately set back the // expiration time to the original expiraiton time fixture.DecrementBlocks(1); - BOOST_CHECK_NE(fixture.expirationTime(), 6); + BOOST_CHECK_EQUAL(fixture.expirationTime(), 3); fixture.IncrementBlocks(1); BOOST_CHECK_EQUAL(fixture.expirationTime(), 6); @@ -1723,7 +1723,7 @@ BOOST_AUTO_TEST_CASE(normalization_does_not_kill_sort_order) BOOST_AUTO_TEST_CASE(normalization_does_not_kill_expirations) { ClaimTrieChainFixture fixture; - fixture.setExpirationTime(3); + fixture.setExpirationForkHeight(800, 3, 800); fixture.setNormalizationForkHeight(4); // need to see that claims expiring on the frame when we normalize aren't kept // need to see that supports expiring on the frame when we normalize aren't kept diff --git a/src/validation.cpp b/src/validation.cpp index cf222980b..faa794c9d 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1575,12 +1575,7 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI assert(merkleHash == pindex->pprev->hashClaimTrie); } - if (pindex->nHeight == Params().GetConsensus().nExtendedClaimExpirationForkHeight) - { - LogPrintf("Decremented past the extended claim expiration hard fork height\n"); - trieCache.setExpirationTime(Params().GetConsensus().GetExpirationTime(pindex->nHeight-1)); - trieCache.forkForExpirationChange(false); - } + trieCache.expirationForkActive(pindex->nHeight, false); return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN; } @@ -1939,13 +1934,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl // Get the script flags for this block unsigned int flags = GetBlockScriptFlags(pindex, chainparams.GetConsensus()); - // v 13 LBRYcrd hard fork to extend expiration time - if (pindex->nHeight == Params().GetConsensus().nExtendedClaimExpirationForkHeight) - { - LogPrintf("Incremented past the extended claim expiration hard fork height\n"); - trieCache.setExpirationTime(chainparams.GetConsensus().GetExpirationTime(pindex->nHeight)); - trieCache.forkForExpirationChange(true); - } + trieCache.expirationForkActive(pindex->nHeight, true); int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1; LogPrint(BCLog::BENCH, " - Fork checks: %.2fms [%.2fs (%.2fms/blk)]\n", MILLI * (nTime2 - nTime1), nTimeForks * MICRO, nTimeForks * MILLI / nBlocksTotal); @@ -2015,35 +2004,13 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl return error("ConnectBlock(): CheckInputs on %s failed with %s", tx.GetHash().ToString(), FormatStateMessage(state)); control.Add(vChecks); - - // To handle claim updates, stick all claims found in the inputs into a map of - // name: (txhash, nOut). When running through the outputs, if any claim's - // name is found in the map, send the name's txhash and nOut to the trie cache, - // and then remove the name: (txhash, nOut) mapping from the map. - // If there are two or more claims in the inputs with the same name, only - // use the first. - - spentClaimsType spentClaims; - - for (unsigned int j = 0; j < tx.vin.size(); j++) - { - const CTxIn& txin = tx.vin[j]; - const Coin& coin = view.AccessCoin(txin.prevout); - - if (coin.out.scriptPubKey.empty()) - continue; - - int nValidAtHeight; - if (SpendClaim(trieCache, coin.out.scriptPubKey, COutPoint(txin.prevout.hash, txin.prevout.n), coin.nHeight, nValidAtHeight, spentClaims)) - mClaimUndoHeights[j] = nValidAtHeight; - } - - for (unsigned int j = 0; j < tx.vout.size(); j++) { - const CTxOut& txout = tx.vout[j]; - - if (!txout.scriptPubKey.empty()) - AddSpendClaim(trieCache, txout.scriptPubKey, COutPoint(tx.GetHash(), j), txout.nValue, pindex->nHeight, spentClaims); - } + CUpdateCacheCallbacks callbacks = { + .findScriptKey = {}, + .claimUndoHeights = [&mClaimUndoHeights](int index, int nValidAtHeight) { + mClaimUndoHeights.emplace(index, nValidAtHeight); + } + }; + UpdateCache(tx, trieCache, view, pindex->nHeight, callbacks); } CTxUndo undoDummy; @@ -2082,7 +2049,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl if (trieCache.getMerkleHash() != block.hashClaimTrie) { - if (trieCache.checkConsistency()) + if (!trieCache.empty() && trieCache.checkConsistency()) trieCache.dumpToLog(trieCache.begin()); return state.DoS(100, error("ConnectBlock() : the merkle root of the claim trie does not match " "(actual=%s vs block=%s on height=%d)", trieCache.getMerkleHash().GetHex(),