Fix expiration fork usage

Signed-off-by: Anthony Fieroni <bvbfan@abv.bg>
This commit is contained in:
Anthony Fieroni 2019-07-09 18:02:54 +03:00
parent 55da76a515
commit 934908c79e
10 changed files with 196 additions and 191 deletions

View file

@ -2,8 +2,9 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "claimscriptop.h" #include <coins.h>
#include "nameclaim.h" #include <claimscriptop.h>
#include <nameclaim.h>
CClaimScriptAddOp::CClaimScriptAddOp(const COutPoint& point, CAmount nValue, int nHeight) CClaimScriptAddOp::CClaimScriptAddOp(const COutPoint& point, CAmount nValue, int nHeight)
: point(point), nValue(nValue), nHeight(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."); 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 class CSpendClaimHistory : public CClaimScriptSpendOp
{ {
public: public:
CSpendClaimHistory(spentClaimsType& spentClaims, const COutPoint& point, int nHeight, int& nValidHeight) using CClaimScriptSpendOp::CClaimScriptSpendOp;
: CClaimScriptSpendOp(point, nHeight, nValidHeight), spentClaims(spentClaims)
{
}
bool spendClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId) override bool spendClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId) override
{ {
if (CClaimScriptSpendOp::spendClaim(trieCache, name, claimId)) { if (CClaimScriptSpendOp::spendClaim(trieCache, name, claimId)) {
spentClaims.emplace_back(name, claimId); callback(name, claimId);
return true; return true;
} }
return false; return false;
} }
std::function<void(const std::string& name, const uint160& claimId)> callback;
private:
spentClaimsType& spentClaims;
}; };
CSpendClaimHistory spendClaim(spentClaims, point, nHeight, nValidHeight); spentClaimsType spentClaims;
return ProcessClaim(spendClaim, trieCache, scriptPubKey);
} 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 class CAddSpendClaim : public CClaimScriptAddOp
{ {
public: public:
CAddSpendClaim(spentClaimsType& spentClaims, const COutPoint& point, CAmount nValue, int nHeight) using CClaimScriptAddOp::CClaimScriptAddOp;
: CClaimScriptAddOp(point, nValue, nHeight), spentClaims(spentClaims)
{
}
bool updateClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId) override bool updateClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId) override
{ {
spentClaimsType::iterator itSpent = spentClaims.begin(); if (callback(name, claimId))
for (; itSpent != spentClaims.end(); ++itSpent) { return CClaimScriptAddOp::updateClaim(trieCache, name, claimId);
return false;
}
std::function<bool(const std::string& name, const uint160& claimId)> 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)) { if (itSpent->second == claimId && trieCache.normalizeClaimName(name) == trieCache.normalizeClaimName(itSpent->first)) {
spentClaims.erase(itSpent); spentClaims.erase(itSpent);
return CClaimScriptAddOp::updateClaim(trieCache, name, claimId); return true;
} }
} }
return false; return false;
} };
ProcessClaim(addClaim, trieCache, txout.scriptPubKey);
private: }
spentClaimsType& spentClaims; }
};
CAddSpendClaim addClaim(spentClaims, point, nValue, nHeight);
return ProcessClaim(addClaim, trieCache, scriptPubKey);
}

View file

