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 <evo/assetlocktx.h>
6 : #include <evo/cbtx.h>
7 : #include <evo/deterministicmns.h>
8 : #include <evo/dmnstate.h>
9 : #include <evo/mnhftx.h>
10 : #include <evo/netinfo.h>
11 : #include <evo/providertx.h>
12 : #include <evo/simplifiedmns.h>
13 : #include <evo/smldiff.h>
14 : #include <llmq/commitment.h>
15 : #include <rpc/evo_util.h>
16 : #include <util/std23.h>
17 :
18 : #include <core_io.h>
19 : #include <rpc/util.h>
20 : #include <util/check.h>
21 :
22 : #include <univalue.h>
23 :
24 : #include <map>
25 : #include <string>
26 :
27 : namespace {
28 : #define RESULT_MAP_ENTRY(name, type, desc) {name, {type, name, desc}}
29 7848 : const std::map<std::string, RPCResult> RPCRESULT_MAP{{
30 436 : {"addresses",
31 436 : {RPCResult::Type::OBJ, "addresses", "Network addresses of the masternode",
32 872 : {
33 436 : {RPCResult::Type::ARR, "core_p2p", /*optional=*/true, "Addresses used for protocol P2P",
34 218 : {{RPCResult::Type::STR, "address", ""}}},
35 436 : {RPCResult::Type::ARR, "platform_p2p", /*optional=*/true, "Addresses used for Platform P2P",
36 218 : {{RPCResult::Type::STR, "address", ""}}},
37 436 : {RPCResult::Type::ARR, "platform_https", /*optional=*/true, "Addresses used for Platform HTTPS API",
38 218 : {{RPCResult::Type::STR, "address", ""}}},
39 : }}},
40 218 : RESULT_MAP_ENTRY("collateralAddress", RPCResult::Type::STR, "Dash address used for collateral"),
41 218 : RESULT_MAP_ENTRY("collateralHash", RPCResult::Type::STR_HEX, "Collateral transaction hash"),
42 218 : RESULT_MAP_ENTRY("collateralIndex", RPCResult::Type::NUM, "Collateral transaction output index"),
43 218 : RESULT_MAP_ENTRY("consecutivePayments", RPCResult::Type::NUM, "Consecutive payments masternode has received in payment cycle"),
44 218 : RESULT_MAP_ENTRY("height", RPCResult::Type::NUM, "Block height"),
45 218 : RESULT_MAP_ENTRY("inputsHash", RPCResult::Type::STR_HEX, "Hash of all the outpoints of the transaction inputs"),
46 218 : RESULT_MAP_ENTRY("lastPaidHeight", RPCResult::Type::NUM, "Height masternode was last paid"),
47 218 : RESULT_MAP_ENTRY("llmqType", RPCResult::Type::NUM, "Quorum type"),
48 218 : RESULT_MAP_ENTRY("memberIndex", RPCResult::Type::NUM, "Quorum member index"),
49 218 : RESULT_MAP_ENTRY("merkleRootMNList", RPCResult::Type::STR_HEX, "Merkle root of the masternode list"),
50 218 : RESULT_MAP_ENTRY("merkleRootQuorums", RPCResult::Type::STR_HEX, "Merkle root of the quorum list"),
51 218 : RESULT_MAP_ENTRY("operatorPayoutAddress", RPCResult::Type::STR, "Dash address used for operator reward payments"),
52 218 : RESULT_MAP_ENTRY("operatorReward", RPCResult::Type::NUM, "Fraction in %% of reward shared with the operator between 0 and 10000"),
53 218 : RESULT_MAP_ENTRY("outpoint", RPCResult::Type::STR_HEX,"The outpoint of the masternode"),
54 218 : RESULT_MAP_ENTRY("ownerAddress", RPCResult::Type::STR, "Dash address used for payee updates and proposal voting"),
55 218 : RESULT_MAP_ENTRY("payoutAddress", RPCResult::Type::STR, "Dash address used for masternode reward payments"),
56 218 : RESULT_MAP_ENTRY("platformHTTPPort", RPCResult::Type::NUM, "TCP port of Platform HTTP API (DEPRECATED, returned only if config option -deprecatedrpc=service is passed)"),
57 218 : RESULT_MAP_ENTRY("platformNodeID", RPCResult::Type::STR_HEX, "Node ID derived from P2P public key for Platform P2P"),
58 218 : RESULT_MAP_ENTRY("platformP2PPort", RPCResult::Type::NUM, "TCP port of Platform P2P (DEPRECATED, returned only if config option -deprecatedrpc=service is passed)"),
59 218 : RESULT_MAP_ENTRY("PoSeBanHeight", RPCResult::Type::NUM, "Height masternode was banned for Proof of Service violations"),
60 218 : RESULT_MAP_ENTRY("PoSePenalty", RPCResult::Type::NUM, "Proof of Service penalty score"),
61 218 : RESULT_MAP_ENTRY("PoSeRevivedHeight", RPCResult::Type::NUM, "Height masternode recovered from Proof of Service violations"),
62 218 : RESULT_MAP_ENTRY("proTxHash", RPCResult::Type::STR_HEX, "Hash of the masternode's initial ProRegTx"),
63 218 : RESULT_MAP_ENTRY("pubKeyOperator", RPCResult::Type::STR, "BLS public key used for operator signing"),
64 218 : RESULT_MAP_ENTRY("quorumIndex", RPCResult::Type::NUM, "Quorum index. Relevant for rotation quorums only, 0 for non-rotating quorums"),
65 218 : RESULT_MAP_ENTRY("quorumHash", RPCResult::Type::STR_HEX, "Hash of the quorum"),
66 218 : RESULT_MAP_ENTRY("quorumSig", RPCResult::Type::STR_HEX, "BLS recovered threshold signature of quorum"),
67 218 : RESULT_MAP_ENTRY("registeredHeight", RPCResult::Type::NUM, "Height masternode was registered"),
68 218 : RESULT_MAP_ENTRY("revocationReason", RPCResult::Type::NUM, "Reason for ProUpRegTx revocation"),
69 218 : RESULT_MAP_ENTRY("service", RPCResult::Type::STR, "IP address and port of the masternode (DEPRECATED, returned only if config option -deprecatedrpc=service is passed)"),
70 218 : RESULT_MAP_ENTRY("type", RPCResult::Type::NUM, "Masternode type"),
71 218 : RESULT_MAP_ENTRY("type_str", RPCResult::Type::STR, "Masternode type (human-readable string)"),
72 218 : RESULT_MAP_ENTRY("version", RPCResult::Type::NUM, "Special transaction version"),
73 218 : RESULT_MAP_ENTRY("votingAddress", RPCResult::Type::STR, "Dash address used for voting"),
74 : }};
75 : #undef RESULT_MAP_ENTRY
76 :
77 : template <typename Obj>
78 0 : std::string GetDeprecatedServiceField(const Obj& obj)
79 : {
80 0 : return CHECK_NONFATAL(obj.netInfo)->GetPrimary().ToStringAddrPort();
81 0 : }
82 : } // anonymous namespace
83 :
84 33555 : RPCResult GetRpcResult(const std::string& key, bool optional, const std::string& override_name)
85 : {
86 33555 : if (const auto it = RPCRESULT_MAP.find(key); it != RPCRESULT_MAP.end()) {
87 33555 : const auto& ret{it->second};
88 33555 : return RPCResult{ret.m_type, override_name.empty() ? ret.m_key_name : override_name, optional, ret.m_description, ret.m_inner};
89 : }
90 0 : throw NonFatalCheckError(strprintf("Requested invalid RPCResult for nonexistent key \"%s\"", key).c_str(),
91 : __FILE__, __LINE__, __func__);
92 0 : }
93 :
94 191 : RPCResult CAssetLockPayload::GetJsonHelp(const std::string& key, bool optional)
95 : {
96 382 : return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The asset lock special transaction",
97 573 : {
98 191 : GetRpcResult("version"),
99 382 : {RPCResult::Type::ARR, "creditOutputs", "", {
100 764 : {RPCResult::Type::OBJ, "", "", {
101 191 : {RPCResult::Type::NUM, "value", "The value in Dash"},
102 191 : {RPCResult::Type::NUM, "valueSat", "The value in duffs"},
103 764 : {RPCResult::Type::OBJ, "scriptPubKey", "", {
104 191 : {RPCResult::Type::STR, "asm", "The asm"},
105 191 : {RPCResult::Type::STR_HEX, "hex", "The hex"},
106 191 : {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
107 : }}}}}}
108 : }};
109 0 : }
110 :
111 0 : UniValue CAssetLockPayload::ToJson() const
112 : {
113 0 : UniValue outputs(UniValue::VARR);
114 0 : for (const CTxOut& credit_output : creditOutputs) {
115 0 : UniValue out(UniValue::VOBJ);
116 0 : out.pushKV("value", ValueFromAmount(credit_output.nValue));
117 0 : out.pushKV("valueSat", credit_output.nValue);
118 0 : UniValue spk(UniValue::VOBJ);
119 0 : ScriptToUniv(credit_output.scriptPubKey, spk, /*include_hex=*/true, /*include_address=*/false);
120 0 : out.pushKV("scriptPubKey", spk);
121 0 : outputs.push_back(out);
122 0 : }
123 :
124 0 : UniValue ret(UniValue::VOBJ);
125 0 : ret.pushKV("version", nVersion);
126 0 : ret.pushKV("creditOutputs", outputs);
127 0 : return ret;
128 0 : }
129 :
130 191 : RPCResult CAssetUnlockPayload::GetJsonHelp(const std::string& key, bool optional)
131 : {
132 382 : return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The asset unlock special transaction",
133 1337 : {
134 191 : GetRpcResult("version"),
135 191 : {RPCResult::Type::NUM, "index", "Index of the transaction"},
136 191 : {RPCResult::Type::NUM, "fee", "Transaction fee in duffs awarded to the miner"},
137 191 : {RPCResult::Type::NUM, "requestedHeight", "Payment chain block height known by Platform when signing the withdrawal"},
138 191 : GetRpcResult("quorumHash"),
139 191 : GetRpcResult("quorumSig"),
140 : }};
141 0 : }
142 :
143 0 : UniValue CAssetUnlockPayload::ToJson() const
144 : {
145 0 : UniValue ret(UniValue::VOBJ);
146 0 : ret.pushKV("version", nVersion);
147 0 : ret.pushKV("index", index);
148 0 : ret.pushKV("fee", fee);
149 0 : ret.pushKV("requestedHeight", requestedHeight);
150 0 : ret.pushKV("quorumHash", quorumHash.ToString());
151 0 : ret.pushKV("quorumSig", quorumSig.ToString());
152 0 : return ret;
153 0 : }
154 :
155 283 : RPCResult CCbTx::GetJsonHelp(const std::string& key, bool optional)
156 : {
157 566 : return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The coinbase special transaction",
158 2264 : {
159 283 : GetRpcResult("version"),
160 283 : GetRpcResult("height"),
161 283 : GetRpcResult("merkleRootMNList"),
162 283 : GetRpcResult("merkleRootQuorums", /*optional=*/true),
163 283 : {RPCResult::Type::NUM, "bestCLHeightDiff", /*optional=*/true, "Blocks between the current block and the last known block with a ChainLock"},
164 283 : {RPCResult::Type::STR_HEX, "bestCLSignature", /*optional=*/true, "Best ChainLock signature known by the miner"},
165 283 : {RPCResult::Type::NUM, "creditPoolBalance", /*optional=*/true, "Balance in the Platform credit pool"},
166 : }};
167 0 : }
168 :
169 0 : UniValue CCbTx::ToJson() const
170 : {
171 0 : UniValue ret(UniValue::VOBJ);
172 0 : ret.pushKV("version", std23::to_underlying(nVersion));
173 0 : ret.pushKV("height", nHeight);
174 0 : ret.pushKV("merkleRootMNList", merkleRootMNList.ToString());
175 0 : if (nVersion >= CCbTx::Version::MERKLE_ROOT_QUORUMS) {
176 0 : ret.pushKV("merkleRootQuorums", merkleRootQuorums.ToString());
177 0 : if (nVersion >= CCbTx::Version::CLSIG_AND_BALANCE) {
178 0 : ret.pushKV("bestCLHeightDiff", bestCLHeightDiff);
179 0 : ret.pushKV("bestCLSignature", bestCLSignature.ToString());
180 0 : ret.pushKV("creditPoolBalance", ValueFromAmount(creditPoolBalance));
181 0 : }
182 0 : }
183 0 : return ret;
184 0 : }
185 :
186 : // CDeterministicMN::ToJson() defined in evo/deterministicmns.cpp
187 92 : RPCResult CDeterministicMN::GetJsonHelp(const std::string& key, bool optional)
188 : {
189 184 : return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The masternode's details",
190 736 : {
191 92 : GetRpcResult("type_str", /*optional=*/false, /*override_name=*/"type"),
192 92 : GetRpcResult("proTxHash"),
193 92 : GetRpcResult("collateralHash"),
194 92 : GetRpcResult("collateralIndex"),
195 92 : GetRpcResult("collateralAddress", /*optional=*/true),
196 92 : GetRpcResult("operatorReward"),
197 92 : CDeterministicMNState::GetJsonHelp(/*key=*/"state", /*optional=*/false),
198 : }};
199 0 : }
200 :
201 184 : RPCResult CDeterministicMNState::GetJsonHelp(const std::string& key, bool optional)
202 : {
203 368 : return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The masternode state",
204 3496 : {
205 184 : {RPCResult::Type::NUM, "version", "Version of the masternode state"},
206 184 : GetRpcResult("service", /*optional=*/true),
207 184 : GetRpcResult("addresses"),
208 184 : GetRpcResult("registeredHeight"),
209 184 : GetRpcResult("lastPaidHeight"),
210 184 : GetRpcResult("consecutivePayments"),
211 184 : GetRpcResult("PoSePenalty"),
212 184 : GetRpcResult("PoSeRevivedHeight"),
213 184 : GetRpcResult("PoSeBanHeight"),
214 184 : GetRpcResult("revocationReason"),
215 184 : GetRpcResult("ownerAddress"),
216 184 : GetRpcResult("votingAddress"),
217 184 : GetRpcResult("platformNodeID", /*optional=*/true),
218 184 : GetRpcResult("platformP2PPort", /*optional=*/true),
219 184 : GetRpcResult("platformHTTPPort", /*optional=*/true),
220 184 : GetRpcResult("payoutAddress", /*optional=*/true),
221 184 : GetRpcResult("pubKeyOperator"),
222 184 : GetRpcResult("operatorPayoutAddress", /*optional=*/true),
223 : }};
224 0 : }
225 :
226 0 : UniValue CDeterministicMNState::ToJson(MnType nType) const
227 : {
228 0 : UniValue obj(UniValue::VOBJ);
229 0 : obj.pushKV("version", nVersion);
230 0 : if (IsServiceDeprecatedRPCEnabled()) {
231 0 : obj.pushKV("service", GetDeprecatedServiceField(*this));
232 0 : }
233 0 : obj.pushKV("addresses", GetNetInfoWithLegacyFields(*this, nType));
234 0 : obj.pushKV("registeredHeight", nRegisteredHeight);
235 0 : obj.pushKV("lastPaidHeight", nLastPaidHeight);
236 0 : obj.pushKV("consecutivePayments", nConsecutivePayments);
237 0 : obj.pushKV("PoSePenalty", nPoSePenalty);
238 0 : obj.pushKV("PoSeRevivedHeight", nPoSeRevivedHeight);
239 0 : obj.pushKV("PoSeBanHeight", nPoSeBanHeight);
240 0 : obj.pushKV("revocationReason", nRevocationReason);
241 0 : obj.pushKV("ownerAddress", EncodeDestination(PKHash(keyIDOwner)));
242 0 : obj.pushKV("votingAddress", EncodeDestination(PKHash(keyIDVoting)));
243 0 : if (nType == MnType::Evo) {
244 0 : obj.pushKV("platformNodeID", platformNodeID.ToString());
245 0 : if (IsServiceDeprecatedRPCEnabled()) {
246 0 : obj.pushKV("platformP2PPort", GetPlatformPort</*is_p2p=*/true>(*this));
247 0 : obj.pushKV("platformHTTPPort", GetPlatformPort</*is_p2p=*/false>(*this));
248 0 : }
249 0 : }
250 :
251 0 : CTxDestination dest;
252 0 : if (ExtractDestination(scriptPayout, dest)) {
253 0 : obj.pushKV("payoutAddress", EncodeDestination(dest));
254 0 : }
255 0 : obj.pushKV("pubKeyOperator", pubKeyOperator.ToString());
256 0 : if (ExtractDestination(scriptOperatorPayout, dest)) {
257 0 : obj.pushKV("operatorPayoutAddress", EncodeDestination(dest));
258 0 : }
259 0 : return obj;
260 0 : }
261 :
262 : // CDeterministicMNStateDiff::ToJson() defined in evo/dmnstate.cpp
263 92 : RPCResult CDeterministicMNStateDiff::GetJsonHelp(const std::string& key, bool optional)
264 : {
265 184 : return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The masternode state diff",
266 1748 : {
267 92 : {RPCResult::Type::NUM, "version", "Version of the masternode state diff"},
268 92 : GetRpcResult("service", /*optional=*/true),
269 92 : GetRpcResult("registeredHeight", /*optional=*/true),
270 92 : GetRpcResult("lastPaidHeight", /*optional=*/true),
271 92 : GetRpcResult("consecutivePayments", /*optional=*/true),
272 92 : GetRpcResult("PoSePenalty", /*optional=*/true),
273 92 : GetRpcResult("PoSeRevivedHeight", /*optional=*/true),
274 92 : GetRpcResult("PoSeBanHeight", /*optional=*/true),
275 92 : GetRpcResult("revocationReason", /*optional=*/true),
276 92 : GetRpcResult("ownerAddress", /*optional=*/true),
277 92 : GetRpcResult("votingAddress", /*optional=*/true),
278 92 : GetRpcResult("payoutAddress", /*optional=*/true),
279 92 : GetRpcResult("operatorPayoutAddress", /*optional=*/true),
280 92 : GetRpcResult("pubKeyOperator", /*optional=*/true),
281 92 : GetRpcResult("platformNodeID", /*optional=*/true),
282 92 : GetRpcResult("platformP2PPort", /*optional=*/true),
283 92 : GetRpcResult("platformHTTPPort", /*optional=*/true),
284 92 : GetRpcResult("addresses", /*optional=*/true),
285 : }};
286 0 : }
287 :
288 191 : RPCResult CProRegTx::GetJsonHelp(const std::string& key, bool optional)
289 : {
290 382 : return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The masternode registration special transaction",
291 3056 : {
292 191 : GetRpcResult("version"),
293 191 : GetRpcResult("type"),
294 191 : GetRpcResult("collateralHash"),
295 191 : GetRpcResult("collateralIndex"),
296 191 : GetRpcResult("service", /*optional=*/true),
297 191 : GetRpcResult("addresses"),
298 191 : GetRpcResult("ownerAddress"),
299 191 : GetRpcResult("votingAddress"),
300 191 : GetRpcResult("payoutAddress", /*optional=*/true),
301 191 : GetRpcResult("pubKeyOperator"),
302 191 : GetRpcResult("operatorReward"),
303 191 : GetRpcResult("platformNodeID", /*optional=*/true),
304 191 : GetRpcResult("platformP2PPort", /*optional=*/true),
305 191 : GetRpcResult("platformHTTPPort", /*optional=*/true),
306 191 : GetRpcResult("inputsHash"),
307 : }};
308 0 : }
309 :
310 0 : UniValue CProRegTx::ToJson() const
311 : {
312 0 : UniValue ret(UniValue::VOBJ);
313 0 : ret.pushKV("version", nVersion);
314 0 : ret.pushKV("type", std23::to_underlying(nType));
315 0 : ret.pushKV("collateralHash", collateralOutpoint.hash.ToString());
316 0 : ret.pushKV("collateralIndex", collateralOutpoint.n);
317 0 : if (IsServiceDeprecatedRPCEnabled()) {
318 0 : ret.pushKV("service", GetDeprecatedServiceField(*this));
319 0 : }
320 0 : ret.pushKV("addresses", GetNetInfoWithLegacyFields(*this, nType));
321 0 : ret.pushKV("ownerAddress", EncodeDestination(PKHash(keyIDOwner)));
322 0 : ret.pushKV("votingAddress", EncodeDestination(PKHash(keyIDVoting)));
323 0 : if (CTxDestination dest; ExtractDestination(scriptPayout, dest)) {
324 0 : ret.pushKV("payoutAddress", EncodeDestination(dest));
325 0 : }
326 0 : ret.pushKV("pubKeyOperator", pubKeyOperator.ToString());
327 0 : ret.pushKV("operatorReward", (double)nOperatorReward / 100);
328 0 : if (nType == MnType::Evo) {
329 0 : ret.pushKV("platformNodeID", platformNodeID.ToString());
330 0 : if (IsServiceDeprecatedRPCEnabled()) {
331 0 : ret.pushKV("platformP2PPort", GetPlatformPort</*is_p2p=*/true>(*this));
332 0 : ret.pushKV("platformHTTPPort", GetPlatformPort</*is_p2p=*/false>(*this));
333 0 : }
334 0 : }
335 0 : ret.pushKV("inputsHash", inputsHash.ToString());
336 0 : return ret;
337 0 : }
338 :
339 191 : RPCResult CProUpRegTx::GetJsonHelp(const std::string& key, bool optional)
340 : {
341 382 : return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The masternode update registrar special transaction",
342 1337 : {
343 191 : GetRpcResult("version"),
344 191 : GetRpcResult("proTxHash"),
345 191 : GetRpcResult("votingAddress"),
346 191 : GetRpcResult("payoutAddress", /*optional=*/true),
347 191 : GetRpcResult("pubKeyOperator"),
348 191 : GetRpcResult("inputsHash"),
349 : }};
350 0 : }
351 :
352 0 : UniValue CProUpRegTx::ToJson() const
353 : {
354 0 : UniValue ret(UniValue::VOBJ);
355 0 : ret.pushKV("version", nVersion);
356 0 : ret.pushKV("proTxHash", proTxHash.ToString());
357 0 : ret.pushKV("votingAddress", EncodeDestination(PKHash(keyIDVoting)));
358 0 : if (CTxDestination dest; ExtractDestination(scriptPayout, dest)) {
359 0 : ret.pushKV("payoutAddress", EncodeDestination(dest));
360 0 : }
361 0 : ret.pushKV("pubKeyOperator", pubKeyOperator.ToString());
362 0 : ret.pushKV("inputsHash", inputsHash.ToString());
363 0 : return ret;
364 0 : }
365 :
366 191 : RPCResult CProUpRevTx::GetJsonHelp(const std::string& key, bool optional)
367 : {
368 382 : return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The masternode operator revocation special transaction",
369 955 : {
370 191 : GetRpcResult("version"),
371 191 : GetRpcResult("proTxHash"),
372 191 : {RPCResult::Type::NUM, "reason", "Reason for masternode service revocation"},
373 191 : GetRpcResult("inputsHash", /*optional=*/true),
374 : }};
375 0 : }
376 :
377 0 : UniValue CProUpRevTx::ToJson() const
378 : {
379 0 : UniValue ret(UniValue::VOBJ);
380 0 : ret.pushKV("version", nVersion);
381 0 : ret.pushKV("proTxHash", proTxHash.ToString());
382 0 : ret.pushKV("reason", nReason);
383 0 : ret.pushKV("inputsHash", inputsHash.ToString());
384 0 : return ret;
385 0 : }
386 :
387 191 : RPCResult CProUpServTx::GetJsonHelp(const std::string& key, bool optional)
388 : {
389 382 : return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The masternode update service special transaction",
390 2101 : {
391 191 : GetRpcResult("version"),
392 191 : GetRpcResult("type"),
393 191 : GetRpcResult("proTxHash"),
394 191 : GetRpcResult("service", /*optional=*/true),
395 191 : GetRpcResult("addresses"),
396 191 : GetRpcResult("operatorPayoutAddress", /*optional=*/true),
397 191 : GetRpcResult("platformNodeID", /*optional=*/true),
398 191 : GetRpcResult("platformP2PPort", /*optional=*/true),
399 191 : GetRpcResult("platformHTTPPort", /*optional=*/true),
400 191 : GetRpcResult("inputsHash"),
401 : }};
402 0 : }
403 :
404 0 : UniValue CProUpServTx::ToJson() const
405 : {
406 0 : UniValue ret(UniValue::VOBJ);
407 0 : ret.pushKV("version", nVersion);
408 0 : ret.pushKV("type", std23::to_underlying(nType));
409 0 : ret.pushKV("proTxHash", proTxHash.ToString());
410 0 : if (IsServiceDeprecatedRPCEnabled()) {
411 0 : ret.pushKV("service", GetDeprecatedServiceField(*this));
412 0 : }
413 0 : ret.pushKV("addresses", GetNetInfoWithLegacyFields(*this, nType));
414 0 : if (CTxDestination dest; ExtractDestination(scriptOperatorPayout, dest)) {
415 0 : ret.pushKV("operatorPayoutAddress", EncodeDestination(dest));
416 0 : }
417 0 : if (nType == MnType::Evo) {
418 0 : ret.pushKV("platformNodeID", platformNodeID.ToString());
419 0 : if (IsServiceDeprecatedRPCEnabled()) {
420 0 : ret.pushKV("platformP2PPort", GetPlatformPort</*is_p2p=*/true>(*this));
421 0 : ret.pushKV("platformHTTPPort", GetPlatformPort</*is_p2p=*/false>(*this));
422 0 : }
423 0 : }
424 0 : ret.pushKV("inputsHash", inputsHash.ToString());
425 0 : return ret;
426 0 : }
427 :
428 736 : RPCResult CSimplifiedMNListDiff::GetJsonHelp(const std::string& key, bool optional)
429 : {
430 1472 : return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The simplified masternode list diff",
431 9568 : {
432 736 : {RPCResult::Type::NUM, "nVersion", "Version of the diff"},
433 736 : {RPCResult::Type::STR_HEX, "baseBlockHash", "Hash of the base block"},
434 736 : {RPCResult::Type::STR_HEX, "blockHash", "Hash of the ending block"},
435 736 : {RPCResult::Type::STR_HEX, "cbTxMerkleTree", "Coinbase transaction merkle tree"},
436 736 : {RPCResult::Type::STR_HEX, "cbTx", "Coinbase raw transaction"},
437 1472 : {RPCResult::Type::ARR, "deletedMNs", "ProRegTx hashes of deleted masternodes",
438 736 : {{RPCResult::Type::STR_HEX, "hash", ""}}},
439 1472 : {RPCResult::Type::ARR, "mnList", "Masternode list details",
440 736 : {CSimplifiedMNListEntry::GetJsonHelp(/*key=*/"", /*optional=*/false)}},
441 1472 : {RPCResult::Type::ARR, "deletedQuorums", "Deleted quorums",
442 2208 : {{RPCResult::Type::OBJ, "", "", {
443 736 : GetRpcResult("llmqType"),
444 736 : GetRpcResult("quorumHash"),
445 : }}}},
446 1472 : {RPCResult::Type::ARR, "newQuorums", "New quorums",
447 736 : {llmq::CFinalCommitment::GetJsonHelp(/*key=*/"", /*optional=*/false)}},
448 736 : GetRpcResult("merkleRootMNList", /*optional=*/true),
449 736 : GetRpcResult("merkleRootQuorums", /*optional=*/true),
450 1472 : {RPCResult::Type::ARR, "quorumsCLSigs", "ChainLock signature details", {
451 1472 : {RPCResult::Type::OBJ, "", "", {
452 1472 : {RPCResult::Type::ARR, "<sig_hex>", "Array of quorum indices, keyed by BLS signature", {
453 736 : {RPCResult::Type::NUM, "", "Quorum index"}
454 : }}}}}},
455 : }};
456 0 : }
457 :
458 0 : UniValue CSimplifiedMNListDiff::ToJson(bool extended) const
459 : {
460 0 : UniValue obj(UniValue::VOBJ);
461 :
462 0 : obj.pushKV("nVersion", nVersion);
463 0 : obj.pushKV("baseBlockHash", baseBlockHash.ToString());
464 0 : obj.pushKV("blockHash", blockHash.ToString());
465 :
466 0 : CDataStream ssCbTxMerkleTree(SER_NETWORK, PROTOCOL_VERSION);
467 0 : ssCbTxMerkleTree << cbTxMerkleTree;
468 0 : obj.pushKV("cbTxMerkleTree", HexStr(ssCbTxMerkleTree));
469 :
470 0 : obj.pushKV("cbTx", EncodeHexTx(CTransaction(cbTx)));
471 :
472 0 : UniValue deletedMNsArr(UniValue::VARR);
473 0 : for (const auto& h : deletedMNs) {
474 0 : deletedMNsArr.push_back(h.ToString());
475 : }
476 0 : obj.pushKV("deletedMNs", deletedMNsArr);
477 :
478 0 : UniValue mnListArr(UniValue::VARR);
479 0 : for (const auto& e : mnList) {
480 0 : mnListArr.push_back(e.ToJson(extended));
481 : }
482 0 : obj.pushKV("mnList", mnListArr);
483 :
484 0 : UniValue deletedQuorumsArr(UniValue::VARR);
485 0 : for (const auto& e : deletedQuorums) {
486 0 : UniValue eObj(UniValue::VOBJ);
487 0 : eObj.pushKV("llmqType", e.first);
488 0 : eObj.pushKV("quorumHash", e.second.ToString());
489 0 : deletedQuorumsArr.push_back(eObj);
490 0 : }
491 0 : obj.pushKV("deletedQuorums", deletedQuorumsArr);
492 :
493 0 : UniValue newQuorumsArr(UniValue::VARR);
494 0 : for (const auto& e : newQuorums) {
495 0 : newQuorumsArr.push_back(e.ToJson());
496 : }
497 0 : obj.pushKV("newQuorums", newQuorumsArr);
498 :
499 : // Do not assert special tx type here since this can be called prior to DIP0003 activation
500 0 : if (const auto opt_cbTxPayload = GetTxPayload<CCbTx>(cbTx, /*assert_type=*/false)) {
501 0 : obj.pushKV("merkleRootMNList", opt_cbTxPayload->merkleRootMNList.ToString());
502 0 : if (opt_cbTxPayload->nVersion >= CCbTx::Version::MERKLE_ROOT_QUORUMS) {
503 0 : obj.pushKV("merkleRootQuorums", opt_cbTxPayload->merkleRootQuorums.ToString());
504 0 : }
505 0 : }
506 :
507 0 : UniValue quorumsCLSigsArr(UniValue::VARR);
508 0 : for (const auto& [signature, quorumsIndexes] : quorumsCLSigs) {
509 0 : UniValue j(UniValue::VOBJ);
510 0 : UniValue idxArr(UniValue::VARR);
511 0 : for (const auto& idx : quorumsIndexes) {
512 0 : idxArr.push_back(idx);
513 : }
514 0 : j.pushKV(signature.ToString(), idxArr);
515 0 : quorumsCLSigsArr.push_back(j);
516 0 : }
517 0 : obj.pushKV("quorumsCLSigs", quorumsCLSigsArr);
518 0 : return obj;
519 0 : }
520 :
521 736 : RPCResult CSimplifiedMNListEntry::GetJsonHelp(const std::string& key, bool optional)
522 : {
523 1472 : return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The simplified masternode list entry",
524 10304 : {
525 736 : {RPCResult::Type::NUM, "nVersion", "Version of the entry"},
526 736 : GetRpcResult("type", /*optional=*/false, /*override_name=*/"nType"),
527 736 : {RPCResult::Type::STR_HEX, "proRegTxHash", "Hash of the ProRegTx identifying the masternode"},
528 736 : {RPCResult::Type::STR_HEX, "confirmedHash", "Hash of the block where the masternode was confirmed"},
529 736 : GetRpcResult("service", /*optional=*/true),
530 736 : GetRpcResult("addresses"),
531 736 : GetRpcResult("pubKeyOperator"),
532 736 : GetRpcResult("votingAddress"),
533 736 : {RPCResult::Type::BOOL, "isValid", "Returns true if the masternode is not Proof-of-Service banned"},
534 736 : GetRpcResult("platformHTTPPort", /*optional=*/true),
535 736 : GetRpcResult("platformNodeID", /*optional=*/true),
536 736 : GetRpcResult("payoutAddress", /*optional=*/true),
537 736 : GetRpcResult("operatorPayoutAddress", /*optional=*/true),
538 : }};
539 0 : }
540 :
541 0 : UniValue CSimplifiedMNListEntry::ToJson(bool extended) const
542 : {
543 0 : UniValue obj(UniValue::VOBJ);
544 0 : obj.pushKV("nVersion", nVersion);
545 0 : obj.pushKV("nType", std23::to_underlying(nType));
546 0 : obj.pushKV("proRegTxHash", proRegTxHash.ToString());
547 0 : obj.pushKV("confirmedHash", confirmedHash.ToString());
548 0 : if (IsServiceDeprecatedRPCEnabled()) {
549 0 : obj.pushKV("service", GetDeprecatedServiceField(*this));
550 0 : }
551 0 : obj.pushKV("addresses", GetNetInfoWithLegacyFields(*this, nType));
552 0 : obj.pushKV("pubKeyOperator", pubKeyOperator.ToString());
553 0 : obj.pushKV("votingAddress", EncodeDestination(PKHash(keyIDVoting)));
554 0 : obj.pushKV("isValid", isValid);
555 0 : if (nType == MnType::Evo) {
556 0 : if (IsServiceDeprecatedRPCEnabled()) {
557 0 : obj.pushKV("platformHTTPPort", GetPlatformPort</*is_p2p=*/false>(*this));
558 0 : }
559 0 : obj.pushKV("platformNodeID", platformNodeID.ToString());
560 0 : }
561 :
562 0 : if (extended) {
563 0 : CTxDestination dest;
564 0 : if (ExtractDestination(scriptPayout, dest)) {
565 0 : obj.pushKV("payoutAddress", EncodeDestination(dest));
566 0 : }
567 0 : if (ExtractDestination(scriptOperatorPayout, dest)) {
568 0 : obj.pushKV("operatorPayoutAddress", EncodeDestination(dest));
569 0 : }
570 0 : }
571 0 : return obj;
572 0 : }
573 :
574 191 : RPCResult MNHFTx::GetJsonHelp(const std::string& key, bool optional)
575 : {
576 382 : return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The masternode hard fork payload",
577 764 : {
578 191 : {RPCResult::Type::NUM, "versionBit", "Version bit associated with the hard fork"},
579 191 : GetRpcResult("quorumHash"),
580 191 : {RPCResult::Type::STR_HEX, "sig", "BLS signature by a quorum public key"},
581 : }};
582 0 : }
583 :
584 0 : UniValue MNHFTx::ToJson() const
585 : {
586 0 : UniValue obj(UniValue::VOBJ);
587 0 : obj.pushKV("versionBit", versionBit);
588 0 : obj.pushKV("quorumHash", quorumHash.ToString());
589 0 : obj.pushKV("sig", sig.ToString());
590 0 : return obj;
591 0 : }
592 :
593 191 : RPCResult MNHFTxPayload::GetJsonHelp(const std::string& key, bool optional)
594 : {
595 382 : return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The masternode hard fork signal special transaction",
596 573 : {
597 191 : GetRpcResult("version"),
598 191 : MNHFTx::GetJsonHelp(/*key=*/"signal", /*optional=*/false),
599 : }};
600 0 : }
601 :
602 0 : UniValue MNHFTxPayload::ToJson() const
603 : {
604 0 : UniValue ret(UniValue::VOBJ);
605 0 : ret.pushKV("version", nVersion);
606 0 : ret.pushKV("signal", signal.ToJson());
607 0 : return ret;
608 0 : }
|