Bitcoin ABC 0.32.5
P2P Digital Currency
avalanche.cpp
Go to the documentation of this file.
1// Copyright (c) 2020 The Bitcoin developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
10#include <avalanche/proof.h>
14#include <common/args.h>
15#include <config.h>
16#include <core_io.h>
17#include <index/txindex.h>
18#include <key_io.h>
19#include <net_processing.h>
20#include <node/context.h>
22#include <rpc/blockchain.h>
24#include <rpc/server.h>
25#include <rpc/server_util.h>
26#include <rpc/util.h>
27#include <util/strencodings.h>
28#include <util/translation.h>
29
30#include <univalue.h>
31
34
36 return RPCHelpMan{
37 "getavalanchekey",
38 "Returns the key used to sign avalanche messages.\n",
39 {},
41 RPCExamples{HelpExampleRpc("getavalanchekey", "")},
42 [&](const RPCHelpMan &self, const Config &config,
43 const JSONRPCRequest &request) -> UniValue {
44 NodeContext &node = EnsureAnyNodeContext(request.context);
46 return HexStr(avalanche.getSessionPubKey());
47 },
48 };
49}
50
51static CPubKey ParsePubKey(const UniValue &param) {
52 const std::string &keyHex = param.get_str();
53 if ((keyHex.length() != 2 * CPubKey::COMPRESSED_SIZE &&
54 keyHex.length() != 2 * CPubKey::SIZE) ||
55 !IsHex(keyHex)) {
57 strprintf("Invalid public key: %s\n", keyHex));
58 }
59
60 return HexToPubKey(keyHex);
61}
62
66 auto localProof = avalanche.getLocalProof();
67 if (localProof && localProof->getId() == proof->getId()) {
68 return true;
69 }
70
71 return avalanche.withPeerManager([&](avalanche::PeerManager &pm) {
72 return pm.getProof(proof->getId()) || pm.registerProof(proof, state);
73 });
74}
75
77 avalanche::ProofRef proof) {
79 return registerProofIfNeeded(avalanche, std::move(proof), state);
80}
81
83 const std::string &dgHex, CPubKey &auth) {
84 bilingual_str error;
85 if (!avalanche::Delegation::FromHex(dg, dgHex, error)) {
87 }
88
90 if (!dg.verify(state, auth)) {
92 "The delegation is invalid: " + state.ToString());
93 }
94}
95
97 const std::string &proofHex) {
98 bilingual_str error;
99 if (!avalanche::Proof::FromHex(proof, proofHex, error)) {
101 }
102
103 Amount stakeUtxoDustThreshold = avalanche::PROOF_DUST_THRESHOLD;
104 if (node.avalanche) {
105 // If Avalanche is enabled, use the configured dust threshold
106 node.avalanche->withPeerManager([&](avalanche::PeerManager &pm) {
107 stakeUtxoDustThreshold = pm.getStakeUtxoDustThreshold();
108 });
109 }
110
112 {
113 LOCK(cs_main);
114 if (!proof.verify(stakeUtxoDustThreshold, *Assert(node.chainman),
115 state)) {
117 "The proof is invalid: " + state.ToString());
118 }
119 }
120}
121
123 return RPCHelpMan{
124 "addavalanchenode",
125 "Add a node in the set of peers to poll for avalanche.\n",
126 {
128 "Node to be added to avalanche."},
130 "The public key of the node."},
132 "Proof that the node is not a sybil."},
134 "The proof delegation the the node public key"},
135 },
137 "Whether the addition succeeded or not."},
139 HelpExampleRpc("addavalanchenode", "5, \"<pubkey>\", \"<proof>\"")},
140 [&](const RPCHelpMan &self, const Config &config,
141 const JSONRPCRequest &request) -> UniValue {
142 const NodeId nodeid = request.params[0].getInt<int64_t>();
143 CPubKey key = ParsePubKey(request.params[1]);
144
145 auto proof = RCUPtr<avalanche::Proof>::make();
146 NodeContext &node = EnsureAnyNodeContext(request.context);
148
149 verifyProofOrThrow(node, *proof, request.params[2].get_str());
150
151 const avalanche::ProofId &proofid = proof->getId();
152 if (key != proof->getMaster()) {
153 if (request.params.size() < 4 || request.params[3].isNull()) {
154 throw JSONRPCError(
156 "The public key does not match the proof");
157 }
158
160 CPubKey auth;
161 verifyDelegationOrThrow(dg, request.params[3].get_str(), auth);
162
163 if (dg.getProofId() != proofid) {
164 throw JSONRPCError(
166 "The delegation does not match the proof");
167 }
168
169 if (key != auth) {
170 throw JSONRPCError(
172 "The public key does not match the delegation");
173 }
174 }
175
176 if (!registerProofIfNeeded(avalanche, proof)) {
178 "The proof has conflicting utxos");
179 }
180
181 if (!node.connman->ForNode(nodeid, [&](CNode *pnode) {
182 LOCK(pnode->cs_avalanche_pubkey);
183 bool expected = false;
184 if (pnode->m_avalanche_enabled.compare_exchange_strong(
185 expected, true)) {
186 pnode->m_avalanche_pubkey = std::move(key);
187 }
188 return true;
189 })) {
190 throw JSONRPCError(
192 strprintf("The node does not exist: %d", nodeid));
193 }
194
195 return avalanche.withPeerManager([&](avalanche::PeerManager &pm) {
196 if (!pm.addNode(nodeid, proofid)) {
197 return false;
198 }
199
200 pm.addUnbroadcastProof(proofid);
201 return true;
202 });
203 },
204 };
205}
206
208 return RPCHelpMan{
209 "buildavalancheproof",
210 "Build a proof for avalanche's sybil resistance.\n",
211 {
213 "The proof's sequence"},
215 "A timestamp indicating when the proof expire"},
217 "The master private key in base58-encoding"},
218 {
219 "stakes",
222 "The stakes to be signed and associated private keys",
223 {
224 {
225 "stake",
228 "A stake to be attached to this proof",
229 {
230 {"txid", RPCArg::Type::STR_HEX,
231 RPCArg::Optional::NO, "The transaction id"},
233 "The output number"},
234 {"amount", RPCArg::Type::AMOUNT,
235 RPCArg::Optional::NO, "The amount in this UTXO"},
237 "The height at which this UTXO was mined"},
238 {"iscoinbase", RPCArg::Type::BOOL,
239 RPCArg::Default{false},
240 "Indicate wether the UTXO is a coinbase"},
241 {"privatekey", RPCArg::Type::STR,
243 "private key in base58-encoding"},
244 },
245 },
246 },
247 },
248 {"payoutAddress", RPCArg::Type::STR, RPCArg::Optional::NO,
249 "A payout address"},
250 },
252 "A string that is a serialized, hex-encoded proof data."},
253 RPCExamples{HelpExampleRpc("buildavalancheproof",
254 "0 1234567800 \"<master>\" []")},
255 [&](const RPCHelpMan &self, const Config &config,
256 const JSONRPCRequest &request) -> UniValue {
257 const uint64_t sequence = request.params[0].getInt<int64_t>();
258 const int64_t expiration = request.params[1].getInt<int64_t>();
259
260 CKey masterKey = DecodeSecret(request.params[2].get_str());
261 if (!masterKey.IsValid()) {
262 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid master key");
263 }
264
265 CTxDestination payoutAddress = DecodeDestination(
266 request.params[4].get_str(), config.GetChainParams());
267
268 if (!IsValidDestination(payoutAddress)) {
270 "Invalid payout address");
271 }
272
273 avalanche::ProofBuilder pb(sequence, expiration, masterKey,
274 GetScriptForDestination(payoutAddress));
275
276 const UniValue &stakes = request.params[3].get_array();
277 for (size_t i = 0; i < stakes.size(); i++) {
278 const UniValue &stake = stakes[i];
280 stake,
281 {
282 {"txid", UniValue::VSTR},
283 {"vout", UniValue::VNUM},
284 // "amount" is also required but check is done below
285 // due to UniValue::VNUM erroneously not accepting
286 // quoted numerics (which are valid JSON)
287 {"height", UniValue::VNUM},
288 {"privatekey", UniValue::VSTR},
289 });
290
291 int nOut = stake.find_value("vout").getInt<int>();
292 if (nOut < 0) {
294 "vout cannot be negative");
295 }
296
297 const int height = stake.find_value("height").getInt<int>();
298 if (height < 1) {
300 "height must be positive");
301 }
302
303 const TxId txid(ParseHashO(stake, "txid"));
304 const COutPoint utxo(txid, nOut);
305
306 if (!stake.exists("amount")) {
307 throw JSONRPCError(RPC_INVALID_PARAMETER, "Missing amount");
308 }
309
310 const Amount amount =
311 AmountFromValue(stake.find_value("amount"));
312
313 const UniValue &iscbparam = stake.find_value("iscoinbase");
314 const bool iscoinbase =
315 iscbparam.isNull() ? false : iscbparam.get_bool();
316 CKey key =
317 DecodeSecret(stake.find_value("privatekey").get_str());
318
319 if (!key.IsValid()) {
321 "Invalid private key");
322 }
323
324 if (!pb.addUTXO(utxo, amount, uint32_t(height), iscoinbase,
325 std::move(key))) {
327 "Duplicated stake");
328 }
329 }
330
331 const avalanche::ProofRef proof = pb.build();
332
333 return proof->ToHex();
334 },
335 };
336}
337
339 return RPCHelpMan{
340 "decodeavalancheproof",
341 "Convert a serialized, hex-encoded proof, into JSON object. "
342 "The validity of the proof is not verified.\n",
343 {
345 "The proof hex string"},
346 },
347 RPCResult{
349 "",
350 "",
351 {
352 {RPCResult::Type::NUM, "sequence",
353 "The proof's sequential number"},
354 {RPCResult::Type::NUM, "expiration",
355 "A timestamp indicating when the proof expires"},
356 {RPCResult::Type::STR_HEX, "master", "The master public key"},
357 {RPCResult::Type::STR, "signature",
358 "The proof signature (base64 encoded)"},
360 "payoutscript",
361 "The proof payout script",
362 {
363 {RPCResult::Type::STR, "asm", "Decoded payout script"},
365 "Raw payout script in hex format"},
366 {RPCResult::Type::STR, "type",
367 "The output type (e.g. " + GetAllOutputTypes() + ")"},
368 {RPCResult::Type::NUM, "reqSigs",
369 "The required signatures"},
371 "addresses",
372 "",
373 {
374 {RPCResult::Type::STR, "address", "eCash address"},
375 }},
376 }},
377 {RPCResult::Type::STR_HEX, "limitedid",
378 "A hash of the proof data excluding the master key."},
379 {RPCResult::Type::STR_HEX, "proofid",
380 "A hash of the limitedid and master key."},
381 {RPCResult::Type::STR_AMOUNT, "staked_amount",
382 "The total staked amount of this proof in " +
383 Currency::get().ticker + "."},
384 {RPCResult::Type::NUM, "score", "The score of this proof."},
386 "stakes",
387 "",
388 {
390 "",
391 "",
392 {
394 "The transaction id"},
395 {RPCResult::Type::NUM, "vout", "The output number"},
397 "The amount in this UTXO"},
398 {RPCResult::Type::NUM, "height",
399 "The height at which this UTXO was mined"},
400 {RPCResult::Type::BOOL, "iscoinbase",
401 "Indicate whether the UTXO is a coinbase"},
402 {RPCResult::Type::STR_HEX, "pubkey",
403 "This UTXO's public key"},
404 {RPCResult::Type::STR, "signature",
405 "Signature of the proofid with this UTXO's private "
406 "key (base64 encoded)"},
407 }},
408 }},
409 }},
410 RPCExamples{HelpExampleCli("decodeavalancheproof", "\"<hex proof>\"") +
411 HelpExampleRpc("decodeavalancheproof", "\"<hex proof>\"")},
412 [&](const RPCHelpMan &self, const Config &config,
413 const JSONRPCRequest &request) -> UniValue {
414 avalanche::Proof proof;
415 bilingual_str error;
416 if (!avalanche::Proof::FromHex(proof, request.params[0].get_str(),
417 error)) {
419 }
420
421 UniValue result(UniValue::VOBJ);
422 result.pushKV("sequence", proof.getSequence());
423 result.pushKV("expiration", proof.getExpirationTime());
424 result.pushKV("master", HexStr(proof.getMaster()));
425 result.pushKV("signature", EncodeBase64(proof.getSignature()));
426
427 const auto payoutScript = proof.getPayoutScript();
428 UniValue payoutScriptObj(UniValue::VOBJ);
429 ScriptPubKeyToUniv(payoutScript, payoutScriptObj,
430 /* fIncludeHex */ true);
431 result.pushKV("payoutscript", payoutScriptObj);
432
433 result.pushKV("limitedid", proof.getLimitedId().ToString());
434 result.pushKV("proofid", proof.getId().ToString());
435
436 result.pushKV("staked_amount", proof.getStakedAmount());
437 result.pushKV("score", uint64_t(proof.getScore()));
438
439 UniValue stakes(UniValue::VARR);
440 for (const avalanche::SignedStake &s : proof.getStakes()) {
441 const COutPoint &utxo = s.getStake().getUTXO();
443 stake.pushKV("txid", utxo.GetTxId().ToString());
444 stake.pushKV("vout", uint64_t(utxo.GetN()));
445 stake.pushKV("amount", s.getStake().getAmount());
446 stake.pushKV("height", uint64_t(s.getStake().getHeight()));
447 stake.pushKV("iscoinbase", s.getStake().isCoinbase());
448 stake.pushKV("pubkey", HexStr(s.getStake().getPubkey()));
449 // Only PKHash destination is supported, so this is safe
450 stake.pushKV("address",
451 EncodeDestination(PKHash(s.getStake().getPubkey()),
452 config));
453 stake.pushKV("signature", EncodeBase64(s.getSignature()));
454 stakes.push_back(stake);
455 }
456 result.pushKV("stakes", stakes);
457
458 return result;
459 },
460 };
461}
462
464 return RPCHelpMan{
465 "delegateavalancheproof",
466 "Delegate the avalanche proof to another public key.\n",
467 {
469 "The limited id of the proof to be delegated."},
471 "The private key in base58-encoding. Must match the proof master "
472 "public key or the upper level parent delegation public key if "
473 " supplied."},
475 "The public key to delegate the proof to."},
477 "A string that is the serialized, hex-encoded delegation for the "
478 "proof and which is a parent for the delegation to build."},
479 },
481 "A string that is a serialized, hex-encoded delegation."},
483 HelpExampleRpc("delegateavalancheproof",
484 "\"<limitedproofid>\" \"<privkey>\" \"<pubkey>\"")},
485 [&](const RPCHelpMan &self, const Config &config,
486 const JSONRPCRequest &request) -> UniValue {
487 avalanche::LimitedProofId limitedProofId{
488 ParseHashV(request.params[0], "limitedproofid")};
489
490 const CKey privkey = DecodeSecret(request.params[1].get_str());
491 if (!privkey.IsValid()) {
493 "The private key is invalid");
494 }
495
496 const CPubKey pubkey = ParsePubKey(request.params[2]);
497
498 std::unique_ptr<avalanche::DelegationBuilder> dgb;
499 if (request.params.size() >= 4 && !request.params[3].isNull()) {
501 CPubKey auth;
502 verifyDelegationOrThrow(dg, request.params[3].get_str(), auth);
503
504 if (dg.getProofId() !=
505 limitedProofId.computeProofId(dg.getProofMaster())) {
506 throw JSONRPCError(
508 "The delegation does not match the proof");
509 }
510
511 if (privkey.GetPubKey() != auth) {
512 throw JSONRPCError(
514 "The private key does not match the delegation");
515 }
516
517 dgb = std::make_unique<avalanche::DelegationBuilder>(dg);
518 } else {
519 dgb = std::make_unique<avalanche::DelegationBuilder>(
520 limitedProofId, privkey.GetPubKey());
521 }
522
523 if (!dgb->addLevel(privkey, pubkey)) {
525 "Unable to build the delegation");
526 }
527
528 DataStream ss{};
529 ss << dgb->build();
530 return HexStr(ss);
531 },
532 };
533}
534
536 return RPCHelpMan{
537 "decodeavalanchedelegation",
538 "Convert a serialized, hex-encoded avalanche proof delegation, into "
539 "JSON object. \n"
540 "The validity of the delegation is not verified.\n",
541 {
543 "The delegation hex string"},
544 },
545 RPCResult{
547 "",
548 "",
549 {
550 {RPCResult::Type::STR_HEX, "pubkey",
551 "The public key the proof is delegated to."},
552 {RPCResult::Type::STR_HEX, "proofmaster",
553 "The delegated proof master public key."},
554 {RPCResult::Type::STR_HEX, "delegationid",
555 "The identifier of this delegation."},
556 {RPCResult::Type::STR_HEX, "limitedid",
557 "A delegated proof data hash excluding the master key."},
558 {RPCResult::Type::STR_HEX, "proofid",
559 "A hash of the delegated proof limitedid and master key."},
560 {RPCResult::Type::NUM, "depth",
561 "The number of delegation levels."},
563 "levels",
564 "",
565 {
567 "",
568 "",
569 {
570 {RPCResult::Type::NUM, "index",
571 "The index of this delegation level."},
572 {RPCResult::Type::STR_HEX, "pubkey",
573 "This delegated public key for this level"},
574 {RPCResult::Type::STR, "signature",
575 "Signature of this delegation level (base64 "
576 "encoded)"},
577 }},
578 }},
579 }},
580 RPCExamples{HelpExampleCli("decodeavalanchedelegation",
581 "\"<hex delegation>\"") +
582 HelpExampleRpc("decodeavalanchedelegation",
583 "\"<hex delegation>\"")},
584 [&](const RPCHelpMan &self, const Config &config,
585 const JSONRPCRequest &request) -> UniValue {
586 avalanche::Delegation delegation;
587 bilingual_str error;
589 delegation, request.params[0].get_str(), error)) {
591 }
592
593 UniValue result(UniValue::VOBJ);
594 result.pushKV("pubkey", HexStr(delegation.getDelegatedPubkey()));
595 result.pushKV("proofmaster", HexStr(delegation.getProofMaster()));
596 result.pushKV("delegationid", delegation.getId().ToString());
597 result.pushKV("limitedid",
598 delegation.getLimitedProofId().ToString());
599 result.pushKV("proofid", delegation.getProofId().ToString());
600
601 auto levels = delegation.getLevels();
602 result.pushKV("depth", uint64_t(levels.size()));
603
604 UniValue levelsArray(UniValue::VARR);
605 for (auto &level : levels) {
607 obj.pushKV("pubkey", HexStr(level.pubkey));
608 obj.pushKV("signature", EncodeBase64(level.sig));
609 levelsArray.push_back(std::move(obj));
610 }
611 result.pushKV("levels", levelsArray);
612
613 return result;
614 },
615 };
616}
617
619 return RPCHelpMan{
620 "getavalancheinfo",
621 "Returns an object containing various state info regarding avalanche "
622 "networking.\n",
623 {},
624 RPCResult{
626 "",
627 "",
628 {
629 {RPCResult::Type::BOOL, "ready_to_poll",
630 "Whether the node is ready to start polling and voting."},
632 "local",
633 "Only available if -avaproof has been supplied to the node",
634 {
635 {RPCResult::Type::BOOL, "verified",
636 "Whether the node local proof has been locally verified "
637 "or not."},
638 {RPCResult::Type::STR, "verification_status",
639 "The proof verification status. Only available if the "
640 "\"verified\" flag is false."},
641 {RPCResult::Type::STR_HEX, "proofid",
642 "The node local proof id."},
643 {RPCResult::Type::STR_HEX, "limited_proofid",
644 "The node local limited proof id."},
645 {RPCResult::Type::STR_HEX, "master",
646 "The node local proof master public key."},
647 {RPCResult::Type::STR, "payout_address",
648 "The node local proof payout address. This might be "
649 "omitted if the payout script is not one of P2PK, P2PKH "
650 "or P2SH, in which case decodeavalancheproof can be used "
651 "to get more details."},
652 {RPCResult::Type::STR_AMOUNT, "stake_amount",
653 "The node local proof staked amount."},
654 }},
656 "network",
657 "",
658 {
659 {RPCResult::Type::NUM, "proof_count",
660 "The number of valid avalanche proofs we know exist "
661 "(including this node's local proof if applicable)."},
662 {RPCResult::Type::NUM, "connected_proof_count",
663 "The number of avalanche proofs with at least one node "
664 "we are connected to (including this node's local proof "
665 "if applicable)."},
666 {RPCResult::Type::NUM, "dangling_proof_count",
667 "The number of avalanche proofs with no node attached."},
668 {RPCResult::Type::NUM, "finalized_proof_count",
669 "The number of known avalanche proofs that have been "
670 "finalized by avalanche."},
671 {RPCResult::Type::NUM, "conflicting_proof_count",
672 "The number of known avalanche proofs that conflict with "
673 "valid proofs."},
674 {RPCResult::Type::NUM, "immature_proof_count",
675 "The number of known avalanche proofs that have immature "
676 "utxos."},
677 {RPCResult::Type::STR_AMOUNT, "total_stake_amount",
678 "The total staked amount over all the valid proofs in " +
680 " (including this node's local proof if "
681 "applicable)."},
682 {RPCResult::Type::STR_AMOUNT, "connected_stake_amount",
683 "The total staked amount over all the connected proofs "
684 "in " +
686 " (including this node's local proof if "
687 "applicable)."},
688 {RPCResult::Type::STR_AMOUNT, "dangling_stake_amount",
689 "The total staked amount over all the dangling proofs "
690 "in " +
692 " (including this node's local proof if "
693 "applicable)."},
694 {RPCResult::Type::STR_AMOUNT, "immature_stake_amount",
695 "The total staked amount over all the immature proofs "
696 "in " +
698 " (including this node's local proof if "
699 "applicable)."},
700 {RPCResult::Type::NUM, "node_count",
701 "The number of avalanche nodes we are connected to "
702 "(including this node if a local proof is set)."},
703 {RPCResult::Type::NUM, "connected_node_count",
704 "The number of avalanche nodes associated with an "
705 "avalanche proof (including this node if a local proof "
706 "is set)."},
707 {RPCResult::Type::NUM, "pending_node_count",
708 "The number of avalanche nodes pending for a proof."},
709 }},
710 },
711 },
712 RPCExamples{HelpExampleCli("getavalancheinfo", "") +
713 HelpExampleRpc("getavalancheinfo", "")},
714 [&](const RPCHelpMan &self, const Config &config,
715 const JSONRPCRequest &request) -> UniValue {
716 NodeContext &node = EnsureAnyNodeContext(request.context);
718
720 ret.pushKV("ready_to_poll", avalanche.isQuorumEstablished());
721
722 auto localProof = avalanche.getLocalProof();
723 if (localProof != nullptr) {
725 const bool verified = avalanche.withPeerManager(
726 [&](const avalanche::PeerManager &pm) {
727 const avalanche::ProofId &proofid = localProof->getId();
728 return pm.isBoundToPeer(proofid);
729 });
730 local.pushKV("verified", verified);
731 const bool sharing = avalanche.canShareLocalProof();
732 if (!verified) {
734 avalanche.getLocalProofRegistrationState();
735 // If the local proof is not registered but the state is
736 // valid, no registration attempt occurred yet.
737 local.pushKV("verification_status",
738 state.IsValid()
739 ? (sharing ? "pending verification"
740 : "pending inbound connections")
741 : state.GetRejectReason());
742 }
743 local.pushKV("proofid", localProof->getId().ToString());
744 local.pushKV("limited_proofid",
745 localProof->getLimitedId().ToString());
746 local.pushKV("master", HexStr(localProof->getMaster()));
747 CTxDestination destination;
748 if (ExtractDestination(localProof->getPayoutScript(),
749 destination)) {
750 local.pushKV("payout_address",
751 EncodeDestination(destination, config));
752 }
753 local.pushKV("stake_amount", localProof->getStakedAmount());
754 ret.pushKV("local", local);
755 }
756
757 avalanche.withPeerManager([&](avalanche::PeerManager &pm) {
758 UniValue network(UniValue::VOBJ);
759
760 uint64_t proofCount{0};
761 uint64_t connectedProofCount{0};
762 uint64_t finalizedProofCount{0};
763 uint64_t connectedNodeCount{0};
764 Amount totalStakes = Amount::zero();
765 Amount connectedStakes = Amount::zero();
766
767 pm.forEachPeer([&](const avalanche::Peer &peer) {
768 CHECK_NONFATAL(peer.proof != nullptr);
769
770 const bool isLocalProof =
771 localProof &&
772 peer.proof->getId() == localProof->getId();
773
774 ++proofCount;
775 const Amount proofStake = peer.proof->getStakedAmount();
776
777 totalStakes += proofStake;
778
779 if (peer.hasFinalized) {
780 ++finalizedProofCount;
781 }
782
783 if (peer.node_count > 0 || isLocalProof) {
784 ++connectedProofCount;
785 connectedStakes += proofStake;
786 }
787
788 connectedNodeCount += peer.node_count + isLocalProof;
789 });
790
791 Amount immatureStakes = Amount::zero();
793 [&](const avalanche::ProofRef &proof) {
794 immatureStakes += proof->getStakedAmount();
795 });
796
797 network.pushKV("proof_count", proofCount);
798 network.pushKV("connected_proof_count", connectedProofCount);
799 network.pushKV("dangling_proof_count",
800 proofCount - connectedProofCount);
801
802 network.pushKV("finalized_proof_count", finalizedProofCount);
803 network.pushKV(
804 "conflicting_proof_count",
805 uint64_t(pm.getConflictingProofPool().countProofs()));
806 network.pushKV(
807 "immature_proof_count",
808 uint64_t(pm.getImmatureProofPool().countProofs()));
809
810 network.pushKV("total_stake_amount", totalStakes);
811 network.pushKV("connected_stake_amount", connectedStakes);
812 network.pushKV("dangling_stake_amount",
813 totalStakes - connectedStakes);
814 network.pushKV("immature_stake_amount", immatureStakes);
815
816 const uint64_t pendingNodes = pm.getPendingNodeCount();
817 network.pushKV("node_count", connectedNodeCount + pendingNodes);
818 network.pushKV("connected_node_count", connectedNodeCount);
819 network.pushKV("pending_node_count", pendingNodes);
820
821 ret.pushKV("network", network);
822 });
823
824 return ret;
825 },
826 };
827}
828
830 return RPCHelpMan{
831 "getavalanchepeerinfo",
832 "Returns data about an avalanche peer as a json array of objects. If "
833 "no proofid is provided, returns data about all the peers.\n",
834 {
836 "The hex encoded avalanche proof identifier."},
837 },
838 RPCResult{
840 "",
841 "",
842 {{
844 "",
845 "",
846 {{
847 {RPCResult::Type::NUM, "avalanche_peerid",
848 "The avalanche internal peer identifier"},
849 {RPCResult::Type::NUM, "availability_score",
850 "DEPRECATED: The agreggated availability score of this "
851 "peer's nodes. This score is no longer computed starting "
852 "with version 0.30.12 and is always 0. This field is only "
853 "returned if the -deprecatedrpc=peer_availability_score "
854 "option is enabled."},
855 {RPCResult::Type::STR_HEX, "proofid",
856 "The avalanche proof id used by this peer"},
857 {RPCResult::Type::STR_HEX, "proof",
858 "The avalanche proof used by this peer"},
859 {RPCResult::Type::NUM, "nodecount",
860 "The number of nodes for this peer"},
862 "node_list",
863 "",
864 {
865 {RPCResult::Type::NUM, "nodeid",
866 "Node id, as returned by getpeerinfo"},
867 }},
868 }},
869 }},
870 },
871 RPCExamples{HelpExampleCli("getavalanchepeerinfo", "") +
872 HelpExampleCli("getavalanchepeerinfo", "\"proofid\"") +
873 HelpExampleRpc("getavalanchepeerinfo", "") +
874 HelpExampleRpc("getavalanchepeerinfo", "\"proofid\"")},
875 [&](const RPCHelpMan &self, const Config &config,
876 const JSONRPCRequest &request) -> UniValue {
877 NodeContext &node = EnsureAnyNodeContext(request.context);
879 const ArgsManager &argsman = EnsureArgsman(node);
880
881 auto peerToUniv = [&argsman](const avalanche::PeerManager &pm,
882 const avalanche::Peer &peer) {
884
885 obj.pushKV("avalanche_peerid", uint64_t(peer.peerid));
886 if (IsDeprecatedRPCEnabled(argsman,
887 "peer_availability_score")) {
888 obj.pushKV("availability_score", 0);
889 }
890 obj.pushKV("proofid", peer.getProofId().ToString());
891 obj.pushKV("proof", peer.proof->ToHex());
892
894 pm.forEachNode(peer, [&](const avalanche::Node &n) {
895 nodes.push_back(n.nodeid);
896 });
897
898 obj.pushKV("nodecount", uint64_t(peer.node_count));
899 obj.pushKV("node_list", nodes);
900
901 return obj;
902 };
903
905
906 avalanche.withPeerManager([&](const avalanche::PeerManager &pm) {
907 // If a proofid is provided, only return the associated peer
908 if (!request.params[0].isNull()) {
909 const avalanche::ProofId proofid =
910 avalanche::ProofId::fromHex(
911 request.params[0].get_str());
912 if (!pm.isBoundToPeer(proofid)) {
913 throw JSONRPCError(RPC_INVALID_PARAMETER,
914 "Proofid not found");
915 }
916
917 pm.forPeer(proofid, [&](const avalanche::Peer &peer) {
918 ret.push_back(peerToUniv(pm, peer));
919 return true;
920 });
921
922 return;
923 }
924
925 // If no proofid is provided, return all the peers
926 pm.forEachPeer([&](const avalanche::Peer &peer) {
927 ret.push_back(peerToUniv(pm, peer));
928 });
929 });
930
931 return ret;
932 },
933 };
934}
935
937 return RPCHelpMan{
938 "getavalancheproofs",
939 "Returns an object containing all tracked proofids.\n",
940 {},
941 RPCResult{
943 "",
944 "",
945 {
947 "valid",
948 "",
949 {
950 {RPCResult::Type::STR_HEX, "proofid",
951 "Avalanche proof id"},
952 }},
954 "conflicting",
955 "",
956 {
957 {RPCResult::Type::STR_HEX, "proofid",
958 "Avalanche proof id"},
959 }},
961 "immature",
962 "",
963 {
964 {RPCResult::Type::STR_HEX, "proofid",
965 "Avalanche proof id"},
966 }},
967 },
968 },
969 RPCExamples{HelpExampleCli("getavalancheproofs", "") +
970 HelpExampleRpc("getavalancheproofs", "")},
971 [&](const RPCHelpMan &self, const Config &config,
972 const JSONRPCRequest &request) -> UniValue {
973 NodeContext &node = EnsureAnyNodeContext(request.context);
975
977 avalanche.withPeerManager([&](avalanche::PeerManager &pm) {
978 auto appendProofIds = [&ret](const avalanche::ProofPool &pool,
979 const std::string &key) {
980 UniValue arrOut(UniValue::VARR);
981 for (const avalanche::ProofId &proofid :
982 pool.getProofIds()) {
983 arrOut.push_back(proofid.ToString());
984 }
985 ret.pushKV(key, arrOut);
986 };
987
988 appendProofIds(pm.getValidProofPool(), "valid");
989 appendProofIds(pm.getConflictingProofPool(), "conflicting");
990 appendProofIds(pm.getImmatureProofPool(), "immature");
991 });
992
993 return ret;
994 },
995 };
996}
997
999 return RPCHelpMan{
1000 "getstakingreward",
1001 "Return a list of possible staking reward winners based on the "
1002 "previous "
1003 "block hash.\n",
1004 {
1006 "The previous block hash, hex encoded."},
1007 {"recompute", RPCArg::Type::BOOL, RPCArg::Default{false},
1008 "Whether to recompute the staking reward winner if there is a "
1009 "cached value."},
1010 },
1011 RPCResult{
1013 "",
1014 "",
1015 {
1017 "winner",
1018 "The winning proof",
1019 {
1020 {RPCResult::Type::STR_HEX, "proofid",
1021 "The winning proofid"},
1022 {RPCResult::Type::STR, "asm", "Decoded payout script"},
1024 "Raw payout script in hex format"},
1025 {RPCResult::Type::STR, "type",
1026 "The output type (e.g. " + GetAllOutputTypes() + ")"},
1027 {RPCResult::Type::NUM, "reqSigs",
1028 "The required signatures"},
1030 "addresses",
1031 "",
1032 {
1033 {RPCResult::Type::STR, "address", "eCash address"},
1034 }},
1035 }},
1036 }},
1037 RPCExamples{HelpExampleRpc("getstakingreward", "<blockhash>")},
1038 [&](const RPCHelpMan &self, const Config &config,
1039 const JSONRPCRequest &request) -> UniValue {
1040 const NodeContext &node = EnsureAnyNodeContext(request.context);
1043
1044 const BlockHash blockhash(
1045 ParseHashV(request.params[0], "blockhash"));
1046
1047 const CBlockIndex *pprev;
1048 {
1049 LOCK(cs_main);
1050 pprev = chainman.m_blockman.LookupBlockIndex(blockhash);
1051 }
1052
1053 if (!pprev) {
1054 throw JSONRPCError(
1056 strprintf("Block not found: %s\n", blockhash.ToString()));
1057 }
1058
1060 config.GetChainParams().GetConsensus(), pprev)) {
1061 throw JSONRPCError(
1063 strprintf(
1064 "Staking rewards are not activated for block %s\n",
1065 blockhash.ToString()));
1066 }
1067
1068 if (!request.params[1].isNull() && request.params[1].get_bool()) {
1069 // Force recompute the staking reward winner by first erasing
1070 // the cached entry if any
1071 avalanche.eraseStakingRewardWinner(blockhash);
1072 }
1073
1074 if (!avalanche.computeStakingReward(pprev)) {
1075 throw JSONRPCError(
1077 strprintf("Unable to determine a staking reward winner "
1078 "for block %s\n",
1079 blockhash.ToString()));
1080 }
1081
1082 std::vector<std::pair<avalanche::ProofId, CScript>> winners;
1083 if (!avalanche.getStakingRewardWinners(blockhash, winners)) {
1084 throw JSONRPCError(
1086 strprintf("Unable to retrieve the staking reward winner "
1087 "for block %s\n",
1088 blockhash.ToString()));
1089 }
1090
1091 UniValue winnersArr(UniValue::VARR);
1092 for (auto &winner : winners) {
1093 UniValue stakingRewardsObj(UniValue::VOBJ);
1094 ScriptPubKeyToUniv(winner.second, stakingRewardsObj,
1095 /*fIncludeHex=*/true);
1096 stakingRewardsObj.pushKV("proofid", winner.first.GetHex());
1097 winnersArr.push_back(stakingRewardsObj);
1098 }
1099
1100 return winnersArr;
1101 },
1102 };
1103}
1104
1106 return RPCHelpMan{
1107 "hasstakingreward",
1108 "Return true if a staking reward winner exists based on the previous "
1109 "block hash.\n",
1110 {
1112 "The previous block hash, hex encoded."},
1113 },
1115 "Whether staking reward winner has been computed for "
1116 "previous block hash or not."},
1117 RPCExamples{HelpExampleRpc("hasstakingreward", "<blockhash>")},
1118 [&](const RPCHelpMan &self, const Config &config,
1119 const JSONRPCRequest &request) -> UniValue {
1120 const NodeContext &node = EnsureAnyNodeContext(request.context);
1123
1124 const BlockHash blockhash(
1125 ParseHashV(request.params[0], "blockhash"));
1126
1127 const CBlockIndex *pprev;
1128 {
1129 LOCK(cs_main);
1130 pprev = chainman.m_blockman.LookupBlockIndex(blockhash);
1131 }
1132
1133 if (!pprev) {
1134 throw JSONRPCError(
1136 strprintf("Block not found: %s\n", blockhash.ToString()));
1137 }
1138
1140 config.GetChainParams().GetConsensus(), pprev)) {
1141 throw JSONRPCError(
1143 strprintf(
1144 "Staking rewards are not activated for block %s\n",
1145 blockhash.ToString()));
1146 }
1147
1148 std::vector<std::pair<avalanche::ProofId, CScript>> winners;
1149 if (!avalanche.getStakingRewardWinners(blockhash, winners)) {
1150 return false;
1151 }
1152 return winners.size() > 0;
1153 },
1154 };
1155}
1156
1158 return RPCHelpMan{
1159 "setstakingreward",
1160 "Set the staking reward winner for the given previous block hash.\n",
1161 {
1163 "The previous block hash, hex encoded."},
1165 "The payout script for the staking reward, hex encoded."},
1166 {"append", RPCArg::Type::BOOL, RPCArg::Default{false},
1167 "Append to the list of possible winners instead of replacing."},
1168 },
1170 "Whether the payout script was set or not"},
1172 HelpExampleRpc("setstakingreward", "<blockhash> <payout script>")},
1173 [&](const RPCHelpMan &self, const Config &config,
1174 const JSONRPCRequest &request) -> UniValue {
1175 const NodeContext &node = EnsureAnyNodeContext(request.context);
1178
1179 const BlockHash blockhash(
1180 ParseHashV(request.params[0], "blockhash"));
1181
1182 const CBlockIndex *pprev;
1183 {
1184 LOCK(cs_main);
1185 pprev = chainman.m_blockman.LookupBlockIndex(blockhash);
1186 }
1187
1188 if (!pprev) {
1189 throw JSONRPCError(
1191 strprintf("Block not found: %s\n", blockhash.ToString()));
1192 }
1193
1195 config.GetChainParams().GetConsensus(), pprev)) {
1196 throw JSONRPCError(
1198 strprintf(
1199 "Staking rewards are not activated for block %s\n",
1200 blockhash.ToString()));
1201 }
1202
1203 const std::vector<uint8_t> data =
1204 ParseHex(request.params[1].get_str());
1205 CScript payoutScript(data.begin(), data.end());
1206
1207 std::vector<CScript> payoutScripts;
1208
1209 if (!request.params[2].isNull() && request.params[2].get_bool()) {
1210 // Append mode, initialize our list with the current winners
1211 // and the new one will be added to the back of that list. If
1212 // there is no winner the list will remain empty.
1213 avalanche.getStakingRewardWinners(blockhash, payoutScripts);
1214 }
1215
1216 if (std::find(payoutScripts.begin(), payoutScripts.end(),
1217 payoutScript) != payoutScripts.end()) {
1218 throw JSONRPCError(
1220 strprintf(
1221 "Staking rewards winner is already set for block %s\n",
1222 blockhash.ToString()));
1223 }
1224
1225 payoutScripts.push_back(std::move(payoutScript));
1226
1227 // This will return true upon insertion or false upon replacement.
1228 // We want to convey the success of the RPC, so we always return
1229 // true.
1230 avalanche.setStakingRewardWinners(pprev, payoutScripts);
1231 return true;
1232 },
1233 };
1234}
1235
1237 return RPCHelpMan{
1238 "getremoteproofs",
1239 "Get the list of remote proofs for the given node id.\n",
1240 {
1242 "The node identifier."},
1243 },
1244 RPCResult{
1246 "proofs",
1247 "",
1248 {{
1250 "proof",
1251 "",
1252 {{
1253 {RPCResult::Type::STR_HEX, "proofid",
1254 "The hex encoded proof identifier."},
1255 {RPCResult::Type::BOOL, "present",
1256 "Whether the node has the proof."},
1257 {RPCResult::Type::NUM, "last_update",
1258 "The last time this proof status was updated."},
1259 }},
1260 }},
1261 },
1262 RPCExamples{HelpExampleRpc("getremoteproofs", "<nodeid>")},
1263 [&](const RPCHelpMan &self, const Config &config,
1264 const JSONRPCRequest &request) -> UniValue {
1265 NodeContext &node = EnsureAnyNodeContext(request.context);
1267
1268 const NodeId nodeid = request.params[0].getInt<int64_t>();
1269 auto remoteProofs = avalanche.withPeerManager(
1270 [nodeid](const avalanche::PeerManager &pm) {
1271 return pm.getRemoteProofs(nodeid);
1272 });
1273
1274 UniValue arrOut(UniValue::VARR);
1275
1276 for (const auto &remoteProof : remoteProofs) {
1278 obj.pushKV("proofid", remoteProof.proofid.ToString());
1279 obj.pushKV("present", remoteProof.present);
1280 obj.pushKV("last_update", remoteProof.lastUpdate.count());
1281
1282 arrOut.push_back(obj);
1283 }
1284
1285 return arrOut;
1286 },
1287 };
1288}
1289
1291 return RPCHelpMan{
1292 "getrawavalancheproof",
1293 "Lookup for a known avalanche proof by id.\n",
1294 {
1296 "The hex encoded avalanche proof identifier."},
1297 },
1298 RPCResult{
1300 "",
1301 "",
1302 {{
1303 {RPCResult::Type::STR_HEX, "proof",
1304 "The hex encoded proof matching the identifier."},
1305 {RPCResult::Type::BOOL, "immature",
1306 "Whether the proof has immature utxos."},
1307 {RPCResult::Type::BOOL, "boundToPeer",
1308 "Whether the proof is bound to an avalanche peer."},
1309 {RPCResult::Type::BOOL, "conflicting",
1310 "Whether the proof has a conflicting UTXO with an avalanche "
1311 "peer."},
1312 {RPCResult::Type::BOOL, "finalized",
1313 "Whether the proof is finalized by vote."},
1314 }},
1315 },
1316 RPCExamples{HelpExampleRpc("getrawavalancheproof", "<proofid>")},
1317 [&](const RPCHelpMan &self, const Config &config,
1318 const JSONRPCRequest &request) -> UniValue {
1319 NodeContext &node = EnsureAnyNodeContext(request.context);
1321
1322 const avalanche::ProofId proofid =
1323 avalanche::ProofId::fromHex(request.params[0].get_str());
1324
1325 bool isImmature = false;
1326 bool isBoundToPeer = false;
1327 bool conflicting = false;
1328 bool finalized = false;
1329 auto proof = avalanche.withPeerManager(
1330 [&](const avalanche::PeerManager &pm) {
1331 isImmature = pm.isImmature(proofid);
1332 isBoundToPeer = pm.isBoundToPeer(proofid);
1333 conflicting = pm.isInConflictingPool(proofid);
1334 finalized =
1335 pm.forPeer(proofid, [&](const avalanche::Peer &p) {
1336 return p.hasFinalized;
1337 });
1338 return pm.getProof(proofid);
1339 });
1340
1341 if (!proof) {
1342 throw JSONRPCError(RPC_INVALID_PARAMETER, "Proof not found");
1343 }
1344
1346
1347 DataStream ss{};
1348 ss << *proof;
1349 ret.pushKV("proof", HexStr(ss));
1350 ret.pushKV("immature", isImmature);
1351 ret.pushKV("boundToPeer", isBoundToPeer);
1352 ret.pushKV("conflicting", conflicting);
1353 ret.pushKV("finalized", finalized);
1354
1355 return ret;
1356 },
1357 };
1358}
1359
1361 return RPCHelpMan{
1362 "invalidateavalancheproof",
1363 "Reject a known avalanche proof by id.\n",
1364 {
1366 "The hex encoded avalanche proof identifier."},
1367 },
1368 RPCResult{
1370 "success",
1371 "",
1372 },
1373 RPCExamples{HelpExampleRpc("invalidateavalancheproof", "<proofid>")},
1374 [&](const RPCHelpMan &self, const Config &config,
1375 const JSONRPCRequest &request) -> UniValue {
1376 NodeContext &node = EnsureAnyNodeContext(request.context);
1378
1379 const avalanche::ProofId proofid =
1380 avalanche::ProofId::fromHex(request.params[0].get_str());
1381
1382 avalanche.withPeerManager([&](avalanche::PeerManager &pm) {
1383 if (!pm.exists(proofid) && !pm.isDangling(proofid)) {
1384 throw JSONRPCError(RPC_INVALID_PARAMETER,
1385 "Proof not found");
1386 }
1387
1388 if (!pm.rejectProof(
1389 proofid,
1391 throw JSONRPCError(RPC_INTERNAL_ERROR,
1392 "Failed to reject the proof");
1393 }
1394
1395 pm.setInvalid(proofid);
1396 });
1397
1398 if (avalanche.isRecentlyFinalized(proofid)) {
1399 // If the proof was previously finalized, clear the status.
1400 // Because there is no way to selectively delete an entry from a
1401 // Bloom filter, we have to clear the whole filter which could
1402 // cause extra voting rounds.
1403 avalanche.clearFinalizedItems();
1404 }
1405
1406 return true;
1407 },
1408 };
1409}
1410
1412 return RPCHelpMan{
1413 "isfinalblock",
1414 "Check if a block has been finalized by avalanche votes.\n",
1415 {
1417 "The hash of the block."},
1418 },
1420 "Whether the block has been finalized by avalanche votes."},
1421 RPCExamples{HelpExampleRpc("isfinalblock", "<block hash>") +
1422 HelpExampleCli("isfinalblock", "<block hash>")},
1423 [&](const RPCHelpMan &self, const Config &config,
1424 const JSONRPCRequest &request) -> UniValue {
1425 NodeContext &node = EnsureAnyNodeContext(request.context);
1427
1428 if (!avalanche.isQuorumEstablished()) {
1430 "Avalanche is not ready to poll yet.");
1431 }
1432
1433 ChainstateManager &chainman = EnsureAnyChainman(request.context);
1434 const BlockHash blockhash(
1435 ParseHashV(request.params[0], "blockhash"));
1436 const CBlockIndex *pindex;
1437
1438 {
1439 LOCK(cs_main);
1440 pindex = chainman.m_blockman.LookupBlockIndex(blockhash);
1441
1442 if (!pindex) {
1444 "Block not found");
1445 }
1446 }
1447
1448 return chainman.ActiveChainstate().IsBlockAvalancheFinalized(
1449 pindex);
1450 },
1451 };
1452}
1453
1455 return RPCHelpMan{
1456 "isfinaltransaction",
1457 "Check if a transaction has been finalized by avalanche votes.\n",
1458 {
1460 "The id of the transaction."},
1462 "The block in which to look for the transaction"},
1463 },
1464 RPCResult{
1465 RPCResult::Type::BOOL, "success",
1466 "Whether the transaction has been finalized by avalanche votes."},
1467 RPCExamples{HelpExampleRpc("isfinaltransaction", "<txid> <blockhash>") +
1468 HelpExampleCli("isfinaltransaction", "<txid> <blockhash>")},
1469 [&](const RPCHelpMan &self, const Config &config,
1470 const JSONRPCRequest &request) -> UniValue {
1471 const NodeContext &node = EnsureAnyNodeContext(request.context);
1473 const CTxMemPool &mempool = EnsureMemPool(node);
1475
1476 const TxId txid = TxId(ParseHashV(request.params[0], "txid"));
1477 CBlockIndex *pindex = nullptr;
1478
1479 if (!request.params[1].isNull()) {
1480 const BlockHash blockhash(
1481 ParseHashV(request.params[1], "blockhash"));
1482
1483 LOCK(cs_main);
1484 pindex = chainman.m_blockman.LookupBlockIndex(blockhash);
1485 if (!pindex) {
1487 "Block not found");
1488 }
1489 }
1490
1491 bool f_txindex_ready = false;
1492 if (g_txindex && !pindex) {
1493 f_txindex_ready = g_txindex->BlockUntilSyncedToCurrentChain();
1494 }
1495
1496 BlockHash hash_block;
1498 pindex, &mempool, txid, hash_block, chainman.m_blockman);
1499
1500 if (!avalanche.isQuorumEstablished()) {
1502 "Avalanche is not ready to poll yet.");
1503 }
1504
1505 if (!tx) {
1506 std::string errmsg;
1507 if (pindex) {
1508 if (WITH_LOCK(::cs_main,
1509 return !pindex->nStatus.hasData())) {
1511 "Block data not downloaded yet.");
1512 }
1513 errmsg = "No such transaction found in the provided block.";
1514 } else if (!g_txindex) {
1515 errmsg = "No such transaction. Use -txindex or provide a "
1516 "block hash to enable blockchain transaction "
1517 "queries.";
1518 } else if (!f_txindex_ready) {
1519 errmsg = "No such transaction. Blockchain transactions are "
1520 "still in the process of being indexed.";
1521 } else {
1522 errmsg = "No such mempool or blockchain transaction.";
1523 }
1525 }
1526
1527 if (!pindex) {
1528 LOCK(cs_main);
1529 pindex = chainman.m_blockman.LookupBlockIndex(hash_block);
1530 }
1531
1532 if (!tx) {
1533 // Tx not found, we should have raised an error at this stage
1534 return false;
1535 }
1536
1537 if (WITH_LOCK(
1538 mempool.cs,
1539 return mempool.isAvalancheFinalizedPreConsensus(txid))) {
1540 // The transaction is finalized
1541 return true;
1542 }
1543
1544 // Return true if the tx is in a finalized block
1545 return !node.mempool->exists(txid) &&
1546 chainman.ActiveChainstate().IsBlockAvalancheFinalized(
1547 pindex);
1548 },
1549 };
1550}
1551
1553 return RPCHelpMan{
1554 "reconsideravalancheproof",
1555 "Reconsider a known avalanche proof.\n",
1556 {
1558 "The hex encoded avalanche proof."},
1559 },
1560 RPCResult{
1562 "success",
1563 "Whether the proof has been successfully registered.",
1564 },
1565 RPCExamples{HelpExampleRpc("reconsideravalancheproof", "<proof hex>")},
1566 [&](const RPCHelpMan &self, const Config &config,
1567 const JSONRPCRequest &request) -> UniValue {
1568 auto proof = RCUPtr<avalanche::Proof>::make();
1569
1570 NodeContext &node = EnsureAnyNodeContext(request.context);
1572
1573 // Verify the proof. Note that this is redundant with the
1574 // verification done when adding the proof to the pool, but we get a
1575 // chance to give a better error message.
1576 verifyProofOrThrow(node, *proof, request.params[0].get_str());
1577
1578 // There is no way to selectively clear the invalidation status of
1579 // a single proof, so we clear the whole Bloom filter. This could
1580 // cause extra voting rounds.
1581 avalanche.withPeerManager([&](avalanche::PeerManager &pm) {
1582 if (pm.isInvalid(proof->getId())) {
1583 pm.clearAllInvalid();
1584 }
1585 });
1586
1587 // Add the proof to the pool if we don't have it already. Since the
1588 // proof verification has already been done, a failure likely
1589 // indicates that there already is a proof with conflicting utxos.
1591 if (!registerProofIfNeeded(avalanche, proof, state)) {
1593 strprintf("%s (%s)\n",
1594 state.GetRejectReason(),
1595 state.GetDebugMessage()));
1596 }
1597
1598 return avalanche.withPeerManager(
1599 [&](const avalanche::PeerManager &pm) {
1600 return pm.isBoundToPeer(proof->getId());
1601 });
1602 },
1603 };
1604}
1605
1607 return RPCHelpMan{
1608 "sendavalancheproof",
1609 "Broadcast an avalanche proof.\n",
1610 {
1612 "The avalanche proof to broadcast."},
1613 },
1615 "Whether the proof was sent successfully or not."},
1616 RPCExamples{HelpExampleRpc("sendavalancheproof", "<proof>")},
1617 [&](const RPCHelpMan &self, const Config &config,
1618 const JSONRPCRequest &request) -> UniValue {
1619 auto proof = RCUPtr<avalanche::Proof>::make();
1620
1621 NodeContext &node = EnsureAnyNodeContext(request.context);
1623
1624 // Verify the proof. Note that this is redundant with the
1625 // verification done when adding the proof to the pool, but we get a
1626 // chance to give a better error message.
1627 verifyProofOrThrow(node, *proof, request.params[0].get_str());
1628
1629 // Add the proof to the pool if we don't have it already. Since the
1630 // proof verification has already been done, a failure likely
1631 // indicates that there already is a proof with conflicting utxos.
1632 const avalanche::ProofId &proofid = proof->getId();
1634 if (!registerProofIfNeeded(avalanche, proof, state)) {
1636 strprintf("%s (%s)\n",
1637 state.GetRejectReason(),
1638 state.GetDebugMessage()));
1639 }
1640
1641 avalanche.withPeerManager([&](avalanche::PeerManager &pm) {
1642 pm.addUnbroadcastProof(proofid);
1643 });
1644
1645 if (node.peerman) {
1646 node.peerman->RelayProof(proofid);
1647 }
1648
1649 return true;
1650 },
1651 };
1652}
1653
1655 return RPCHelpMan{
1656 "verifyavalancheproof",
1657 "Verify an avalanche proof is valid and return the error otherwise.\n",
1658 {
1660 "Proof to verify."},
1661 },
1663 "Whether the proof is valid or not."},
1664 RPCExamples{HelpExampleRpc("verifyavalancheproof", "\"<proof>\"")},
1665 [&](const RPCHelpMan &self, const Config &config,
1666 const JSONRPCRequest &request) -> UniValue {
1667 avalanche::Proof proof;
1668 verifyProofOrThrow(EnsureAnyNodeContext(request.context), proof,
1669 request.params[0].get_str());
1670
1671 return true;
1672 },
1673 };
1674}
1675
1677 return RPCHelpMan{
1678 "verifyavalanchedelegation",
1679 "Verify an avalanche delegation is valid and return the error "
1680 "otherwise.\n",
1681 {
1683 "The avalanche proof delegation to verify."},
1684 },
1686 "Whether the delegation is valid or not."},
1687 RPCExamples{HelpExampleRpc("verifyavalanchedelegation", "\"<proof>\"")},
1688 [&](const RPCHelpMan &self, const Config &config,
1689 const JSONRPCRequest &request) -> UniValue {
1690 avalanche::Delegation delegation;
1691 CPubKey dummy;
1692 verifyDelegationOrThrow(delegation, request.params[0].get_str(),
1693 dummy);
1694
1695 return true;
1696 },
1697 };
1698}
1699
1701 return RPCHelpMan{
1702 "setflakyproof",
1703 "Add or remove a proofid from the flaky list. This means that an "
1704 "additional staking reward winner will be accepted if this proof is "
1705 "the selected one.\n",
1706 {
1708 "The avalanche proof id."},
1710 "Whether to add (true) or remove (false) the proof from the flaky "
1711 "list"},
1712 },
1714 "Whether the addition/removal is successful."},
1715 RPCExamples{HelpExampleRpc("setflakyproof", "\"<proofid>\" true")},
1716 [&](const RPCHelpMan &self, const Config &config,
1717 const JSONRPCRequest &request) -> UniValue {
1718 NodeContext &node = EnsureAnyNodeContext(request.context);
1721
1722 const auto proofid =
1723 avalanche::ProofId::fromHex(request.params[0].get_str());
1724 const bool addNotRemove = request.params[1].get_bool();
1725
1726 if (avalanche.withPeerManager(
1727 [&proofid, addNotRemove](avalanche::PeerManager &pm) {
1728 if (addNotRemove) {
1729 return pm.setFlaky(proofid);
1730 }
1731 return pm.unsetFlaky(proofid);
1732 })) {
1733 const CBlockIndex *pprev =
1734 WITH_LOCK(cs_main, return chainman.ActiveTip());
1735 // Force recompute the staking reward winner by first erasing
1736 // the cached entry if any
1737 avalanche.eraseStakingRewardWinner(pprev->GetBlockHash());
1738 return avalanche.computeStakingReward(pprev);
1739 }
1740
1741 return false;
1742 }};
1743}
1744
1746 return RPCHelpMan{
1747 "getflakyproofs",
1748 "List the flaky proofs (set via setflakyproof).\n",
1749 {},
1750 RPCResult{
1752 "flaky_proofs",
1753 "",
1754 {{
1756 "proof",
1757 "",
1758 {{
1759 {RPCResult::Type::STR_HEX, "proofid",
1760 "The hex encoded proof identifier."},
1761 {RPCResult::Type::STR_AMOUNT, "staked_amount",
1762 "The proof stake amount, only present if the proof is "
1763 "known."},
1765 "payout",
1766 "The proof payout script, only present if the proof is "
1767 "known.",
1768 {
1769 {RPCResult::Type::STR, "asm", "Decoded payout script"},
1771 "Raw payout script in hex format"},
1772 {RPCResult::Type::STR, "type",
1773 "The output type (e.g. " + GetAllOutputTypes() + ")"},
1774 {RPCResult::Type::NUM, "reqSigs",
1775 "The required signatures"},
1777 "addresses",
1778 "",
1779 {
1780 {RPCResult::Type::STR, "address",
1781 "eCash address"},
1782 }},
1783 }},
1784 }},
1785 }},
1786 },
1787 RPCExamples{HelpExampleRpc("getflakyproofs", "")},
1788 [&](const RPCHelpMan &self, const Config &config,
1789 const JSONRPCRequest &request) -> UniValue {
1790 NodeContext &node = EnsureAnyNodeContext(request.context);
1792
1793 UniValue flakyProofs(UniValue::VARR);
1794 avalanche.withPeerManager([&flakyProofs](
1796 pm.forEachFlakyProof([&](const avalanche::ProofId &proofid) {
1797 UniValue flakyProof(UniValue::VOBJ);
1798 flakyProof.pushKV("proofid", proofid.GetHex());
1799
1800 const auto proof = pm.getProof(proofid);
1801 if (proof) {
1802 flakyProof.pushKV("staked_amount",
1803 proof->getStakedAmount());
1804 UniValue payout(UniValue::VOBJ);
1805 ScriptPubKeyToUniv(proof->getPayoutScript(), payout,
1806 /*fIncludeHex=*/true);
1807 flakyProof.pushKV("payout", payout);
1808 }
1809
1810 flakyProofs.push_back(flakyProof);
1811 });
1812 });
1813
1814 return flakyProofs;
1815 }};
1816}
1817
1819 return RPCHelpMan{
1820 "getavailabilityscore",
1821 "Return the node availability score.\n",
1822 {
1823 {"nodeid", RPCArg::Type::NUM, RPCArg::Optional::NO, "The node id."},
1824 },
1825 RPCResult{RPCResult::Type::NUM, "availability_score",
1826 "The node availability score (if any)."},
1827 RPCExamples{HelpExampleRpc("getavailabilityscore", "<nodeid>")},
1828 [&](const RPCHelpMan &self, const Config &config,
1829 const JSONRPCRequest &request) -> UniValue {
1830 const NodeContext &node = EnsureAnyNodeContext(request.context);
1831 const CConnman &connman = EnsureConnman(node);
1832
1833 const NodeId nodeid(request.params[0].getInt<int64_t>());
1834
1835 CNodeStats nodeStats;
1836 if (connman.GetNodeStats(nodeid, nodeStats) &&
1837 nodeStats.m_availabilityScore) {
1838 return *nodeStats.m_availabilityScore;
1839 }
1840
1841 return UniValue::VNULL;
1842 },
1843 };
1844}
1845
1847 return RPCHelpMan{
1848 "getstakecontendervote",
1849 "Return the stake contender avalanche vote.\n",
1850 {
1852 "The prevblockhash used to compute the stake contender ID, hex "
1853 "encoded."},
1855 "The proofid used to compute the stake contender ID, hex "
1856 "encoded."},
1857 },
1859 "The vote that would be returned if polled."},
1860 RPCExamples{HelpExampleRpc("getstakecontendervote",
1861 "<prevblockhash> <proofid>")},
1862 [&](const RPCHelpMan &self, const Config &config,
1863 const JSONRPCRequest &request) -> UniValue {
1864 const NodeContext &node = EnsureAnyNodeContext(request.context);
1866
1867 const BlockHash prevblockhash(
1868 ParseHashV(request.params[0], "prevblockhash"));
1869 const avalanche::ProofId proofid(
1870 ParseHashV(request.params[1], "proofid"));
1871 const avalanche::StakeContenderId contenderId(prevblockhash,
1872 proofid);
1873 return avalanche.getStakeContenderStatus(contenderId);
1874 },
1875 };
1876}
1877
1879 return RPCHelpMan{
1880 "finalizetransaction",
1881 "Force finalize a mempool transaction. No attempt is made to poll for "
1882 "this transaction and this could cause the node to disagree with the "
1883 "network. This can fail if the transaction to be finalized would "
1884 "overflow the block size. Upon success it will be included in the "
1885 "block template.\n",
1886 {
1888 "The id of the transaction to be finalized."},
1889 },
1891 "finalized_txids",
1892 "The list of the successfully finalized txids if any (it can "
1893 "include ancestors of the target txid).",
1894 {{
1896 "txid",
1897 "The finalized transaction id.",
1898 }}},
1899 RPCExamples{HelpExampleRpc("finalizetransaction", "<txid>")},
1900 [&](const RPCHelpMan &self, const Config &config,
1901 const JSONRPCRequest &request) -> UniValue {
1902 const NodeContext &node = EnsureAnyNodeContext(request.context);
1903 CTxMemPool &mempool = EnsureAnyMemPool(request.context);
1904 const ChainstateManager &chainman = EnsureChainman(node);
1905
1906 const TxId txid(ParseHashV(request.params[0], "txid"));
1907
1908 LOCK2(cs_main, mempool.cs);
1909 auto entry = mempool.GetIter(txid);
1910 if (!entry) {
1912 "The transaction is not in the mempool.");
1913 }
1914
1915 const CBlockIndex *tip = chainman.ActiveTip();
1916 if (!tip) {
1918 "There is no active chain tip.");
1919 }
1920
1922
1923 std::vector<TxId> finalizedTxids;
1924 if (!mempool.setAvalancheFinalized(**entry, chainman.GetConsensus(),
1925 *tip, finalizedTxids)) {
1926 // If the function returned false, the finalizedTxids vector
1927 // should not be relied upon
1928 return ret;
1929 }
1930
1931 for (TxId &finalizedTxid : finalizedTxids) {
1932 ret.push_back(finalizedTxid.ToString());
1933
1934 // FIXME we might want to remove from the recent rejects as well
1935 // if it exists so we don't vote against this tx anymore. For
1936 // now this is a private data from the PeerManager and can only
1937 // be cleared entirely. Also a rejected transaction is not
1938 // expected to be in the mempool in the first place so this is
1939 // probably safe.
1940 }
1941
1942 return ret;
1943 },
1944 };
1945}
1946
1948 return RPCHelpMan{
1949 "removetransaction",
1950 "Remove a transaction and all its descendants from the mempool. If the "
1951 "transaction is final it is removed anyway. No attempt is made to poll "
1952 "for this transaction and this could cause the node to disagree with "
1953 "the network.\n",
1954 {
1956 "The id of the transaction to be removed."},
1957 },
1959 "removed_txids",
1960 "The list of the removed txids if any (it can include "
1961 "descendants of the target txid).",
1962 {{
1964 "txid",
1965 "The removed transaction id.",
1966 }}},
1967 RPCExamples{HelpExampleRpc("removetransaction", "<txid>")},
1968 [&](const RPCHelpMan &self, const Config &config,
1969 const JSONRPCRequest &request) -> UniValue {
1970 CTxMemPool &mempool = EnsureAnyMemPool(request.context);
1971
1972 const TxId txid(ParseHashV(request.params[0], "txid"));
1973
1974 LOCK(mempool.cs);
1975 auto iter = mempool.GetIter(txid);
1976 if (!iter) {
1978 "The transaction is not in the mempool.");
1979 }
1980
1981 // This mostly mimics the CTxMemPool::removeRecursive function so we
1982 // can return the list of removed txids
1983 CTxMemPool::setEntries setDescendants;
1984 mempool.CalculateDescendants(*iter, setDescendants);
1985
1987 for (auto &it : setDescendants) {
1988 ret.push_back((*it)->GetSharedTx()->GetId().ToString());
1989 }
1990
1991 mempool.RemoveStaged(setDescendants, MemPoolRemovalReason::MANUAL);
1992
1993 return ret;
1994 },
1995 };
1996}
1997
1999 return RPCHelpMan{
2000 "getfinaltransactions",
2001 "Returns all finalized transactions that have not been included in a "
2002 "finalized block yet.",
2003 {
2004 {"verbose", RPCArg::Type::BOOL, RPCArg::Default{false},
2005 "True for a json object, false for an array of transaction ids"},
2006 },
2007 {
2008 RPCResult{"for verbose = false",
2010 "",
2011 "",
2012 {
2013 {RPCResult::Type::STR_HEX, "", "The transaction id"},
2014 }},
2015 RPCResult{"for verbose = true",
2017 "",
2018 "",
2019 {{
2021 "",
2022 "",
2023 DecodeTxDoc(/*txid_field_doc=*/"The transaction id",
2024 /*wallet=*/false),
2025 }}},
2026 },
2027 RPCExamples{HelpExampleCli("getfinaltransactions", "true") +
2028 HelpExampleRpc("getfinaltransactions", "true")},
2029 [&](const RPCHelpMan &self, const Config &config,
2030 const JSONRPCRequest &request) -> UniValue {
2031 const bool fVerbose =
2032 !request.params[0].isNull() && request.params[0].get_bool();
2033
2034 const CTxMemPool &mempool = EnsureAnyMemPool(request.context);
2035
2036 UniValue finalTxs(UniValue::VARR);
2037 {
2038 LOCK(mempool.cs);
2039 mempool.finalizedTxs.forEachLeaf(
2040 [fVerbose, &finalTxs](const CTxMemPoolEntryRef &entryRef) {
2041 if (!fVerbose) {
2042 finalTxs.push_back(
2043 entryRef->GetTx().GetId().GetHex());
2044 } else {
2046 TxToUniv(entryRef->GetTx(), BlockHash(), tx,
2047 /*include_hex=*/true);
2048 finalTxs.push_back(std::move(tx));
2049 }
2050 return true;
2051 });
2052 }
2053
2054 return finalTxs;
2055 },
2056 };
2057}
2058
2060 // clang-format off
2061 static const CRPCCommand commands[] = {
2062 // category actor (function)
2063 // ----------------- --------------------
2064 { "avalanche", getavalanchekey, },
2065 { "avalanche", addavalanchenode, },
2066 { "avalanche", buildavalancheproof, },
2067 { "avalanche", decodeavalancheproof, },
2068 { "avalanche", delegateavalancheproof, },
2069 { "avalanche", decodeavalanchedelegation, },
2070 { "avalanche", getavalancheinfo, },
2071 { "avalanche", getavalanchepeerinfo, },
2072 { "avalanche", getavalancheproofs, },
2073 { "avalanche", getstakingreward, },
2074 { "hidden", hasstakingreward, },
2075 { "avalanche", setstakingreward, },
2076 { "avalanche", getremoteproofs, },
2077 { "avalanche", getrawavalancheproof, },
2078 { "avalanche", invalidateavalancheproof, },
2079 { "avalanche", isfinalblock, },
2080 { "avalanche", isfinaltransaction, },
2081 { "avalanche", reconsideravalancheproof, },
2082 { "avalanche", sendavalancheproof, },
2083 { "avalanche", verifyavalancheproof, },
2084 { "avalanche", verifyavalanchedelegation, },
2085 { "avalanche", setflakyproof, },
2086 { "avalanche", getflakyproofs, },
2087 { "avalanche", finalizetransaction, },
2088 { "avalanche", removetransaction, },
2089 { "avalanche", getfinaltransactions, },
2090 { "hidden", getavailabilityscore, },
2091 { "hidden", getstakecontendervote, },
2092 };
2093 // clang-format on
2094
2095 for (const auto &c : commands) {
2096 t.appendCommand(c.name, &c);
2097 }
2098}
static RPCHelpMan buildavalancheproof()
Definition: avalanche.cpp:207
static RPCHelpMan invalidateavalancheproof()
Definition: avalanche.cpp:1360
static RPCHelpMan delegateavalancheproof()
Definition: avalanche.cpp:463
static RPCHelpMan getremoteproofs()
Definition: avalanche.cpp:1236
static RPCHelpMan decodeavalanchedelegation()
Definition: avalanche.cpp:535
static RPCHelpMan sendavalancheproof()
Definition: avalanche.cpp:1606
static RPCHelpMan getavalancheproofs()
Definition: avalanche.cpp:936
static void verifyDelegationOrThrow(avalanche::Delegation &dg, const std::string &dgHex, CPubKey &auth)
Definition: avalanche.cpp:82
static RPCHelpMan getrawavalancheproof()
Definition: avalanche.cpp:1290
static void verifyProofOrThrow(const NodeContext &node, avalanche::Proof &proof, const std::string &proofHex)
Definition: avalanche.cpp:96
void RegisterAvalancheRPCCommands(CRPCTable &t)
Definition: avalanche.cpp:2059
static RPCHelpMan getavalanchekey()
Definition: avalanche.cpp:35
static RPCHelpMan hasstakingreward()
Definition: avalanche.cpp:1105
static RPCHelpMan addavalanchenode()
Definition: avalanche.cpp:122
static CPubKey ParsePubKey(const UniValue &param)
Definition: avalanche.cpp:51
static RPCHelpMan finalizetransaction()
Definition: avalanche.cpp:1878
static RPCHelpMan getavailabilityscore()
Definition: avalanche.cpp:1818
static RPCHelpMan getstakecontendervote()
Definition: avalanche.cpp:1846
static RPCHelpMan verifyavalanchedelegation()
Definition: avalanche.cpp:1676
static RPCHelpMan setflakyproof()
Definition: avalanche.cpp:1700
static RPCHelpMan getfinaltransactions()
Definition: avalanche.cpp:1998
static RPCHelpMan removetransaction()
Definition: avalanche.cpp:1947
static RPCHelpMan setstakingreward()
Definition: avalanche.cpp:1157
static RPCHelpMan getflakyproofs()
Definition: avalanche.cpp:1745
static RPCHelpMan isfinalblock()
Definition: avalanche.cpp:1411
static RPCHelpMan reconsideravalancheproof()
Definition: avalanche.cpp:1552
static RPCHelpMan isfinaltransaction()
Definition: avalanche.cpp:1454
static RPCHelpMan getstakingreward()
Definition: avalanche.cpp:998
static bool registerProofIfNeeded(const avalanche::Processor &avalanche, avalanche::ProofRef proof, avalanche::ProofRegistrationState &state)
Definition: avalanche.cpp:63
static RPCHelpMan getavalanchepeerinfo()
Definition: avalanche.cpp:829
static RPCHelpMan verifyavalancheproof()
Definition: avalanche.cpp:1654
static RPCHelpMan getavalancheinfo()
Definition: avalanche.cpp:618
static RPCHelpMan decodeavalancheproof()
Definition: avalanche.cpp:338
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:53
#define Assert(val)
Identity function.
Definition: check.h:84
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: blockindex.h:25
BlockHash GetBlockHash() const
Definition: blockindex.h:130
Definition: net.h:824
void GetNodeStats(std::vector< CNodeStats > &vstats) const
Definition: net.cpp:2776
An encapsulated secp256k1 private key.
Definition: key.h:28
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:97
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:210
Information about a peer.
Definition: net.h:395
An encapsulated public key.
Definition: pubkey.h:31
static constexpr unsigned int COMPRESSED_SIZE
Definition: pubkey.h:37
static constexpr unsigned int SIZE
secp256k1:
Definition: pubkey.h:36
RPC command dispatcher.
Definition: server.h:194
void appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
Definition: server.cpp:328
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:221
std::set< txiter, CompareIteratorById > setEntries
Definition: txmempool.h:321
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
Definition: txmempool.h:317
bool setAvalancheFinalized(const CTxMemPoolEntryRef &tx, const Consensus::Params &params, const CBlockIndex &active_chain_tip, std::vector< TxId > &finalizedTxIds) EXCLUSIVE_LOCKS_REQUIRED(bool isAvalancheFinalizedPreConsensus(const TxId &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.h:541
RadixTree< CTxMemPoolEntry, MemPoolEntryRadixTreeAdapter > finalizedTxs
Definition: txmempool.h:324
void CalculateDescendants(txiter it, setEntries &setDescendants) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Populate setDescendants with all in-mempool descendants of hash.
Definition: txmempool.cpp:243
void RemoveStaged(const setEntries &stage, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
Remove a set of transactions from the mempool.
Definition: txmempool.cpp:837
std::optional< txiter > GetIter(const TxId &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Returns an iterator to the given txid, if found.
Definition: txmempool.cpp:745
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
Definition: validation.h:1186
SnapshotCompletionResult MaybeCompleteSnapshotValidation() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex *GetSnapshotBaseBlock() const EXCLUSIVE_LOCKS_REQUIRED(Chainstate ActiveChainstate)() const
Once the background validation chainstate has reached the height which is the base of the UTXO snapsh...
Definition: validation.h:1437
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Definition: validation.h:1444
const Consensus::Params & GetConsensus() const
Definition: validation.h:1282
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Definition: validation.h:1327
Definition: config.h:19
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:173
static RCUPtr make(Args &&...args)
Construct a new object that is owned by the pointer.
Definition: rcu.h:112
void push_back(UniValue val)
Definition: univalue.cpp:96
const std::string & get_str() const
const UniValue & find_value(std::string_view key) const
Definition: univalue.cpp:229
@ VNULL
Definition: univalue.h:30
@ VOBJ
Definition: univalue.h:31
@ VSTR
Definition: univalue.h:33
@ VARR
Definition: univalue.h:32
@ VNUM
Definition: univalue.h:34
bool isNull() const
Definition: univalue.h:104
size_t size() const
Definition: univalue.h:92
Int getInt() const
Definition: univalue.h:157
const UniValue & get_array() const
bool exists(const std::string &key) const
Definition: univalue.h:99
void pushKV(std::string key, UniValue val)
Definition: univalue.cpp:115
bool get_bool() const
bool IsValid() const
Definition: validation.h:119
std::string GetRejectReason() const
Definition: validation.h:123
std::string GetDebugMessage() const
Definition: validation.h:124
std::string ToString() const
Definition: validation.h:125
ProofId getProofId() const
Definition: delegation.cpp:56
const std::vector< Level > & getLevels() const
Definition: delegation.h:64
static bool FromHex(Delegation &dg, const std::string &dgHex, bilingual_str &errorOut)
Definition: delegation.cpp:16
bool verify(DelegationState &state, CPubKey &auth) const
Definition: delegation.cpp:73
const CPubKey & getProofMaster() const
Definition: delegation.h:62
const DelegationId & getId() const
Definition: delegation.h:60
const CPubKey & getDelegatedPubkey() const
Definition: delegation.cpp:60
const LimitedProofId & getLimitedProofId() const
Definition: delegation.h:61
std::vector< RemoteProof > getRemoteProofs(const NodeId nodeid) const
bool isDangling(const ProofId &proofid) const
bool unsetFlaky(const ProofId &proofid)
bool exists(const ProofId &proofid) const
Return true if the (valid) proof exists, but only for non-dangling proofs.
Definition: peermanager.h:411
const ProofPool & getValidProofPool() const
Definition: peermanager.h:510
bool forPeer(const ProofId &proofid, Callable &&func) const
Definition: peermanager.h:419
bool addNode(NodeId nodeid, const ProofId &proofid)
Node API.
Definition: peermanager.cpp:33
void addUnbroadcastProof(const ProofId &proofid)
Proof broadcast API.
bool isBoundToPeer(const ProofId &proofid) const
size_t getPendingNodeCount() const
Definition: peermanager.h:319
const ProofPool & getImmatureProofPool() const
Definition: peermanager.h:514
void forEachPeer(Callable &&func) const
Definition: peermanager.h:425
void setInvalid(const ProofId &proofid)
void forEachNode(const Peer &peer, Callable &&func) const
Definition: peermanager.h:345
const Amount & getStakeUtxoDustThreshold() const
Definition: peermanager.h:530
void forEachFlakyProof(Callable &&func) const
Definition: peermanager.h:457
bool isInvalid(const ProofId &proofid) const
bool isImmature(const ProofId &proofid) const
bool rejectProof(const ProofId &proofid, RejectionMode mode=RejectionMode::DEFAULT)
const ProofPool & getConflictingProofPool() const
Definition: peermanager.h:511
bool isInConflictingPool(const ProofId &proofid) const
ProofRef getProof(const ProofId &proofid) const
bool registerProof(const ProofRef &proof, ProofRegistrationState &registrationState, RegistrationMode mode=RegistrationMode::DEFAULT)
bool addUTXO(COutPoint utxo, Amount amount, uint32_t height, bool is_coinbase, CKey key)
int64_t getExpirationTime() const
Definition: proof.h:164
static bool FromHex(Proof &proof, const std::string &hexProof, bilingual_str &errorOut)
Definition: proof.cpp:52
bool verify(const Amount &stakeUtxoDustThreshold, ProofValidationState &state) const
Definition: proof.cpp:120
Amount getStakedAmount() const
Definition: proof.cpp:105
const CPubKey & getMaster() const
Definition: proof.h:165
uint64_t getSequence() const
Definition: proof.h:163
const LimitedProofId & getLimitedId() const
Definition: proof.h:171
const SchnorrSig & getSignature() const
Definition: proof.h:168
const CScript & getPayoutScript() const
Definition: proof.h:167
uint32_t getScore() const
Definition: proof.h:175
const ProofId & getId() const
Definition: proof.h:170
const std::vector< SignedStake > & getStakes() const
Definition: proof.h:166
Map a proof to each utxo.
Definition: proofpool.h:57
size_t countProofs() const
Definition: proofpool.cpp:129
void forEachProof(Callable &&func) const
Definition: proofpool.h:118
ProofIdSet getProofIds() const
Definition: proofpool.cpp:101
std::string ToString() const
Definition: uint256.h:80
std::string GetHex() const
Definition: uint256.cpp:16
CBlockIndex * LookupBlockIndex(const BlockHash &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
void ScriptPubKeyToUniv(const CScript &scriptPubKey, UniValue &out, bool fIncludeHex)
Definition: core_write.cpp:194
void TxToUniv(const CTransaction &tx, const BlockHash &hashBlock, UniValue &entry, bool include_hex=true, const CTxUndo *txundo=nullptr, TxVerbosity verbosity=TxVerbosity::SHOW_DETAILS, std::function< bool(const CTxOut &)> is_change_func={})
Definition: core_write.cpp:221
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: cs_main.cpp:7
int64_t NodeId
Definition: eviction.h:16
std::string EncodeDestination(const CTxDestination &dest, const Config &config)
Definition: key_io.cpp:167
CTxDestination DecodeDestination(const std::string &addr, const CChainParams &params)
Definition: key_io.cpp:174
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:77
static constexpr Amount PROOF_DUST_THRESHOLD
Minimum amount per utxo.
Definition: proof.h:41
Definition: init.h:31
CTransactionRef GetTransaction(const CBlockIndex *const block_index, const CTxMemPool *const mempool, const TxId &txid, BlockHash &hashBlock, const BlockManager &blockman)
Return transaction with a given txid.
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:315
std::vector< RPCResult > DecodeTxDoc(const std::string &txid_field_doc, bool wallet)
Explain the UniValue "decoded" transaction object, may include extra fields if processed by wallet.
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:58
@ RPC_MISC_ERROR
General application defined errors std::exception thrown in command handling.
Definition: protocol.h:38
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
Definition: protocol.h:46
@ RPC_INTERNAL_ERROR
Definition: protocol.h:33
@ RPC_DESERIALIZATION_ERROR
Error parsing or validating structure in raw format.
Definition: protocol.h:50
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
Definition: protocol.h:42
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:153
Amount AmountFromValue(const UniValue &value)
Definition: util.cpp:58
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:170
std::string GetAllOutputTypes()
Definition: util.cpp:308
CPubKey HexToPubKey(const std::string &hex_in)
Definition: util.cpp:194
uint256 ParseHashO(const UniValue &o, std::string strKey)
Definition: util.cpp:93
uint256 ParseHashV(const UniValue &v, std::string strName)
Utilities: convert hex-encoded values (throws error if not hex).
Definition: util.cpp:76
void RPCTypeCheckObj(const UniValue &o, const std::map< std::string, UniValueType > &typesExpected, bool fAllowNull, bool fStrict)
Check for expected keys/value types in an Object.
Definition: util.cpp:29
bool IsDeprecatedRPCEnabled(const ArgsManager &args, const std::string &method)
Definition: server.cpp:408
ChainstateManager & EnsureAnyChainman(const std::any &context)
Definition: server_util.cpp:59
NodeContext & EnsureAnyNodeContext(const std::any &context)
Definition: server_util.cpp:21
CTxMemPool & EnsureMemPool(const NodeContext &node)
Definition: server_util.cpp:29
ChainstateManager & EnsureChainman(const NodeContext &node)
Definition: server_util.cpp:52
CTxMemPool & EnsureAnyMemPool(const std::any &context)
Definition: server_util.cpp:37
ArgsManager & EnsureArgsman(const NodeContext &node)
Definition: server_util.cpp:41
avalanche::Processor & EnsureAvalanche(const NodeContext &node)
Definition: server_util.cpp:81
CConnman & EnsureConnman(const NodeContext &node)
Definition: server_util.cpp:63
bool IsStakingRewardsActivated(const Consensus::Params &params, const CBlockIndex *pprev)
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:158
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:260
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:240
std::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:85
Definition: amount.h:19
static constexpr Amount zero() noexcept
Definition: amount.h:32
A BlockHash is a unqiue identifier for a block.
Definition: blockhash.h:13
POD that contains various stats about a node.
Definition: net.h:213
std::optional< double > m_availabilityScore
Definition: net.h:248
static const Currency & get()
Definition: amount.cpp:18
std::string ticker
Definition: amount.h:150
@ STR_HEX
Special type that is a STR with only hex chars.
@ AMOUNT
Special type representing a floating point amount (can be either NUM or STR)
@ OMITTED
Optional argument for which the default value is omitted from help text for one of two reasons:
@ NO
Required arg.
@ STR_HEX
Special string with only hex chars.
@ STR_AMOUNT
Special string to represent a floating point amount.
bool forEachLeaf(Callable &&func) const
Definition: radix.h:144
A TxId is the identifier of a transaction.
Definition: txid.h:14
NodeId nodeid
Definition: node.h:21
uint32_t node_count
Definition: peermanager.h:89
ProofRef proof
Definition: peermanager.h:91
static ProofId fromHex(const std::string &str)
Definition: proofid.h:21
StakeContenderIds are unique for each block to ensure that the peer polling for their acceptance has ...
Bilingual messages:
Definition: translation.h:17
std::string original
Definition: translation.h:18
NodeContext struct containing references to chain state and connection state.
Definition: context.h:48
#define LOCK2(cs1, cs2)
Definition: sync.h:309
#define LOCK(cs)
Definition: sync.h:306
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:357
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1202
std::unique_ptr< TxIndex > g_txindex
The global transaction index, used in GetTransaction. May be null.
Definition: txindex.cpp:16
@ MANUAL
Manual removal via RPC.
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
std::string EncodeBase64(Span< const uint8_t > input)
template std::vector< std::byte > ParseHex(std::string_view)
bool IsHex(std::string_view str)
Returns true if each character in str is a hex character, and has an even number of hex digits.