@ -225,26 +225,21 @@ typedef std::pair<std::string, uint160> spentClaimType;
typedef std::vector<spentClaimType> spentClaimsType; typedef std::vector<spentClaimType> spentClaimsType;
struct CUpdateCacheCallbacks
{
std::function<CScript(const COutPoint& point)> findScriptKey;
std::function<void(int, int)> claimUndoHeights;
};
/** /**
* Function to spend claim from tie, keeping the successful list on * 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] 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] point pair of transaction hash and its index
* @param[in] nHeight entry height of the claim * @param[in] nHeight entry height of the claim
* @param[out] nValidHeight valid height of the claim * @param[out] fallback optional callbacks
* @param[out] spentClaims inserts successfully spent claim
*/ */
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 = {});
/**
* 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);
#endif // CLAIMSCRIPTOP_H #endif // CLAIMSCRIPTOP_H

View file

@ -92,7 +92,6 @@ void CClaimTrieData::reorderClaims(const supportEntryType& supports)
CClaimTrie::CClaimTrie(bool fMemory, bool fWipe, int proportionalDelayFactor) CClaimTrie::CClaimTrie(bool fMemory, bool fWipe, int proportionalDelayFactor)
{ {
nProportionalDelayFactor = proportionalDelayFactor; nProportionalDelayFactor = proportionalDelayFactor;
nExpirationTime = Params().GetConsensus().nOriginalClaimExpirationTime;
db.reset(new CDBWrapper(GetDataDir() / "claimtrie", 100 * 1024 * 1024, fMemory, fWipe, false)); 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"); LogPrintf("Loading the claim trie from disk...\n");
nNextHeight = tip ? tip->nHeight + 1 : 0; base->nNextHeight = nNextHeight = tip ? tip->nHeight + 1 : 0;
base->nNextHeight = nNextHeight;
base->nExpirationTime = Params().GetConsensus().GetExpirationTime(nNextHeight - 1); // -1 okay
clear(); clear();
base->clear(); base->clear();
@ -532,14 +529,9 @@ CClaimTrieCacheBase::CClaimTrieCacheBase(CClaimTrie* base, bool fRequireTakeover
nNextHeight = base->nNextHeight; nNextHeight = base->nNextHeight;
} }
void CClaimTrieCacheBase::setExpirationTime(int time) int CClaimTrieCacheBase::expirationTime() const
{ {
base->nExpirationTime = time; return Params().GetConsensus().nOriginalClaimExpirationTime;
}
int CClaimTrieCacheBase::expirationTime()
{
return base->nExpirationTime;
} }
uint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(CClaimTrie::iterator& it) 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); CClaimValue claim(outPoint, claimId, nAmount, nHeight, nValidAtHeight);
if (nValidAtHeight < nNextHeight) { if (nValidAtHeight < nNextHeight) {
CNameOutPointType entry(adjustNameForValidHeight(name, nValidAtHeight), claim.outPoint); CNameOutPointType entry(adjustNameForValidHeight(name, nValidAtHeight), claim.outPoint);
addToExpirationQueue(claim.nHeight + base->nExpirationTime, entry); addToExpirationQueue(claim.nHeight + expirationTime(), entry);
CClaimIndexElement element = {name, claim}; CClaimIndexElement element = {name, claim};
claimsToAdd.push_back(element); claimsToAdd.push_back(element);
return insertClaimIntoTrie(name, claim, false); return insertClaimIntoTrie(name, claim, false);
@ -745,7 +737,7 @@ bool CClaimTrieCacheBase::addClaimToQueues(const std::string& name, const CClaim
itQueueRow->second.push_back(entry); itQueueRow->second.push_back(entry);
itQueueNameRow->second.emplace_back(claim.outPoint, claim.nValidAtHeight); itQueueNameRow->second.emplace_back(claim.outPoint, claim.nValidAtHeight);
CNameOutPointType expireEntry(name, claim.outPoint); CNameOutPointType expireEntry(name, claim.outPoint);
addToExpirationQueue(claim.nHeight + base->nExpirationTime, expireEntry); addToExpirationQueue(claim.nHeight + expirationTime(), expireEntry);
return true; return true;
} }
@ -798,7 +790,7 @@ bool CClaimTrieCacheBase::removeClaim(const std::string& name, const COutPoint&
std::string adjusted = adjustNameForValidHeight(name, nValidAtHeight); std::string adjusted = adjustNameForValidHeight(name, nValidAtHeight);
if (removeClaimFromQueue(adjusted, outPoint, claim) || removeClaimFromTrie(name, outPoint, claim, fCheckTakeover)) { 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); removeFromExpirationQueue(adjusted, outPoint, expirationHeight);
claimsToDelete.insert(claim); claimsToDelete.insert(claim);
nValidAtHeight = claim.nValidAtHeight; nValidAtHeight = claim.nValidAtHeight;
@ -880,7 +872,7 @@ bool CClaimTrieCacheBase::addSupportToQueues(const std::string& name, const CSup
itQueueRow->second.push_back(entry); itQueueRow->second.push_back(entry);
itQueueNameRow->second.emplace_back(support.outPoint, support.nValidAtHeight); itQueueNameRow->second.emplace_back(support.outPoint, support.nValidAtHeight);
CNameOutPointType expireEntry(name, support.outPoint); CNameOutPointType expireEntry(name, support.outPoint);
addSupportToExpirationQueue(support.nHeight + base->nExpirationTime, expireEntry); addSupportToExpirationQueue(support.nHeight + expirationTime(), expireEntry);
return true; return true;
} }
@ -929,7 +921,7 @@ bool CClaimTrieCacheBase::undoSpendSupport(const std::string& name, const COutPo
CSupportValue support(outPoint, supportedClaimId, nAmount, nHeight, nValidAtHeight); CSupportValue support(outPoint, supportedClaimId, nAmount, nHeight, nValidAtHeight);
if (nValidAtHeight < nNextHeight) { if (nValidAtHeight < nNextHeight) {
CNameOutPointType entry(adjustNameForValidHeight(name, nValidAtHeight), support.outPoint); CNameOutPointType entry(adjustNameForValidHeight(name, nValidAtHeight), support.outPoint);
addSupportToExpirationQueue(support.nHeight + base->nExpirationTime, entry); addSupportToExpirationQueue(support.nHeight + expirationTime(), entry);
return insertSupportIntoMap(name, support, false); return insertSupportIntoMap(name, support, false);
} else { } else {
return addSupportToQueues(name, support); return addSupportToQueues(name, support);
@ -943,7 +935,7 @@ bool CClaimTrieCacheBase::removeSupport(const std::string& name, const COutPoint
std::string adjusted = adjustNameForValidHeight(name, nValidAtHeight); std::string adjusted = adjustNameForValidHeight(name, nValidAtHeight);
if (removeSupportFromQueue(adjusted, outPoint, support) || removeSupportFromMap(name, outPoint, support, fCheckTakeover)) { 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); removeSupportFromExpirationQueue(adjusted, outPoint, expirationHeight);
nValidAtHeight = support.nValidAtHeight; nValidAtHeight = support.nValidAtHeight;
return true; return true;
@ -1244,7 +1236,7 @@ bool CClaimTrieCacheBase::decrementBlock(insertUndoType& insertUndo, claimQueueR
if (!expireSupportUndo.empty()) { if (!expireSupportUndo.empty()) {
for (auto itSupportExpireUndo = expireSupportUndo.crbegin(); itSupportExpireUndo != expireSupportUndo.crend(); ++itSupportExpireUndo) { for (auto itSupportExpireUndo = expireSupportUndo.crbegin(); itSupportExpireUndo != expireSupportUndo.crend(); ++itSupportExpireUndo) {
insertSupportIntoMap(itSupportExpireUndo->first, itSupportExpireUndo->second, false); insertSupportIntoMap(itSupportExpireUndo->first, itSupportExpireUndo->second, false);
if (nNextHeight == itSupportExpireUndo->second.nHeight + base->nExpirationTime) { if (nNextHeight == itSupportExpireUndo->second.nHeight + expirationTime()) {
auto itSupportExpireRow = getSupportExpirationQueueCacheRow(nNextHeight, true); auto itSupportExpireRow = getSupportExpirationQueueCacheRow(nNextHeight, true);
itSupportExpireRow->second.emplace_back(itSupportExpireUndo->first, itSupportExpireUndo->second.outPoint); 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); insertClaimIntoTrie(itExpireUndo->first, itExpireUndo->second, false);
CClaimIndexElement element = {itExpireUndo->first, itExpireUndo->second}; CClaimIndexElement element = {itExpireUndo->first, itExpireUndo->second};
claimsToAdd.push_back(element); claimsToAdd.push_back(element);
if (nNextHeight == itExpireUndo->second.nHeight + base->nExpirationTime) { if (nNextHeight == itExpireUndo->second.nHeight + expirationTime()) {
auto itExpireRow = getExpirationQueueCacheRow(nNextHeight, true); auto itExpireRow = getExpirationQueueCacheRow(nNextHeight, true);
itExpireRow->second.emplace_back(itExpireUndo->first, itExpireUndo->second.outPoint); itExpireRow->second.emplace_back(itExpireUndo->first, itExpireUndo->second.outPoint);
} }

View file

@ -302,7 +302,6 @@ struct CClaimsForNameType
class CClaimTrie : public CPrefixTrie<std::string, CClaimTrieData> class CClaimTrie : public CPrefixTrie<std::string, CClaimTrieData>
{ {
int nNextHeight = 0; int nNextHeight = 0;
int nExpirationTime = 0;
int nProportionalDelayFactor = 0; int nProportionalDelayFactor = 0;
std::unique_ptr<CDBWrapper> db; std::unique_ptr<CDBWrapper> db;
@ -434,6 +433,8 @@ public:
virtual bool getProofForName(const std::string& name, CClaimTrieProof& proof); virtual bool getProofForName(const std::string& name, CClaimTrieProof& proof);
virtual bool getInfoForName(const std::string& name, CClaimValue& claim) const; virtual bool getInfoForName(const std::string& name, CClaimValue& claim) const;
virtual int expirationTime() const;
bool finalizeDecrement(std::vector<std::pair<std::string, int>>& takeoverHeightUndo); bool finalizeDecrement(std::vector<std::pair<std::string, int>>& takeoverHeightUndo);
virtual CClaimsForNameType getClaimsForName(const std::string& name) const; virtual CClaimsForNameType getClaimsForName(const std::string& name) const;
@ -441,9 +442,6 @@ public:
CAmount getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector<CSupportValue>* supports = nullptr) const; CAmount getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector<CSupportValue>* supports = nullptr) const;
CAmount getEffectiveAmountForClaim(const CClaimsForNameType& claims, const uint160& claimId, std::vector<CSupportValue>* supports = nullptr) const; CAmount getEffectiveAmountForClaim(const CClaimsForNameType& claims, const uint160& claimId, std::vector<CSupportValue>* supports = nullptr) const;
void setExpirationTime(int time);
int expirationTime();
CClaimTrie::const_iterator begin() const; CClaimTrie::const_iterator begin() const;
CClaimTrie::const_iterator end() const; CClaimTrie::const_iterator end() const;
CClaimTrie::const_iterator find(const std::string& name) const; CClaimTrie::const_iterator find(const std::string& name) const;
@ -539,16 +537,27 @@ private:
class CClaimTrieCacheExpirationFork : public CClaimTrieCacheBase class CClaimTrieCacheExpirationFork : public CClaimTrieCacheBase
{ {
public: public:
explicit CClaimTrieCacheExpirationFork(CClaimTrie* base, bool fRequireTakeoverHeights = true) explicit CClaimTrieCacheExpirationFork(CClaimTrie* base, bool fRequireTakeoverHeights = true);
: CClaimTrieCacheBase(base, fRequireTakeoverHeights)
{
}
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<std::pair<std::string, int>>& takeoverHeightUndo) override;
bool decrementBlock(insertUndoType& insertUndo,
claimQueueRowType& expireUndo,
insertUndoType& insertSupportUndo,
supportQueueRowType& expireSupportUndo) override;
private: private:
int nExpirationTime;
bool forkForExpirationChange(bool increment);
void removeAndAddSupportToExpirationQueue(expirationQueueRowType& row, int height, bool increment); void removeAndAddSupportToExpirationQueue(expirationQueueRowType& row, int height, bool increment);
void removeAndAddToExpirationQueue(expirationQueueRowType& row, int height, bool increment); void removeAndAddToExpirationQueue(expirationQueueRowType& row, int height, bool increment);
}; };

View file

@ -1,4 +1,6 @@
#include "claimtrie.h"
#include <chainparams.h>
#include <claimtrie.h>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
@ -7,6 +9,46 @@
#include <boost/locale/localization_backend.hpp> #include <boost/locale/localization_backend.hpp>
#include <boost/scope_exit.hpp> #include <boost/scope_exit.hpp>
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<std::pair<std::string, int>>& 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) void CClaimTrieCacheExpirationFork::removeAndAddToExpirationQueue(expirationQueueRowType& row, int height, bool increment)
{ {
for (auto e = row.begin(); e != row.end(); ++e) { for (auto e = row.begin(); e != row.end(); ++e) {
@ -150,7 +192,7 @@ bool CClaimTrieCacheNormalizationFork::normalizeAllNamesInTrieIfNecessary(insert
auto supports = getSupportsForName(it.key()); auto supports = getSupportsForName(it.key());
for (auto& support : supports) { for (auto& support : supports) {
// if it's already going to expire just skip it // if it's already going to expire just skip it
if (support.nHeight + base->nExpirationTime <= nNextHeight) if (support.nHeight + expirationTime() <= nNextHeight)
continue; continue;
CSupportValue removed; CSupportValue removed;
@ -167,7 +209,7 @@ bool CClaimTrieCacheNormalizationFork::normalizeAllNamesInTrieIfNecessary(insert
continue; continue;
for (auto& claim : it->claims) { for (auto& claim : it->claims) {
if (claim.nHeight + base->nExpirationTime <= nNextHeight) if (claim.nHeight + expirationTime() <= nNextHeight)
continue; continue;
CClaimValue removed; CClaimValue removed;

View file

@ -1765,9 +1765,6 @@ bool AppInitMain(InitInterfaces& interfaces)
} }
LogPrintf("nBestHeight = %d\n", chain_active_height); 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)) if (gArgs.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION))
StartTorControl(); StartTorControl();

View file

@ -43,6 +43,35 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam
return nNewTime - nOldTime; return nNewTime - nOldTime;
} }
void blockToCache(const CBlock* pblock, CClaimTrieCache& trieCache, int nHeight)
{
insertUndoType dummyInsertUndo;
claimQueueRowType dummyExpireUndo;
insertUndoType dummyInsertSupportUndo;
supportQueueRowType dummyExpireSupportUndo;
std::vector<std::pair<std::string, int> > 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() { BlockAssembler::Options::Options() {
blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE); blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE);
nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT; nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT;
@ -110,12 +139,6 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
CBlockIndex* pindexPrev = ::ChainActive().Tip(); CBlockIndex* pindexPrev = ::ChainActive().Tip();
assert(pindexPrev != nullptr); assert(pindexPrev != nullptr);
nHeight = pindexPrev->nHeight + 1; nHeight = pindexPrev->nHeight + 1;
if (!pclaimTrie)
{
LogPrintf("CreateNewBlock(): pclaimTrie is invalid");
return NULL;
}
CClaimTrieCache trieCache(pclaimTrie);
pblock->nVersion = ComputeBlockVersion(pindexPrev, chainparams.GetConsensus()); pblock->nVersion = ComputeBlockVersion(pindexPrev, chainparams.GetConsensus());
// -regtest only: allow overriding block.nVersion with // -regtest only: allow overriding block.nVersion with
// -blockversion=N to test forking scenarios // -blockversion=N to test forking scenarios
@ -142,7 +165,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
int nPackagesSelected = 0; int nPackagesSelected = 0;
int nDescendantsUpdated = 0; int nDescendantsUpdated = 0;
addPackageTxs(nPackagesSelected, nDescendantsUpdated, trieCache); addPackageTxs(nPackagesSelected, nDescendantsUpdated);
int64_t nTime1 = GetTimeMicros(); int64_t nTime1 = GetTimeMicros();
@ -170,20 +193,14 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
pblock->nNonce = 0; pblock->nNonce = 0;
pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]); pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]);
insertUndoType dummyInsertUndo; CClaimTrieCache trieCache(pclaimTrie);
claimQueueRowType dummyExpireUndo; blockToCache(pblock, trieCache, nHeight);
insertUndoType dummyInsertSupportUndo;
supportQueueRowType dummyExpireSupportUndo;
std::vector<std::pair<std::string, int> > dummyTakeoverHeightUndo;
trieCache.incrementBlock(dummyInsertUndo, dummyExpireUndo, dummyInsertSupportUndo, dummyExpireSupportUndo, dummyTakeoverHeightUndo);
pblock->hashClaimTrie = trieCache.getMerkleHash(); pblock->hashClaimTrie = trieCache.getMerkleHash();
CValidationState state; CValidationState state;
if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) { if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) {
// if (trieCache.checkConsistency()) // TODO: bring back after prefixtrie merge if (!trieCache.empty() && trieCache.checkConsistency())
// trieCache.dumpToLog(trieCache.begin()); trieCache.dumpToLog(trieCache.begin());
throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state))); throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state)));
} }
int64_t nTime2 = GetTimeMicros(); int64_t nTime2 = GetTimeMicros();
@ -303,42 +320,6 @@ void BlockAssembler::SortForBlock(const CTxMemPool::setEntries& package, std::ve
std::sort(sortedEntries.begin(), sortedEntries.end(), CompareTxIterByAncestorCount()); 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 // This transaction selection algorithm orders the mempool based
// on feerate of a transaction including all unconfirmed ancestors. // on feerate of a transaction including all unconfirmed ancestors.
// Since we don't remove transactions from the mempool as we select them // Since we don't remove transactions from the mempool as we select them
@ -349,7 +330,7 @@ void iterToTrieCache(CTxMemPool::txiter iter, CClaimTrieCache& trieCache, const
// Each time through the loop, we compare the best transaction in // Each time through the loop, we compare the best transaction in
// mapModifiedTxs with the next transaction in the mempool to decide what // mapModifiedTxs with the next transaction in the mempool to decide what
// transaction package to work on next. // 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 // mapModifiedTx will store sorted packages after they are modified
// because some of their txs are already in the block // because some of their txs are already in the block
@ -466,7 +447,6 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
SortForBlock(ancestors, sortedEntries); SortForBlock(ancestors, sortedEntries);
for (size_t i=0; i<sortedEntries.size(); ++i) { for (size_t i=0; i<sortedEntries.size(); ++i) {
iterToTrieCache(sortedEntries[i], trieCache, inBlock, nHeight);
AddToBlock(sortedEntries[i]); AddToBlock(sortedEntries[i]);
// Erase from the modified set, if present // Erase from the modified set, if present
mapModifiedTx.erase(sortedEntries[i]); mapModifiedTx.erase(sortedEntries[i]);

View file

@ -175,7 +175,7 @@ private:
/** Add transactions based on feerate including unconfirmed ancestors /** Add transactions based on feerate including unconfirmed ancestors
* Increments nPackagesSelected / nDescendantsUpdated with corresponding * Increments nPackagesSelected / nDescendantsUpdated with corresponding
* statistics from the package selection (for logging statistics). */ * statistics from the package selection (for logging statistics). */
void addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated, CClaimTrieCache& trieCache) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs); void addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs);
// helper functions for addPackageTxs() // helper functions for addPackageTxs()
/** Remove confirmed (inBlock) entries from given set */ /** Remove confirmed (inBlock) entries from given set */

