Initial undo removal

Signed-off-by: Anthony Fieroni <bvbfan@abv.bg>
This commit is contained in:
Anthony Fieroni 2019-12-05 19:22:26 +02:00 committed by Brannon King
parent 106a4c26da
commit 0fce479923
9 changed files with 164 additions and 327 deletions

View file

@ -25,19 +25,18 @@ int CClaimTrieCacheExpirationFork::expirationTime() const
return base->nExtendedClaimExpirationTime;
}
bool CClaimTrieCacheExpirationFork::incrementBlock(insertUndoType& insertUndo, claimUndoType& expireUndo,
insertUndoType& insertSupportUndo, supportUndoType& expireSupportUndo, takeoverUndoType& takeoverUndo)
bool CClaimTrieCacheExpirationFork::incrementBlock()
{
if (CClaimTrieCacheBase::incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverUndo)) {
if (CClaimTrieCacheBase::incrementBlock()) {
expirationHeight = nNextHeight;
return true;
}
return false;
}
bool CClaimTrieCacheExpirationFork::decrementBlock(insertUndoType& insertUndo, claimUndoType& expireUndo, insertUndoType& insertSupportUndo, supportUndoType& expireSupportUndo)
bool CClaimTrieCacheExpirationFork::decrementBlock()
{
if (CClaimTrieCacheBase::decrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo)) {
if (CClaimTrieCacheBase::decrementBlock()) {
expirationHeight = nNextHeight;
return true;
}
@ -53,9 +52,9 @@ void CClaimTrieCacheExpirationFork::initializeIncrement()
forkForExpirationChange(true);
}
bool CClaimTrieCacheExpirationFork::finalizeDecrement(takeoverUndoType& takeoverUndo)
bool CClaimTrieCacheExpirationFork::finalizeDecrement()
{
auto ret = CClaimTrieCacheBase::finalizeDecrement(takeoverUndo);
auto ret = CClaimTrieCacheBase::finalizeDecrement();
if (ret && nNextHeight == base->nExtendedClaimExpirationForkHeight)
forkForExpirationChange(false);
return ret;
@ -137,41 +136,30 @@ std::string CClaimTrieCacheNormalizationFork::normalizeClaimName(const std::stri
return normalized;
}
bool CClaimTrieCacheNormalizationFork::normalizeAllNamesInTrieIfNecessary(takeoverUndoType& takeoverUndo)
bool CClaimTrieCacheNormalizationFork::normalizeAllNamesInTrieIfNecessary()
{
ensureTransacting();
// make the new nodes
db << "INSERT INTO nodes(name) SELECT NORMALIZED(name) AS nn FROM claims WHERE nn != nodeName "
"AND validHeight <= ?1 AND expirationHeight > ?1 ON CONFLICT(name) DO UPDATE SET hash = NULL" << nNextHeight;
db << "UPDATE nodes SET hash = NULL WHERE name IN "
"(SELECT NORMALIZED(name) AS nn FROM supports WHERE nn != nodeName "
"AND validHeight <= ?1 AND expirationHeight > ?1)" << nNextHeight;
db << "INSERT INTO nodes(name) "
"SELECT NORMALIZED(name) AS nc FROM claims WHERE nc != nodeName "
"AND activationHeight <= ?1 AND expirationHeight > ?1 "
"UNION SELECT NORMALIZED(name) AS ns FROM supports WHERE ns != nodeName "
"AND activationHeight <= ?1 AND expirationHeight > ?1 "
"ON CONFLICT(name) DO UPDATE SET hash = NULL" << nNextHeight;
// update the claims and supports
db << "UPDATE claims SET nodeName = NORMALIZED(name) WHERE validHeight <= ?1 AND expirationHeight > ?1" << nNextHeight;
db << "UPDATE supports SET nodeName = NORMALIZED(name) WHERE validHeight <= ?1 AND expirationHeight > ?1" << nNextHeight;
db << "UPDATE claims SET nodeName = NORMALIZED(name) WHERE activationHeight <= ?1 AND expirationHeight > ?1" << nNextHeight;
db << "UPDATE supports SET nodeName = NORMALIZED(name) WHERE activationHeight <= ?1 AND expirationHeight > ?1" << nNextHeight;
// remove the old nodes
auto query = db << "SELECT name, IFNULL(takeoverHeight, 0), takeoverID FROM nodes WHERE name NOT IN "
"(SELECT nodeName FROM claims WHERE validHeight <= ?1 AND expirationHeight > ?1)";
for (auto&& row: query) {
std::string name;
int takeoverHeight;
std::unique_ptr<CUint160> takeoverID;
row >> name >> takeoverHeight >> takeoverID;
if (name.empty()) continue; // preserve our root node
if (takeoverHeight > 0)
takeoverUndo.emplace_back(name, std::make_pair(takeoverHeight, takeoverID ? *takeoverID : CUint160()));
// we need to let the tree structure method do the actual node delete:
db << "UPDATE nodes SET hash = NULL WHERE name = ?" << name;
}
db << "UPDATE nodes SET hash = NULL WHERE takeoverHeight IS NULL";
db << "UPDATE nodes SET hash = NULL WHERE name NOT IN "
"(SELECT nodeName FROM claims WHERE activationHeight <= ?1 AND expirationHeight > ?1 "
"UNION SELECT nodeName FROM supports WHERE activationHeight <= ?1 AND expirationHeight > ?1)" << nNextHeight;
// work around a bug in the old implementation:
db << "UPDATE claims SET validHeight = ?1 " // force a takeover on these
"WHERE blockHeight < ?1 AND validHeight > ?1 AND nodeName != name" << nNextHeight;
db << "UPDATE claims SET activationHeight = ?1 " // force a takeover on these
"WHERE blockHeight < ?1 AND activationHeight > ?1 AND nodeName != name" << nNextHeight;
return true;
}
@ -180,34 +168,37 @@ bool CClaimTrieCacheNormalizationFork::unnormalizeAllNamesInTrieIfNecessary()
{
ensureTransacting();
db << "INSERT INTO nodes(name) SELECT name FROM claims WHERE name != nodeName "
"AND validHeight < ?1 AND expirationHeight > ?1 ON CONFLICT(name) DO UPDATE SET hash = NULL" << nNextHeight;
db << "INSERT INTO nodes(name) "
"SELECT name FROM claims WHERE name != nodeName "
"AND activationHeight < ?1 AND expirationHeight > ?1 "
"UNION SELECT name FROM supports WHERE name != nodeName "
"AND activationHeight < ?1 AND expirationHeight > ?1 "
"ON CONFLICT(name) DO UPDATE SET hash = NULL" << nNextHeight;
db << "UPDATE nodes SET hash = NULL WHERE name IN "
"(SELECT name FROM supports WHERE name != nodeName UNION "
"SELECT nodeName FROM supports WHERE name != nodeName UNION "
"SELECT nodeName FROM claims WHERE name != nodeName)";
"(SELECT nodeName FROM supports WHERE name != nodeName "
"UNION SELECT nodeName FROM claims WHERE name != nodeName)";
db << "UPDATE claims SET nodeName = name";
db << "UPDATE supports SET nodeName = name";
// we need to let the tree structure method do the actual node delete
db << "UPDATE nodes SET hash = NULL WHERE name NOT IN "
"(SELECT name FROM claims)";
"(SELECT DISTINCT name FROM claims)";
return true;
}
bool CClaimTrieCacheNormalizationFork::incrementBlock(insertUndoType& insertUndo, claimUndoType& expireUndo,
insertUndoType& insertSupportUndo, supportUndoType& expireSupportUndo, takeoverUndoType& takeoverUndo)
bool CClaimTrieCacheNormalizationFork::incrementBlock()
{
if (nNextHeight == base->nNormalizedNameForkHeight)
normalizeAllNamesInTrieIfNecessary(takeoverUndo);
return CClaimTrieCacheExpirationFork::incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverUndo);
normalizeAllNamesInTrieIfNecessary();
return CClaimTrieCacheExpirationFork::incrementBlock();
}
bool CClaimTrieCacheNormalizationFork::decrementBlock(insertUndoType& insertUndo, claimUndoType& expireUndo, insertUndoType& insertSupportUndo, supportUndoType& expireSupportUndo)
bool CClaimTrieCacheNormalizationFork::decrementBlock()
{
auto ret = CClaimTrieCacheExpirationFork::decrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo);
auto ret = CClaimTrieCacheExpirationFork::decrementBlock();
if (ret && nNextHeight == base->nNormalizedNameForkHeight)
unnormalizeAllNamesInTrieIfNecessary();
return ret;
@ -417,9 +408,9 @@ void CClaimTrieCacheHashFork::initializeIncrement()
}
}
bool CClaimTrieCacheHashFork::finalizeDecrement(takeoverUndoType& takeoverUndo)
bool CClaimTrieCacheHashFork::finalizeDecrement()
{
auto ret = CClaimTrieCacheNormalizationFork::finalizeDecrement(takeoverUndo);
auto ret = CClaimTrieCacheNormalizationFork::finalizeDecrement();
if (ret && nNextHeight == base->nAllClaimsInMerkleForkHeight - 1) {
ensureTransacting();
db << "UPDATE nodes SET hash = NULL";

View file

@ -12,18 +12,9 @@ public:
int expirationTime() const override;
virtual void initializeIncrement();
bool finalizeDecrement(takeoverUndoType& takeoverHeightUndo) override;
bool incrementBlock(insertUndoType& insertUndo,
claimUndoType& expireUndo,
insertUndoType& insertSupportUndo,
supportUndoType& expireSupportUndo,
takeoverUndoType& takeoverHeightUndo) override;
bool decrementBlock(insertUndoType& insertUndo,
claimUndoType& expireUndo,
insertUndoType& insertSupportUndo,
supportUndoType& expireSupportUndo) override;
bool incrementBlock() override;
bool decrementBlock() override;
bool finalizeDecrement() override;
protected:
int expirationHeight;
@ -43,16 +34,8 @@ public:
// see: https://unicode.org/reports/tr15/#Norm_Forms
std::string normalizeClaimName(const std::string& name, bool force = false) const; // public only for validating name field on update op
bool incrementBlock(insertUndoType& insertUndo,
claimUndoType& expireUndo,
insertUndoType& insertSupportUndo,
supportUndoType& expireSupportUndo,
takeoverUndoType& takeoverHeightUndo) override;
bool decrementBlock(insertUndoType& insertUndo,
claimUndoType& expireUndo,
insertUndoType& insertSupportUndo,
supportUndoType& expireSupportUndo) override;
bool incrementBlock() override;
bool decrementBlock() override;
bool getProofForName(const std::string& name, const CUint160& claim, CClaimTrieProof& proof) override;
bool getInfoForName(const std::string& name, CClaimValue& claim, int heightOffset = 0) const override;
@ -63,7 +46,7 @@ protected:
int getDelayForName(const std::string& name, const CUint160& claimId) const override;
private:
bool normalizeAllNamesInTrieIfNecessary(takeoverUndoType& takeovers);
bool normalizeAllNamesInTrieIfNecessary();
bool unnormalizeAllNamesInTrieIfNecessary();
};
@ -74,7 +57,7 @@ public:
bool getProofForName(const std::string& name, const CUint160& claim, CClaimTrieProof& proof) override;
void initializeIncrement() override;
bool finalizeDecrement(takeoverUndoType& takeoverHeightUndo) override;
bool finalizeDecrement() override;
bool allowSupportMetadata() const;

View file

@ -25,8 +25,6 @@
%ignore CSupportValue(CSupportValue &&);
%ignore CTxOutPoint(CTxOutPoint &&);
#define SWIG_INTERFACE
%include "uints.h"
%include "txoutpoint.h"
%include "data.h"
@ -45,19 +43,11 @@
%template(claimsNsupports) std::vector<CClaimNsupports>;
%template(proofPair) std::pair<bool, CUint256>;
%template(intClaimPair) std::pair<int, CUint160>;
%template(proofNodePair) std::pair<unsigned char, CUint256>;
%template(claimUndoPair) std::pair<std::string, CClaimValue>;
%template(supportUndoPair) std::pair<std::string, CSupportValue>;
%template(takeoverUndoPair) std::pair<std::string, std::pair<int, CUint160>>;
%template(proofNodes) std::vector<CClaimTrieProofNode>;
%template(proofPairs) std::vector<std::pair<bool, CUint256>>;
%template(proofNodeChildren) std::vector<std::pair<unsigned char, CUint256>>;
%template(claimUndoType) std::vector<claimUndoPair>;
%template(supportUndoType) std::vector<supportUndoPair>;
%template(insertUndoType) std::vector<CNameOutPointHeightType>;
%template(takeoverUndoType) std::vector<takeoverUndoPair>;
%inline %{
struct CIterateCallback {
@ -74,6 +64,6 @@ void getNamesInTrie(const CClaimTrieCache& cache, CIterateCallback* cb)
}
%}
%typemap(in,numinputs=0) CClaimValue&, CClaimTrieProof&, insertUndoType&, claimUndoType&, supportUndoType&, takeoverUndoType& %{
%typemap(in,numinputs=0) CClaimValue&, CClaimTrieProof& %{
$1 = &$input;
%}

View file

@ -59,29 +59,36 @@ CClaimTrie::CClaimTrie(bool fWipe, int height,
nExtendedClaimExpirationForkHeight(nExtendedClaimExpirationForkHeight),
nAllClaimsInMerkleForkHeight(nAllClaimsInMerkleForkHeight)
{
db << "CREATE TABLE IF NOT EXISTS nodes (name TEXT NOT NULL PRIMARY KEY, parent TEXT REFERENCES nodes(name) DEFERRABLE INITIALLY DEFERRED, "
"hash BLOB COLLATE BINARY, takeoverHeight INTEGER, takeoverID BLOB COLLATE BINARY)";
db << "CREATE TABLE IF NOT EXISTS nodes (name TEXT NOT NULL PRIMARY KEY, "
"parent TEXT REFERENCES nodes(name) DEFERRABLE INITIALLY DEFERRED, "
"hash BLOB COLLATE BINARY)";
db << "CREATE INDEX IF NOT EXISTS nodes_hash ON nodes (hash)";
db << "CREATE INDEX IF NOT EXISTS nodes_parent ON nodes (parent)";
db << "CREATE TABLE IF NOT EXISTS takeover (name TEXT NOT NULL, height INTEGER NOT NULL, "
"claimID BLOB COLLATE BINARY, UNIQUE (name, height, claimID));";
db << "CREATE INDEX IF NOT EXISTS takeover_name ON takeover (name)";
db << "CREATE INDEX IF NOT EXISTS takeover_height ON takeover (height)";
db << "CREATE TABLE IF NOT EXISTS claims (claimID BLOB NOT NULL COLLATE BINARY PRIMARY KEY, name TEXT NOT NULL, "
"nodeName TEXT NOT NULL REFERENCES nodes(name) DEFERRABLE INITIALLY DEFERRED, "
"txID BLOB NOT NULL COLLATE BINARY, txN INTEGER NOT NULL, blockHeight INTEGER NOT NULL, "
"validHeight INTEGER NOT NULL, expirationHeight INTEGER NOT NULL, "
"amount INTEGER NOT NULL, metadata BLOB COLLATE BINARY);";
"validHeight INTEGER NOT NULL, activationHeight INTEGER NOT NULL, "
"expirationHeight INTEGER NOT NULL, amount INTEGER NOT NULL, metadata BLOB COLLATE BINARY);";
db << "CREATE INDEX IF NOT EXISTS claims_validHeight ON claims (validHeight)";
db << "CREATE INDEX IF NOT EXISTS claims_activationHeight ON claims (activationHeight)";
db << "CREATE INDEX IF NOT EXISTS claims_expirationHeight ON claims (expirationHeight)";
db << "CREATE INDEX IF NOT EXISTS claims_nodeName ON claims (nodeName)";
db << "CREATE TABLE IF NOT EXISTS supports (txID BLOB NOT NULL COLLATE BINARY, txN INTEGER NOT NULL, "
"supportedClaimID BLOB NOT NULL COLLATE BINARY, name TEXT NOT NULL, nodeName TEXT NOT NULL, "
"blockHeight INTEGER NOT NULL, validHeight INTEGER NOT NULL, expirationHeight INTEGER NOT NULL, "
"amount INTEGER NOT NULL, metadata BLOB COLLATE BINARY, PRIMARY KEY(txID, txN));";
"blockHeight INTEGER NOT NULL, validHeight INTEGER NOT NULL, activationHeight INTEGER NOT NULL, "
"expirationHeight INTEGER NOT NULL, amount INTEGER NOT NULL, metadata BLOB COLLATE BINARY, PRIMARY KEY(txID, txN));";
db << "CREATE INDEX IF NOT EXISTS supports_supportedClaimID ON supports (supportedClaimID)";
db << "CREATE INDEX IF NOT EXISTS supports_validHeight ON supports (validHeight)";
db << "CREATE INDEX IF NOT EXISTS supports_activationHeight ON supports (activationHeight)";
db << "CREATE INDEX IF NOT EXISTS supports_expirationHeight ON supports (expirationHeight)";
db << "CREATE INDEX IF NOT EXISTS supports_nodeName ON supports (nodeName)";
@ -95,6 +102,7 @@ CClaimTrie::CClaimTrie(bool fWipe, int height,
db << "DELETE FROM nodes";
db << "DELETE FROM claims";
db << "DELETE FROM supports";
db << "DELETE FROM takeover";
}
db << "INSERT OR IGNORE INTO nodes(name, hash) VALUES('', ?)" << one; // ensure that we always have our root node
@ -120,14 +128,14 @@ bool CClaimTrie::SyncToDisk()
bool CClaimTrie::empty()
{
int64_t count;
db << "SELECT COUNT(*) FROM (SELECT 1 FROM claims WHERE validHeight < ?1 AND expirationHeight >= ?1 LIMIT 1)" << nNextHeight >> count;
db << "SELECT COUNT(*) FROM (SELECT 1 FROM claims WHERE activationHeight < ?1 AND expirationHeight >= ?1 LIMIT 1)" << nNextHeight >> count;
return count == 0;
}
bool CClaimTrieCacheBase::haveClaim(const std::string& name, const CTxOutPoint& outPoint) const
{
auto query = db << "SELECT 1 FROM claims WHERE nodeName = ?1 AND txID = ?2 AND txN = ?3 "
"AND validHeight < ?4 AND expirationHeight >= ?4 LIMIT 1"
"AND activationHeight < ?4 AND expirationHeight >= ?4 LIMIT 1"
<< name << outPoint.hash << outPoint.n << nNextHeight;
return query.begin() != query.end();
}
@ -135,7 +143,7 @@ bool CClaimTrieCacheBase::haveClaim(const std::string& name, const CTxOutPoint&
bool CClaimTrieCacheBase::haveSupport(const std::string& name, const CTxOutPoint& outPoint) const
{
auto query = db << "SELECT 1 FROM supports WHERE nodeName = ?1 AND txID = ?2 AND txN = ?3 "
"AND validHeight < ?4 AND expirationHeight >= ?4 LIMIT 1"
"AND activationHeight < ?4 AND expirationHeight >= ?4 LIMIT 1"
<< name << outPoint.hash << outPoint.n << nNextHeight;
return query.begin() != query.end();
}
@ -143,7 +151,7 @@ bool CClaimTrieCacheBase::haveSupport(const std::string& name, const CTxOutPoint
supportEntryType CClaimTrieCacheBase::getSupportsForName(const std::string& name) const
{
// includes values that are not yet valid
auto query = db << "SELECT supportedClaimID, txID, txN, blockHeight, validHeight, amount "
auto query = db << "SELECT supportedClaimID, txID, txN, blockHeight, activationHeight, amount "
"FROM supports WHERE nodeName = ? AND expirationHeight >= ?" << name << nNextHeight;
supportEntryType ret;
for (auto&& row: query) {
@ -157,8 +165,8 @@ supportEntryType CClaimTrieCacheBase::getSupportsForName(const std::string& name
bool CClaimTrieCacheBase::haveClaimInQueue(const std::string& name, const CTxOutPoint& outPoint, int& nValidAtHeight) const
{
auto query = db << "SELECT validHeight FROM claims WHERE nodeName = ? AND txID = ? AND txN = ? "
"AND validHeight >= ? AND expirationHeight >= validHeight LIMIT 1"
auto query = db << "SELECT activationHeight FROM claims WHERE nodeName = ? AND txID = ? AND txN = ? "
"AND activationHeight >= ? AND expirationHeight >= activationHeight LIMIT 1"
<< name << outPoint.hash << outPoint.n << nNextHeight;
for (auto&& row: query) {
row >> nValidAtHeight;
@ -169,8 +177,8 @@ bool CClaimTrieCacheBase::haveClaimInQueue(const std::string& name, const CTxOut
bool CClaimTrieCacheBase::haveSupportInQueue(const std::string& name, const CTxOutPoint& outPoint, int& nValidAtHeight) const
{
auto query = db << "SELECT validHeight FROM supports WHERE nodeName = ? AND txID = ? AND txN = ? "
"AND validHeight >= ? AND expirationHeight >= validHeight LIMIT 1"
auto query = db << "SELECT activationHeight FROM supports WHERE nodeName = ? AND txID = ? AND txN = ? "
"AND activationHeight >= ? AND expirationHeight >= activationHeight LIMIT 1"
<< name << outPoint.hash << outPoint.n << nNextHeight;
for (auto&& row: query) {
row >> nValidAtHeight;
@ -183,7 +191,7 @@ bool CClaimTrieCacheBase::deleteNodeIfPossible(const std::string& name, std::str
{
if (name.empty()) return false;
// to remove a node it must have one or less children and no claims
db << "SELECT COUNT(*) FROM (SELECT 1 FROM claims WHERE nodeName = ?1 AND validHeight < ?2 AND expirationHeight >= ?2 LIMIT 1)"
db << "SELECT COUNT(*) FROM (SELECT 1 FROM claims WHERE nodeName = ?1 AND activationHeight < ?2 AND expirationHeight >= ?2 LIMIT 1)"
<< name << nNextHeight >> claims;
if (claims > 0) return false; // still has claims
// we now know it has no claims, but we need to check its children
@ -308,7 +316,7 @@ std::size_t CClaimTrieCacheBase::getTotalNamesInTrie() const
{
// you could do this select from the nodes table, but you would have to ensure it is not dirty first
std::size_t ret;
db << "SELECT COUNT(DISTINCT nodeName) FROM claims WHERE validHeight < ?1 AND expirationHeight >= ?1"
db << "SELECT COUNT(DISTINCT nodeName) FROM claims WHERE activationHeight < ?1 AND expirationHeight >= ?1"
<< nNextHeight >> ret;
return ret;
}
@ -316,7 +324,7 @@ std::size_t CClaimTrieCacheBase::getTotalNamesInTrie() const
std::size_t CClaimTrieCacheBase::getTotalClaimsInTrie() const
{
std::size_t ret;
db << "SELECT COUNT(*) FROM claims WHERE validHeight < ?1 AND expirationHeight >= ?1"
db << "SELECT COUNT(*) FROM claims WHERE activationHeight < ?1 AND expirationHeight >= ?1"
<< nNextHeight >> ret;
return ret;
}
@ -328,12 +336,12 @@ int64_t CClaimTrieCacheBase::getTotalValueOfClaimsInTrie(bool fControllingOnly)
"SELECT SUM(amount) FROM (SELECT c.amount as amount, "
"(SELECT(SELECT IFNULL(SUM(s.amount),0)+c.amount FROM supports s "
"WHERE s.supportedClaimID = c.claimID AND c.nodeName = s.nodeName "
"AND s.validHeight < ?1 AND s.expirationHeight >= ?1) as effective "
"AND s.activationHeight < ?1 AND s.expirationHeight >= ?1) as effective "
"ORDER BY effective DESC LIMIT 1) as winner FROM claims c "
"WHERE c.validHeight < ?1 AND c.expirationHeight >= ?1 GROUP BY c.nodeName)"
"WHERE c.activationHeight < ?1 AND c.expirationHeight >= ?1 GROUP BY c.nodeName)"
:
"SELECT SUM(amount) FROM (SELECT c.amount as amount "
"FROM claims c WHERE c.validHeight < ?1 AND s.expirationHeight >= ?1)";
"FROM claims c WHERE c.activationHeight < ?1 AND s.expirationHeight >= ?1)";
db << query << nNextHeight >> ret;
return ret;
@ -341,8 +349,8 @@ int64_t CClaimTrieCacheBase::getTotalValueOfClaimsInTrie(bool fControllingOnly)
bool CClaimTrieCacheBase::getInfoForName(const std::string& name, CClaimValue& claim, int heightOffset) const
{
auto nextHeight = nNextHeight + heightOffset;
auto ret = false;
auto nextHeight = nNextHeight + heightOffset;
for (auto&& row: claimHashQuery << nextHeight << name) {
row >> claim.outPoint.hash >> claim.outPoint.n >> claim.claimId
>> claim.nHeight >> claim.nValidAtHeight >> claim.nAmount >> claim.nEffectiveAmount;
@ -355,15 +363,13 @@ bool CClaimTrieCacheBase::getInfoForName(const std::string& name, CClaimValue& c
CClaimSupportToName CClaimTrieCacheBase::getClaimsForName(const std::string& name) const
{
int nLastTakeoverHeight = 0;
db << "SELECT takeoverHeight FROM nodes WHERE name = ?" << name
>> [&nLastTakeoverHeight](int takeoverHeight) {
nLastTakeoverHeight = takeoverHeight;
};
int nLastTakeoverHeight;
db << "SELECT IFNULL(MAX(height), 0) FROM takeover WHERE name = ?" << name
>> nLastTakeoverHeight;
claimEntryType claims;
{
auto query = db << "SELECT claimID, txID, txN, blockHeight, validHeight, amount "
auto query = db << "SELECT claimID, txID, txN, blockHeight, activationHeight, amount "
"FROM claims WHERE nodeName = ? AND expirationHeight >= ?"
<< name << nNextHeight;
for (auto &&row: query) {
@ -429,7 +435,9 @@ bool CClaimTrieCacheBase::checkConsistency()
{
// verify that all claims hash to the values on the nodes
auto query = db << "SELECT name, hash, IFNULL(takeoverHeight, 0) FROM nodes";
auto query = db << "SELECT n.name, n.hash, "
"(SELECT t.height FROM takeover t WHERE t.name = n.name "
"ORDER BY t.height DESC LIMIT 1) FROM nodes n";
for (auto&& row: query) {
std::string name;
CUint256 hash;
@ -489,16 +497,21 @@ bool CClaimTrieCacheBase::flush()
CClaimTrieCacheBase::CClaimTrieCacheBase(CClaimTrie* base)
: base(base), db(base->dbFile, sharedConfig), transacting(false),
childHashQuery(db << "SELECT name, hash, IFNULL(takeoverHeight, 0) FROM nodes WHERE parent = ? ORDER BY name"),
claimHashQuery(db << "SELECT c.txID, c.txN, c.claimID, c.blockHeight, c.validHeight, c.amount, "
"(SELECT IFNULL(SUM(s.amount),0)+c.amount FROM supports s WHERE s.supportedClaimID = c.claimID "
"AND s.nodeName = c.nodeName AND s.validHeight < ?1 AND s.expirationHeight >= ?1) as effectiveAmount "
"FROM claims c WHERE c.nodeName = ?2 AND c.validHeight < ?1 AND c.expirationHeight >= ?1 "
childHashQuery(db << "SELECT n.name, n.hash, (SELECT t.height FROM takeover t "
"WHERE t.name = n.name ORDER BY t.height DESC LIMIT 1) FROM nodes n "
"WHERE n.parent = ? ORDER BY n.name"),
claimHashQuery(db << "SELECT c.txID, c.txN, c.claimID, c.blockHeight, c.activationHeight, c.amount, "
"(SELECT IFNULL(SUM(s.amount),0)+c.amount FROM supports s "
"WHERE s.supportedClaimID = c.claimID AND s.nodeName = c.nodeName "
"AND s.activationHeight < ?1 AND s.expirationHeight >= ?1) as effectiveAmount "
"FROM claims c WHERE c.nodeName = ?2 AND c.activationHeight < ?1 "
"AND c.expirationHeight >= ?1 "
"ORDER BY effectiveAmount DESC, c.blockHeight, c.txID, c.txN"),
proofClaimQuery("SELECT name, IFNULL(takeoverHeight, 0) FROM nodes WHERE "
"name IN (WITH RECURSIVE prefix(p) AS (VALUES(?) UNION ALL "
proofClaimQuery("SELECT n.name, (SELECT t.height FROM takeover t WHERE t.name = n.name "
"ORDER BY t.height DESC LIMIT 1) FROM nodes n "
"WHERE n.name IN (WITH RECURSIVE prefix(p) AS (VALUES(?) UNION ALL "
"SELECT POPS(p) FROM prefix WHERE p != '') SELECT p FROM prefix) "
"ORDER BY name")
"ORDER BY n.name")
{
assert(base);
nNextHeight = base->nNextHeight;
@ -531,14 +544,15 @@ CUint256 CClaimTrieCacheBase::getMerkleHash()
ensureTreeStructureIsUpToDate();
CUint256 hash;
db << "SELECT hash FROM nodes WHERE name = ''"
>>[&hash](std::unique_ptr<CUint256> rootHash) {
>> [&hash](std::unique_ptr<CUint256> rootHash) {
if (rootHash)
hash = std::move(*rootHash);
};
if (!hash.IsNull())
return hash;
assert(transacting); // no data changed but we didn't have the root hash there already?
db << "SELECT name, IFNULL(takeoverHeight, 0) FROM nodes WHERE hash IS NULL ORDER BY SIZE(name) DESC"
db << "SELECT n.name, (SELECT t.height FROM takeover t WHERE t.name = n.name "
"ORDER BY t.height DESC LIMIT 1) FROM nodes n WHERE n.hash IS NULL ORDER BY SIZE(n.name) DESC"
>> [this, &hash](const std::string& name, int takeoverHeight) {
hash = computeNodeHash(name, takeoverHeight);
db << "UPDATE nodes SET hash = ? WHERE name = ?" << hash << name;
@ -548,7 +562,9 @@ CUint256 CClaimTrieCacheBase::getMerkleHash()
bool CClaimTrieCacheBase::getLastTakeoverForName(const std::string& name, CUint160& claimId, int& takeoverHeight) const
{
auto query = db << "SELECT takeoverHeight, takeoverID FROM nodes WHERE name = ? AND takeoverID IS NOT NULL" << name;
auto query = db << "SELECT t.height, t.claimID FROM takeover t JOIN claims c "
"ON t.claimID = c.claimID AND c.expirationHeight > ?1 "
"WHERE t.name = ?2 ORDER BY t.height DESC LIMIT 1" << nNextHeight << name;
auto it = query.begin();
if (it == query.end())
return false;
@ -578,9 +594,9 @@ bool CClaimTrieCacheBase::addClaim(const std::string& name, const CTxOutPoint& o
auto nodeName = adjustNameForValidHeight(name, nValidHeight);
auto expires = expirationTime() + nHeight;
db << "INSERT INTO claims(claimID, name, nodeName, txID, txN, amount, blockHeight, validHeight, expirationHeight, metadata) "
"VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" << claimId << name << nodeName
<< outPoint.hash << outPoint.n << nAmount << nHeight << nValidHeight << expires << metadata;
db << "INSERT INTO claims(claimID, name, nodeName, txID, txN, amount, blockHeight, validHeight, activationHeight, expirationHeight, metadata) "
"VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
<< claimId << name << nodeName << outPoint.hash << outPoint.n << nAmount << nHeight << nValidHeight << nValidHeight << expires << metadata;
if (nValidHeight < nNextHeight)
db << "INSERT INTO nodes(name) VALUES(?) ON CONFLICT(name) DO UPDATE SET hash = NULL" << nodeName;
@ -599,9 +615,9 @@ bool CClaimTrieCacheBase::addSupport(const std::string& name, const CTxOutPoint&
auto nodeName = adjustNameForValidHeight(name, nValidHeight);
auto expires = expirationTime() + nHeight;
db << "INSERT INTO supports(supportedClaimID, name, nodeName, txID, txN, amount, blockHeight, validHeight, expirationHeight, metadata) "
"VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" << supportedClaimId << name << nodeName
<< outPoint.hash << outPoint.n << nAmount << nHeight << nValidHeight << expires << metadata;
db << "INSERT INTO supports(supportedClaimID, name, nodeName, txID, txN, amount, blockHeight, validHeight, activationHeight, expirationHeight, metadata) "
"VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
<< supportedClaimId << name << nodeName << outPoint.hash << outPoint.n << nAmount << nHeight << nValidHeight << nValidHeight << expires << metadata;
if (nValidHeight < nNextHeight)
db << "UPDATE nodes SET hash = NULL WHERE name = ?" << nodeName;
@ -619,7 +635,7 @@ bool CClaimTrieCacheBase::removeClaim(const CUint160& claimId, const CTxOutPoint
// 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
auto query = db << "SELECT nodeName, validHeight FROM claims WHERE claimID = ? AND txID = ? AND txN = ? AND expirationHeight >= ?"
auto query = db << "SELECT nodeName, activationHeight FROM claims WHERE claimID = ? AND txID = ? AND txN = ? AND expirationHeight >= ?"
<< claimId << outPoint.hash << outPoint.n << nNextHeight;
auto it = query.begin();
if (it == query.end()) return false;
@ -634,7 +650,7 @@ bool CClaimTrieCacheBase::removeClaim(const CUint160& claimId, const CTxOutPoint
// we had a bug in the old code where that situation would force a zero delay on re-add
if (true) { // TODO: hard fork this out (which we already tried once but failed)
db << "SELECT nodeName FROM claims WHERE nodeName LIKE ?1 "
"AND validHeight < ?2 AND expirationHeight > ?2 ORDER BY nodeName LIMIT 1"
"AND activationHeight < ?2 AND expirationHeight > ?2 ORDER BY nodeName LIMIT 1"
<< nodeName + '%' << nNextHeight
>> [this, &nodeName](const std::string& shortestMatch) {
if (shortestMatch != nodeName)
@ -649,7 +665,7 @@ bool CClaimTrieCacheBase::removeSupport(const CTxOutPoint& outPoint, std::string
{
ensureTransacting();
auto query = db << "SELECT nodeName, validHeight FROM supports WHERE txID = ? AND txN = ? AND expirationHeight >= ?"
auto query = db << "SELECT nodeName, activationHeight FROM supports WHERE txID = ? AND txN = ? AND expirationHeight >= ?"
<< outPoint.hash << outPoint.n << nNextHeight;
auto it = query.begin();
if (it == query.end()) return false;
@ -1107,9 +1123,7 @@ static const boost::container::flat_map<std::pair<int, std::string>, int> takeov
{{658098, "le-temps-nous-glisse-entre-les-doigts"}, 600099},
};
bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimUndoType& expireUndo,
insertUndoType& insertSupportUndo, supportUndoType& expireSupportUndo,
takeoverUndoType& takeoverUndo)
bool CClaimTrieCacheBase::incrementBlock()
{
// the plan:
// for every claim and support that becomes active this block set its node hash to null (aka, dirty)
@ -1118,65 +1132,25 @@ bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimUndoTy
ensureTransacting();
db << "INSERT INTO nodes(name) SELECT nodeName FROM claims "
"WHERE validHeight = ?1 AND expirationHeight > ?1 "
"WHERE (activationHeight = ?1 AND expirationHeight > ?1) "
"OR expirationHeight = ?1 "
"UNION SELECT nodeName FROM supports "
"WHERE (activationHeight = ?1 AND expirationHeight > ?1) "
"OR expirationHeight = ?1 "
"ON CONFLICT(name) DO UPDATE SET hash = NULL" << nNextHeight;
db << "UPDATE nodes SET hash = NULL WHERE name IN "
"(SELECT nodeName FROM supports WHERE validHeight = ?1 AND expirationHeight > ?1)" << nNextHeight;
assert(expireUndo.empty());
{
auto becomingExpired = db << "SELECT txID, txN, nodeName, claimID, validHeight, blockHeight, amount "
"FROM claims WHERE expirationHeight = ?" << nNextHeight;
for (auto &&row: becomingExpired) {
CClaimValue value;
std::string name;
row >> value.outPoint.hash >> value.outPoint.n >> name
>> value.claimId >> value.nValidAtHeight >> value.nHeight >> value.nAmount;
expireUndo.emplace_back(std::move(name), std::move(value));
}
}
db << "UPDATE nodes SET hash = NULL WHERE name IN (SELECT nodeName FROM claims WHERE expirationHeight = ?)" << nNextHeight;
assert(expireSupportUndo.empty());
{
auto becomingExpired = db << "SELECT txID, txN, nodeName, supportedClaimID, validHeight, blockHeight, amount "
"FROM supports WHERE expirationHeight = ?" << nNextHeight;
for (auto &&row: becomingExpired) {
CSupportValue value;
std::string name;
row >> value.outPoint.hash >> value.outPoint.n >> name
>> value.supportedClaimId >> value.nValidAtHeight >> value.nHeight >> value.nAmount;
expireSupportUndo.emplace_back(std::move(name), std::move(value));
}
}
db << "UPDATE nodes SET hash = NULL WHERE name IN (SELECT nodeName FROM supports WHERE expirationHeight = ?)" << nNextHeight;
// takeover handling:
std::vector<std::string> takeovers;
db << "SELECT name FROM nodes WHERE hash IS NULL"
>> [&takeovers](std::string name) {
takeovers.push_back(std::move(name));
};
auto getTakeoverQuery = db << "SELECT IFNULL(takeoverHeight, 0), takeoverID FROM nodes WHERE name = ?";
auto candidateQuery = db << "UPDATE nodes SET takeoverHeight = ?, takeoverID = ? WHERE name = ?";
for (const auto& nameWithTakeover : takeovers) {
>> [this](const std::string& nameWithTakeover) {
// if somebody activates on this block and they are the new best, then everybody activates on this block
CClaimValue candidateValue;
auto hasCandidate = getInfoForName(nameWithTakeover, candidateValue, 1);
// now that they're all in get the winner:
int existingHeight;
std::unique_ptr<CUint160> existingID;
getTakeoverQuery << nameWithTakeover >> std::tie(existingHeight, existingID);
getTakeoverQuery++; // reset it
auto hasBeenSetBefore = existingID && !existingID->IsNull();
auto takeoverHappening = !hasCandidate || (hasBeenSetBefore && *existingID != candidateValue.claimId);
if (takeoverHappening && activateAllFor(insertUndo, insertSupportUndo, nameWithTakeover))
CUint160 existingID;
int existingHeight = 0;
auto hasBeenSetBefore = getLastTakeoverForName(nameWithTakeover, existingID, existingHeight);
auto takeoverHappening = !hasCandidate || (hasBeenSetBefore && existingID != candidateValue.claimId);
if (takeoverHappening && activateAllFor(nameWithTakeover))
hasCandidate = getInfoForName(nameWithTakeover, candidateValue, 1);
// This is a super ugly hack to work around bug in old code.
@ -1189,106 +1163,62 @@ bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimUndoTy
logPrint << "Takeover on " << nameWithTakeover << " at " << nNextHeight << ", happening: " << takeoverHappening << ", set before: " << hasBeenSetBefore << Clog::endl;
if (takeoverHappening || !hasBeenSetBefore) {
takeoverUndo.emplace_back(nameWithTakeover, std::make_pair(existingHeight, hasBeenSetBefore ? *existingID : CUint160()));
if (hasCandidate)
candidateQuery << nNextHeight << candidateValue.claimId << nameWithTakeover;
else
candidateQuery << nullptr << nullptr << nameWithTakeover;
candidateQuery++;
if ((takeoverHappening || !hasBeenSetBefore) && hasCandidate) {
db << "INSERT INTO takeover(name, height, claimID) VALUES(?, ?, ?)"
<< nameWithTakeover << nNextHeight << candidateValue.claimId;
assert(db.rows_modified());
}
}
};
getTakeoverQuery.used(true);
candidateQuery.used(true);
nNextHeight++;
return true;
}
bool CClaimTrieCacheBase::activateAllFor(insertUndoType& insertUndo, insertUndoType& insertSupportUndo, const std::string& name)
bool CClaimTrieCacheBase::activateAllFor(const std::string& name)
{
// now that we know a takeover is happening, we bring everybody in:
auto ret = false;
{
db << "SELECT txID, txN, validHeight FROM claims WHERE nodeName = ?1 AND validHeight > ?2 AND expirationHeight > ?2"
<< name << nNextHeight
>> [this, &insertUndo, &name](CUint256 txId, uint32_t n, int oldValidHeight) {
CTxOutPoint outPoint(std::move(txId), n);
logPrint << "Early activation of claim " << name << ", " << outPoint.ToString() << " at " << nNextHeight << Clog::endl;
insertUndo.emplace_back(name, std::move(outPoint), oldValidHeight);
};
}
// and then update them all to activate now:
db << "UPDATE claims SET validHeight = ?1 WHERE nodeName = ?2 AND validHeight > ?1 AND expirationHeight > ?1" << nNextHeight << name;
// all to activate now:
db << "UPDATE claims SET activationHeight = ?1 WHERE nodeName = ?2 AND activationHeight > ?1 AND expirationHeight > ?1" << nNextHeight << name;
ret |= db.rows_modified() > 0;
// then do the same for supports:
{
db << "SELECT txID, txN, validHeight FROM supports WHERE nodeName = ?1 AND validHeight > ?2 AND expirationHeight > ?2"
<< name << nNextHeight
>> [this, &insertSupportUndo, &name](CUint256 txId, uint32_t n, int oldValidHeight) {
CTxOutPoint outPoint(std::move(txId), n);
logPrint << "Early activation of support " << name << ", " << outPoint.ToString() << " at " << nNextHeight << Clog::endl;
insertSupportUndo.emplace_back(name, std::move(outPoint), oldValidHeight);
};
}
// and then update them all to activate now:
db << "UPDATE supports SET validHeight = ?1 WHERE nodeName = ?2 AND validHeight > ?1 AND expirationHeight > ?1" << nNextHeight << name;
db << "UPDATE supports SET activationHeight = ?1 WHERE nodeName = ?2 AND activationHeight > ?1 AND expirationHeight > ?1" << nNextHeight << name;
ret |= db.rows_modified() > 0;
return ret;
}
bool CClaimTrieCacheBase::decrementBlock(insertUndoType& insertUndo, claimUndoType& expireUndo,
insertUndoType& insertSupportUndo, supportUndoType& expireSupportUndo)
bool CClaimTrieCacheBase::decrementBlock()
{
ensureTransacting();
nNextHeight--;
auto updateNodes = "INSERT INTO nodes(name) VALUES(?) ON CONFLICT(name) DO UPDATE SET hash = NULL";
db << "INSERT INTO nodes(name) SELECT name FROM claims "
"WHERE expirationHeight = ?1 OR activationHeight = ?1 "
"UNION SELECT name FROM supports "
"WHERE expirationHeight = ?1 OR activationHeight = ?1 "
"ON CONFLICT(name) DO UPDATE SET hash = NULL"
<< nNextHeight;
// to actually delete the expired items and then restore them here I would have to look up the metadata in the block
// that doesn't sound very fun so we modified the other queries to exclude expired items
for (auto it = expireSupportUndo.crbegin(); it != expireSupportUndo.crend(); ++it)
db << updateNodes << it->first;
db << "UPDATE claims SET activationHeight = validHeight WHERE activationHeight = ?"
<< nNextHeight;
for (auto it = expireUndo.crbegin(); it != expireUndo.crend(); ++it)
db << updateNodes << it->first;
for (auto it = insertSupportUndo.crbegin(); it != insertSupportUndo.crend(); ++it) {
logPrint << "Resetting support valid height to " << it->nValidHeight << " for " << it->name << Clog::endl;
db << "UPDATE supports SET validHeight = ? WHERE txID = ? AND txN = ?"
<< it->nValidHeight << it->outPoint.hash << it->outPoint.n;
db << updateNodes << it->name;
}
for (auto it = insertUndo.crbegin(); it != insertUndo.crend(); ++it) {
logPrint << "Resetting valid height to " << it->nValidHeight << " for " << it->name << Clog::endl;
db << "UPDATE claims SET validHeight = ? WHERE nodeName = ? AND txID = ? AND txN = ?"
<< it->nValidHeight << it->name << it->outPoint.hash << it->outPoint.n;
db << updateNodes << it->name;
}
db << "UPDATE supports SET activationHeight = validHeight WHERE activationHeight = ?"
<< nNextHeight;
return true;
}
bool CClaimTrieCacheBase::finalizeDecrement(takeoverUndoType& takeoverUndo)
bool CClaimTrieCacheBase::finalizeDecrement()
{
db << "UPDATE nodes SET hash = NULL WHERE name IN "
"(SELECT nodeName FROM claims WHERE validHeight = ?1 AND expirationHeight > ?1)" << nNextHeight;
"(SELECT nodeName FROM claims WHERE activationHeight = ?1 AND expirationHeight > ?1 "
"UNION SELECT nodeName FROM supports WHERE activationHeight = ?1 AND expirationHeight > ?1 "
"UNION SELECT DISTINCT name FROM takeover WHERE height = ?1)" << nNextHeight;
db << "UPDATE nodes SET hash = NULL WHERE name IN "
"(SELECT nodeName FROM supports WHERE validHeight = ?1 AND expirationHeight > ?1)" << nNextHeight;
db << "DELETE FROM takeover WHERE height = ?" << nNextHeight;
auto updateNodes = "UPDATE nodes SET takeoverHeight = ?, takeoverID = ?, hash = NULL WHERE name = ?";
for (auto it = takeoverUndo.crbegin(); it != takeoverUndo.crend(); ++it) {
if (it->second.second.IsNull())
db << updateNodes << nullptr << nullptr << it->first;
else
db << updateNodes << it->second.first << it->second.second << it->first;
}
return true;
}
@ -1309,7 +1239,6 @@ int CClaimTrieCacheBase::getDelayForName(const std::string& name, const CUint160
removalWorkaround.erase(hit);
return 0;
}
return found ? std::min((nNextHeight - winningTakeoverHeight) / base->nProportionalDelayFactor, 4032) : 0;
}
@ -1370,8 +1299,8 @@ bool CClaimTrieCacheBase::getProofForName(const std::string& name, const CUint16
bool CClaimTrieCacheBase::findNameForClaim(std::vector<unsigned char> claim, CClaimValue& value, std::string& name) const
{
std::reverse(claim.begin(), claim.end());
auto query = db << "SELECT nodeName, claimId, txID, txN, amount, validHeight, blockHeight "
"FROM claims WHERE SUBSTR(claimID, ?) = ? AND validHeight < ? AND expirationHeight >= ?"
auto query = db << "SELECT nodeName, claimID, txID, txN, amount, activationHeight, blockHeight "
"FROM claims WHERE SUBSTR(claimID, ?) = ? AND activationHeight < ? AND expirationHeight >= ?"
<< -int(claim.size()) << claim << nNextHeight << nNextHeight;
auto hit = false;
for (auto&& row: query) {
@ -1385,7 +1314,7 @@ bool CClaimTrieCacheBase::findNameForClaim(std::vector<unsigned char> claim, CCl
void CClaimTrieCacheBase::getNamesInTrie(std::function<void(const std::string&)> callback) const
{
db << "SELECT DISTINCT nodeName FROM claims WHERE validHeight < ? AND expirationHeight >= ?"
db << "SELECT DISTINCT nodeName FROM claims WHERE activationHeight < ? AND expirationHeight >= ?"
<< nNextHeight << nNextHeight
>> [&callback](const std::string& name) {
callback(name);

View file

@ -56,24 +56,6 @@ protected:
const int64_t nAllClaimsInMerkleForkHeight;
};
template <typename T>
using queueEntryType = std::pair<std::string, T>;
#ifdef SWIG_INTERFACE // swig has a problem with using in typedef
using claimUndoPair = std::pair<std::string, CClaimValue>;
using supportUndoPair = std::pair<std::string, CSupportValue>;
using takeoverUndoPair = std::pair<std::string, std::pair<int, CUint160>>;
#else
using claimUndoPair = queueEntryType<CClaimValue>;
using supportUndoPair = queueEntryType<CSupportValue>;
using takeoverUndoPair = queueEntryType<std::pair<int, CUint160>>;
#endif
typedef std::vector<claimUndoPair> claimUndoType;
typedef std::vector<supportUndoPair> supportUndoType;
typedef std::vector<CNameOutPointHeightType> insertUndoType;
typedef std::vector<takeoverUndoPair> takeoverUndoType;
class CClaimTrieCacheBase
{
public:
@ -104,23 +86,14 @@ public:
bool removeClaim(const CUint160& claimId, const CTxOutPoint& outPoint, std::string& nodeName, int& validHeight);
bool removeSupport(const CTxOutPoint& outPoint, std::string& nodeName, int& validHeight);
virtual bool incrementBlock(insertUndoType& insertUndo,
claimUndoType& expireUndo,
insertUndoType& insertSupportUndo,
supportUndoType& expireSupportUndo,
takeoverUndoType& takeoverHeightUndo);
virtual bool decrementBlock(insertUndoType& insertUndo,
claimUndoType& expireUndo,
insertUndoType& insertSupportUndo,
supportUndoType& expireSupportUndo);
virtual bool getProofForName(const std::string& name, const CUint160& claim, CClaimTrieProof& proof);
virtual bool getInfoForName(const std::string& name, CClaimValue& claim, int heightOffset = 0) const;
virtual bool incrementBlock();
virtual bool decrementBlock();
virtual bool finalizeDecrement();
virtual int expirationTime() const;
virtual bool finalizeDecrement(takeoverUndoType& takeoverHeightUndo);
virtual bool getProofForName(const std::string& name, const CUint160& claim, CClaimTrieProof& proof);
virtual bool getInfoForName(const std::string& name, CClaimValue& claim, int heightOffset = 0) const;
virtual CClaimSupportToName getClaimsForName(const std::string& name) const;
virtual std::string adjustNameForValidHeight(const std::string& name, int validHeight) const;
@ -153,7 +126,7 @@ private:
friend struct ClaimTrieChainFixture;
friend class CClaimTrieCacheTest;
bool activateAllFor(insertUndoType& insertUndo, insertUndoType& insertSupportUndo, const std::string& takeover);
bool activateAllFor(const std::string& name);
};
#endif // CLAIMTRIE_TRIE_H

View file

@ -56,12 +56,6 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam
void blockToCache(const CBlock* pblock, CClaimTrieCache& trieCache, int nHeight)
{
insertUndoType dummyInsertUndo;
claimUndoType dummyExpireUndo;
insertUndoType dummyInsertSupportUndo;
supportUndoType dummyExpireSupportUndo;
takeoverUndoType dummyTakeoverUndo;
CUpdateCacheCallbacks callbacks = {
.findScriptKey = [&pblock](const COutPoint& point) {
for (auto& tx : pblock->vtx)
@ -80,7 +74,7 @@ void blockToCache(const CBlock* pblock, CClaimTrieCache& trieCache, int nHeight)
if (!tx->IsCoinBase())
UpdateCache(*tx, trieCache, view, nHeight, callbacks);
trieCache.incrementBlock(dummyInsertUndo, dummyExpireUndo, dummyInsertSupportUndo, dummyExpireSupportUndo, dummyTakeoverUndo);
trieCache.incrementBlock();
}
BlockAssembler::Options::Options() {

View file

@ -222,12 +222,7 @@ BOOST_AUTO_TEST_CASE(claimtriecache_normalization)
BOOST_CHECK(trieCache.getInfoForName(name, nval1));
BOOST_CHECK_EQUAL(nval1.claimId, ClaimIdHash(tx1.GetHash(), 0));
insertUndoType insertUndo;
claimUndoType expireUndo;
insertUndoType insertSupportUndo;
supportUndoType expireSupportUndo;
takeoverUndoType takeoverUndo;
BOOST_CHECK(trieCache.incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverUndo));
BOOST_CHECK(trieCache.incrementBlock());
BOOST_CHECK(trieCache.shouldNormalize());
}
@ -309,18 +304,13 @@ BOOST_AUTO_TEST_CASE(normalization_removal_test)
cache.addClaim("aB", COutPoint(tx3.GetHash(), 0), ClaimIdHash(tx3.GetHash(), 0), 3, height);
cache.addSupport("AB", COutPoint(sx1.GetHash(), 0), ClaimIdHash(tx1.GetHash(), 0), 1, height);
cache.addSupport("Ab", COutPoint(sx2.GetHash(), 0), ClaimIdHash(tx2.GetHash(), 0), 1, height);
insertUndoType insertUndo;
claimUndoType expireUndo;
insertUndoType insertSupportUndo;
supportUndoType expireSupportUndo;
takeoverUndoType takeoverUndo;
BOOST_CHECK(cache.incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverUndo));
BOOST_CHECK(cache.incrementBlock());
BOOST_CHECK(cache.getClaimsForName("ab").claimsNsupports.size() == 3U);
BOOST_CHECK(cache.getClaimsForName("ab").claimsNsupports[0].supports.size() == 1U);
BOOST_CHECK(cache.getClaimsForName("ab").claimsNsupports[1].supports.size() == 0U);
BOOST_CHECK(cache.getClaimsForName("ab").claimsNsupports[2].supports.size() == 1U);
BOOST_CHECK(cache.decrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo));
BOOST_CHECK(cache.finalizeDecrement(takeoverUndo));
BOOST_CHECK(cache.decrementBlock());
BOOST_CHECK(cache.finalizeDecrement());
std::string unused;
BOOST_CHECK(cache.removeSupport(COutPoint(sx1.GetHash(), 0), unused, height));
BOOST_CHECK(cache.removeSupport(COutPoint(sx2.GetHash(), 0), unused, height));

View file

@ -74,22 +74,12 @@ class CBlockUndo
{
public:
std::vector<CTxUndo> vtxundo; // for all but the coinbase
insertUndoType insertUndo; // any claims that went from the queue to the trie
claimUndoType expireUndo; // any claims that expired
insertUndoType insertSupportUndo; // any supports that went from the support queue to the support map
supportUndoType expireSupportUndo; // any supports that expired
takeoverUndoType takeoverUndo;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(vtxundo);
READWRITE(insertUndo);
READWRITE(expireUndo);
READWRITE(insertSupportUndo);
READWRITE(expireSupportUndo);
READWRITE(takeoverUndo);
}
};

View file

@ -1507,8 +1507,7 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
return DISCONNECT_FAILED;
}
const bool decremented = trieCache.decrementBlock(blockUndo.insertUndo, blockUndo.expireUndo, blockUndo.insertSupportUndo, blockUndo.expireSupportUndo);
assert(decremented);
assert(trieCache.decrementBlock());
// undo transactions in reverse order
for (int i = block.vtx.size() - 1; i >= 0; i--) {
@ -1562,7 +1561,7 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
// move best block pointer to prevout block
view.SetBestBlock(pindex->pprev->GetBlockHash());
assert(trieCache.finalizeDecrement(blockUndo.takeoverUndo));
assert(trieCache.finalizeDecrement());
if (!equals(trieCache.getMerkleHash(), pindex->pprev->hashClaimTrie)) {
LogPrintf("Hash comparison failure at block %d\n", pindex->nHeight);
assert(false);
@ -2035,9 +2034,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
}
// TODO: if the "just check" flag is set, we should reduce the work done here. Incrementing blocks twice per mine is not efficient.
const auto incremented = trieCache.incrementBlock(blockundo.insertUndo, blockundo.expireUndo,
blockundo.insertSupportUndo, blockundo.expireSupportUndo, blockundo.takeoverUndo);
assert(incremented);
assert(trieCache.incrementBlock());
if (!equals(trieCache.getMerkleHash(), block.hashClaimTrie)) {
return state.DoS(100, error("ConnectBlock() : the merkle root of the claim trie does not match "