LCOV - code coverage report
Current view: top level - src/llmq - ehf_signals.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 71 73 97.3 %
Date: 2026-06-25 07:23:43 Functions: 12 12 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2023-2025 The Dash Core developers
       2             : // Distributed under the MIT/X11 software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include <llmq/ehf_signals.h>
       6             : 
       7             : #include <chainparams.h>
       8             : #include <consensus/validation.h>
       9             : #include <deploymentstatus.h>
      10             : #include <evo/chainhelper.h>
      11             : #include <evo/mnhftx.h>
      12             : #include <index/txindex.h> // g_txindex
      13             : #include <llmq/commitment.h>
      14             : #include <llmq/quorumsman.h>
      15             : #include <llmq/signing_shares.h>
      16             : #include <primitives/transaction.h>
      17             : #include <validation.h>
      18             : #include <versionbits.h>
      19             : 
      20             : namespace llmq {
      21        1980 : CEHFSignalsHandler::CEHFSignalsHandler(ChainstateManager& chainman, CSigningManager& sigman,
      22             :                                        CSigSharesManager& shareman, const CQuorumManager& qman) :
      23         660 :     m_chainman(chainman),
      24         660 :     sigman(sigman),
      25         660 :     shareman(shareman),
      26         660 :     qman(qman)
      27        1320 : {
      28         660 :     sigman.RegisterRecoveredSigsListener(this);
      29        1320 : }
      30             : 
      31        1980 : CEHFSignalsHandler::~CEHFSignalsHandler()
      32        1980 : {
      33         660 :     sigman.UnregisterRecoveredSigsListener(this);
      34        1980 : }
      35             : 
      36       81273 : void CEHFSignalsHandler::UpdatedBlockTip(const CBlockIndex* const pindexNew)
      37             : {
      38       81273 :     if (!DeploymentActiveAfter(pindexNew, Params().GetConsensus(), Consensus::DEPLOYMENT_V20)) return;
      39             : 
      40       52399 :     const auto ehfSignals = m_chainman.ActiveChainstate().ChainHelper().ehf_manager->GetSignalsStage(pindexNew);
      41      157197 :     for (const auto& deployment : Params().GetConsensus().vDeployments) {
      42             :         // Skip deployments that do not use dip0023
      43      104798 :         if (!deployment.useEHF) continue;
      44             :         // Try to sign only activable deployments that haven't been mined yet
      45       77549 :         if (ehfSignals.find(deployment.bit) == ehfSignals.end() && Params().IsValidMNActivation(deployment.bit, pindexNew->GetMedianTimePast())) {
      46       24244 :             trySignEHFSignal(deployment.bit, pindexNew);
      47       24244 :         }
      48             :     }
      49       81273 : }
      50             : 
      51       24244 : void CEHFSignalsHandler::trySignEHFSignal(int bit, const CBlockIndex* const pindex)
      52             : {
      53       24244 :     MNHFTxPayload mnhfPayload;
      54       24244 :     mnhfPayload.signal.versionBit = bit;
      55       24244 :     const uint256 requestId = mnhfPayload.GetRequestId();
      56             : 
      57       24244 :     const Consensus::LLMQType& llmqType = Params().GetConsensus().llmqTypeMnhf;
      58       24244 :     const auto& llmq_params_opt = Params().GetLLMQ(llmqType);
      59       24244 :     if (!llmq_params_opt.has_value()) {
      60           0 :         return;
      61             :     }
      62       24244 :     if (sigman.HasRecoveredSigForId(llmqType, requestId)) {
      63        7894 :         WITH_LOCK(cs, ids.insert(requestId));
      64             : 
      65        3947 :         LogPrint(BCLog::EHF, "CEHFSignalsHandler::trySignEHFSignal: already signed bit=%d at height=%d id=%s\n", bit, pindex->nHeight, requestId.ToString());
      66             :         // no need to sign same message one more time
      67        3947 :         return;
      68             :     }
      69             : 
      70       20297 :     const auto quorum = llmq::SelectQuorumForSigning(llmq_params_opt.value(), m_chainman.ActiveChain(), qman, requestId);
      71       20297 :     if (!quorum) {
      72       16743 :         LogPrintf("CEHFSignalsHandler::trySignEHFSignal no quorum for id=%s\n", requestId.ToString());
      73       16743 :         return;
      74             :     }
      75             : 
      76        3554 :     LogPrint(BCLog::EHF, "CEHFSignalsHandler::trySignEHFSignal: bit=%d at height=%d id=%s\n", bit, pindex->nHeight, requestId.ToString());
      77        3554 :     mnhfPayload.signal.quorumHash = quorum->qc->quorumHash;
      78        3554 :     const uint256 msgHash = mnhfPayload.PrepareTx().GetHash();
      79             : 
      80        7108 :     WITH_LOCK(cs, ids.insert(requestId));
      81        3554 :     shareman.AsyncSignIfMember(llmqType, sigman, requestId, msgHash, quorum->qc->quorumHash, false, true);
      82       24244 : }
      83             : 
      84       26973 : RecoveredSigResult CEHFSignalsHandler::HandleNewRecoveredSig(const CRecoveredSig& recoveredSig)
      85             : {
      86       26973 :     if (g_txindex) {
      87       26973 :         g_txindex->BlockUntilSyncedToCurrentChain();
      88       26973 :     }
      89             : 
      90       53946 :     if (WITH_LOCK(cs, return ids.find(recoveredSig.getId()) == ids.end())) {
      91             :         // Do nothing, it's not for this handler
      92       26742 :         return std::monostate{};
      93             :     }
      94             : 
      95         462 :     const auto ehfSignals = m_chainman.ActiveChainstate().ChainHelper().ehf_manager->GetSignalsStage(
      96         462 :         WITH_LOCK(::cs_main, return m_chainman.ActiveTip()));
      97         231 :     MNHFTxPayload mnhfPayload;
      98         450 :     for (const auto& deployment : Params().GetConsensus().vDeployments) {
      99             :         // skip deployments that do not use dip0023 or that have already been mined
     100         450 :         if (!deployment.useEHF || ehfSignals.find(deployment.bit) != ehfSignals.end()) continue;
     101             : 
     102         237 :         mnhfPayload.signal.versionBit = deployment.bit;
     103         237 :         const uint256 expectedId = mnhfPayload.GetRequestId();
     104         237 :         LogPrint(BCLog::EHF, "CEHFSignalsHandler::HandleNewRecoveredSig expecting ID=%s received=%s\n", expectedId.ToString(), recoveredSig.getId().ToString());
     105         237 :         if (recoveredSig.getId() != expectedId) {
     106             :             // wrong deployment! Check the next one
     107           6 :             continue;
     108             :         }
     109             : 
     110         231 :         mnhfPayload.signal.quorumHash = recoveredSig.getQuorumHash();
     111         231 :         mnhfPayload.signal.sig = recoveredSig.sig.Get();
     112             : 
     113         231 :         CMutableTransaction tx = mnhfPayload.PrepareTx();
     114             : 
     115         231 :         CTransactionRef tx_to_sent = MakeTransactionRef(std::move(tx));
     116         231 :         LogPrintf("CEHFSignalsHandler::HandleNewRecoveredSig Special EHF TX is created hash=%s\n",
     117             :                   tx_to_sent->GetHash().ToString());
     118         231 :         LOCK(::cs_main);
     119         231 :         const MempoolAcceptResult result = m_chainman.ProcessTransaction(tx_to_sent);
     120         231 :         if (result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
     121         188 :             return tx_to_sent;
     122             :         }
     123          43 :         LogPrintf("CEHFSignalsHandler::HandleNewRecoveredSig -- AcceptToMemoryPool failed: %s\n",
     124             :                   result.m_state.ToString());
     125          43 :         return std::monostate{};
     126         231 :     }
     127           0 :     return std::monostate{};
     128       26973 : }
     129             : } // namespace llmq

Generated by: LCOV version 1.16