Bitcoin ABC 0.31.2
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>
23#include <rpc/server.h>
24#include <rpc/server_util.h>
25#include <rpc/util.h>
26#include <util/strencodings.h>
27#include <util/translation.h>
28
29#include <univalue.h>
30
33
35 return RPCHelpMan{
36 "getavalanchekey",
37 "Returns the key used to sign avalanche messages.\n",
38 {},
40 RPCExamples{HelpExampleRpc("getavalanchekey", "")},
41 [&](const RPCHelpMan &self, const Config &config,
42 const JSONRPCRequest &request) -> UniValue {
43 NodeContext &node = EnsureAnyNodeContext(request.context);
45 return HexStr(avalanche.getSessionPubKey());
46 },
47 };
48}
49
50static CPubKey ParsePubKey(const UniValue &param) {
51 const std::string keyHex = param.get_str();
52 if ((keyHex.length() != 2 * CPubKey::COMPRESSED_SIZE &&
53 keyHex.length() != 2 * CPubKey::SIZE) ||
54 !IsHex(keyHex)) {
56 strprintf("Invalid public key: %s\n", keyHex));
57 }
58
59 return HexToPubKey(keyHex);
60}
61
65 auto localProof = avalanche.getLocalProof();
66 if (localProof && localProof->getId() == proof->getId()) {
67 return true;
68 }
69
70 return avalanche.withPeerManager([&](avalanche::PeerManager &pm) {
71 return pm.getProof(proof->getId()) || pm.registerProof(proof, state);
72 });
73}
74
76 avalanche::ProofRef proof) {
78 return registerProofIfNeeded(avalanche, std::move(proof), state);
79}
80
82 const std::string &dgHex, CPubKey &auth) {
84 if (!avalanche::Delegation::FromHex(dg, dgHex, error)) {
86 }
87
89 if (!dg.verify(state, auth)) {
91 "The delegation is invalid: " + state.ToString());
92 }
93}
94
96 const std::string &proofHex) {
98 if (!avalanche::Proof::FromHex(proof, proofHex, error)) {
100 }
101
102 Amount stakeUtxoDustThreshold = avalanche::PROOF_DUST_THRESHOLD;
103 if (node.avalanche) {
104 // If Avalanche is enabled, use the configured dust threshold
105 node.avalanche->withPeerManager([&](avalanche::PeerManager &pm) {
106 stakeUtxoDustThreshold = pm.getStakeUtxoDustThreshold();
107 });
108 }
109
111 {
112 LOCK(cs_main);
113 if (!proof.verify(stakeUtxoDustThreshold, *Assert(node.chainman),
114 state)) {
116 "The proof is invalid: " + state.ToString());
117 }
118 }
119}
120
122 return RPCHelpMan{
123 "addavalanchenode",
124 "Add a node in the set of peers to poll for avalanche.\n",
125 {
127 "Node to be added to avalanche."},
129 "The public key of the node."},
131 "Proof that the node is not a sybil."},
133 "The proof delegation the the node public key"},
134 },
136 "Whether the addition succeeded or not."},
138 HelpExampleRpc("addavalanchenode", "5, \"<pubkey>\", \"<proof>\"")},
139 [&](const RPCHelpMan &self, const Config &config,
140 const JSONRPCRequest &request) -> UniValue {
141 const NodeId nodeid = request.params[0].getInt<int64_t>();
142 CPubKey key = ParsePubKey(request.params[1]);
143
144 auto proof = RCUPtr<avalanche::Proof>::make();
145 NodeContext &node = EnsureAnyNodeContext(request.context);
147
148 verifyProofOrThrow(node, *proof, request.params[2].get_str());
149
150 const avalanche::ProofId &proofid = proof->getId();
151 if (key != proof->getMaster()) {
152 if (request.params.size() < 4 || request.params[3].isNull()) {
153 throw JSONRPCError(
155 "The public key does not match the proof");
156 }
157
159 CPubKey auth;
160 verifyDelegationOrThrow(dg, request.params[3].get_str(), auth);
161
162 if (dg.getProofId() != proofid) {
163 throw JSONRPCError(
165 "The delegation does not match the proof");
166 }
167
168 if (key != auth) {
169 throw JSONRPCError(
171 "The public key does not match the delegation");
172 }
173 }
174
175 if (!registerProofIfNeeded(avalanche, proof)) {
177 "The proof has conflicting utxos");
178 }
179
180 if (!node.connman->ForNode(nodeid, [&](CNode *pnode) {
181 LOCK(pnode->cs_avalanche_pubkey);
182 bool expected = false;
183 if (pnode->m_avalanche_enabled.compare_exchange_strong(
184 expected, true)) {
185 pnode->m_avalanche_pubkey = std::move(key);
186 }
187 return true;
188 })) {
189 throw JSONRPCError(
191 strprintf("The node does not exist: %d", nodeid));
192 }
193
194 return avalanche.withPeerManager([&](avalanche::PeerManager &pm) {
195 if (!pm.addNode(nodeid, proofid)) {
196 return false;
197 }
198
199 pm.addUnbroadcastProof(proofid);
200 return true;
201 });
202 },
203 };
204}
205
207 return RPCHelpMan{
208 "buildavalancheproof",
209 "Build a proof for avalanche's sybil resistance.\n",
210 {
212 "The proof's sequence"},
214 "A timestamp indicating when the proof expire"},
216 "The master private key in base58-encoding"},
217 {
218 "stakes",
221 "The stakes to be signed and associated private keys",
222 {
223 {
224 "stake",
227 "A stake to be attached to this proof",
228 {
229 {"txid", RPCArg::Type::STR_HEX,
230 RPCArg::Optional::NO, "The transaction id"},
232 "The output number"},
233 {"amount", RPCArg::Type::AMOUNT,
234 RPCArg::Optional::NO, "The amount in this UTXO"},
236 "The height at which this UTXO was mined"},
237 {"iscoinbase", RPCArg::Type::BOOL,
238 RPCArg::Default{false},
239 "Indicate wether the UTXO is a coinbase"},
240 {"privatekey", RPCArg::Type::STR,
242 "private key in base58-encoding"},
243 },
244 },
245 },
246 },
247 {"payoutAddress", RPCArg::Type::STR, RPCArg::Optional::NO,
248 "A payout address"},
249 },
251 "A string that is a serialized, hex-encoded proof data."},
252 RPCExamples{HelpExampleRpc("buildavalancheproof",
253 "0 1234567800 \"<master>\" []")},
254 [&](const RPCHelpMan &self, const Config &config,
255 const JSONRPCRequest &request) -> UniValue {
256 const uint64_t sequence = request.params[0].getInt<int64_t>();
257 const int64_t expiration = request.params[1].getInt<int64_t>();
258
259 CKey masterKey = DecodeSecret(request.params[2].get_str());
260 if (!masterKey.IsValid()) {
261 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid master key");
262 }
263
264 CTxDestination payoutAddress = DecodeDestination(
265 request.params[4].get_str(), config.GetChainParams());
266
267 if (!IsValidDestination(payoutAddress)) {
269 "Invalid payout address");
270 }
271
272 avalanche::ProofBuilder pb(sequence, expiration, masterKey,
273 GetScriptForDestination(payoutAddress));
274
275 const UniValue &stakes = request.params[3].get_array();
276 for (size_t i = 0; i < stakes.size(); i++) {
277 const UniValue &stake = stakes[i];
279 stake,
280 {
281 {"txid", UniValue::VSTR},
282 {"vout", UniValue::VNUM},
283 // "amount" is also required but check is done below
284 // due to UniValue::VNUM erroneously not accepting
285 // quoted numerics (which are valid JSON)
286 {"height", UniValue::VNUM},
287 {"privatekey", UniValue::VSTR},
288 });
289
290 int nOut = stake.find_value("vout").getInt<int>();
291 if (nOut < 0) {
293 "vout cannot be negative");
294 }
295
296 const int height = stake.find_value("height").getInt<int>();
297 if (height < 1) {
299 "height must be positive");
300 }
301
302 const TxId txid(ParseHashO(stake, "txid"));
303 const COutPoint utxo(txid, nOut);
304
305 if (!stake.exists("amount")) {
306 throw JSONRPCError(RPC_INVALID_PARAMETER, "Missing amount");
307 }
308
309 const Amount amount =
310 AmountFromValue(stake.find_value("amount"));
311
312 const UniValue &iscbparam = stake.find_value("iscoinbase");
313 const bool iscoinbase =
314 iscbparam.isNull() ? false : iscbparam.get_bool();
315 CKey key =
316 DecodeSecret(stake.find_value("privatekey").get_str());
317
318 if (!key.IsValid()) {
320 "Invalid private key");
321 }
322
323 if (!pb.addUTXO(utxo, amount, uint32_t(height), iscoinbase,
324 std::move(key))) {
326 "Duplicated stake");
327 }
328 }
329
330 const avalanche::ProofRef proof = pb.build();
331
332 return proof->ToHex();
333 },
334 };
335}
336
338 return RPCHelpMan{
339 "decodeavalancheproof",
340 "Convert a serialized, hex-encoded proof, into JSON object. "
341 "The validity of the proof is not verified.\n",
342 {
344 "The proof hex string"},
345 },
346 RPCResult{
348 "",
349 "",
350 {
351 {RPCResult::Type::NUM, "sequence",
352 "The proof's sequential number"},
353 {RPCResult::Type::NUM, "expiration",
354 "A timestamp indicating when the proof expires"},
355 {RPCResult::Type::STR_HEX, "master", "The master public key"},
356 {RPCResult::Type::STR, "signature",
357 "The proof signature (base64 encoded)"},
359 "payoutscript",
360 "The proof payout script",
361 {
362 {RPCResult::Type::STR, "asm", "Decoded payout script"},
364 "Raw payout script in hex format"},
365 {RPCResult::Type::STR, "type",
366 "The output type (e.g. " + GetAllOutputTypes() + ")"},
367 {RPCResult::Type::NUM, "reqSigs",
368 "The required signatures"},
370 "addresses",
371 "",
372 {
373 {RPCResult::Type::STR, "address", "eCash address"},
374 }},
375 }},
376 {RPCResult::Type::STR_HEX, "limitedid",
377 "A hash of the proof data excluding the master key."},
378 {RPCResult::Type::STR_HEX, "proofid",
379 "A hash of the limitedid and master key."},
380 {RPCResult::Type::STR_AMOUNT, "staked_amount",
381 "The total staked amount of this proof in " +
382 Currency::get().ticker + "."},
383 {RPCResult::Type::NUM, "score", "The score of this proof."},
385 "stakes",
386 "",
387 {
389 "",
390 "",
391 {
393 "The transaction id"},
394 {RPCResult::Type::NUM, "vout", "The output number"},
396 "The amount in this UTXO"},
397 {RPCResult::Type::NUM, "height",
398 "The height at which this UTXO was mined"},
399 {RPCResult::Type::BOOL, "iscoinbase",
400 "Indicate whether the UTXO is a coinbase"},
401 {RPCResult::Type::STR_HEX, "pubkey",
402 "This UTXO's public key"},
403 {RPCResult::Type::STR, "signature",
404 "Signature of the proofid with this UTXO's private "
405 "key (base64 encoded)"},
406 }},
407 }},
408 }},
409 RPCExamples{HelpExampleCli("decodeavalancheproof", "\"<hex proof>\"") +
410 HelpExampleRpc("decodeavalancheproof", "\"<hex proof>\"")},
411 [&](const RPCHelpMan &self, const Config &config,
412 const JSONRPCRequest &request) -> UniValue {
413 avalanche::Proof proof;
415 if (!avalanche::Proof::FromHex(proof, request.params[0].get_str(),
416 error)) {
418 }
419
420 UniValue result(UniValue::VOBJ);
421 result.pushKV("sequence", proof.getSequence());
422 result.pushKV("expiration", proof.getExpirationTime());
423 result.pushKV("master", HexStr(proof.getMaster()));
424 result.pushKV("signature", EncodeBase64(proof.getSignature()));
425
426 const auto payoutScript = proof.getPayoutScript();
427 UniValue payoutScriptObj(UniValue::VOBJ);
428 ScriptPubKeyToUniv(payoutScript, payoutScriptObj,
429 /* fIncludeHex */ true);
430 result.pushKV("payoutscript", payoutScriptObj);
431
432 result.pushKV("limitedid", proof.getLimitedId().ToString());
433 result.pushKV("proofid", proof.getId().ToString());
434
435 result.pushKV("staked_amount", proof.getStakedAmount());
436 result.pushKV("score", uint64_t(proof.getScore()));
437
438 UniValue stakes(UniValue::VARR);
439 for (const avalanche::SignedStake &s : proof.getStakes()) {
440 const COutPoint &utxo = s.getStake().getUTXO();
442 stake.pushKV("txid", utxo.GetTxId().ToString());
443 stake.pushKV("vout", uint64_t(utxo.GetN()));
444 stake.pushKV("amount", s.getStake().getAmount());
445 stake.pushKV("height", uint64_t(s.getStake().getHeight()));
446 stake.pushKV("iscoinbase", s.getStake().isCoinbase());
447 stake.pushKV("pubkey", HexStr(s.getStake().getPubkey()));
448 // Only PKHash destination is supported, so this is safe
449 stake.pushKV("address",
450 EncodeDestination(PKHash(s.getStake().getPubkey()),
451 config));
452 stake.pushKV("signature", EncodeBase64(s.getSignature()));
453 stakes.push_back(stake);
454 }
455 result.pushKV("stakes", stakes);
456
457 return result;
458 },
459 };
460}
461
463 return RPCHelpMan{
464 "delegateavalancheproof",
465 "Delegate the avalanche proof to another public key.\n",
466 {
468 "The limited id of the proof to be delegated."},
470 "The private key in base58-encoding. Must match the proof master "
471 "public key or the upper level parent delegation public key if "
472 " supplied."},
474 "The public key to delegate the proof to."},
476 "A string that is the serialized, hex-encoded delegation for the "
477 "proof and which is a parent for the delegation to build."},
478 },
480 "A string that is a serialized, hex-encoded delegation."},
482 HelpExampleRpc("delegateavalancheproof",
483 "\"<limitedproofid>\" \"<privkey>\" \"<pubkey>\"")},
484 [&](const RPCHelpMan &self, const Config &config,
485 const JSONRPCRequest &request) -> UniValue {
486 avalanche::LimitedProofId limitedProofId{
487 ParseHashV(request.params[0], "limitedproofid")};
488
489 const CKey privkey = DecodeSecret(request.params[1].get_str());
490 if (!privkey.IsValid()) {
492 "The private key is invalid");
493 }
494
495 const CPubKey pubkey = ParsePubKey(request.params[2]);
496
497 std::unique_ptr<avalanche::DelegationBuilder> dgb;
498 if (request.params.size() >= 4 && !request.params[3].isNull()) {
500 CPubKey auth;
501 verifyDelegationOrThrow(dg, request.params[3].get_str(), auth);
502
503 if (dg.getProofId() !=
504 limitedProofId.computeProofId(dg.getProofMaster())) {
505 throw JSONRPCError(
507 "The delegation does not match the proof");
508 }
509
510 if (privkey.GetPubKey() != auth) {
511 throw JSONRPCError(
513 "The private key does not match the delegation");
514 }
515
516 dgb = std::make_unique<avalanche::DelegationBuilder>(dg);
517 } else {
518 dgb = std::make_unique<avalanche::DelegationBuilder>(
519 limitedProofId, privkey.GetPubKey());
520 }
521
522 if (!dgb->addLevel(privkey, pubkey)) {
524 "Unable to build the delegation");
525 }
526
528 ss << dgb->build();
529 return HexStr(ss);
530 },
531 };
532}
533
535 return RPCHelpMan{
536 "decodeavalanchedelegation",
537 "Convert a serialized, hex-encoded avalanche proof delegation, into "
538 "JSON object. \n"
539 "The validity of the delegation is not verified.\n",
540 {
542 "The delegation hex string"},
543 },
544 RPCResult{
546 "",
547 "",
548 {
549 {RPCResult::Type::STR_HEX, "pubkey",
550 "The public key the proof is delegated to."},
551 {RPCResult::Type::STR_HEX, "proofmaster",
552 "The delegated proof master public key."},
553 {RPCResult::Type::STR_HEX, "delegationid",
554 "The identifier of this delegation."},
555 {RPCResult::Type::STR_HEX, "limitedid",
556 "A delegated proof data hash excluding the master key."},
557 {RPCResult::Type::STR_HEX, "proofid",
558 "A hash of the delegated proof limitedid and master key."},
559 {RPCResult::Type::NUM, "depth",
560 "The number of delegation levels."},
562 "levels",
563 "",
564 {
566 "",
567 "",
568 {
569 {RPCResult::Type::NUM, "index",
570 "The index of this delegation level."},
571 {RPCResult::Type::STR_HEX, "pubkey",
572 "This delegated public key for this level"},
573 {RPCResult::Type::STR, "signature",
574 "Signature of this delegation level (base64 "
575 "encoded)"},
576 }},
577 }},
578 }},
579 RPCExamples{HelpExampleCli("decodeavalanchedelegation",
580 "\"<hex delegation>\"") +
581 HelpExampleRpc("decodeavalanchedelegation",
582 "\"<hex delegation>\"")},
583 [&](const RPCHelpMan &self, const Config &config,
584 const JSONRPCRequest &request) -> UniValue {
585 avalanche::Delegation delegation;
588 delegation, request.params[0].get_str(), error)) {
590 }
591
592 UniValue result(UniValue::VOBJ);
593 result.pushKV("pubkey", HexStr(delegation.getDelegatedPubkey()));
594 result.pushKV("proofmaster", HexStr(delegation.getProofMaster()));
595 result.pushKV("delegationid", delegation.getId().ToString());
596 result.pushKV("limitedid",
597 delegation.getLimitedProofId().ToString());
598 result.pushKV("proofid", delegation.getProofId().ToString());
599
600 auto levels = delegation.getLevels();
601 result.pushKV("depth", uint64_t(levels.size()));
602
603 UniValue levelsArray(UniValue::VARR);
604 for (auto &level : levels) {
606 obj.pushKV("pubkey", HexStr(level.pubkey));
607 obj.pushKV("signature", EncodeBase64(level.sig));
608 levelsArray.push_back(std::move(obj));
609 }
610 result.pushKV("levels", levelsArray);
611
612 return result;
613 },
614 };
615}
616
618 return RPCHelpMan{
619 "getavalancheinfo",
620 "Returns an object containing various state info regarding avalanche "
621 "networking.\n",
622 {},
623 RPCResult{
625 "",
626 "",
627 {
628 {RPCResult::Type::BOOL, "ready_to_poll",
629 "Whether the node is ready to start polling and voting."},
631 "local",
632 "Only available if -avaproof has been supplied to the node",
633 {
634 {RPCResult::Type::BOOL, "verified",
635 "Whether the node local proof has been locally verified "
636 "or not."},
637 {RPCResult::Type::STR, "verification_status",
638 "The proof verification status. Only available if the "
639 "\"verified\" flag is false."},
640 {RPCResult::Type::STR_HEX, "proofid",
641 "The node local proof id."},
642 {RPCResult::Type::STR_HEX, "limited_proofid",
643 "The node local limited proof id."},
644 {RPCResult::Type::STR_HEX, "master",
645 "The node local proof master public key."},
646 {RPCResult::Type::STR, "payout_address",
647 "The node local proof payout address. This might be "
648 "omitted if the payout script is not one of P2PK, P2PKH "
649 "or P2SH, in which case decodeavalancheproof can be used "
650 "to get more details."},
651 {RPCResult::Type::STR_AMOUNT, "stake_amount",
652 "The node local proof staked amount."},
653 }},
655 "network",
656 "",
657 {
658 {RPCResult::Type::NUM, "proof_count",
659 "The number of valid avalanche proofs we know exist "
660 "(including this node's local proof if applicable)."},
661 {RPCResult::Type::NUM, "connected_proof_count",
662 "The number of avalanche proofs with at least one node "
663 "we are connected to (including this node's local proof "
664 "if applicable)."},
665 {RPCResult::Type::NUM, "dangling_proof_count",
666 "The number of avalanche proofs with no node attached."},
667 {RPCResult::Type::NUM, "finalized_proof_count",
668 "The number of known avalanche proofs that have been "
669 "finalized by avalanche."},
670 {RPCResult::Type::NUM, "conflicting_proof_count",
671 "The number of known avalanche proofs that conflict with "
672 "valid proofs."},
673 {RPCResult::Type::NUM, "immature_proof_count",
674 "The number of known avalanche proofs that have immature "
675 "utxos."},
676 {RPCResult::Type::STR_AMOUNT, "total_stake_amount",
677 "The total staked amount over all the valid proofs in " +
679 " (including this node's local proof if "
680 "applicable)."},
681 {RPCResult::Type::STR_AMOUNT, "connected_stake_amount",
682 "The total staked amount over all the connected proofs "
683 "in " +
685 " (including this node's local proof if "
686 "applicable)."},
687 {RPCResult::Type::STR_AMOUNT, "dangling_stake_amount",
688 "The total staked amount over all the dangling proofs "
689 "in " +
691 " (including this node's local proof if "
692 "applicable)."},
693 {RPCResult::Type::STR_AMOUNT, "immature_stake_amount",
694 "The total staked amount over all the immature proofs "
695 "in " +
697 " (including this node's local proof if "
698 "applicable)."},
699 {RPCResult::Type::NUM, "node_count",
700 "The number of avalanche nodes we are connected to "
701 "(including this node if a local proof is set)."},
702 {RPCResult::Type::NUM, "connected_node_count",
703 "The number of avalanche nodes associated with an "
704 "avalanche proof (including this node if a local proof "
705 "is set)."},
706 {RPCResult::Type::NUM, "pending_node_count",
707 "The number of avalanche nodes pending for a proof."},
708 }},
709 },
710 },
711 RPCExamples{HelpExampleCli("getavalancheinfo", "") +
712 HelpExampleRpc("getavalancheinfo", "")},
713 [&](const RPCHelpMan &self, const Config &config,
714 const JSONRPCRequest &request) -> UniValue {
715 NodeContext &node = EnsureAnyNodeContext(request.context);
717
719 ret.pushKV("ready_to_poll", avalanche.isQuorumEstablished());
720
721 auto localProof = avalanche.getLocalProof();
722 if (localProof != nullptr) {
724 const bool verified = avalanche.withPeerManager(
725 [&](const avalanche::PeerManager &pm) {
726 const avalanche::ProofId &proofid = localProof->getId();
727 return pm.isBoundToPeer(proofid);
728 });
729 local.pushKV("verified", verified);
730 const bool sharing = avalanche.canShareLocalProof();
731 if (!verified) {
733 avalanche.getLocalProofRegistrationState();
734 // If the local proof is not registered but the state is
735 // valid, no registration attempt occurred yet.
736 local.pushKV("verification_status",
737 state.IsValid()
738 ? (sharing ? "pending verification"
739 : "pending inbound connections")
740 : state.GetRejectReason());
741 }
742 local.pushKV("proofid", localProof->getId().ToString());
743 local.pushKV("limited_proofid",
744 localProof->getLimitedId().ToString());
745 local.pushKV("master", HexStr(localProof->getMaster()));
746 CTxDestination destination;
747 if (ExtractDestination(localProof->getPayoutScript(),
748 destination)) {
749 local.pushKV("payout_address",
750 EncodeDestination(destination, config));
751 }
752 local.pushKV("stake_amount", localProof->getStakedAmount());
753 ret.pushKV("local", local);
754 }
755
756 avalanche.withPeerManager([&](avalanche::PeerManager &pm) {
757 UniValue network(UniValue::VOBJ);
758
759 uint64_t proofCount{0};
760 uint64_t connectedProofCount{0};
761 uint64_t finalizedProofCount{0};
762 uint64_t connectedNodeCount{0};
763 Amount totalStakes = Amount::zero();
764 Amount connectedStakes = Amount::zero();
765
766 pm.forEachPeer([&](const avalanche::Peer &peer) {
767 CHECK_NONFATAL(peer.proof != nullptr);
768
769 const bool isLocalProof =
770 localProof &&
771 peer.proof->getId() == localProof->getId();
772
773 ++proofCount;
774 const Amount proofStake = peer.proof->getStakedAmount();
775
776 totalStakes += proofStake;
777
778 if (peer.hasFinalized) {
779 ++finalizedProofCount;
780 }
781
782 if (peer.node_count > 0 || isLocalProof) {
783 ++connectedProofCount;
784 connectedStakes += proofStake;
785 }
786
787 connectedNodeCount += peer.node_count + isLocalProof;
788 });
789
790 Amount immatureStakes = Amount::zero();
792 [&](const avalanche::ProofRef &proof) {
793 immatureStakes += proof->getStakedAmount();
794 });
795
796 network.pushKV("proof_count", proofCount);
797 network.pushKV("connected_proof_count", connectedProofCount);
798 network.pushKV("dangling_proof_count",
799 proofCount - connectedProofCount);
800
801 network.pushKV("finalized_proof_count", finalizedProofCount);
802 network.pushKV(
803 "conflicting_proof_count",
804 uint64_t(pm.getConflictingProofPool().countProofs()));
805 network.pushKV(
806 "immature_proof_count",
807 uint64_t(pm.getImmatureProofPool().countProofs()));
808
809 network.pushKV("total_stake_amount", totalStakes);
810 network.pushKV("connected_stake_amount", connectedStakes);
811 network.pushKV("dangling_stake_amount",
812 totalStakes - connectedStakes);
813 network.pushKV("immature_stake_amount", immatureStakes);
814
815 const uint64_t pendingNodes = pm.getPendingNodeCount();
816 network.pushKV("node_count", connectedNodeCount + pendingNodes);
817 network.pushKV("connected_node_count", connectedNodeCount);
818 network.pushKV("pending_node_count", pendingNodes);
819
820 ret.pushKV("network", network);
821 });
822
823 return ret;
824 },
825 };
826}
827
829 return RPCHelpMan{
830 "getavalanchepeerinfo",
831 "Returns data about an avalanche peer as a json array of objects. If "
832 "no proofid is provided, returns data about all the peers.\n",
833 {
835 "The hex encoded avalanche proof identifier."},
836 },
837 RPCResult{
839 "",
840 "",
841 {{
843 "",
844 "",
845 {{
846 {RPCResult::Type::NUM, "avalanche_peerid",
847 "The avalanche internal peer identifier"},
848 {RPCResult::Type::NUM, "availability_score",
849 "DEPRECATED: The agreggated availability score of this "
850 "peer's nodes. This score is no longer computed starting "
851 "with version 0.30.12 and is always 0. This field is only "
852 "returned if the -deprecatedrpc=peer_availability_score "
853 "option is enabled."},
854 {RPCResult::Type::STR_HEX, "proofid",
855 "The avalanche proof id used by this peer"},
856 {RPCResult::Type::STR_HEX, "proof",
857 "The avalanche proof used by this peer"},
858 {RPCResult::Type::NUM, "nodecount",
859 "The number of nodes for this peer"},
861 "node_list",
862 "",
863 {
864 {RPCResult::Type::NUM, "nodeid",
865 "Node id, as returned by getpeerinfo"},
866 }},
867 }},
868 }},
869 },
870 RPCExamples{HelpExampleCli("getavalanchepeerinfo", "") +
871 HelpExampleCli("getavalanchepeerinfo", "\"proofid\"") +
872 HelpExampleRpc("getavalanchepeerinfo", "") +
873 HelpExampleRpc("getavalanchepeerinfo", "\"proofid\"")},
874 [&](const RPCHelpMan &self, const Config &config,
875 const JSONRPCRequest &request) -> UniValue {
876 NodeContext &node = EnsureAnyNodeContext(request.context);
878 const ArgsManager &argsman = EnsureArgsman(node);
879
880 auto peerToUniv = [&argsman](const avalanche::PeerManager &pm,
881 const avalanche::Peer &peer) {
883
884 obj.pushKV("avalanche_peerid", uint64_t(peer.peerid));
885 if (IsDeprecatedRPCEnabled(argsman,
886 "peer_availability_score")) {
887 obj.pushKV("availability_score", 0);
888 }
889 obj.pushKV("proofid", peer.getProofId().ToString());
890 obj.pushKV("proof", peer.proof->ToHex());
891
893 pm.forEachNode(peer, [&](const avalanche::Node &n) {
894 nodes.push_back(n.nodeid);
895 });
896
897 obj.pushKV("nodecount", uint64_t(peer.node_count));
898 obj.pushKV("node_list", nodes);
899
900 return obj;
901 };
902
904
905 avalanche.withPeerManager([&](const avalanche::PeerManager &pm) {
906 // If a proofid is provided, only return the associated peer
907 if (!request.params[0].isNull()) {
908 const avalanche::ProofId proofid =
909 avalanche::ProofId::fromHex(
910 request.params[0].get_str());
911 if (!pm.isBoundToPeer(proofid)) {
912 throw JSONRPCError(RPC_INVALID_PARAMETER,
913 "Proofid not found");
914 }
915
916 pm.forPeer(proofid, [&](const avalanche::Peer &peer) {
917 ret.push_back(peerToUniv(pm, peer));
918 return true;
919 });
920
921 return;
922 }
923
924 // If no proofid is provided, return all the peers
925 pm.forEachPeer([&](const avalanche::Peer &peer) {
926 ret.push_back(peerToUniv(pm, peer));
927 });
928 });
929
930 return ret;
931 },
932 };
933}
934
936 return RPCHelpMan{
937 "getavalancheproofs",
938 "Returns an object containing all tracked proofids.\n",
939 {},
940 RPCResult{
942 "",
943 "",
944 {
946 "valid",
947 "",
948 {
949 {RPCResult::Type::STR_HEX, "proofid",
950 "Avalanche proof id"},
951 }},
953 "conflicting",
954 "",
955 {
956 {RPCResult::Type::STR_HEX, "proofid",
957 "Avalanche proof id"},
958 }},
960 "immature",
961 "",
962 {
963 {RPCResult::Type::STR_HEX, "proofid",
964 "Avalanche proof id"},
965 }},
966 },
967 },
968 RPCExamples{HelpExampleCli("getavalancheproofs", "") +
969 HelpExampleRpc("getavalancheproofs", "")},
970 [&](const RPCHelpMan &self, const Config &config,
971 const JSONRPCRequest &request) -> UniValue {
972 NodeContext &node = EnsureAnyNodeContext(request.context);
974
976 avalanche.withPeerManager([&](avalanche::PeerManager &pm) {
977 auto appendProofIds = [&ret](const avalanche::ProofPool &pool,
978 const std::string &key) {
979 UniValue arrOut(UniValue::VARR);
980 for (const avalanche::ProofId &proofid :
981 pool.getProofIds()) {
982 arrOut.push_back(proofid.ToString());
983 }
984 ret.pushKV(key, arrOut);
985 };
986
987 appendProofIds(pm.getValidProofPool(), "valid");
988 appendProofIds(pm.getConflictingProofPool(), "conflicting");
989 appendProofIds(pm.getImmatureProofPool(), "immature");
990 });
991
992 return ret;
993 },
994 };
995}
996
998 return RPCHelpMan{
999 "getstakingreward",
1000 "Return a list of possible staking reward winners based on the "
1001 "previous "
1002 "block hash.\n",
1003 {
1005 "The previous block hash, hex encoded."},
1006 {"recompute", RPCArg::Type::BOOL, RPCArg::Default{false},
1007 "Whether to recompute the staking reward winner if there is a "
1008 "cached value."},
1009 },
1010 RPCResult{
1012 "",
1013 "",
1014 {
1016 "winner",
1017 "The winning proof",
1018 {
1019 {RPCResult::Type::STR_HEX, "proofid",
1020 "The winning proofid"},
1021 {RPCResult::Type::STR, "asm", "Decoded payout script"},
1023 "Raw payout script in hex format"},
1024 {RPCResult::Type::STR, "type",
1025 "The output type (e.g. " + GetAllOutputTypes() + ")"},
1026 {RPCResult::Type::NUM, "reqSigs",
1027 "The required signatures"},
1029 "addresses",
1030 "",
1031 {
1032 {RPCResult::Type::STR, "address", "eCash address"},
1033 }},
1034 }},
1035 }},
1036 RPCExamples{HelpExampleRpc("getstakingreward", "<blockhash>")},
1037 [&](const RPCHelpMan &self, const Config &config,
1038 const JSONRPCRequest &request) -> UniValue {
1039 const NodeContext &node = EnsureAnyNodeContext(request.context);
1042
1043 const BlockHash blockhash(
1044 ParseHashV(request.params[0], "blockhash"));
1045
1046 const CBlockIndex *pprev;
1047 {
1048 LOCK(cs_main);
1049 pprev = chainman.m_blockman.LookupBlockIndex(blockhash);
1050 }
1051
1052 if (!pprev) {
1053 throw JSONRPCError(
1055 strprintf("Block not found: %s\n", blockhash.ToString()));
1056 }
1057
1059 config.GetChainParams().GetConsensus(), pprev)) {
1060 throw JSONRPCError(
1062 strprintf(
1063 "Staking rewards are not activated for block %s\n",
1064 blockhash.ToString()));
1065 }
1066
1067 if (!request.params[1].isNull() && request.params[1].get_bool()) {
1068 // Force recompute the staking reward winner by first erasing
1069 // the cached entry if any
1070 avalanche.eraseStakingRewardWinner(blockhash);
1071 }
1072
1073 if (!avalanche.computeStakingReward(pprev)) {
1074 throw JSONRPCError(
1076 strprintf("Unable to determine a staking reward winner "
1077 "for block %s\n",
1078 blockhash.ToString()));
1079 }
1080
1081 std::vector<std::pair<avalanche::ProofId, CScript>> winners;
1082 if (!avalanche.getStakingRewardWinners(blockhash, winners)) {
1083 throw JSONRPCError(
1085 strprintf("Unable to retrieve the staking reward winner "
1086 "for block %s\n",
1087 blockhash.ToString()));
1088 }
1089
1090 UniValue winnersArr(UniValue::VARR);
1091 for (auto &winner : winners) {
1092 UniValue stakingRewardsObj(UniValue::VOBJ);
1093 ScriptPubKeyToUniv(winner.second, stakingRewardsObj,
1094 /*fIncludeHex=*/true);
1095 stakingRewardsObj.pushKV("proofid", winner.first.GetHex());
1096 winnersArr.push_back(stakingRewardsObj);
1097 }
1098
1099 return winnersArr;
1100 },
1101 };
1102}
1103
1105 return RPCHelpMan{
1106 "hasstakingreward",
1107 "Return true if a staking reward winner exists based on the previous "
1108 "block hash.\n",
1109 {
1111 "The previous block hash, hex encoded."},
1112 },
1114 "Whether staking reward winner has been computed for "
1115 "previous block hash or not."},
1116 RPCExamples{HelpExampleRpc("hasstakingreward", "<blockhash>")},
1117 [&](const RPCHelpMan &self, const Config &config,
1118 const JSONRPCRequest &request) -> UniValue {
1119 const NodeContext &node = EnsureAnyNodeContext(request.context);
1122
1123 const BlockHash blockhash(
1124 ParseHashV(request.params[0], "blockhash"));
1125
1126 const CBlockIndex *pprev;
1127 {
1128 LOCK(cs_main);
1129 pprev = chainman.m_blockman.LookupBlockIndex(blockhash);
1130 }
1131
1132 if (!pprev) {
1133 throw JSONRPCError(
1135 strprintf("Block not found: %s\n", blockhash.ToString()));
1136 }
1137
1139 config.GetChainParams().GetConsensus(), pprev)) {
1140 throw JSONRPCError(
1142 strprintf(
1143 "Staking rewards are not activated for block %s\n",
1144 blockhash.ToString()));
1145 }
1146
1147 std::vector<std::pair<avalanche::ProofId, CScript>> winners;
1148 if (!avalanche.getStakingRewardWinners(blockhash, winners)) {
1149 return false;
1150 }
1151 return winners.size() > 0;
1152 },
1153 };
1154}
1155
1157 return RPCHelpMan{
1158 "setstakingreward",
1159 "Set the staking reward winner for the given previous block hash.\n",
1160 {
1162 "The previous block hash, hex encoded."},
1164 "The payout script for the staking reward, hex encoded."},
1165 {"append", RPCArg::Type::BOOL, RPCArg::Default{false},
1166 "Append to the list of possible winners instead of replacing."},
1167 },
1169 "Whether the payout script was set or not"},
1171 HelpExampleRpc("setstakingreward", "<blockhash> <payout script>")},
1172 [&](const RPCHelpMan &self, const Config &config,
1173 const JSONRPCRequest &request) -> UniValue {
1174 const NodeContext &node = EnsureAnyNodeContext(request.context);
1177
1178 const BlockHash blockhash(
1179 ParseHashV(request.params[0], "blockhash"));
1180
1181 const CBlockIndex *pprev;
1182 {
1183 LOCK(cs_main);
1184 pprev = chainman.m_blockman.LookupBlockIndex(blockhash);
1185 }
1186
1187 if (!pprev) {
1188 throw JSONRPCError(
1190 strprintf("Block not found: %s\n", blockhash.ToString()));
1191 }
1192
1194 config.GetChainParams().GetConsensus(), pprev)) {
1195 throw JSONRPCError(
1197 strprintf(
1198 "Staking rewards are not activated for block %s\n",
1199 blockhash.ToString()));
1200 }
1201
1202 const std::vector<uint8_t> data =
1203 ParseHex(request.params[1].get_str());
1204 CScript payoutScript(data.begin(), data.end());
1205
1206 std::vector<CScript> payoutScripts;
1207
1208 if (!request.params[2].isNull() && request.params[2].get_bool()) {
1209 // Append mode, initialize our list with the current winners
1210 // and the new one will be added to the back of that list. If
1211 // there is no winner the list will remain empty.
1212 avalanche.getStakingRewardWinners(blockhash, payoutScripts);
1213 }
1214
1215 if (std::find(payoutScripts.begin(), payoutScripts.end(),
1216 payoutScript) != payoutScripts.end()) {
1217 throw JSONRPCError(
1219 strprintf(
1220 "Staking rewards winner is already set for block %s\n",
1221 blockhash.ToString()));
1222 }
1223
1224 payoutScripts.push_back(std::move(payoutScript));
1225
1226 // This will return true upon insertion or false upon replacement.
1227 // We want to convey the success of the RPC, so we always return
1228 // true.
1229 avalanche.setStakingRewardWinners(pprev, payoutScripts);
1230 return true;
1231 },
1232 };
1233}
1234
1236 return RPCHelpMan{
1237 "getremoteproofs",
1238 "Get the list of remote proofs for the given node id.\n",
1239 {
1241 "The node identifier."},
1242 },
1243 RPCResult{
1245 "proofs",
1246 "",
1247 {{
1249 "proof",
1250 "",
1251 {{
1252 {RPCResult::Type::STR_HEX, "proofid",
1253 "The hex encoded proof identifier."},
1254 {RPCResult::Type::BOOL, "present",
1255 "Whether the node has the proof."},
1256 {RPCResult::Type::NUM, "last_update",
1257 "The last time this proof status was updated."},
1258 }},
1259 }},
1260 },
1261 RPCExamples{HelpExampleRpc("getremoteproofs", "<nodeid>")},
1262 [&](const RPCHelpMan &self, const Config &config,
1263 const JSONRPCRequest &request) -> UniValue {
1264 NodeContext &node = EnsureAnyNodeContext(request.context);
1266
1267 const NodeId nodeid = request.params[0].getInt<int64_t>();
1268 auto remoteProofs = avalanche.withPeerManager(
1269 [nodeid](const avalanche::PeerManager &pm) {
1270 return pm.getRemoteProofs(nodeid);
1271 });
1272
1273 UniValue arrOut(UniValue::VARR);
1274
1275 for (const auto &remoteProof : remoteProofs) {
1277 obj.pushKV("proofid", remoteProof.proofid.ToString());
1278 obj.pushKV("present", remoteProof.present);
1279 obj.pushKV("last_update", remoteProof.lastUpdate.count());
1280
1281 arrOut.push_back(obj);
1282 }
1283
1284 return arrOut;
1285 },
1286 };
1287}
1288
1290 return RPCHelpMan{
1291 "getrawavalancheproof",
1292 "Lookup for a known avalanche proof by id.\n",
1293 {
1295 "The hex encoded avalanche proof identifier."},
1296 },
1297 RPCResult{
1299 "",
1300 "",
1301 {{
1302 {RPCResult::Type::STR_HEX, "proof",
1303 "The hex encoded proof matching the identifier."},
1304 {RPCResult::Type::BOOL, "immature",
1305 "Whether the proof has immature utxos."},
1306 {RPCResult::Type::BOOL, "boundToPeer",
1307 "Whether the proof is bound to an avalanche peer."},
1308 {RPCResult::Type::BOOL, "conflicting",
1309 "Whether the proof has a conflicting UTXO with an avalanche "
1310 "peer."},
1311 {RPCResult::Type::BOOL, "finalized",
1312 "Whether the proof is finalized by vote."},
1313 }},
1314 },
1315 RPCExamples{HelpExampleRpc("getrawavalancheproof", "<proofid>")},
1316 [&](const RPCHelpMan &self, const Config &config,
1317 const JSONRPCRequest &request) -> UniValue {
1318 NodeContext &node = EnsureAnyNodeContext(request.context);
1320
1321 const avalanche::ProofId proofid =
1322 avalanche::ProofId::fromHex(request.params[0].get_str());
1323
1324 bool isImmature = false;
1325 bool isBoundToPeer = false;
1326 bool conflicting = false;
1327 bool finalized = false;
1328 auto proof = avalanche.withPeerManager(
1329 [&](const avalanche::PeerManager &pm) {
1330 isImmature = pm.isImmature(proofid);
1331 isBoundToPeer = pm.isBoundToPeer(proofid);
1332 conflicting = pm.isInConflictingPool(proofid);
1333 finalized =
1334 pm.forPeer(proofid, [&](const avalanche::Peer &p) {
1335 return p.hasFinalized;
1336 });
1337 return pm.getProof(proofid);
1338 });
1339
1340 if (!proof) {
1341 throw JSONRPCError(RPC_INVALID_PARAMETER, "Proof not found");
1342 }
1343
1345
1347 ss << *proof;
1348 ret.pushKV("proof", HexStr(ss));
1349 ret.pushKV("immature", isImmature);
1350 ret.pushKV("boundToPeer", isBoundToPeer);
1351 ret.pushKV("conflicting", conflicting);
1352 ret.pushKV("finalized", finalized);
1353
1354 return ret;
1355 },
1356 };
1357}
1358
1360 return RPCHelpMan{
1361 "invalidateavalancheproof",
1362 "Reject a known avalanche proof by id.\n",
1363 {
1365 "The hex encoded avalanche proof identifier."},
1366 },
1367 RPCResult{
1369 "success",
1370 "",
1371 },
1372 RPCExamples{HelpExampleRpc("invalidateavalancheproof", "<proofid>")},
1373 [&](const RPCHelpMan &self, const Config &config,
1374 const JSONRPCRequest &request) -> UniValue {
1375 NodeContext &node = EnsureAnyNodeContext(request.context);
1377
1378 const avalanche::ProofId proofid =
1379 avalanche::ProofId::fromHex(request.params[0].get_str());
1380
1381 avalanche.withPeerManager([&](avalanche::PeerManager &pm) {
1382 if (!pm.exists(proofid) && !pm.isDangling(proofid)) {
1383 throw JSONRPCError(RPC_INVALID_PARAMETER,
1384 "Proof not found");
1385 }
1386
1387 if (!pm.rejectProof(
1388 proofid,
1390 throw JSONRPCError(RPC_INTERNAL_ERROR,
1391 "Failed to reject the proof");
1392 }
1393
1394 pm.setInvalid(proofid);
1395 });
1396
1397 if (avalanche.isRecentlyFinalized(proofid)) {
1398 // If the proof was previously finalized, clear the status.
1399 // Because there is no way to selectively delete an entry from a
1400 // Bloom filter, we have to clear the whole filter which could
1401 // cause extra voting rounds.
1402 avalanche.clearFinalizedItems();
1403 }
1404
1405 return true;
1406 },
1407 };
1408}
1409
1411 return RPCHelpMan{
1412 "isfinalblock",
1413 "Check if a block has been finalized by avalanche votes.\n",
1414 {
1416 "The hash of the block."},
1417 },
1419 "Whether the block has been finalized by avalanche votes."},
1420 RPCExamples{HelpExampleRpc("isfinalblock", "<block hash>") +
1421 HelpExampleCli("isfinalblock", "<block hash>")},
1422 [&](const RPCHelpMan &self, const Config &config,
1423 const JSONRPCRequest &request) -> UniValue {
1424 NodeContext &node = EnsureAnyNodeContext(request.context);
1426
1427 if (!avalanche.isQuorumEstablished()) {
1429 "Avalanche is not ready to poll yet.");
1430 }
1431
1432 ChainstateManager &chainman = EnsureAnyChainman(request.context);
1433 const BlockHash blockhash(
1434 ParseHashV(request.params[0], "blockhash"));
1435 const CBlockIndex *pindex;
1436
1437 {
1438 LOCK(cs_main);
1439 pindex = chainman.m_blockman.LookupBlockIndex(blockhash);
1440
1441 if (!pindex) {
1443 "Block not found");
1444 }
1445 }
1446
1447 return chainman.ActiveChainstate().IsBlockAvalancheFinalized(
1448 pindex);
1449 },
1450 };
1451}
1452
1454 return RPCHelpMan{
1455 "isfinaltransaction",
1456 "Check if a transaction has been finalized by avalanche votes.\n",
1457 {
1459 "The id of the transaction."},
1461 "The block in which to look for the transaction"},
1462 },
1463 RPCResult{
1464 RPCResult::Type::BOOL, "success",
1465 "Whether the transaction has been finalized by avalanche votes."},
1466 RPCExamples{HelpExampleRpc("isfinaltransaction", "<txid> <blockhash>") +
1467 HelpExampleCli("isfinaltransaction", "<txid> <blockhash>")},
1468 [&](const RPCHelpMan &self, const Config &config,
1469 const JSONRPCRequest &request) -> UniValue {
1470 const NodeContext &node = EnsureAnyNodeContext(request.context);
1472 const CTxMemPool &mempool = EnsureMemPool(node);
1474
1475 const TxId txid = TxId(ParseHashV(request.params[0], "txid"));
1476 CBlockIndex *pindex = nullptr;
1477
1478 if (!request.params[1].isNull()) {
1479 const BlockHash blockhash(
1480 ParseHashV(request.params[1], "blockhash"));
1481
1482 LOCK(cs_main);
1483 pindex = chainman.m_blockman.LookupBlockIndex(blockhash);
1484 if (!pindex) {
1486 "Block not found");
1487 }
1488 }
1489
1490 bool f_txindex_ready = false;
1491 if (g_txindex && !pindex) {
1492 f_txindex_ready = g_txindex->BlockUntilSyncedToCurrentChain();
1493 }
1494
1495 BlockHash hash_block;
1497 pindex, &mempool, txid, hash_block, chainman.m_blockman);
1498
1499 if (!avalanche.isQuorumEstablished()) {
1501 "Avalanche is not ready to poll yet.");
1502 }
1503
1504 if (!tx) {
1505 std::string errmsg;
1506 if (pindex) {
1507 if (WITH_LOCK(::cs_main,
1508 return !pindex->nStatus.hasData())) {
1510 "Block data not downloaded yet.");
1511 }
1512 errmsg = "No such transaction found in the provided block.";
1513 } else if (!g_txindex) {
1514 errmsg = "No such transaction. Use -txindex or provide a "
1515 "block hash to enable blockchain transaction "
1516 "queries.";
1517 } else if (!f_txindex_ready) {
1518 errmsg = "No such transaction. Blockchain transactions are "
1519 "still in the process of being indexed.";
1520 } else {
1521 errmsg = "No such mempool or blockchain transaction.";
1522 }
1524 }
1525
1526 if (!pindex) {
1527 LOCK(cs_main);
1528 pindex = chainman.m_blockman.LookupBlockIndex(hash_block);
1529 }
1530
1531 if (!tx) {
1532 // Tx not found, we should have raised an error at this stage
1533 return false;
1534 }
1535
1536 if (mempool.isAvalancheFinalized(txid)) {
1537 // The transaction is finalized
1538 return true;
1539 }
1540
1541 // Return true if the tx is in a finalized block
1542 return !node.mempool->exists(txid) &&
1543 chainman.ActiveChainstate().IsBlockAvalancheFinalized(
1544 pindex);
1545 },
1546 };
1547}
1548
1550 return RPCHelpMan{
1551 "reconsideravalancheproof",
1552 "Reconsider a known avalanche proof.\n",
1553 {
1555 "The hex encoded avalanche proof."},
1556 },
1557 RPCResult{
1559 "success",
1560 "Whether the proof has been successfully registered.",
1561 },
1562 RPCExamples{HelpExampleRpc("reconsideravalancheproof", "<proof hex>")},
1563 [&](const RPCHelpMan &self, const Config &config,
1564 const JSONRPCRequest &request) -> UniValue {
1565 auto proof = RCUPtr<avalanche::Proof>::make();
1566
1567 NodeContext &node = EnsureAnyNodeContext(request.context);
1569
1570 // Verify the proof. Note that this is redundant with the
1571 // verification done when adding the proof to the pool, but we get a
1572 // chance to give a better error message.
1573 verifyProofOrThrow(node, *proof, request.params[0].get_str());
1574
1575 // There is no way to selectively clear the invalidation status of
1576 // a single proof, so we clear the whole Bloom filter. This could
1577 // cause extra voting rounds.
1578 avalanche.withPeerManager([&](avalanche::PeerManager &pm) {
1579 if (pm.isInvalid(proof->getId())) {
1580 pm.clearAllInvalid();
1581 }
1582 });
1583
1584 // Add the proof to the pool if we don't have it already. Since the
1585 // proof verification has already been done, a failure likely
1586 // indicates that there already is a proof with conflicting utxos.
1588 if (!registerProofIfNeeded(avalanche, proof, state)) {
1590 strprintf("%s (%s)\n",
1591 state.GetRejectReason(),
1592 state.GetDebugMessage()));
1593 }
1594
1595 return avalanche.withPeerManager(
1596 [&](const avalanche::PeerManager &pm) {
1597 return pm.isBoundToPeer(proof->getId());
1598 });
1599 },
1600 };
1601}
1602
1604 return RPCHelpMan{
1605 "sendavalancheproof",
1606 "Broadcast an avalanche proof.\n",
1607 {
1609 "The avalanche proof to broadcast."},
1610 },
1612 "Whether the proof was sent successfully or not."},
1613 RPCExamples{HelpExampleRpc("sendavalancheproof", "<proof>")},
1614 [&](const RPCHelpMan &self, const Config &config,
1615 const JSONRPCRequest &request) -> UniValue {
1616 auto proof = RCUPtr<avalanche::Proof>::make();
1617
1618 NodeContext &node = EnsureAnyNodeContext(request.context);
1620
1621 // Verify the proof. Note that this is redundant with the
1622 // verification done when adding the proof to the pool, but we get a
1623 // chance to give a better error message.
1624 verifyProofOrThrow(node, *proof, request.params[0].get_str());
1625
1626 // Add the proof to the pool if we don't have it already. Since the
1627 // proof verification has already been done, a failure likely
1628 // indicates that there already is a proof with conflicting utxos.
1629 const avalanche::ProofId &proofid = proof->getId();
1631 if (!registerProofIfNeeded(avalanche, proof, state)) {
1633 strprintf("%s (%s)\n",
1634 state.GetRejectReason(),
1635 state.GetDebugMessage()));
1636 }
1637
1638 avalanche.withPeerManager([&](avalanche::PeerManager &pm) {
1639 pm.addUnbroadcastProof(proofid);
1640 });
1641
1642 if (node.peerman) {
1643 node.peerman->RelayProof(proofid);
1644 }
1645
1646 return true;
1647 },
1648 };
1649}
1650
1652 return RPCHelpMan{
1653 "verifyavalancheproof",
1654 "Verify an avalanche proof is valid and return the error otherwise.\n",
1655 {
1657 "Proof to verify."},
1658 },
1660 "Whether the proof is valid or not."},
1661 RPCExamples{HelpExampleRpc("verifyavalancheproof", "\"<proof>\"")},
1662 [&](const RPCHelpMan &self, const Config &config,
1663 const JSONRPCRequest &request) -> UniValue {
1664 avalanche::Proof proof;
1665 verifyProofOrThrow(EnsureAnyNodeContext(request.context), proof,
1666 request.params[0].get_str());
1667
1668 return true;
1669 },
1670 };
1671}
1672
1674 return RPCHelpMan{
1675 "verifyavalanchedelegation",
1676 "Verify an avalanche delegation is valid and return the error "
1677 "otherwise.\n",
1678 {
1680 "The avalanche proof delegation to verify."},
1681 },
1683 "Whether the delegation is valid or not."},
1684 RPCExamples{HelpExampleRpc("verifyavalanchedelegation", "\"<proof>\"")},
1685 [&](const RPCHelpMan &self, const Config &config,
1686 const JSONRPCRequest &request) -> UniValue {
1687 avalanche::Delegation delegation;
1688 CPubKey dummy;
1689 verifyDelegationOrThrow(delegation, request.params[0].get_str(),
1690 dummy);
1691
1692 return true;
1693 },
1694 };
1695}
1696
1698 return RPCHelpMan{
1699 "setflakyproof",
1700 "Add or remove a proofid from the flaky list. This means that an "
1701 "additional staking reward winner will be accepted if this proof is "
1702 "the selected one.\n",
1703 {
1705 "The avalanche proof id."},
1707 "Whether to add (true) or remove (false) the proof from the flaky "
1708 "list"},
1709 },
1711 "Whether the addition/removal is successful."},
1712 RPCExamples{HelpExampleRpc("setflakyproof", "\"<proofid>\" true")},
1713 [&](const RPCHelpMan &self, const Config &config,
1714 const JSONRPCRequest &request) -> UniValue {
1715 NodeContext &node = EnsureAnyNodeContext(request.context);
1718
1719 const auto proofid =
1720 avalanche::ProofId::fromHex(request.params[0].get_str());
1721 const bool addNotRemove = request.params[1].get_bool();
1722
1723 if (avalanche.withPeerManager(
1724 [&proofid, addNotRemove](avalanche::PeerManager &pm) {
1725 if (addNotRemove) {
1726 return pm.setFlaky(proofid);
1727 }
1728 return pm.unsetFlaky(proofid);
1729 })) {
1730 const CBlockIndex *pprev =
1731 WITH_LOCK(cs_main, return chainman.ActiveTip());
1732 // Force recompute the staking reward winner by first erasing
1733 // the cached entry if any
1734 avalanche.eraseStakingRewardWinner(pprev->GetBlockHash());
1735 return avalanche.computeStakingReward(pprev);
1736 }
1737
1738 return false;
1739 }};
1740}
1741
1743 return RPCHelpMan{
1744 "getflakyproofs",
1745 "List the flaky proofs (set via setflakyproof).\n",
1746 {},
1747 RPCResult{
1749 "flaky_proofs",
1750 "",
1751 {{
1753 "proof",
1754 "",
1755 {{
1756 {RPCResult::Type::STR_HEX, "proofid",
1757 "The hex encoded proof identifier."},
1758 {RPCResult::Type::STR_AMOUNT, "staked_amount",
1759 "The proof stake amount, only present if the proof is "
1760 "known."},
1762 "payout",
1763 "The proof payout script, only present if the proof is "
1764 "known.",
1765 {
1766 {RPCResult::Type::STR, "asm", "Decoded payout script"},
1768 "Raw payout script in hex format"},
1769 {RPCResult::Type::STR, "type",
1770 "The output type (e.g. " + GetAllOutputTypes() + ")"},
1771 {RPCResult::Type::NUM, "reqSigs",
1772 "The required signatures"},
1774 "addresses",
1775 "",
1776 {
1777 {RPCResult::Type::STR, "address",
1778 "eCash address"},
1779 }},
1780 }},
1781 }},
1782 }},
1783 },
1784 RPCExamples{HelpExampleRpc("getflakyproofs", "")},
1785 [&](const RPCHelpMan &self, const Config &config,
1786 const JSONRPCRequest &request) -> UniValue {
1787 NodeContext &node = EnsureAnyNodeContext(request.context);
1789
1790 UniValue flakyProofs(UniValue::VARR);
1791 avalanche.withPeerManager([&flakyProofs](
1793 pm.forEachFlakyProof([&](const avalanche::ProofId &proofid) {
1794 UniValue flakyProof(UniValue::VOBJ);
1795 flakyProof.pushKV("proofid", proofid.GetHex());
1796
1797 const auto proof = pm.getProof(proofid);
1798 if (proof) {
1799 flakyProof.pushKV("staked_amount",
1800 proof->getStakedAmount());
1801 UniValue payout(UniValue::VOBJ);
1802 ScriptPubKeyToUniv(proof->getPayoutScript(), payout,
1803 /*fIncludeHex=*/true);
1804 flakyProof.pushKV("payout", payout);
1805 }
1806
1807 flakyProofs.push_back(flakyProof);
1808 });
1809 });
1810
1811 return flakyProofs;
1812 }};
1813}
1814
1816 return RPCHelpMan{
1817 "getavailabilityscore",
1818 "Return the node availability score.\n",
1819 {
1820 {"nodeid", RPCArg::Type::NUM, RPCArg::Optional::NO, "The node id."},
1821 },
1822 RPCResult{RPCResult::Type::NUM, "availability_score",
1823 "The node availability score (if any)."},
1824 RPCExamples{HelpExampleRpc("getavailabilityscore", "<nodeid>")},
1825 [&](const RPCHelpMan &self, const Config &config,
1826 const JSONRPCRequest &request) -> UniValue {
1827 const NodeContext &node = EnsureAnyNodeContext(request.context);
1828 const CConnman &connman = EnsureConnman(node);
1829
1830 const NodeId nodeid(request.params[0].getInt<int64_t>());
1831
1832 CNodeStats nodeStats;
1833 if (connman.GetNodeStats(nodeid, nodeStats) &&
1834 nodeStats.m_availabilityScore) {
1835 return *nodeStats.m_availabilityScore;
1836 }
1837
1838 return UniValue::VNULL;
1839 },
1840 };
1841}
1842
1844 return RPCHelpMan{
1845 "getstakecontendervote",
1846 "Return the stake contender avalanche vote.\n",
1847 {
1849 "The prevblockhash used to compute the stake contender ID, hex "
1850 "encoded."},
1852 "The proofid used to compute the stake contender ID, hex "
1853 "encoded."},
1854 },
1856 "The vote that would be returned if polled."},
1857 RPCExamples{HelpExampleRpc("getstakecontendervote",
1858 "<prevblockhash> <proofid>")},
1859 [&](const RPCHelpMan &self, const Config &config,
1860 const JSONRPCRequest &request) -> UniValue {
1861 const NodeContext &node = EnsureAnyNodeContext(request.context);
1863
1864 const BlockHash prevblockhash(
1865 ParseHashV(request.params[0], "prevblockhash"));
1866 const avalanche::ProofId proofid(
1867 ParseHashV(request.params[1], "proofid"));
1868 const avalanche::StakeContenderId contenderId(prevblockhash,
1869 proofid);
1870 return avalanche.getStakeContenderStatus(contenderId);
1871 },
1872 };
1873}
1874
1876 // clang-format off
1877 static const CRPCCommand commands[] = {
1878 // category actor (function)
1879 // ----------------- --------------------
1880 { "avalanche", getavalanchekey, },
1881 { "avalanche", addavalanchenode, },
1882 { "avalanche", buildavalancheproof, },
1883 { "avalanche", decodeavalancheproof, },
1884 { "avalanche", delegateavalancheproof, },
1885 { "avalanche", decodeavalanchedelegation, },
1886 { "avalanche", getavalancheinfo, },
1887 { "avalanche", getavalanchepeerinfo, },
1888 { "avalanche", getavalancheproofs, },
1889 { "avalanche", getstakingreward, },
1890 { "hidden", hasstakingreward, },
1891 { "avalanche", setstakingreward, },
1892 { "avalanche", getremoteproofs, },
1893 { "avalanche", getrawavalancheproof, },
1894 { "avalanche", invalidateavalancheproof, },
1895 { "avalanche", isfinalblock, },
1896 { "avalanche", isfinaltransaction, },
1897 { "avalanche", reconsideravalancheproof, },
1898 { "avalanche", sendavalancheproof, },
1899 { "avalanche", verifyavalancheproof, },
1900 { "avalanche", verifyavalanchedelegation, },
1901 { "avalanche", setflakyproof, },
1902 { "avalanche", getflakyproofs, },
1903 { "hidden", getavailabilityscore, },
1904 { "hidden", getstakecontendervote, },
1905 };
1906 // clang-format on
1907
1908 for (const auto &c : commands) {
1909 t.appendCommand(c.name, &c);
1910 }
1911}
static RPCHelpMan buildavalancheproof()
Definition: avalanche.cpp:206
static RPCHelpMan invalidateavalancheproof()
Definition: avalanche.cpp:1359
static RPCHelpMan delegateavalancheproof()
Definition: avalanche.cpp:462
static RPCHelpMan getremoteproofs()
Definition: avalanche.cpp:1235
static RPCHelpMan decodeavalanchedelegation()
Definition: avalanche.cpp:534
static RPCHelpMan sendavalancheproof()
Definition: avalanche.cpp:1603
static RPCHelpMan getavalancheproofs()
Definition: avalanche.cpp:935
static void verifyDelegationOrThrow(avalanche::Delegation &dg, const std::string &dgHex, CPubKey &auth)
Definition: avalanche.cpp:81
static RPCHelpMan getrawavalancheproof()
Definition: avalanche.cpp:1289
static void verifyProofOrThrow(const NodeContext &node, avalanche::Proof &proof, const std::string &proofHex)
Definition: avalanche.cpp:95
void RegisterAvalancheRPCCommands(CRPCTable &t)
Definition: avalanche.cpp:1875
static RPCHelpMan getavalanchekey()
Definition: avalanche.cpp:34
static RPCHelpMan hasstakingreward()
Definition: avalanche.cpp:1104
static RPCHelpMan addavalanchenode()
Definition: avalanche.cpp:121
static CPubKey ParsePubKey(const UniValue &param)
Definition: avalanche.cpp:50
static RPCHelpMan getavailabilityscore()
Definition: avalanche.cpp:1815
static RPCHelpMan getstakecontendervote()
Definition: avalanche.cpp:1843
static RPCHelpMan verifyavalanchedelegation()
Definition: avalanche.cpp:1673
static RPCHelpMan setflakyproof()
Definition: avalanche.cpp:1697
static RPCHelpMan setstakingreward()
Definition: avalanche.cpp:1156
static RPCHelpMan getflakyproofs()
Definition: avalanche.cpp:1742
static RPCHelpMan isfinalblock()
Definition: avalanche.cpp:1410
static RPCHelpMan reconsideravalancheproof()
Definition: avalanche.cpp:1549
static RPCHelpMan isfinaltransaction()
Definition: avalanche.cpp:1453
static RPCHelpMan getstakingreward()
Definition: avalanche.cpp:997
static bool registerProofIfNeeded(const avalanche::Processor &avalanche, avalanche::ProofRef proof, avalanche::ProofRegistrationState &state)
Definition: avalanche.cpp:62
static RPCHelpMan getavalanchepeerinfo()
Definition: avalanche.cpp:828
static RPCHelpMan verifyavalancheproof()
Definition: avalanche.cpp:1651
static RPCHelpMan getavalancheinfo()
Definition: avalanche.cpp:617
static RPCHelpMan decodeavalancheproof()
Definition: avalanche.cpp:337
#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:856
void GetNodeStats(std::vector< CNodeStats > &vstats) const
Definition: net.cpp:3120
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:177
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:460
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:327
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:214
bool isAvalancheFinalized(const TxId &txid) const
Definition: txmempool.h:530
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
Definition: validation.h:1149
SnapshotCompletionResult MaybeCompleteSnapshotValidation(std::function< void(bilingual_str)> shutdown_fnc=[](bilingual_str msg) { AbortNode(msg.original, msg);}) 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:1397
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Definition: validation.h:1287
Definition: config.h:19
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:509
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:513
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:529
void forEachFlakyProof(Callable &&func) const
Definition: peermanager.h:456
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:510
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:190
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: cs_main.cpp:7
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
bool error(const char *fmt, const Args &...args)
Definition: logging.h:263
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.
int64_t NodeId
Definition: nodeid.h:10
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:315
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
@ SER_NETWORK
Definition: serialize.h:152
bool IsDeprecatedRPCEnabled(const ArgsManager &args, const std::string &method)
Definition: server.cpp:407
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
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:287
std::optional< double > m_availabilityScore
Definition: net.h:322
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.
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
NodeContext struct containing references to chain state and connection state.
Definition: context.h:46
#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
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.
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:11