Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add transactions.mempool.lockedTransactions and chainlocks.blockHeight stats #6237

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/evo/deterministicmns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <univalue.h>
#include <messagesigner.h>
#include <uint256.h>
#include <stats/client.h>

#include <optional>
#include <memory>
Expand Down Expand Up @@ -645,6 +646,15 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, gsl::not_null<co
updatesRet = {newList, oldList, diff};
}

::g_stats_client->gauge("masternodes.count", newList.GetAllMNsCount());
::g_stats_client->gauge("masternodes.weighted_count", newList.GetValidWeightedMNsCount());
::g_stats_client->gauge("masternodes.enabled", newList.GetValidMNsCount());
::g_stats_client->gauge("masternodes.weighted_enabled", newList.GetValidWeightedMNsCount());
::g_stats_client->gauge("masternodes.evo.count", newList.GetAllEvoCount());
::g_stats_client->gauge("masternodes.evo.enabled", newList.GetValidEvoCount());
::g_stats_client->gauge("masternodes.mn.count", newList.GetAllMNsCount() - newList.GetAllEvoCount());
::g_stats_client->gauge("masternodes.mn.enabled", newList.GetValidMNsCount() - newList.GetValidEvoCount());

if (nHeight == consensusParams.DIP0003EnforcementHeight) {
if (!consensusParams.DIP0003EnforcementHash.IsNull() && consensusParams.DIP0003EnforcementHash != pindex->GetBlockHash()) {
LogPrintf("CDeterministicMNManager::%s -- DIP3 enforcement block has wrong hash: hash=%s, expected=%s, nHeight=%d\n", __func__,
Expand Down
2 changes: 2 additions & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,7 @@ static void PeriodicStats(NodeContext& node)
const ArgsManager& args = *Assert(node.args);
ChainstateManager& chainman = *Assert(node.chainman);
const CTxMemPool& mempool = *Assert(node.mempool);
const llmq::CInstantSendManager& isman = *Assert(node.llmq_ctx->isman);
CCoinsStats stats{CoinStatsHashType::NONE};
chainman.ActiveChainstate().ForceFlushStateToDisk();
if (WITH_LOCK(cs_main, return GetUTXOStats(&chainman.ActiveChainstate().CoinsDB(), chainman.m_blockman, stats, node.rpc_interruption_point, chainman.ActiveChain().Tip()))) {
Expand Down Expand Up @@ -880,6 +881,7 @@ static void PeriodicStats(NodeContext& node)
::g_stats_client->gauge("transactions.mempool.memoryUsageBytes", (int64_t) mempool.DynamicMemoryUsage(), 1.0f);
::g_stats_client->gauge("transactions.mempool.minFeePerKb", mempool.GetMinFee(args.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK(), 1.0f);
}
::g_stats_client->gauge("transactions.mempool.lockedTransactions", isman.GetInstantSendLockCount(), 1.0f);
}

static bool AppInitServers(NodeContext& node)
Expand Down
2 changes: 2 additions & 0 deletions src/llmq/chainlocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <node/ui_interface.h>
#include <scheduler.h>
#include <spork.h>
#include <stats/client.h>
#include <txmempool.h>
#include <util/thread.h>
#include <util/time.h>
Expand Down Expand Up @@ -499,6 +500,7 @@ void CChainLocksHandler::EnforceBestChainLock()

GetMainSignals().NotifyChainLock(currentBestChainLockBlockIndex, clsig);
uiInterface.NotifyChainLock(clsig->getBlockHash().ToString(), clsig->getHeight());
::g_stats_client->gauge("chainlocks.blockHeight", clsig->getHeight(), 1.0f);
}

MessageProcessingResult CChainLocksHandler::HandleNewRecoveredSig(const llmq::CRecoveredSig& recoveredSig)
Expand Down
21 changes: 21 additions & 0 deletions src/llmq/instantsend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <util/ranges.h>
#include <util/thread.h>
#include <validation.h>
#include <stats/client.h>

#include <cxxtimer.hpp>

Expand Down Expand Up @@ -774,6 +775,17 @@ PeerMsgRet CInstantSendManager::ProcessMessageInstantSendLock(const CNode& pfrom
LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s, islock=%s: received islock, peer=%d\n", __func__,
islock->txid.ToString(), hash.ToString(), pfrom.GetId());

auto time_diff = [&] () -> int64_t {
LOCK(cs_timingsTxSeen);
if (auto it = timingsTxSeen.find(islock->txid); it != timingsTxSeen.end()) {
// This is the normal case where we received the TX before the islock
return GetTimeMillis() - it->second;
}
// But if we received the islock and don't know when we got the tx, then say 0, to indicate we received the islock first.
return 0;
}();
::g_stats_client->timing("islock_ms", time_diff);

LOCK(cs_pendingLocks);
pendingInstantSendLocks.emplace(hash, std::make_pair(pfrom.GetId(), islock));
return {};
Expand Down Expand Up @@ -1164,6 +1176,15 @@ void CInstantSendManager::AddNonLockedTx(const CTransactionRef& tx, const CBlock
++it;
}
}

{
LOCK(cs_timingsTxSeen);
// Only insert the time the first time we see the tx, as we sometimes try to resign
if (auto it = timingsTxSeen.find(tx->GetHash()); it == timingsTxSeen.end()) {
timingsTxSeen[tx->GetHash()] = GetTimeMillis();
}
Comment on lines +1183 to +1185
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's avoid double lookup on map here:

Suggested change
if (auto it = timingsTxSeen.find(tx->GetHash()); it == timingsTxSeen.end()) {
timingsTxSeen[tx->GetHash()] = GetTimeMillis();
}
timingsTxSeen.try_emplace(tx->GetHash(), GetTimeMillis());

emplace() and try_emplace() are similar, but difference in performance - one is expecting success by default, other is expecting failure by default

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

proof that it works:

$ cat a.cpp 
#include <iostream>
#include <unordered_map>

using namespace std;

int main() {
    unordered_map<int, int> m;
    if (m.try_emplace(2, 3).second) cout << "OK" << endl; else cout << "FAIL" << endl;
    if (m.try_emplace(3, 4).second) cout << "OK" << endl; else cout << "FAIL" << endl;
    if (m.try_emplace(2, 5).second) cout << "OK" << endl; else cout << "FAIL" << endl;
    for (auto i : m) {
        cout << i.first << ' ' << i.second << endl;
    }
}
$ ./a 
OK
OK
FAIL
3 4
2 3

}

LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s, pindexMined=%s\n", __func__,
tx->GetHash().ToString(), pindexMined ? pindexMined->GetBlockHash().ToString() : "");
}
Expand Down
3 changes: 3 additions & 0 deletions src/llmq/instantsend.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,9 @@ class CInstantSendManager : public CRecoveredSigsListener
mutable Mutex cs_pendingRetry;
std::unordered_set<uint256, StaticSaltedHasher> pendingRetryTxs GUARDED_BY(cs_pendingRetry);

