Initial undo removal
Signed-off-by: Anthony Fieroni <bvbfan@abv.bg>
This commit is contained in:
parent
106a4c26da
commit
0fce479923
9 changed files with 164 additions and 327 deletions
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
%}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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));
|
||||
|
|
10
src/undo.h
10
src/undo.h
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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 "
|
||||
|
|
Loading…
Reference in a new issue