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