mutable Mutex cs_timingsTxSeen;
std::unordered_map<uint256, int64_t, StaticSaltedHasher> timingsTxSeen GUARDED_BY(cs_timingsTxSeen);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems as this map can indefinitely grow and eat all significant amount of RAM


public:
explicit CInstantSendManager(CChainLocksHandler& _clhandler, CChainState& chainstate, CQuorumManager& _qman,
CSigningManager& _sigman, CSigSharesManager& _shareman, CSporkManager& sporkman,
Expand Down
26 changes: 25 additions & 1 deletion src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2301,7 +2301,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,

::g_stats_client->timing("ConnectBlock_ms", (nTime8 - nTimeStart) / 1000, 1.0f);
::g_stats_client->gauge("blocks.tip.SizeBytes", ::GetSerializeSize(block, PROTOCOL_VERSION), 1.0f);
::g_stats_client->gauge("blocks.tip.Height", m_chain.Height(), 1.0f);
::g_stats_client->gauge("blocks.tip.Height", m_chain.Height() + 1, 1.0f); // without the +1, the "tip.Height" doesn't match rpc calls like `getblockcount`
::g_stats_client->gauge("blocks.tip.Version", block.nVersion, 1.0f);
::g_stats_client->gauge("blocks.tip.NumTransactions", block.vtx.size(), 1.0f);
::g_stats_client->gauge("blocks.tip.SigOps", nSigOps, 1.0f);
Expand Down Expand Up @@ -2623,6 +2623,8 @@ bool CChainState::DisconnectTip(BlockValidationState& state, DisconnectedBlockTr
AssertLockHeld(cs_main);
if (m_mempool) AssertLockHeld(m_mempool->cs);

int64_t nTime1 = GetTimeMicros();

CBlockIndex *pindexDelete = m_chain.Tip();
assert(pindexDelete);
// Read block from disk.
Expand Down Expand Up @@ -2681,6 +2683,19 @@ bool CChainState::DisconnectTip(BlockValidationState& state, DisconnectedBlockTr
// Let wallets know transactions went from 1-confirmed to
// 0-confirmed or conflicted:
GetMainSignals().BlockDisconnected(pblock, pindexDelete);

int64_t nTime2 = GetTimeMicros();

unsigned int nSigOps = 0;
for (const auto& tx : block.vtx) {
nSigOps += GetLegacySigOpCount(*tx);
}
::g_stats_client->timing("DisconnectTip_ms", (nTime2 - nTime1) / 1000, 1.0f);
::g_stats_client->gauge("blocks.tip.SizeBytes", ::GetSerializeSize(block, PROTOCOL_VERSION), 1.0f);
::g_stats_client->gauge("blocks.tip.Height", m_chain.Height(), 1.0f);
::g_stats_client->gauge("blocks.tip.Version", block.nVersion, 1.0f);
::g_stats_client->gauge("blocks.tip.NumTransactions", block.vtx.size(), 1.0f);
::g_stats_client->gauge("blocks.tip.SigOps", nSigOps, 1.0f);
return true;
}

Expand Down Expand Up @@ -2799,7 +2814,16 @@ bool CChainState::ConnectTip(BlockValidationState& state, CBlockIndex* pindexNew
LogPrint(BCLog::BENCHMARK, " - Connect postprocess: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime6 - nTime5) * MILLI, nTimePostConnect * MICRO, nTimePostConnect * MILLI / nBlocksTotal);
LogPrint(BCLog::BENCHMARK, "- Connect block: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime6 - nTime1) * MILLI, nTimeTotal * MICRO, nTimeTotal * MILLI / nBlocksTotal);

unsigned int nSigOps = 0;
for (const auto& tx : blockConnecting.vtx) {
nSigOps += GetLegacySigOpCount(*tx);
}
::g_stats_client->timing("ConnectTip_ms", (nTime6 - nTime1) / 1000, 1.0f);
::g_stats_client->gauge("blocks.tip.SizeBytes", ::GetSerializeSize(blockConnecting, PROTOCOL_VERSION), 1.0f);
::g_stats_client->gauge("blocks.tip.Height", m_chain.Height(), 1.0f);
::g_stats_client->gauge("blocks.tip.Version", blockConnecting.nVersion, 1.0f);
::g_stats_client->gauge("blocks.tip.NumTransactions", blockConnecting.vtx.size(), 1.0f);
::g_stats_client->gauge("blocks.tip.SigOps", nSigOps, 1.0f);

connectTrace.BlockConnected(pindexNew, std::move(pthisBlock));
return true;
Expand Down
Loading