View file

@ -72,7 +72,7 @@ static BlockAssembler AssemblerForTest()
} }
// Test Fixtures // Test Fixtures
struct ClaimTrieChainFixture: public CClaimTrieCacheBase struct ClaimTrieChainFixture: public CClaimTrieCacheExpirationFork
{ {
std::vector<CTransaction> coinbase_txs; std::vector<CTransaction> coinbase_txs;
std::vector<int> marks; std::vector<int> marks;
@ -86,9 +86,9 @@ struct ClaimTrieChainFixture: public CClaimTrieCacheBase
int64_t originalExpiration; int64_t originalExpiration;
int64_t extendedExpiration; int64_t extendedExpiration;
using CClaimTrieCacheBase::getSupportsForName; using CClaimTrieCacheExpirationFork::getSupportsForName;
ClaimTrieChainFixture(): CClaimTrieCacheBase(pclaimTrie), ClaimTrieChainFixture(): CClaimTrieCacheExpirationFork(pclaimTrie),
unique_block_counter(0), normalization_original(-1), expirationForkHeight(-1) unique_block_counter(0), normalization_original(-1), expirationForkHeight(-1)
{ {
fRequireStandard = false; fRequireStandard = false;
@ -114,14 +114,12 @@ struct ClaimTrieChainFixture: public CClaimTrieCacheBase
DecrementBlocks(chainActive.Height()); DecrementBlocks(chainActive.Height());
auto& consensus = const_cast<Consensus::Params&>(Params().GetConsensus()); auto& consensus = const_cast<Consensus::Params&>(Params().GetConsensus());
if (normalization_original >= 0) if (normalization_original >= 0)
{
consensus.nNormalizedNameForkHeight = normalization_original; consensus.nNormalizedNameForkHeight = normalization_original;
}
if (expirationForkHeight >= 0) { if (expirationForkHeight >= 0) {
consensus.nExtendedClaimExpirationForkHeight = expirationForkHeight; consensus.nExtendedClaimExpirationForkHeight = expirationForkHeight;
consensus.nExtendedClaimExpirationTime = extendedExpiration; consensus.nExtendedClaimExpirationTime = extendedExpiration;
consensus.nOriginalClaimExpirationTime = originalExpiration; consensus.nOriginalClaimExpirationTime = originalExpiration;
base->nExpirationTime = originalExpiration;
} }
} }
@ -136,7 +134,7 @@ struct ClaimTrieChainFixture: public CClaimTrieCacheBase
consensus.nExtendedClaimExpirationForkHeight = target; consensus.nExtendedClaimExpirationForkHeight = target;
consensus.nExtendedClaimExpirationTime = postForkExpirationTime; consensus.nExtendedClaimExpirationTime = postForkExpirationTime;
consensus.nOriginalClaimExpirationTime = preForkExpirationTime; consensus.nOriginalClaimExpirationTime = preForkExpirationTime;
base->nExpirationTime = targetMinusCurrent >= 0 ? preForkExpirationTime : postForkExpirationTime; setExpirationTime(targetMinusCurrent >= 0 ? preForkExpirationTime : postForkExpirationTime);
} }
void setNormalizationForkHeight(int targetMinusCurrent) { void setNormalizationForkHeight(int targetMinusCurrent) {
@ -292,6 +290,7 @@ struct ClaimTrieChainFixture: public CClaimTrieCacheBase
num_txs_for_next_block = 0; num_txs_for_next_block = 0;
nNextHeight = chainActive.Height() + 1; nNextHeight = chainActive.Height() + 1;
} }
setExpirationTime(Params().GetConsensus().GetExpirationTime(nNextHeight - 1));
} }
//disconnect i blocks from tip //disconnect i blocks from tip
@ -306,9 +305,10 @@ struct ClaimTrieChainFixture: public CClaimTrieCacheBase
} }
BOOST_CHECK_EQUAL(state.IsValid(), true); BOOST_CHECK_EQUAL(state.IsValid(), true);
BOOST_CHECK_EQUAL(ActivateBestChain(state, Params()), true); BOOST_CHECK_EQUAL(ActivateBestChain(state, Params()), true);
nNextHeight = chainActive.Height() + 1;
mempool.clear(); mempool.clear();
num_txs_for_next_block = 0; num_txs_for_next_block = 0;
nNextHeight = chainActive.Height() + 1;
setExpirationTime(Params().GetConsensus().GetExpirationTime(nNextHeight - 1));
} }
// decrement back to last mark // 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 // make sure decrementing to before the fork height will apppropriately set back the
// expiration time to the original expiraiton time // expiration time to the original expiraiton time
fixture.DecrementBlocks(1); fixture.DecrementBlocks(1);
BOOST_CHECK_NE(fixture.expirationTime(), 6); BOOST_CHECK_EQUAL(fixture.expirationTime(), 3);
fixture.IncrementBlocks(1); fixture.IncrementBlocks(1);
BOOST_CHECK_EQUAL(fixture.expirationTime(), 6); 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) BOOST_AUTO_TEST_CASE(normalization_does_not_kill_expirations)
{ {
ClaimTrieChainFixture fixture; ClaimTrieChainFixture fixture;
fixture.setExpirationTime(3); fixture.setExpirationForkHeight(800, 3, 800);
fixture.setNormalizationForkHeight(4); fixture.setNormalizationForkHeight(4);
// need to see that claims expiring on the frame when we normalize aren't kept // 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 // need to see that supports expiring on the frame when we normalize aren't kept

View file

@ -1840,12 +1840,7 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
assert(merkleHash == pindex->pprev->hashClaimTrie); assert(merkleHash == pindex->pprev->hashClaimTrie);
} }
if (pindex->nHeight == Params().GetConsensus().nExtendedClaimExpirationForkHeight) trieCache.expirationForkActive(pindex->nHeight, false);
{
LogPrintf("Decremented past the extended claim expiration hard fork height\n");
trieCache.setExpirationTime(Params().GetConsensus().GetExpirationTime(pindex->nHeight-1));
trieCache.forkForExpirationChange(false);
}
return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN; return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN;
} }
@ -2196,13 +2191,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
// Get the script flags for this block // Get the script flags for this block
unsigned int flags = GetBlockScriptFlags(pindex, chainparams.GetConsensus()); unsigned int flags = GetBlockScriptFlags(pindex, chainparams.GetConsensus());
// v 13 LBRYcrd hard fork to extend expiration time trieCache.expirationForkActive(pindex->nHeight, true);
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);
}
int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1; 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); LogPrint(BCLog::BENCH, " - Fork checks: %.2fms [%.2fs (%.2fms/blk)]\n", MILLI * (nTime2 - nTime1), nTimeForks * MICRO, nTimeForks * MILLI / nBlocksTotal);
@ -2291,35 +2280,13 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
tx.GetHash().ToString(), FormatStateMessage(state)); tx.GetHash().ToString(), FormatStateMessage(state));
} }
control.Add(vChecks); control.Add(vChecks);
CUpdateCacheCallbacks callbacks = {
// To handle claim updates, stick all claims found in the inputs into a map of .findScriptKey = {},
// name: (txhash, nOut). When running through the outputs, if any claim's .claimUndoHeights = [&mClaimUndoHeights](int index, int nValidAtHeight) {
// name is found in the map, send the name's txhash and nOut to the trie cache, mClaimUndoHeights.emplace(index, nValidAtHeight);
// 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. UpdateCache(tx, trieCache, view, pindex->nHeight, callbacks);
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);
}
} }
CTxUndo undoDummy; CTxUndo undoDummy;
@ -2358,7 +2325,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
if (trieCache.getMerkleHash() != block.hashClaimTrie) if (trieCache.getMerkleHash() != block.hashClaimTrie)
{ {
if (trieCache.checkConsistency()) if (!trieCache.empty() && trieCache.checkConsistency())
trieCache.dumpToLog(trieCache.begin()); trieCache.dumpToLog(trieCache.begin());
return state.DoS(100, error("ConnectBlock() : the merkle root of the claim trie does not match " 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(), "(actual=%s vs block=%s on height=%d)", trieCache.getMerkleHash().GetHex(),