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
|