track original height (not working)

This commit is contained in:
Brannon King 2020-01-02 17:48:47 -07:00
parent 4b5f9e650b
commit 21774aa1d4
14 changed files with 113 additions and 79 deletions

View file

@ -16,20 +16,20 @@ bool CClaimScriptAddOp::claimName(CClaimTrieCache& trieCache, const std::string&
auto claimId = ClaimIdHash(point.hash, point.n); auto claimId = ClaimIdHash(point.hash, point.n);
LogPrint(BCLog::CLAIMS, "+++ Claim added: %s, c: %.6s, t: %.6s:%d, h: %.6d, a: %d\n", LogPrint(BCLog::CLAIMS, "+++ Claim added: %s, c: %.6s, t: %.6s:%d, h: %.6d, a: %d\n",
name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValue); name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValue);
return addClaim(trieCache, name, claimId, -1); return addClaim(trieCache, name, claimId, -1, -1);
} }
bool CClaimScriptAddOp::updateClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId) bool CClaimScriptAddOp::updateClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId)
{ {
LogPrint(BCLog::CLAIMS, "+++ Claim updated: %s, c: %.6s, t: %.6s:%d, h: %.6d, a: %d\n", LogPrint(BCLog::CLAIMS, "+++ Claim updated: %s, c: %.6s, t: %.6s:%d, h: %.6d, a: %d\n",
name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValue); name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValue);
return addClaim(trieCache, name, claimId, -1); return addClaim(trieCache, name, claimId, -1, -1);
} }
bool CClaimScriptAddOp::addClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId, bool CClaimScriptAddOp::addClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId,
int takeoverHeight) int takeoverHeight, int originalHeight)
{ {
return trieCache.addClaim(name, point, claimId, nValue, nHeight, takeoverHeight); return trieCache.addClaim(name, point, claimId, nValue, nHeight, takeoverHeight, originalHeight);
} }
bool CClaimScriptAddOp::supportClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId) bool CClaimScriptAddOp::supportClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId)
@ -61,8 +61,8 @@ bool CClaimScriptUndoAddOp::updateClaim(CClaimTrieCache& trieCache, const std::s
bool CClaimScriptUndoAddOp::undoAddClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId) bool CClaimScriptUndoAddOp::undoAddClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId)
{ {
std::string nodeName; std::string nodeName;
int validHeight; int validHeight, originalHeight;
bool res = trieCache.removeClaim(claimId, point, nodeName, validHeight); bool res = trieCache.removeClaim(claimId, point, nodeName, validHeight, originalHeight);
if (!res) if (!res)
LogPrint(BCLog::CLAIMS, "Remove claim failed for %s with claimid %s\n", name, claimId.GetHex().substr(0, 6)); LogPrint(BCLog::CLAIMS, "Remove claim failed for %s with claimid %s\n", name, claimId.GetHex().substr(0, 6));
return res; return res;
@ -105,7 +105,7 @@ bool CClaimScriptSpendOp::updateClaim(CClaimTrieCache& trieCache, const std::str
bool CClaimScriptSpendOp::spendClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId) bool CClaimScriptSpendOp::spendClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId)
{ {
std::string nodeName; std::string nodeName;
bool res = trieCache.removeClaim(claimId, point, nodeName, nValidHeight); bool res = trieCache.removeClaim(claimId, point, nodeName, nValidHeight, nOriginalHeight);
if (!res) if (!res)
LogPrint(BCLog::CLAIMS, "Remove claim failed for %s with claimid %s\n", name, claimId.GetHex().substr(0, 6)); LogPrint(BCLog::CLAIMS, "Remove claim failed for %s with claimid %s\n", name, claimId.GetHex().substr(0, 6));
return res; return res;
@ -122,8 +122,8 @@ bool CClaimScriptSpendOp::supportClaim(CClaimTrieCache& trieCache, const std::st
return res; return res;
} }
CClaimScriptUndoSpendOp::CClaimScriptUndoSpendOp(const COutPoint& point, CAmount nValue, int nHeight, int nValidHeight) CClaimScriptUndoSpendOp::CClaimScriptUndoSpendOp(const COutPoint& point, CAmount nValue, int nHeight, int nValidHeight, int nOriginalHeight)
: point(point), nValue(nValue), nHeight(nHeight), nValidHeight(nValidHeight) : point(point), nValue(nValue), nHeight(nHeight), nValidHeight(nValidHeight), nOriginalHeight(nOriginalHeight)
{ {
} }
@ -144,7 +144,8 @@ bool CClaimScriptUndoSpendOp::updateClaim(CClaimTrieCache& trieCache, const std:
bool CClaimScriptUndoSpendOp::undoSpendClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId) bool CClaimScriptUndoSpendOp::undoSpendClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId)
{ {
return trieCache.addClaim(name, point, claimId, nValue, nHeight, nValidHeight); return trieCache.addClaim(name, point, claimId, nValue, nHeight,
nValidHeight, nOriginalHeight);
} }
bool CClaimScriptUndoSpendOp::supportClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId) bool CClaimScriptUndoSpendOp::supportClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId)
@ -188,17 +189,17 @@ void UpdateCache(const CTransaction& tx, CClaimTrieCache& trieCache, const CCoin
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)) {
callback(name, claimId); callback(name, claimId, nOriginalHeight);
return true; return true;
} }
return false; return false;
} }
std::function<void(const std::string& name, const uint160& claimId)> callback; std::function<void(const std::string& name, const uint160& claimId, int originalHeight)> callback;
}; };
spentClaimsType spentClaims; spentClaimsType spentClaims;
for (std::size_t j = 0; j < tx.vin.size(); j++) { for (uint32_t j = 0; j < tx.vin.size(); j++) {
const CTxIn& txin = tx.vin[j]; const CTxIn& txin = tx.vin[j];
const Coin& coin = view.AccessCoin(txin.prevout); const Coin& coin = view.AccessCoin(txin.prevout);
@ -214,13 +215,16 @@ void UpdateCache(const CTransaction& tx, CClaimTrieCache& trieCache, const CCoin
if (scriptPubKey.empty()) if (scriptPubKey.empty())
continue; continue;
int nValidAtHeight; int nValidAtHeight, nOriginalHeight = 0;
CSpendClaimHistory spendClaim(COutPoint(txin.prevout.hash, txin.prevout.n), scriptHeight, nValidAtHeight); CSpendClaimHistory spendClaim(COutPoint(txin.prevout.hash, txin.prevout.n), scriptHeight, nValidAtHeight);
spendClaim.callback = [&spentClaims](const std::string& name, const uint160& claimId) { spendClaim.callback = [&spentClaims, &nOriginalHeight](const std::string& name, const uint160& claimId, int originalHeight) {
spentClaims.emplace_back(name, claimId); spentClaims.push_back({name, claimId, originalHeight});
nOriginalHeight = originalHeight;
}; };
if (ProcessClaim(spendClaim, trieCache, scriptPubKey) && callbacks.claimUndoHeights) if (ProcessClaim(spendClaim, trieCache, scriptPubKey) && callbacks.claimUndoHeights) {
callbacks.claimUndoHeights(j, nValidAtHeight); // assert(nValidAtHeight > 0 && nOriginalHeight > 0); // fails on tests
callbacks.claimUndoHeights(j, uint32_t(nValidAtHeight), uint32_t(nOriginalHeight));
}
} }
class CAddSpendClaim : public CClaimScriptAddOp class CAddSpendClaim : public CClaimScriptAddOp
@ -230,11 +234,15 @@ void UpdateCache(const CTransaction& tx, CClaimTrieCache& trieCache, const CCoin
bool updateClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId) override bool updateClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId) override
{ {
if (callback(name, claimId)) auto originalHeight = callback(name, claimId);
return CClaimScriptAddOp::updateClaim(trieCache, name, claimId); if (originalHeight >= 0) {
LogPrint(BCLog::CLAIMS, "+++ Claim updated: %s, c: %.6s, t: %.6s:%d, h: %.6d, a: %d\n",
name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValue);
return CClaimScriptAddOp::addClaim(trieCache, name, claimId, -1, originalHeight);
}
return false; return false;
} }
std::function<bool(const std::string& name, const uint160& claimId)> callback; std::function<int(const std::string& name, const uint160& claimId)> callback;
}; };
for (std::size_t j = 0; j < tx.vout.size(); j++) { for (std::size_t j = 0; j < tx.vout.size(); j++) {
@ -244,14 +252,14 @@ void UpdateCache(const CTransaction& tx, CClaimTrieCache& trieCache, const CCoin
continue; continue;
CAddSpendClaim addClaim(COutPoint(tx.GetHash(), j), txout.nValue, nHeight); CAddSpendClaim addClaim(COutPoint(tx.GetHash(), j), txout.nValue, nHeight);
addClaim.callback = [&trieCache, &spentClaims](const std::string& name, const uint160& claimId) -> bool { addClaim.callback = [&trieCache, &spentClaims](const std::string& name, const uint160& claimId) -> int {
for (auto itSpent = spentClaims.begin(); itSpent != spentClaims.end(); ++itSpent) { for (auto itSpent = spentClaims.begin(); itSpent != spentClaims.end(); ++itSpent) {
if (itSpent->second == claimId && trieCache.normalizeClaimName(name) == trieCache.normalizeClaimName(itSpent->first)) { if (itSpent->id == claimId && trieCache.normalizeClaimName(name) == trieCache.normalizeClaimName(itSpent->name)) {
spentClaims.erase(itSpent); spentClaims.erase(itSpent);
return true; return itSpent->originalHeight;
} }
} }
return false; return -1;
}; };
ProcessClaim(addClaim, trieCache, txout.scriptPubKey); ProcessClaim(addClaim, trieCache, txout.scriptPubKey);
} }

View file

@ -81,7 +81,8 @@ protected:
* @param[in] name name of the claim * @param[in] name name of the claim
* @param[in] claimId id of the claim * @param[in] claimId id of the claim
*/ */
virtual bool addClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId, int takeoverHeight); virtual bool addClaim(CClaimTrieCache& trieCache, const std::string& name, const uint160& claimId,
int takeoverHeight, int originalHeight);
const COutPoint point; const COutPoint point;
const CAmount nValue; const CAmount nValue;
const int nHeight; const int nHeight;
@ -167,6 +168,7 @@ protected:
const COutPoint point; const COutPoint point;
const int nHeight; const int nHeight;
int& nValidHeight; int& nValidHeight;
int nOriginalHeight;
}; };
/** /**
@ -182,7 +184,7 @@ public:
* @param[in] nHeight entry height of the claim * @param[in] nHeight entry height of the claim
* @param[in] nValidHeight valid height of the claim * @param[in] nValidHeight valid height of the claim
*/ */
CClaimScriptUndoSpendOp(const COutPoint& point, CAmount nValue, int nHeight, int nValidHeight); CClaimScriptUndoSpendOp(const COutPoint& point, CAmount nValue, int nHeight, int nValidHeight, int nOriginalHeight);
/** /**
* Implementation of OP_CLAIM_NAME handler * Implementation of OP_CLAIM_NAME handler
* @see CClaimScriptOp::claimName * @see CClaimScriptOp::claimName
@ -211,6 +213,7 @@ protected:
const CAmount nValue; const CAmount nValue;
const int nHeight; const int nHeight;
const int nValidHeight; const int nValidHeight;
const int nOriginalHeight;
}; };
/** /**
@ -221,13 +224,13 @@ protected:
*/ */
bool ProcessClaim(CClaimScriptOp& claimOp, CClaimTrieCache& trieCache, const CScript& scriptPubKey); bool ProcessClaim(CClaimScriptOp& claimOp, CClaimTrieCache& trieCache, const CScript& scriptPubKey);
typedef std::pair<std::string, uint160> spentClaimType; struct spentClaimType { std::string name; uint160 id; int originalHeight; };
typedef std::vector<spentClaimType> spentClaimsType; typedef std::vector<spentClaimType> spentClaimsType;
struct CUpdateCacheCallbacks struct CUpdateCacheCallbacks
{ {
std::function<CScript(const COutPoint& point)> findScriptKey; std::function<CScript(const COutPoint& point)> findScriptKey;
std::function<void(int, int)> claimUndoHeights; std::function<void(uint32_t, uint32_t, uint32_t)> claimUndoHeights;
}; };
/** /**

View file

@ -75,8 +75,8 @@ CNameOutPointHeightType::CNameOutPointHeightType(std::string name, COutPoint out
{ {
} }
CClaimNsupports::CClaimNsupports(CClaimValue claim, int64_t effectiveAmount, std::vector<CSupportValue> supports) CClaimNsupports::CClaimNsupports(CClaimValue claim, int64_t effectiveAmount, int originalHeight, std::vector<CSupportValue> supports)
: claim(std::move(claim)), effectiveAmount(effectiveAmount), supports(std::move(supports)) : claim(std::move(claim)), effectiveAmount(effectiveAmount), originalHeight(originalHeight), supports(std::move(supports))
{ {
} }

View file

@ -78,12 +78,14 @@ struct CClaimNsupports
CClaimNsupports& operator=(CClaimNsupports&&) = default; CClaimNsupports& operator=(CClaimNsupports&&) = default;
CClaimNsupports& operator=(const CClaimNsupports&) = default; CClaimNsupports& operator=(const CClaimNsupports&) = default;
CClaimNsupports(CClaimValue claim, int64_t effectiveAmount, std::vector<CSupportValue> supports = {}); CClaimNsupports(CClaimValue claim, int64_t effectiveAmount, int originalHeight,
std::vector<CSupportValue> supports = {});
bool IsNull() const; bool IsNull() const;
CClaimValue claim; CClaimValue claim;
int64_t effectiveAmount = 0; int64_t effectiveAmount = 0;
int originalHeight = -1;
std::vector<CSupportValue> supports; std::vector<CSupportValue> supports;
}; };

View file

@ -157,7 +157,7 @@ bool CClaimTrieCacheNormalizationFork::normalizeAllNamesInTrieIfNecessary()
// work around a bug in the old implementation: // work around a bug in the old implementation:
db << "UPDATE claim SET activationHeight = ?1 " // force a takeover on these db << "UPDATE claim SET activationHeight = ?1 " // force a takeover on these
"WHERE blockHeight < ?1 AND activationHeight > ?1 AND nodeName != name" << nNextHeight; "WHERE updateHeight < ?1 AND activationHeight > ?1 AND nodeName != name" << nNextHeight;
return true; return true;
} }

View file

@ -57,7 +57,7 @@ namespace sqlite
return ret; return ret;
} }
inline int commit(database& db, std::size_t attempts = 60) inline int commit(database& db, std::size_t attempts = 200)
{ {
int code = SQLITE_OK; int code = SQLITE_OK;
for (auto i = 0u; i < attempts; ++i) { for (auto i = 0u; i < attempts; ++i) {
@ -67,7 +67,7 @@ namespace sqlite
code = e.get_code(); code = e.get_code();
if (code == SQLITE_LOCKED || code == SQLITE_BUSY) { if (code == SQLITE_LOCKED || code == SQLITE_BUSY) {
using namespace std::chrono_literals; using namespace std::chrono_literals;
std::this_thread::sleep_for(1s); std::this_thread::sleep_for(100ms);
continue; continue;
} }
return code; return code;

View file

@ -88,7 +88,7 @@ CClaimTrie::CClaimTrie(std::size_t cacheBytes, bool fWipe, int height,
db << "CREATE TABLE IF NOT EXISTS claim (claimID BLOB NOT NULL PRIMARY KEY, name BLOB NOT NULL, " db << "CREATE TABLE IF NOT EXISTS claim (claimID BLOB NOT NULL PRIMARY KEY, name BLOB NOT NULL, "
"nodeName BLOB NOT NULL REFERENCES node(name) DEFERRABLE INITIALLY DEFERRED, " "nodeName BLOB NOT NULL REFERENCES node(name) DEFERRABLE INITIALLY DEFERRED, "
"txID BLOB NOT NULL, txN INTEGER NOT NULL, blockHeight INTEGER NOT NULL, " "txID BLOB NOT NULL, txN INTEGER NOT NULL, originalHeight INTEGER NOT NULL, updateHeight INTEGER NOT NULL, "
"validHeight INTEGER NOT NULL, activationHeight INTEGER NOT NULL, " "validHeight INTEGER NOT NULL, activationHeight INTEGER NOT NULL, "
"expirationHeight INTEGER NOT NULL, amount INTEGER NOT NULL);"; "expirationHeight INTEGER NOT NULL, amount INTEGER NOT NULL);";
@ -383,7 +383,7 @@ CClaimSupportToName CClaimTrieCacheBase::getClaimsForName(const std::string& nam
return it != supports.end(); return it != supports.end();
}; };
auto query = db << "SELECT claimID, txID, txN, blockHeight, activationHeight, amount " auto query = db << "SELECT claimID, txID, txN, originalHeight, updateHeight, activationHeight, amount "
"FROM claim WHERE nodeName = ? AND expirationHeight >= ?" "FROM claim WHERE nodeName = ? AND expirationHeight >= ?"
<< name << nNextHeight; << name << nNextHeight;
@ -391,10 +391,11 @@ CClaimSupportToName CClaimTrieCacheBase::getClaimsForName(const std::string& nam
std::vector<CClaimNsupports> claimsNsupports; std::vector<CClaimNsupports> claimsNsupports;
for (auto &&row: query) { for (auto &&row: query) {
CClaimValue claim; CClaimValue claim;
int originalHeight;
row >> claim.claimId >> claim.outPoint.hash >> claim.outPoint.n row >> claim.claimId >> claim.outPoint.hash >> claim.outPoint.n
>> claim.nHeight >> claim.nValidAtHeight >> claim.nAmount; >> originalHeight >> claim.nHeight >> claim.nValidAtHeight >> claim.nAmount;
int64_t nAmount = claim.nValidAtHeight < nNextHeight ? claim.nAmount : 0; int64_t nAmount = claim.nValidAtHeight < nNextHeight ? claim.nAmount : 0;
auto ic = claimsNsupports.emplace(claimsNsupports.end(), claim, nAmount); auto ic = claimsNsupports.emplace(claimsNsupports.end(), claim, nAmount, originalHeight);
for (auto it = supports.begin(); find(it, claim); it = supports.erase(it)) { for (auto it = supports.begin(); find(it, claim); it = supports.erase(it)) {
if (it->nValidAtHeight < nNextHeight) if (it->nValidAtHeight < nNextHeight)
ic->effectiveAmount += it->nAmount; ic->effectiveAmount += it->nAmount;
@ -492,12 +493,12 @@ bool CClaimTrieCacheBase::flush()
const std::string childHashQuery_s = "SELECT name, hash FROM node WHERE parent = ? ORDER BY name"; const std::string childHashQuery_s = "SELECT name, hash FROM node WHERE parent = ? ORDER BY name";
const std::string claimHashQuery_s = const std::string claimHashQuery_s =
"SELECT c.txID, c.txN, c.claimID, c.blockHeight, c.activationHeight, c.amount, " "SELECT c.txID, c.txN, c.claimID, c.updateHeight, c.activationHeight, c.amount, "
"(SELECT IFNULL(SUM(s.amount),0)+c.amount FROM support s " "(SELECT IFNULL(SUM(s.amount),0)+c.amount FROM support s "
"WHERE s.supportedClaimID = c.claimID AND s.nodeName = c.nodeName " "WHERE s.supportedClaimID = c.claimID AND s.nodeName = c.nodeName "
"AND s.activationHeight < ?1 AND s.expirationHeight >= ?1) as effectiveAmount " "AND s.activationHeight < ?1 AND s.expirationHeight >= ?1) as effectiveAmount "
"FROM claim c WHERE c.nodeName = ?2 AND c.activationHeight < ?1 AND c.expirationHeight >= ?1 " "FROM claim c WHERE c.nodeName = ?2 AND c.activationHeight < ?1 AND c.expirationHeight >= ?1 "
"ORDER BY effectiveAmount DESC, c.blockHeight, c.txID, c.txN"; "ORDER BY effectiveAmount DESC, c.updateHeight, c.txID, c.txN";
const std::string claimHashQueryLimit_s = claimHashQuery_s + " LIMIT 1"; const std::string claimHashQueryLimit_s = claimHashQuery_s + " LIMIT 1";
@ -574,7 +575,7 @@ bool CClaimTrieCacheBase::getLastTakeoverForName(const std::string& name, uint16
} }
bool CClaimTrieCacheBase::addClaim(const std::string& name, const COutPoint& outPoint, const uint160& claimId, bool CClaimTrieCacheBase::addClaim(const std::string& name, const COutPoint& outPoint, const uint160& claimId,
int64_t nAmount, int nHeight, int nValidHeight) int64_t nAmount, int nHeight, int nValidHeight, int originalHeight)
{ {
ensureTransacting(); ensureTransacting();
@ -589,15 +590,19 @@ bool CClaimTrieCacheBase::addClaim(const std::string& name, const COutPoint& out
// We would have to make this method return that if we go without the removal // We would have to make this method return that if we go without the removal
// The other problem with 1 is that the outer shell would need to know if the one they removed was a winner or not // The other problem with 1 is that the outer shell would need to know if the one they removed was a winner or not
if (nValidHeight < 0) if (nValidHeight <= 0)
nValidHeight = nHeight + getDelayForName(name, claimId); // sets nValidHeight to the old value nValidHeight = nHeight + getDelayForName(name, claimId); // sets nValidHeight to the old value
if (originalHeight <= 0)
originalHeight = nHeight;
auto nodeName = adjustNameForValidHeight(name, nValidHeight); auto nodeName = adjustNameForValidHeight(name, nValidHeight);
auto expires = expirationTime() + nHeight; auto expires = expirationTime() + nHeight;
db << "INSERT INTO claim(claimID, name, nodeName, txID, txN, amount, blockHeight, validHeight, activationHeight, expirationHeight) " db << "INSERT INTO claim(claimID, name, nodeName, txID, txN, amount, originalHeight, updateHeight, "
"VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" "validHeight, activationHeight, expirationHeight) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
<< claimId << name << nodeName << outPoint.hash << outPoint.n << nAmount << nHeight << nValidHeight << nValidHeight << expires; << claimId << name << nodeName << outPoint.hash << outPoint.n << nAmount
<< originalHeight << nHeight << nValidHeight << nValidHeight << expires;
if (nValidHeight < nNextHeight) if (nValidHeight < nNextHeight)
db << "INSERT INTO node(name) VALUES(?) ON CONFLICT(name) DO UPDATE SET hash = NULL" << nodeName; db << "INSERT INTO node(name) VALUES(?) ON CONFLICT(name) DO UPDATE SET hash = NULL" << nodeName;
@ -626,7 +631,8 @@ bool CClaimTrieCacheBase::addSupport(const std::string& name, const COutPoint& o
return true; return true;
} }
bool CClaimTrieCacheBase::removeClaim(const uint160& claimId, const COutPoint& outPoint, std::string& nodeName, int& validHeight) bool CClaimTrieCacheBase::removeClaim(const uint160& claimId, const COutPoint& outPoint, std::string& nodeName,
int& validHeight, int& originalHeight)
{ {
ensureTransacting(); ensureTransacting();
@ -634,16 +640,19 @@ bool CClaimTrieCacheBase::removeClaim(const uint160& claimId, const COutPoint& o
// when going forward we spend a claim (aka, call removeClaim) before updating it (aka, call addClaim) // when going forward we spend a claim (aka, call removeClaim) before updating it (aka, call addClaim)
// when going backwards we first remove the update by calling removeClaim // when going backwards we first remove the update by calling removeClaim
// we then undo the spend of the previous one by calling addClaim with the original data // we then undo the spend of the previous one by calling addClaim with the original data
// in order to maintain the proper takeover height the udpater will need to use our height returned here // in order to maintain the proper takeover height the updater will need to use our height returned here
auto query = db << "SELECT nodeName, activationHeight FROM claim WHERE claimID = ? AND txID = ? AND txN = ? AND expirationHeight >= ?" auto query = db << "SELECT nodeName, activationHeight, originalHeight FROM claim WHERE claimID = ? AND txID = ? AND txN = ? AND expirationHeight >= ?"
<< claimId << outPoint.hash << outPoint.n << nNextHeight; << claimId << outPoint.hash << outPoint.n << nNextHeight;
auto it = query.begin(); auto it = query.begin();
if (it == query.end()) return false; if (it == query.end())
*it >> nodeName >> validHeight; return false;
*it >> nodeName >> validHeight >> originalHeight;
db << "DELETE FROM claim WHERE claimID = ? AND txID = ? and txN = ?" << claimId << outPoint.hash << outPoint.n; db << "DELETE FROM claim WHERE claimID = ? AND txID = ? and txN = ?" << claimId << outPoint.hash << outPoint.n;
if (!db.rows_modified()) if (!db.rows_modified())
return false; return false;
db << "UPDATE node SET hash = NULL WHERE name = ?" << nodeName; db << "UPDATE node SET hash = NULL WHERE name = ?" << nodeName;
// when node should be deleted from cache but instead it's kept // when node should be deleted from cache but instead it's kept
@ -653,10 +662,10 @@ bool CClaimTrieCacheBase::removeClaim(const uint160& claimId, const COutPoint& o
&& nNextHeight < base->nMaxRemovalWorkaroundHeight) { // TODO: hard fork this out (which we already tried once but failed) && nNextHeight < base->nMaxRemovalWorkaroundHeight) { // TODO: hard fork this out (which we already tried once but failed)
// neither LIKE nor SUBSTR will use an index on a blob, but BETWEEN is a good, fast alternative // neither LIKE nor SUBSTR will use an index on a blob, but BETWEEN is a good, fast alternative
auto end = nodeName + std::string( 256, std::numeric_limits<char>::max()); // 256 == MAX_CLAIM_NAME_SIZE + 1 auto end = nodeName + std::string( 256, std::numeric_limits<char>::max()); // 256 == MAX_CLAIM_NAME_SIZE + 1
auto query = db << "SELECT nodeName FROM claim WHERE nodeName BETWEEN ?1 AND ?2 " auto innerQuery = db << "SELECT nodeName FROM claim WHERE nodeName BETWEEN ?1 AND ?2 "
"AND activationHeight < ?3 AND expirationHeight >= ?3 ORDER BY nodeName LIMIT 1" "AND activationHeight < ?3 AND expirationHeight >= ?3 ORDER BY nodeName LIMIT 1"
<< nodeName << end << nNextHeight; << nodeName << end << nNextHeight;
for (auto&& row: query) { for (auto&& row: innerQuery) {
std::string shortestMatch; std::string shortestMatch;
row >> shortestMatch; row >> shortestMatch;
if (shortestMatch != nodeName) if (shortestMatch != nodeName)
@ -878,7 +887,7 @@ bool CClaimTrieCacheBase::findNameForClaim(std::vector<unsigned char> claim, CCl
return false; return false;
auto maximum = claim; auto maximum = claim;
maximum.insert(maximum.end(), 20 - claim.size(), std::numeric_limits<unsigned char>::max()); maximum.insert(maximum.end(), 20 - claim.size(), std::numeric_limits<unsigned char>::max());
auto query = db << "SELECT nodeName, claimID, txID, txN, amount, activationHeight, blockHeight " auto query = db << "SELECT nodeName, claimID, txID, txN, amount, activationHeight, updateHeight "
"FROM claim WHERE REVERSE(claimID) BETWEEN ?1 AND ?2 " "FROM claim WHERE REVERSE(claimID) BETWEEN ?1 AND ?2 "
"AND activationHeight < ?3 AND expirationHeight >= ?3 LIMIT 2" "AND activationHeight < ?3 AND expirationHeight >= ?3 LIMIT 2"
<< claim << maximum << nNextHeight; << claim << maximum << nNextHeight;
@ -902,7 +911,7 @@ void CClaimTrieCacheBase::getNamesInTrie(std::function<void(const std::string&)>
std::vector<uint160> CClaimTrieCacheBase::getActivatedClaims(int height) { std::vector<uint160> CClaimTrieCacheBase::getActivatedClaims(int height) {
std::vector<uint160> ret; std::vector<uint160> ret;
auto query = db << "SELECT DISTINCT claimID FROM claim WHERE activationHeight = ?1 AND blockHeight < ?1" << height; auto query = db << "SELECT DISTINCT claimID FROM claim WHERE activationHeight = ?1 AND updateHeight < ?1" << height;
for (auto&& row: query) { for (auto&& row: query) {
ret.emplace_back(); ret.emplace_back();
row >> ret.back(); row >> ret.back();
@ -911,7 +920,7 @@ std::vector<uint160> CClaimTrieCacheBase::getActivatedClaims(int height) {
} }
std::vector<uint160> CClaimTrieCacheBase::getClaimsWithActivatedSupports(int height) { std::vector<uint160> CClaimTrieCacheBase::getClaimsWithActivatedSupports(int height) {
std::vector<uint160> ret; std::vector<uint160> ret;
auto query = db << "SELECT DISTINCT supportedClaimID FROM support WHERE activationHeight = ?1 AND blockHeight < ?1" << height; auto query = db << "SELECT DISTINCT supportedClaimID FROM support WHERE activationHeight = ?1 AND updateHeight < ?1" << height;
for (auto&& row: query) { for (auto&& row: query) {
ret.emplace_back(); ret.emplace_back();
row >> ret.back(); row >> ret.back();
@ -920,7 +929,7 @@ std::vector<uint160> CClaimTrieCacheBase::getClaimsWithActivatedSupports(int hei
} }
std::vector<uint160> CClaimTrieCacheBase::getExpiredClaims(int height) { std::vector<uint160> CClaimTrieCacheBase::getExpiredClaims(int height) {
std::vector<uint160> ret; std::vector<uint160> ret;
auto query = db << "SELECT DISTINCT claimID FROM claim WHERE expirationHeight = ?1 AND blockHeight < ?1" << height; auto query = db << "SELECT DISTINCT claimID FROM claim WHERE expirationHeight = ?1 AND updateHeight < ?1" << height;
for (auto&& row: query) { for (auto&& row: query) {
ret.emplace_back(); ret.emplace_back();
row >> ret.back(); row >> ret.back();
@ -929,7 +938,7 @@ std::vector<uint160> CClaimTrieCacheBase::getExpiredClaims(int height) {
} }
std::vector<uint160> CClaimTrieCacheBase::getClaimsWithExpiredSupports(int height) { std::vector<uint160> CClaimTrieCacheBase::getClaimsWithExpiredSupports(int height) {
std::vector<uint160> ret; std::vector<uint160> ret;
auto query = db << "SELECT DISTINCT supportedClaimID FROM support WHERE expirationHeight = ?1 AND blockHeight < ?1" << height; auto query = db << "SELECT DISTINCT supportedClaimID FROM support WHERE expirationHeight = ?1 AND updateHeight < ?1" << height;
for (auto&& row: query) { for (auto&& row: query) {
ret.emplace_back(); ret.emplace_back();
row >> ret.back(); row >> ret.back();

View file

@ -81,12 +81,13 @@ public:
bool haveSupportInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const; bool haveSupportInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const;
bool addClaim(const std::string& name, const COutPoint& outPoint, const uint160& claimId, int64_t nAmount, bool addClaim(const std::string& name, const COutPoint& outPoint, const uint160& claimId, int64_t nAmount,
int nHeight, int nValidHeight = -1); int nHeight, int nValidHeight = -1, int originalHeight = -1);
bool addSupport(const std::string& name, const COutPoint& outPoint, const uint160& supportedClaimId, int64_t nAmount, bool addSupport(const std::string& name, const COutPoint& outPoint, const uint160& supportedClaimId, int64_t nAmount,
int nHeight, int nValidHeight = -1); int nHeight, int nValidHeight = -1);
bool removeClaim(const uint160& claimId, const COutPoint& outPoint, std::string& nodeName, int& validHeight); bool removeClaim(const uint160& claimId, const COutPoint& outPoint, std::string& nodeName,
int& validHeight, int& originalHeight);
bool removeSupport(const COutPoint& outPoint, std::string& nodeName, int& validHeight); bool removeSupport(const COutPoint& outPoint, std::string& nodeName, int& validHeight);
virtual bool incrementBlock(); virtual bool incrementBlock();

View file

@ -17,6 +17,7 @@
#define T_NAMES "names" #define T_NAMES "names"
#define T_EFFECTIVEAMOUNT "effectiveAmount" #define T_EFFECTIVEAMOUNT "effectiveAmount"
#define T_LASTTAKEOVERHEIGHT "lastTakeoverHeight" #define T_LASTTAKEOVERHEIGHT "lastTakeoverHeight"
#define T_ORIGINALHEIGHT "originalHeight"
#define T_SUPPORTS "supports" #define T_SUPPORTS "supports"
#define T_SUPPORTSWITHOUTCLAIM "supportsWithoutClaim" #define T_SUPPORTSWITHOUTCLAIM "supportsWithoutClaim"
#define T_TOTALNAMES "totalNames" #define T_TOTALNAMES "totalNames"
@ -83,12 +84,13 @@ S3(" ", T_NAME, " (string) the original name of this claim
S3(" ", T_VALUE, " (string) the value of this claim") \ S3(" ", T_VALUE, " (string) the value of this claim") \
S3(" ", T_ADDRESS, " (string) the destination address of this claim") \ S3(" ", T_ADDRESS, " (string) the destination address of this claim") \
S3(" ", T_CLAIMID, " (string) the claimId of the claim") \ S3(" ", T_CLAIMID, " (string) the claimId of the claim") \
S3(" ", T_TXID, " (string) the txid of the claim") \ S3(" ", T_TXID, " (string) the txid of the claim or its most recent update") \
S3(" ", T_N, " (numeric) the index of the claim in the transaction's list of outputs") \ S3(" ", T_N, " (numeric) the index of the claim in the transaction's list of outputs") \
S3(" ", T_HEIGHT, " (numeric) the height of the block in which this transaction is located") \ S3(" ", T_HEIGHT, " (numeric) the height of the block in which this transaction is located") \
S3(" ", T_VALIDATHEIGHT, " (numeric) the height at which the support became/becomes valid") \ S3(" ", T_VALIDATHEIGHT, " (numeric) the height at which the support became/becomes valid") \
S3(" ", T_AMOUNT, " (numeric) the amount of the claim") \ S3(" ", T_AMOUNT, " (numeric) the amount of the claim or its most recent update") \
S3(" ", T_EFFECTIVEAMOUNT, " (numeric) the amount plus amount from all supports associated with the claim") \ S3(" ", T_EFFECTIVEAMOUNT, " (numeric) the amount plus amount from all supports associated with the claim") \
S3(" ", T_ORIGINALHEIGHT, " (numeric) the block height where the claim was first created") \
S3(" ", T_PENDINGAMOUNT, " (numeric) expected amount when claim and its supports are all valid") \ S3(" ", T_PENDINGAMOUNT, " (numeric) expected amount when claim and its supports are all valid") \
S3(" ", T_SUPPORTS, ": [ (array of object) supports for this claim") \ S3(" ", T_SUPPORTS, ": [ (array of object) supports for this claim") \
S3(" ", T_VALUE, " (string) the metadata of the support if any") \ S3(" ", T_VALUE, " (string) the metadata of the support if any") \
@ -159,12 +161,13 @@ S3(" ", T_NAME, " (string) the original name of this claim
S3(" ", T_VALUE, " (string) the value of this claim") S3(" ", T_VALUE, " (string) the value of this claim")
S3(" ", T_ADDRESS, " (string) the destination address of this claim") S3(" ", T_ADDRESS, " (string) the destination address of this claim")
S3(" ", T_CLAIMID, " (string) the claimId of the claim") S3(" ", T_CLAIMID, " (string) the claimId of the claim")
S3(" ", T_TXID, " (string) the txid of the claim") S3(" ", T_TXID, " (string) the txid of the claim or its most recent update")
S3(" ", T_N, " (numeric) the index of the claim in the transaction's list of outputs") S3(" ", T_N, " (numeric) the index of the claim in the transaction's list of outputs")
S3(" ", T_HEIGHT, " (numeric) the height of the block in which this transaction is located") S3(" ", T_HEIGHT, " (numeric) the height of the block in which this transaction is located")
S3(" ", T_VALIDATHEIGHT, " (numeric) the height at which the claim became/becomes valid") S3(" ", T_VALIDATHEIGHT, " (numeric) the height at which the claim became/becomes valid")
S3(" ", T_AMOUNT, " (numeric) the amount of the claim") S3(" ", T_AMOUNT, " (numeric) the amount of the claim or its most recent update")
S3(" ", T_EFFECTIVEAMOUNT, " (numeric) the amount plus amount from all supports associated with the claim") S3(" ", T_EFFECTIVEAMOUNT, " (numeric) the amount plus amount from all supports associated with the claim")
S3(" ", T_ORIGINALHEIGHT, " (numeric) the block height where the claim was first created") \
S3(" ", T_PENDINGAMOUNT, " (numeric) expected amount when claim and its support got valid") S3(" ", T_PENDINGAMOUNT, " (numeric) expected amount when claim and its support got valid")
S3(" ", T_SUPPORTS, ": [ (array of object) supports for this claim") S3(" ", T_SUPPORTS, ": [ (array of object) supports for this claim")
S3(" ", T_VALUE, " (string) the metadata of the support if any") S3(" ", T_VALUE, " (string) the metadata of the support if any")

View file

@ -209,6 +209,8 @@ UniValue claimAndSupportsToJSON(const CCoinsViewCache& coinsCache, const CClaimN
auto result = claimToJSON(coinsCache, claim); auto result = claimToJSON(coinsCache, claim);
result.pushKV(T_EFFECTIVEAMOUNT, claimNsupports.effectiveAmount); result.pushKV(T_EFFECTIVEAMOUNT, claimNsupports.effectiveAmount);
if (claimNsupports.originalHeight > 0)
result.pushKV(T_ORIGINALHEIGHT, claimNsupports.originalHeight);
auto fullAmount = amountToClaim(claimNsupports); auto fullAmount = amountToClaim(claimNsupports);
if (fullAmount > claimNsupports.effectiveAmount) if (fullAmount > claimNsupports.effectiveAmount)

View file

@ -31,14 +31,14 @@ public:
} }
bool removeClaimFromTrie(const std::string& key, const COutPoint& outPoint) { bool removeClaimFromTrie(const std::string& key, const COutPoint& outPoint) {
int validHeight; int validHeight, originalHeight;
std::string nodeName; std::string nodeName;
auto p = outPoint; auto p = outPoint;
if (p.hash.IsNull()) if (p.hash.IsNull())
p.hash = Hash(key.begin(), key.end()); p.hash = Hash(key.begin(), key.end());
auto ret = removeClaim(ClaimIdHash(uint256(p.hash), p.n), p, nodeName, validHeight); auto ret = removeClaim(ClaimIdHash(uint256(p.hash), p.n), p, nodeName, validHeight, originalHeight);
assert(!ret || nodeName == key); assert(!ret || nodeName == key);
return ret; return ret;
} }

View file

@ -215,13 +215,13 @@ BOOST_AUTO_TEST_CASE(claimtriecache_normalization)
CClaimTrieCache trieCache(pclaimTrie); CClaimTrieCache trieCache(pclaimTrie);
CBlockIndex* pindex = chainActive.Tip(); CBlockIndex* pindex = chainActive.Tip();
CBlock block; CBlock block;
int amelieValidHeight; int amelieValidHeight, ameliaOriginalHeight;
std::string removed; std::string removed;
BOOST_CHECK(trieCache.shouldNormalize()); BOOST_CHECK(trieCache.shouldNormalize());
BOOST_CHECK(ReadBlockFromDisk(block, pindex, Params().GetConsensus())); BOOST_CHECK(ReadBlockFromDisk(block, pindex, Params().GetConsensus()));
BOOST_CHECK(g_chainstate.DisconnectBlock(block, pindex, coins, trieCache) == DisconnectResult::DISCONNECT_OK); BOOST_CHECK(g_chainstate.DisconnectBlock(block, pindex, coins, trieCache) == DisconnectResult::DISCONNECT_OK);
BOOST_CHECK(!trieCache.shouldNormalize()); BOOST_CHECK(!trieCache.shouldNormalize());
BOOST_CHECK(trieCache.removeClaim(ClaimIdHash(tx2.GetHash(), 0), COutPoint(tx2.GetHash(), 0), removed, amelieValidHeight)); BOOST_CHECK(trieCache.removeClaim(ClaimIdHash(tx2.GetHash(), 0), COutPoint(tx2.GetHash(), 0), removed, amelieValidHeight, ameliaOriginalHeight));
BOOST_CHECK(trieCache.getInfoForName(name, nval1)); BOOST_CHECK(trieCache.getInfoForName(name, nval1));
BOOST_CHECK_EQUAL(nval1.claimId, ClaimIdHash(tx1.GetHash(), 0)); BOOST_CHECK_EQUAL(nval1.claimId, ClaimIdHash(tx1.GetHash(), 0));
@ -301,7 +301,7 @@ BOOST_AUTO_TEST_CASE(normalization_removal_test)
CMutableTransaction sx2 = fixture.MakeSupport(fixture.GetCoinbase(), tx2, "Ab", 1); CMutableTransaction sx2 = fixture.MakeSupport(fixture.GetCoinbase(), tx2, "Ab", 1);
CClaimTrieCache cache(pclaimTrie); CClaimTrieCache cache(pclaimTrie);
int height = chainActive.Height() + 1; int height = chainActive.Height() + 1, originalHeight;
cache.addClaim("AB", COutPoint(tx1.GetHash(), 0), ClaimIdHash(tx1.GetHash(), 0), 1, height); cache.addClaim("AB", COutPoint(tx1.GetHash(), 0), ClaimIdHash(tx1.GetHash(), 0), 1, height);
cache.addClaim("Ab", COutPoint(tx2.GetHash(), 0), ClaimIdHash(tx2.GetHash(), 0), 2, height); cache.addClaim("Ab", COutPoint(tx2.GetHash(), 0), ClaimIdHash(tx2.GetHash(), 0), 2, height);
cache.addClaim("aB", COutPoint(tx3.GetHash(), 0), ClaimIdHash(tx3.GetHash(), 0), 3, height); cache.addClaim("aB", COutPoint(tx3.GetHash(), 0), ClaimIdHash(tx3.GetHash(), 0), 3, height);
@ -317,9 +317,9 @@ BOOST_AUTO_TEST_CASE(normalization_removal_test)
std::string unused; std::string unused;
BOOST_CHECK(cache.removeSupport(COutPoint(sx1.GetHash(), 0), unused, height)); BOOST_CHECK(cache.removeSupport(COutPoint(sx1.GetHash(), 0), unused, height));
BOOST_CHECK(cache.removeSupport(COutPoint(sx2.GetHash(), 0), unused, height)); BOOST_CHECK(cache.removeSupport(COutPoint(sx2.GetHash(), 0), unused, height));
BOOST_CHECK(cache.removeClaim(ClaimIdHash(tx1.GetHash(), 0), COutPoint(tx1.GetHash(), 0), unused, height)); BOOST_CHECK(cache.removeClaim(ClaimIdHash(tx1.GetHash(), 0), COutPoint(tx1.GetHash(), 0), unused, height, originalHeight));
BOOST_CHECK(cache.removeClaim(ClaimIdHash(tx2.GetHash(), 0), COutPoint(tx2.GetHash(), 0), unused, height)); BOOST_CHECK(cache.removeClaim(ClaimIdHash(tx2.GetHash(), 0), COutPoint(tx2.GetHash(), 0), unused, height, originalHeight));
BOOST_CHECK(cache.removeClaim(ClaimIdHash(tx3.GetHash(), 0), COutPoint(tx3.GetHash(), 0), unused, height)); BOOST_CHECK(cache.removeClaim(ClaimIdHash(tx3.GetHash(), 0), COutPoint(tx3.GetHash(), 0), unused, height, originalHeight));
BOOST_CHECK(cache.getClaimsForName("ab").claimsNsupports.size() == 0U); BOOST_CHECK(cache.getClaimsForName("ab").claimsNsupports.size() == 0U);
} }

View file

@ -26,10 +26,11 @@ public:
uint32_t nHeight; // if the outpoint was the last unspent: its height uint32_t nHeight; // if the outpoint was the last unspent: its height
uint32_t nClaimValidHeight; // If the outpoint was a claim or support, the height at which the claim or support should be inserted into the trie uint32_t nClaimValidHeight; // If the outpoint was a claim or support, the height at which the claim or support should be inserted into the trie
bool fIsClaim; // if the outpoint was a claim or support bool fIsClaim; // if the outpoint was a claim or support
uint32_t nClaimOriginalHeight; // If we are a claim, we need to track the original insertion height for that claim
CTxInUndo() : txout(), fCoinBase(false), nHeight(0), nClaimValidHeight(0), fIsClaim(false) {} CTxInUndo() : txout(), fCoinBase(false), nHeight(0), nClaimValidHeight(0), fIsClaim(false), nClaimOriginalHeight(0) {}
CTxInUndo(const CTxOut &txoutIn, bool fCoinBaseIn = false, uint32_t nHeightIn = 0) : CTxInUndo(const CTxOut &txoutIn, bool fCoinBaseIn = false, uint32_t nHeightIn = 0) :
txout(txoutIn), fCoinBase(fCoinBaseIn), nHeight(nHeightIn), nClaimValidHeight(0), fIsClaim(false) {} txout(txoutIn), fCoinBase(fCoinBaseIn), nHeight(nHeightIn), nClaimValidHeight(0), fIsClaim(false), nClaimOriginalHeight(0) {}
ADD_SERIALIZE_METHODS; ADD_SERIALIZE_METHODS;
@ -50,6 +51,7 @@ public:
READWRITE(REF(CTxOutCompressor(REF(txout)))); READWRITE(REF(CTxOutCompressor(REF(txout))));
READWRITE(VARINT(nClaimValidHeight)); READWRITE(VARINT(nClaimValidHeight));
READWRITE(fIsClaim); READWRITE(fIsClaim);
READWRITE(VARINT(nClaimOriginalHeight));
} }
}; };

View file

@ -1489,7 +1489,10 @@ int ApplyTxInUndo(unsigned int index, CTxUndo& txUndo, CCoinsViewCache& view, CC
// restore claim if applicable // restore claim if applicable
if (undo.fIsClaim && !undo.txout.scriptPubKey.empty()) { if (undo.fIsClaim && !undo.txout.scriptPubKey.empty()) {
auto nValidHeight = undo.nClaimValidHeight; auto nValidHeight = undo.nClaimValidHeight;
CClaimScriptUndoSpendOp undoSpend(COutPoint(out.hash, out.n), undo.txout.nValue, undo.nHeight, nValidHeight); auto nOriginalHeight = undo.nClaimOriginalHeight;
// assert(nValidHeight > 0 && nOriginalHeight > 0); // fails unit tests
CClaimScriptUndoSpendOp undoSpend(COutPoint(out.hash, out.n), undo.txout.nValue, undo.nHeight,
nValidHeight, nOriginalHeight);
ProcessClaim(undoSpend, trieCache, undo.txout.scriptPubKey); ProcessClaim(undoSpend, trieCache, undo.txout.scriptPubKey);
} }
@ -1966,7 +1969,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
for (unsigned int i = 0; i < block.vtx.size(); i++) for (unsigned int i = 0; i < block.vtx.size(); i++)
{ {
const CTransaction &tx = *(block.vtx[i]); const CTransaction &tx = *(block.vtx[i]);
std::map<unsigned int, unsigned int> mClaimUndoHeights; std::map<uint32_t, std::pair<uint32_t, uint32_t>> mClaimUndoHeights;
nInputs += tx.vin.size(); nInputs += tx.vin.size();
@ -2016,8 +2019,8 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
control.Add(vChecks); control.Add(vChecks);
CUpdateCacheCallbacks callbacks = { CUpdateCacheCallbacks callbacks = {
.findScriptKey = {}, .findScriptKey = {},
.claimUndoHeights = [&mClaimUndoHeights](int index, int nValidAtHeight) { .claimUndoHeights = [&mClaimUndoHeights](uint32_t index, uint32_t nValidAtHeight, uint32_t nOriginalHeight) {
mClaimUndoHeights.emplace(index, nValidAtHeight); mClaimUndoHeights.emplace(index, std::make_pair(nValidAtHeight, nOriginalHeight));
} }
}; };
UpdateCache(tx, trieCache, view, pindex->nHeight, callbacks); UpdateCache(tx, trieCache, view, pindex->nHeight, callbacks);
@ -2033,7 +2036,8 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
auto& txinUndos = blockundo.vtxundo.back().vprevout; auto& txinUndos = blockundo.vtxundo.back().vprevout;
for (auto itHeight = mClaimUndoHeights.begin(); itHeight != mClaimUndoHeights.end(); ++itHeight) for (auto itHeight = mClaimUndoHeights.begin(); itHeight != mClaimUndoHeights.end(); ++itHeight)
{ {
txinUndos[itHeight->first].nClaimValidHeight = itHeight->second; txinUndos[itHeight->first].nClaimValidHeight = itHeight->second.first;
txinUndos[itHeight->first].nClaimOriginalHeight = itHeight->second.second;
txinUndos[itHeight->first].fIsClaim = true; txinUndos[itHeight->first].fIsClaim = true;
} }
} }