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 11 commits into
base: develop
Choose a base branch
from
Open
12 changes: 12 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 @@ -649,6 +650,17 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, gsl::not_null<co
updatesRet = {newList, oldList, diff};
}

if (::g_stats_client->active()) {
::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
3 changes: 3 additions & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
#include <llmq/dkgsessionmgr.h>
#include <llmq/options.h>
#include <llmq/signing.h>
#include <llmq/instantsend.h>
#include <masternode/meta.h>
#include <masternode/node.h>
#include <masternode/sync.h>
Expand Down Expand Up @@ -826,6 +827,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 @@ -878,6 +880,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.GetIntArg("-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/interface_ui.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 @@ -497,6 +498,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
29 changes: 29 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 @@ -741,6 +742,10 @@ PeerMsgRet CInstantSendManager::ProcessMessage(const CNode& pfrom, PeerManager&
return {};
}

bool ShouldReportISLockTiming() {
return g_stats_client->active() || LogAcceptDebug(BCLog::INSTANTSEND);
}

PeerMsgRet CInstantSendManager::ProcessMessageInstantSendLock(const CNode& pfrom, PeerManager& peerman,
const llmq::CInstantSendLockPtr& islock)
{
Expand Down Expand Up @@ -774,6 +779,23 @@ 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());

if (ShouldReportISLockTiming()) {
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
auto diff = GetTimeMillis() - it->second;
timingsTxSeen.erase(it);
return diff;
}
// 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);
LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s, islock took %dms\n", __func__,
islock->txid.ToString(), time_diff);
}

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

if (ShouldReportISLockTiming()) {
LOCK(cs_timingsTxSeen);
// Only insert the time the first time we see the tx, as we sometimes try to resign
timingsTxSeen.try_emplace(tx->GetHash(), GetTimeMillis());
}

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 @@ -252,6 +252,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

Copy link
Member Author

Choose a reason for hiding this comment

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

resolved in d5dbbdb


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 @@ -2579,7 +2579,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);
Copy link

Choose a reason for hiding this comment

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

should drop all updates for blocks.tip.* stats in ConnectBlock()

Copy link
Member Author

Choose a reason for hiding this comment

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

why?

Copy link

Choose a reason for hiding this comment

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

Because chain tip is updated in ConnectTip/DisconnectTip, not here.

Copy link
Member Author

Choose a reason for hiding this comment

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

Expand Down Expand Up @@ -2901,6 +2901,8 @@ bool CChainState::DisconnectTip(BlockValidationState& state, DisconnectedBlockTr
AssertLockHeld(cs_main);
if (m_mempool) AssertLockHeld(m_mempool->cs);

int64_t nTime1 = GetTimeMicros();
Copy link
Collaborator

@knst knst Mar 11, 2025

Choose a reason for hiding this comment

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

Consider using here SteadyClock::now()? It returns time in time units, not int64_t.

GetTimeMicros is going to be removed by bitcoin#27233


CBlockIndex *pindexDelete = m_chain.Tip();
assert(pindexDelete);
// Read block from disk.
Expand Down Expand Up @@ -2959,6 +2961,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 @@ -3077,7 +3092,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