LCOV - code coverage report
Current view: top level - src/llmq - core_write.cpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 153 208 73.6 %
Date: 2026-06-25 07:23:51 Functions: 10 13 76.9 %

          Line data    Source code
       1             : // Copyright (c) 2018-2025 The Dash Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include <llmq/commitment.h>
       6             : #include <llmq/debug.h>
       7             : #include <llmq/signing.h>
       8             : #include <llmq/snapshot.h>
       9             : 
      10             : #include <core_io.h>
      11             : #include <rpc/util.h>
      12             : 
      13             : #include <univalue.h>
      14             : 
      15             : #include <map>
      16             : #include <string>
      17             : 
      18             : namespace llmq {
      19             : // CDKGDebugSessionStatus::ToJson() defined in llmq/debug.cpp
      20          92 : RPCResult CDKGDebugSessionStatus::GetJsonHelp(const std::string& key, bool optional)
      21             : {
      22         184 :     return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The state of a DKG session",
      23        2668 :     {
      24          92 :         GetRpcResult("llmqType"),
      25          92 :         GetRpcResult("quorumHash"),
      26          92 :         {RPCResult::Type::NUM, "quorumHeight", "Block height of the quorum"},
      27          92 :         {RPCResult::Type::NUM, "phase", "Active DKG phase"},
      28          92 :         {RPCResult::Type::BOOL, "sentContributions", "Returns true if contributions sent"},
      29          92 :         {RPCResult::Type::BOOL, "sentComplaint", "Returns true if complaints sent"},
      30          92 :         {RPCResult::Type::BOOL, "sentJustification", "Returns true if justifications sent"},
      31          92 :         {RPCResult::Type::BOOL, "sentPrematureCommitment", "Returns true if premature commitments sent"},
      32          92 :         {RPCResult::Type::BOOL, "aborted", "Returns true if DKG session aborted"},
      33          92 :         {RPCResult{"for detail_level = 0", RPCResult::Type::NUM, "badMembers", "Number of bad members"}},
      34          92 :         {RPCResult{"for detail_level = 0", RPCResult::Type::NUM, "weComplain", "Number of complaints sent"}},
      35          92 :         {RPCResult{"for detail_level = 0", RPCResult::Type::NUM, "receivedContributions", "Number of contributions received"}},
      36          92 :         {RPCResult{"for detail_level = 0", RPCResult::Type::NUM, "receivedComplaints", "Number of complaints received"}},
      37          92 :         {RPCResult{"for detail_level = 0", RPCResult::Type::NUM, "receivedJustifications", "Number of justifications received"}},
      38          92 :         {RPCResult{"for detail_level = 0", RPCResult::Type::NUM, "receivedPrematureCommitments", "Number of premature commitments received"}},
      39         184 :         {RPCResult{"for detail_level = 1", RPCResult::Type::ARR, "badMembers", "Array of indexes for each bad member", {
      40          92 :             {RPCResult::Type::NUM, "", "Quorum member index"}}}},
      41         184 :         {RPCResult{"for detail_level = 1", RPCResult::Type::ARR, "weComplain", "Array of indexes for each complaint sent", {
      42          92 :             {RPCResult::Type::NUM, "", "Quorum member index"}}}},
      43         184 :         {RPCResult{"for detail_level = 1", RPCResult::Type::ARR, "receivedContributions", "Array of indexes for each contribution received", {
      44          92 :             {RPCResult::Type::NUM, "", "Quorum member index"}}}},
      45         184 :         {RPCResult{"for detail_level = 1", RPCResult::Type::ARR, "receivedComplaints", "Array of indexes for each complaint received", {
      46          92 :             {RPCResult::Type::NUM, "", "Quorum member index"}}}},
      47         184 :         {RPCResult{"for detail_level = 1", RPCResult::Type::ARR, "receivedJustifications", "Array of indexes for each justification received", {
      48          92 :             {RPCResult::Type::NUM, "", "Quorum member index"}}}},
      49         184 :         {RPCResult{"for detail_level = 1", RPCResult::Type::ARR, "receivedPrematureCommitments", "Array of indexes for each commitment received", {
      50          92 :             {RPCResult::Type::NUM, "", "Quorum member index"}}}},
      51         184 :         {RPCResult{"for detail_level = 2", RPCResult::Type::ARR, "badMembers", "Array of objects for each bad member", {
      52         276 :             {RPCResult::Type::OBJ, "", "", {
      53          92 :                 GetRpcResult("memberIndex"),
      54          92 :                 GetRpcResult("proTxHash", /*optional=*/true)}}}}},
      55         184 :         {RPCResult{"for detail_level = 2", RPCResult::Type::ARR, "weComplain", "Array of objects for each complaint sent", {
      56         276 :             {RPCResult::Type::OBJ, "", "", {
      57          92 :                 GetRpcResult("memberIndex"),
      58          92 :                 GetRpcResult("proTxHash", /*optional=*/true)}}}}},
      59         184 :         {RPCResult{"for detail_level = 2", RPCResult::Type::ARR, "receivedContributions", "Array of objects for each contribution received", {
      60         276 :             {RPCResult::Type::OBJ, "", "", {
      61          92 :                 GetRpcResult("memberIndex"),
      62          92 :                 GetRpcResult("proTxHash", /*optional=*/true)}}}}},
      63         184 :         {RPCResult{"for detail_level = 2", RPCResult::Type::ARR, "receivedComplaints", "Array of objects for each complaint received", {
      64         276 :             {RPCResult::Type::OBJ, "", "", {
      65          92 :                 GetRpcResult("memberIndex"),
      66          92 :                 GetRpcResult("proTxHash", /*optional=*/true)}}}}},
      67         184 :         {RPCResult{"for detail_level = 2", RPCResult::Type::ARR, "receivedJustifications", "Array of objects for each justification received", {
      68         276 :             {RPCResult::Type::OBJ, "", "", {
      69          92 :                 GetRpcResult("memberIndex"),
      70          92 :                 GetRpcResult("proTxHash", /*optional=*/true)}}}}},
      71         184 :         {RPCResult{"for detail_level = 2", RPCResult::Type::ARR, "receivedPrematureCommitments", "Array of objects for each commitment received", {
      72         276 :             {RPCResult::Type::OBJ, "", "", {
      73          92 :                 GetRpcResult("memberIndex"),
      74          92 :                 GetRpcResult("proTxHash", /*optional=*/true)}}}}},
      75         184 :         {RPCResult{"for detail_level = 2", RPCResult::Type::ARR, "allMembers", "Array of provider registration transaction hash for all quorum members", {
      76          92 :             GetRpcResult("proTxHash")}}},
      77             :     }};
      78           0 : }
      79             : 
      80             : // CDKGDebugManager::ToJson() defined in llmq/debug.cpp
      81          92 : RPCResult CDKGDebugManager::GetJsonHelp(const std::string& key, bool optional, bool inner_optional)
      82             : {
      83         184 :     return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The state of the node's DKG sessions",
      84         368 :     {
      85          92 :         {RPCResult::Type::NUM, "time", inner_optional, "Adjusted time for the last update, timestamp"},
      86          92 :         {RPCResult::Type::STR, "timeStr", inner_optional, "Adjusted time for the last update, human friendly"},
      87         184 :         {RPCResult::Type::ARR, "session", inner_optional, "", {
      88         368 :             {RPCResult::Type::OBJ, "", "", {
      89          92 :                 {RPCResult::Type::NUM, "llmqType", "Name of quorum"},
      90          92 :                 GetRpcResult("quorumIndex"),
      91          92 :                 CDKGDebugSessionStatus::GetJsonHelp(/*key=*/"status", /*optional=*/false)
      92             :             }},
      93             :         }}
      94             :     }};
      95           0 : }
      96             : 
      97        1111 : RPCResult CFinalCommitment::GetJsonHelp(const std::string& key, bool optional)
      98             : {
      99        2222 :     return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The quorum commitment payload",
     100       14443 :     {
     101        1111 :         {RPCResult::Type::NUM, "version", "Quorum commitment payload version"},
     102        1111 :         GetRpcResult("llmqType"),
     103        1111 :         GetRpcResult("quorumHash"),
     104        1111 :         {RPCResult::Type::NUM, "quorumIndex", "Index of the quorum"},
     105        1111 :         {RPCResult::Type::NUM, "signersCount", "Number of signers for the quorum"},
     106        1111 :         {RPCResult::Type::STR_HEX, "signers", "Bitset representing the aggregated signers"},
     107        1111 :         {RPCResult::Type::NUM, "validMembersCount", "Number of valid members in the quorum"},
     108        1111 :         {RPCResult::Type::STR_HEX, "validMembers", "Bitset of valid members"},
     109        1111 :         {RPCResult::Type::STR_HEX, "quorumPublicKey", "BLS public key of the quorum"},
     110        1111 :         {RPCResult::Type::STR_HEX, "quorumVvecHash", "Hash of the quorum verification vector"},
     111        1111 :         GetRpcResult("quorumSig"),
     112        1111 :         {RPCResult::Type::STR_HEX, "membersSig", "BLS signature from all included commitments"},
     113             :     }};
     114           0 : }
     115             : 
     116           6 : UniValue CFinalCommitment::ToJson() const
     117             : {
     118           6 :     UniValue obj(UniValue::VOBJ);
     119           6 :     obj.pushKV("version", nVersion);
     120           6 :     obj.pushKV("llmqType", std23::to_underlying(llmqType));
     121           6 :     obj.pushKV("quorumHash", quorumHash.ToString());
     122           6 :     obj.pushKV("quorumIndex", quorumIndex);
     123           6 :     obj.pushKV("signersCount", CountSigners());
     124           6 :     obj.pushKV("signers", BitsVectorToHexStr(signers));
     125           6 :     obj.pushKV("validMembersCount", CountValidMembers());
     126           6 :     obj.pushKV("validMembers", BitsVectorToHexStr(validMembers));
     127           6 :     obj.pushKV("quorumPublicKey", quorumPublicKey.ToString(nVersion == LEGACY_BLS_NON_INDEXED_QUORUM_VERSION || nVersion == LEGACY_BLS_INDEXED_QUORUM_VERSION));
     128           6 :     obj.pushKV("quorumVvecHash", quorumVvecHash.ToString());
     129           6 :     obj.pushKV("quorumSig", quorumSig.ToString(nVersion == LEGACY_BLS_NON_INDEXED_QUORUM_VERSION || nVersion == LEGACY_BLS_INDEXED_QUORUM_VERSION));
     130           6 :     obj.pushKV("membersSig", membersSig.ToString(nVersion == LEGACY_BLS_NON_INDEXED_QUORUM_VERSION || nVersion == LEGACY_BLS_INDEXED_QUORUM_VERSION));
     131           6 :     return obj;
     132           6 : }
     133             : 
     134         191 : RPCResult CFinalCommitmentTxPayload::GetJsonHelp(const std::string& key, bool optional)
     135             : {
     136         382 :     return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The quorum commitment special transaction",
     137         764 :     {
     138         191 :         GetRpcResult("version"),
     139         191 :         GetRpcResult("height"),
     140         191 :         CFinalCommitment::GetJsonHelp(/*key=*/"commitment", /*optional=*/false),
     141             :     }};
     142           0 : }
     143             : 
     144           0 : UniValue CFinalCommitmentTxPayload::ToJson() const
     145             : {
     146           0 :     UniValue ret(UniValue::VOBJ);
     147           0 :     ret.pushKV("version", nVersion);
     148           0 :     ret.pushKV("height", nHeight);
     149           0 :     ret.pushKV("commitment", commitment.ToJson());
     150           0 :     return ret;
     151           0 : }
     152             : 
     153          92 : RPCResult CQuorumRotationInfo::GetJsonHelp(const std::string& key, bool optional)
     154             : {
     155         184 :     return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The quorum rotation",
     156        1380 :     {
     157          92 :         {RPCResult::Type::BOOL, "extraShare", "Returns true if an extra share is returned"},
     158          92 :         CQuorumSnapshot::GetJsonHelp(/*key=*/"quorumSnapshotAtHMinusC", /*optional=*/false),
     159          92 :         CQuorumSnapshot::GetJsonHelp(/*key=*/"quorumSnapshotAtHMinus2C", /*optional=*/false),
     160          92 :         CQuorumSnapshot::GetJsonHelp(/*key=*/"quorumSnapshotAtHMinus3C", /*optional=*/false),
     161          92 :         CQuorumSnapshot::GetJsonHelp(/*key=*/"quorumSnapshotAtHMinus4C", /*optional=*/true),
     162          92 :         CSimplifiedMNListDiff::GetJsonHelp(/*key=*/"mnListDiffTip", /*optional=*/false),
     163          92 :         CSimplifiedMNListDiff::GetJsonHelp(/*key=*/"mnListDiffH", /*optional=*/false),
     164          92 :         CSimplifiedMNListDiff::GetJsonHelp(/*key=*/"mnListDiffAtHMinusC", /*optional=*/false),
     165          92 :         CSimplifiedMNListDiff::GetJsonHelp(/*key=*/"mnListDiffAtHMinus2C", /*optional=*/false),
     166          92 :         CSimplifiedMNListDiff::GetJsonHelp(/*key=*/"mnListDiffAtHMinus3C", /*optional=*/false),
     167          92 :         CSimplifiedMNListDiff::GetJsonHelp(/*key=*/"mnListDiffAtHMinus4C", /*optional=*/true),
     168         184 :         {RPCResult::Type::ARR, "lastCommitmentPerIndex", "Most recent commitment for each quorumIndex", {
     169          92 :             CFinalCommitment::GetJsonHelp(/*key=*/"", /*optional=*/false),
     170             :         }},
     171         184 :         {RPCResult::Type::ARR, "quorumSnapshotList", "Snapshots required to reconstruct the quorums built at h' in lastCommitmentPerIndex", {
     172          92 :             CQuorumSnapshot::GetJsonHelp(/*key=*/"", /*optional=*/false),
     173             :         }},
     174         184 :         {RPCResult::Type::ARR, "mnListDiffList", "MnListDiffs required to calculate older quorums", {
     175          92 :             CSimplifiedMNListDiff::GetJsonHelp(/*key=*/"", /*optional=*/false),
     176             :         }},
     177             :     }};
     178           0 : }
     179             : 
     180           0 : UniValue CQuorumRotationInfo::ToJson() const
     181             : {
     182           0 :     UniValue obj(UniValue::VOBJ);
     183           0 :     obj.pushKV("extraShare", extraShare);
     184             : 
     185           0 :     obj.pushKV("quorumSnapshotAtHMinusC", cycleHMinusC.m_snap.ToJson());
     186           0 :     obj.pushKV("quorumSnapshotAtHMinus2C", cycleHMinus2C.m_snap.ToJson());
     187           0 :     obj.pushKV("quorumSnapshotAtHMinus3C", cycleHMinus3C.m_snap.ToJson());
     188             : 
     189           0 :     if (extraShare) {
     190           0 :         obj.pushKV("quorumSnapshotAtHMinus4C", CHECK_NONFATAL(cycleHMinus4C)->m_snap.ToJson());
     191           0 :     }
     192             : 
     193           0 :     obj.pushKV("mnListDiffTip", mnListDiffTip.ToJson());
     194           0 :     obj.pushKV("mnListDiffH", mnListDiffH.ToJson());
     195           0 :     obj.pushKV("mnListDiffAtHMinusC", cycleHMinusC.m_diff.ToJson());
     196           0 :     obj.pushKV("mnListDiffAtHMinus2C", cycleHMinus2C.m_diff.ToJson());
     197           0 :     obj.pushKV("mnListDiffAtHMinus3C", cycleHMinus3C.m_diff.ToJson());
     198             : 
     199           0 :     if (extraShare) {
     200           0 :         obj.pushKV("mnListDiffAtHMinus4C", CHECK_NONFATAL(cycleHMinus4C)->m_diff.ToJson());
     201           0 :     }
     202           0 :     UniValue hqclists(UniValue::VARR);
     203           0 :     for (const auto& qc : lastCommitmentPerIndex) {
     204           0 :         hqclists.push_back(qc.ToJson());
     205             :     }
     206           0 :     obj.pushKV("lastCommitmentPerIndex", hqclists);
     207             : 
     208           0 :     UniValue snapshotlist(UniValue::VARR);
     209           0 :     for (const auto& snap : quorumSnapshotList) {
     210           0 :         snapshotlist.push_back(snap.ToJson());
     211             :     }
     212           0 :     obj.pushKV("quorumSnapshotList", snapshotlist);
     213             : 
     214           0 :     UniValue mnlistdifflist(UniValue::VARR);
     215           0 :     for (const auto& mnlist : mnListDiffList) {
     216           0 :         mnlistdifflist.push_back(mnlist.ToJson());
     217             :     }
     218           0 :     obj.pushKV("mnListDiffList", mnlistdifflist);
     219           0 :     return obj;
     220           0 : }
     221             : 
     222         460 : RPCResult CQuorumSnapshot::GetJsonHelp(const std::string& key, bool optional)
     223             : {
     224         920 :     return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The quorum snapshot",
     225        1840 :     {
     226         920 :         {RPCResult::Type::ARR, "activeQuorumMembers", "Bitset of nodes already in quarters at the start of cycle", {
     227         460 :             {RPCResult::Type::BOOL, "bit", ""}
     228             :         }},
     229         460 :         {RPCResult::Type::NUM, "mnSkipListMode", "Mode of the skip list"},
     230         920 :         {RPCResult::Type::ARR, "mnSkipList", "Skiplist at height", {
     231         460 :             {RPCResult::Type::NUM, "height", ""}
     232             :         }},
     233             :     }};
     234           0 : }
     235             : 
     236           1 : UniValue CQuorumSnapshot::ToJson() const
     237             : {
     238           1 :     UniValue obj(UniValue::VOBJ);
     239           1 :     UniValue activeQ(UniValue::VARR);
     240           8 :     for (const bool h : activeQuorumMembers) {
     241             :         // cppcheck-suppress useStlAlgorithm
     242           7 :         activeQ.push_back(h);
     243             :     }
     244           1 :     obj.pushKV("activeQuorumMembers", activeQ);
     245           1 :     obj.pushKV("mnSkipListMode", std23::to_underlying(mnSkipListMode));
     246           1 :     UniValue skipList(UniValue::VARR);
     247           5 :     for (const auto& h : mnSkipList) {
     248             :         // cppcheck-suppress useStlAlgorithm
     249           4 :         skipList.push_back(h);
     250             :     }
     251           1 :     obj.pushKV("mnSkipList", skipList);
     252           1 :     return obj;
     253           1 : }
     254             : 
     255          92 : RPCResult CRecoveredSig::GetJsonHelp(const std::string& key, bool optional)
     256             : {
     257         184 :     return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The recovered signature",
     258         644 :     {
     259          92 :         GetRpcResult("llmqType"),
     260          92 :         GetRpcResult("quorumHash"),
     261          92 :         {RPCResult::Type::NUM, "id", "Signing session ID"},
     262          92 :         {RPCResult::Type::STR_HEX, "msgHash", "Hash of message"},
     263          92 :         {RPCResult::Type::STR_HEX, "sig", "BLS signature recovered"},
     264          92 :         {RPCResult::Type::STR_HEX, "hash", "Hash of the BLS signature recovered"},
     265             :     }};
     266           0 : }
     267             : 
     268           0 : UniValue CRecoveredSig::ToJson() const
     269             : {
     270           0 :     UniValue ret(UniValue::VOBJ);
     271           0 :     ret.pushKV("llmqType", std23::to_underlying(llmqType));
     272           0 :     ret.pushKV("quorumHash", quorumHash.ToString());
     273           0 :     ret.pushKV("id", id.ToString());
     274           0 :     ret.pushKV("msgHash", msgHash.ToString());
     275           0 :     ret.pushKV("sig", sig.Get().ToString());
     276           0 :     ret.pushKV("hash", sig.Get().GetHash().ToString());
     277           0 :     return ret;
     278           0 : }
     279             : } // namespace llmq

Generated by: LCOV version 1.16