Fix getchangesinblock and unit test

getTotalValueOfClaimsInTrie query is not well performance balanced

Signed-off-by: Anthony Fieroni <bvbfan@abv.bg>
This commit is contained in:
Anthony Fieroni 2019-11-29 16:43:16 +02:00 committed by Brannon King
parent f47826232f
commit 0dad6a7c10
6 changed files with 113 additions and 48 deletions

View file

@ -144,6 +144,7 @@ bool CClaimTrieCacheNormalizationFork::normalizeAllNamesInTrieIfNecessary(takeov
// 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;
@ -181,6 +182,7 @@ bool CClaimTrieCacheNormalizationFork::unnormalizeAllNamesInTrieIfNecessary()
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 << "UPDATE nodes SET hash = NULL WHERE name IN "
"(SELECT name FROM supports WHERE name != nodeName UNION "
"SELECT nodeName FROM supports WHERE name != nodeName UNION "

View file

@ -3,6 +3,7 @@
void CLogPrint::setLogger(ClogBase* log)
{
ss.str({});
logger = log;
}
@ -14,10 +15,16 @@ CLogPrint& CLogPrint::global()
CLogPrint& CLogPrint::operator<<(const Clog& cl)
{
if (logger && cl == Clog::endl) {
if (logger) {
switch(cl) {
case Clog::endl:
ss << '\n';
// fallthrough
case Clog::flush:
logger->LogPrintStr(ss.str());
ss.str({});
break;
}
}
return *this;
}

View file

@ -15,6 +15,7 @@ struct ClogBase
enum struct Clog
{
endl = 0,
flush = 1,
};
struct CLogPrint

View file

@ -61,6 +61,7 @@ CClaimTrie::CClaimTrie(bool fWipe, int height,
{
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 INDEX IF NOT EXISTS nodes_hash ON nodes (hash)";
db << "CREATE INDEX IF NOT EXISTS nodes_parent ON nodes (parent)";
@ -69,6 +70,7 @@ CClaimTrie::CClaimTrie(bool fWipe, int height,
"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);";
db << "CREATE INDEX IF NOT EXISTS claims_validHeight ON claims (validHeight)";
db << "CREATE INDEX IF NOT EXISTS claims_expirationHeight ON claims (expirationHeight)";
db << "CREATE INDEX IF NOT EXISTS claims_nodeName ON claims (nodeName)";
@ -77,6 +79,7 @@ CClaimTrie::CClaimTrie(bool fWipe, int height,
"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));";
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_expirationHeight ON supports (expirationHeight)";
@ -321,11 +324,17 @@ std::size_t CClaimTrieCacheBase::getTotalClaimsInTrie() const
int64_t CClaimTrieCacheBase::getTotalValueOfClaimsInTrie(bool fControllingOnly) const
{
int64_t ret = 0;
std::string query("SELECT SUM(SELECT IFNULL(SUM(s.amount),0)+c.amount FROM supports s "
"WHERE s.supportedClaimID = c.claimID AND s.validHeight < ?1 AND s.expirationHeight >= ?1) "
"FROM claims c WHERE c.validHeight < ?1 AND s.expirationHeight >= ?1");
if (fControllingOnly)
throw std::runtime_error("not implemented yet"); // TODO: finish this
const std::string query = 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 "
"ORDER BY effective DESC LIMIT 1) as winner FROM claims c "
"WHERE c.validHeight < ?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)";
db << query << nNextHeight >> ret;
return ret;
}
@ -448,7 +457,7 @@ bool CClaimTrieCacheBase::checkConsistency()
bool CClaimTrieCacheBase::validateDb(const CUint256& rootHash)
{
logPrint << "Checking claim trie consistency... ";
logPrint << "Checking claim trie consistency... " << Clog::flush;
if (checkConsistency()) {
logPrint << "consistent" << Clog::endl;
if (rootHash != getMerkleHash()) {
@ -569,6 +578,7 @@ bool CClaimTrieCacheBase::addClaim(const std::string& name, const CTxOutPoint& o
if (nValidHeight < 0)
nValidHeight = nHeight + getDelayForName(name, claimId); // sets nValidHeight to the old value
auto nodeName = adjustNameForValidHeight(name, nValidHeight);
auto expires = expirationTime() + nHeight;
@ -589,6 +599,7 @@ bool CClaimTrieCacheBase::addSupport(const std::string& name, const CTxOutPoint&
if (nValidHeight < 0)
nValidHeight = nHeight + getDelayForName(name, supportedClaimId);
auto nodeName = adjustNameForValidHeight(name, nValidHeight);
auto expires = expirationTime() + nHeight;
@ -1113,6 +1124,7 @@ bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimUndoTy
db << "INSERT INTO nodes(name) SELECT nodeName FROM claims "
"WHERE validHeight = ?1 AND 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;
@ -1269,6 +1281,7 @@ bool CClaimTrieCacheBase::finalizeDecrement(takeoverUndoType& takeoverUndo)
{
db << "UPDATE nodes SET hash = NULL WHERE name IN "
"(SELECT nodeName FROM claims WHERE validHeight = ?1 AND expirationHeight > ?1)" << nNextHeight;
db << "UPDATE nodes SET hash = NULL WHERE name IN "
"(SELECT nodeName FROM supports WHERE validHeight = ?1 AND expirationHeight > ?1)" << nNextHeight;

View file

@ -742,47 +742,92 @@ UniValue getclaimproofbyseq(const JSONRPCRequest& request)
return proofToJSON(proof);
}
extern bool UndoReadFromDisk(CBlockUndo&, const CBlockIndex*);
template <typename T>
UniValue removedToJSON(const std::vector<queueEntryType<T>>& undo)
{
UniValue ret(UniValue::VARR);
for (auto& u : undo) {
auto outPoint = COutPoint(u.second.outPoint);
ret.push_back(ClaimIdHash(outPoint.hash, outPoint.n).ToString());
}
return ret;
}
UniValue getchangesinblock(const JSONRPCRequest& request)
{
validateRequest(request, GETCHANGESINBLOCK, 0, 1);
CBlockUndo undo;
{
CBlock block;
LOCK(cs_main);
bool allowSupportMetadata;
CCoinsViewCache coinsCache(pcoinsTip.get());
{
auto index = chainActive.Tip();
if (request.params.size() > 0)
index = BlockHashIndex(ParseHashV(request.params[0], T_BLOCKHASH " (optional parameter)"));
if (!UndoReadFromDisk(undo, index))
if (!ReadBlockFromDisk(block, index, Params().GetConsensus()))
throw JSONRPCError(RPC_INTERNAL_ERROR,
"Unable to read the undo block for height " + std::to_string(index->nHeight));
allowSupportMetadata = index->nHeight >= Params().GetConsensus().nAllClaimsInMerkleForkHeight;
}
auto addedUpdated = [](const insertUndoType& insertUndo) {
UniValue added(UniValue::VARR);
for (auto& a : insertUndo)
added.push_back(ClaimIdHash(uint256(a.outPoint.hash), a.outPoint.n).ToString());
return added;
UniValue claimsAddUp(UniValue::VARR),
claimsRm(UniValue::VARR),
supportsAddUp(UniValue::VARR),
supportsRm(UniValue::VARR);
int op;
std::vector<std::vector<unsigned char> > vvchParams;
auto findScriptKey = [&block](const COutPoint& point) -> CScript {
for (auto& tx : block.vtx)
if (tx->GetHash() == point.hash && point.n < tx->vout.size())
return tx->vout[point.n].scriptPubKey;
return CScript{};
};
for (auto& tx : block.vtx) {
if (tx->IsCoinBase())
continue;
for (auto& txin : tx->vin) {
const Coin& coin = coinsCache.AccessCoin(txin.prevout);
CScript scriptPubKey = coin.out.IsNull() ?
findScriptKey(txin.prevout) : coin.out.scriptPubKey;
if (scriptPubKey.empty())
continue;
if (!DecodeClaimScript(scriptPubKey, op, vvchParams, allowSupportMetadata))
continue;
switch (op) {
case OP_CLAIM_NAME:
claimsRm.push_back(ClaimIdHash(txin.prevout.hash, txin.prevout.n).ToString());
break;
case OP_UPDATE_CLAIM:
claimsRm.push_back(uint160(vvchParams[1]).ToString());
break;
case OP_SUPPORT_CLAIM:
supportsRm.push_back(uint160(vvchParams[1]).ToString());
}
}
for (std::size_t i = 0; i < tx->vout.size(); ++i) {
auto& txout = tx->vout[i];
if (txout.scriptPubKey.empty())
continue;
if (!DecodeClaimScript(txout.scriptPubKey, op, vvchParams, allowSupportMetadata))
continue;
switch (op) {
case OP_CLAIM_NAME:
case OP_UPDATE_CLAIM:
claimsAddUp.push_back(ClaimIdHash(tx->GetHash(), i).ToString());
break;
case OP_SUPPORT_CLAIM:
supportsAddUp.push_back(ClaimIdHash(tx->GetHash(), i).ToString());
}
}
}
UniValue result(UniValue::VOBJ);
result.pushKV(T_CLAIMSADDEDORUPDATED, addedUpdated(undo.insertUndo));
result.pushKV(T_CLAIMSREMOVED, removedToJSON(undo.expireUndo));
result.pushKV(T_SUPPORTSADDEDORUPDATED, addedUpdated(undo.insertSupportUndo));
result.pushKV(T_SUPPORTSREMOVED, removedToJSON(undo.expireSupportUndo));
result.pushKV(T_CLAIMSADDEDORUPDATED, claimsAddUp);
result.pushKV(T_CLAIMSREMOVED, claimsRm);
result.pushKV(T_SUPPORTSADDEDORUPDATED, supportsAddUp);
result.pushKV(T_SUPPORTSREMOVED, supportsRm);
return result;
}

View file

@ -353,19 +353,16 @@ BOOST_AUTO_TEST_CASE(hash_bid_seq_claim_changes_test)
claimHash = getValueHash(COutPoint(tx3.GetHash(), 0), result[T_LASTTAKEOVERHEIGHT].get_int());
ValidatePairs(fixture, jsonToPairs(result[T_PAIRS]), claimHash);
// TODO: repair this or ditch it
// auto getchangesinblock = tableRPC["getchangesinblock"]->actor;
// req.params = UniValue(UniValue::VARR);
// req.params.push_back(UniValue(blockhash.GetHex()));
//
// result = getchangesinblock(req);
// BOOST_REQUIRE_EQUAL(result[T_CLAIMSADDEDORUPDATED].size(), 3);
// BOOST_CHECK_EQUAL(result[T_CLAIMSADDEDORUPDATED][0].get_str(), claimId2.GetHex());
// BOOST_CHECK_EQUAL(result[T_CLAIMSADDEDORUPDATED][1].get_str(), claimId3.GetHex());
// BOOST_CHECK_EQUAL(result[T_CLAIMSADDEDORUPDATED][2].get_str(), claimId4.GetHex());
// BOOST_CHECK_EQUAL(result[T_CLAIMSREMOVED].size(), 0);
// BOOST_CHECK_EQUAL(result[T_SUPPORTSADDEDORUPDATED].size(), 0);
// BOOST_CHECK_EQUAL(result[T_SUPPORTSREMOVED].size(), 0);
auto getchangesinblock = tableRPC["getchangesinblock"]->actor;
req.params = UniValue(UniValue::VARR);
req.params.push_back(UniValue(blockhash.GetHex()));
result = getchangesinblock(req);
BOOST_CHECK_EQUAL(result[T_CLAIMSADDEDORUPDATED].size(), 1);
BOOST_CHECK_EQUAL(result[T_CLAIMSADDEDORUPDATED][0].get_str(), claimId4.GetHex());
BOOST_CHECK_EQUAL(result[T_CLAIMSREMOVED].size(), 0);
BOOST_CHECK_EQUAL(result[T_SUPPORTSADDEDORUPDATED].size(), 0);
BOOST_CHECK_EQUAL(result[T_SUPPORTSREMOVED].size(), 0);
}
BOOST_AUTO_TEST_CASE(claim_rpc_pending_amount_test)