Bitcoin ABC  0.26.3
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 
5 #include <avalanche/avalanche.h>
6 #include <avalanche/delegation.h>
9 #include <avalanche/processor.h>
10 #include <avalanche/proof.h>
11 #include <avalanche/proofbuilder.h>
12 #include <avalanche/validation.h>
13 #include <config.h>
14 #include <core_io.h>
15 #include <index/txindex.h>
16 #include <key_io.h>
17 #include <net_processing.h>
18 #include <node/context.h>
19 #include <rpc/blockchain.h>
20 #include <rpc/server.h>
21 #include <rpc/server_util.h>
22 #include <rpc/util.h>
23 #include <util/strencodings.h>
24 #include <util/translation.h>
25 
26 #include <univalue.h>
27 
29 using node::NodeContext;
30 
32  return RPCHelpMan{
33  "getavalanchekey",
34  "Returns the key used to sign avalanche messages.\n",
35  {},
37  RPCExamples{HelpExampleRpc("getavalanchekey", "")},
38  [&](const RPCHelpMan &self, const Config &config,
39  const JSONRPCRequest &request) -> UniValue {
40  if (!g_avalanche) {
42  "Avalanche is not initialized");
43  }
44 
45  return HexStr(g_avalanche->getSessionPubKey());
46  },
47  };
48 }
49 
50 static 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 
64  auto localProof = g_avalanche->getLocalProof();
65  if (localProof && localProof->getId() == proof->getId()) {
66  return true;
67  }
68 
69  return g_avalanche->withPeerManager([&](avalanche::PeerManager &pm) {
70  return pm.getProof(proof->getId()) ||
71  pm.registerProof(std::move(proof), state);
72  });
73 }
74 
77  return registerProofIfNeeded(std::move(proof), state);
78 }
79 
81  const std::string &dgHex, CPubKey &auth) {
83  if (!avalanche::Delegation::FromHex(dg, dgHex, error)) {
85  }
86 
88  if (!dg.verify(state, auth)) {
90  "The delegation is invalid: " + state.ToString());
91  }
92 }
93 
95  const std::string &proofHex) {
97  if (!avalanche::Proof::FromHex(proof, proofHex, error)) {
99  }
100 
101  Amount stakeUtxoDustThreshold = avalanche::PROOF_DUST_THRESHOLD;
102  if (g_avalanche) {
103  // If Avalanche is enabled, use the configured dust threshold
104  g_avalanche->withPeerManager([&](avalanche::PeerManager &pm) {
105  stakeUtxoDustThreshold = pm.getStakeUtxoDustThreshold();
106  });
107  }
108 
110  {
111  LOCK(cs_main);
112  if (!proof.verify(stakeUtxoDustThreshold, *Assert(node.chainman),
113  state)) {
115  "The proof is invalid: " + state.ToString());
116  }
117  }
118 }
119 
121  return RPCHelpMan{
122  "addavalanchenode",
123  "Add a node in the set of peers to poll for avalanche.\n",
124  {
126  "Node to be added to avalanche."},
128  "The public key of the node."},
130  "Proof that the node is not a sybil."},
132  "The proof delegation the the node public key"},
133  },
134  RPCResult{RPCResult::Type::BOOL, "success",
135  "Whether the addition succeeded or not."},
136  RPCExamples{
137  HelpExampleRpc("addavalanchenode", "5, \"<pubkey>\", \"<proof>\"")},
138  [&](const RPCHelpMan &self, const Config &config,
139  const JSONRPCRequest &request) -> UniValue {
140  RPCTypeCheck(request.params,
141  {UniValue::VNUM, UniValue::VSTR, UniValue::VSTR});
142 
143  if (!g_avalanche) {
145  "Avalanche is not initialized");
146  }
147 
148  const NodeId nodeid = request.params[0].get_int64();
149  CPubKey key = ParsePubKey(request.params[1]);
150 
151  auto proof = RCUPtr<avalanche::Proof>::make();
152  NodeContext &node = EnsureAnyNodeContext(request.context);
153  verifyProofOrThrow(node, *proof, request.params[2].get_str());
154 
155  const avalanche::ProofId &proofid = proof->getId();
156  if (key != proof->getMaster()) {
157  if (request.params.size() < 4 || request.params[3].isNull()) {
158  throw JSONRPCError(
160  "The public key does not match the proof");
161  }
162 
164  CPubKey auth;
165  verifyDelegationOrThrow(dg, request.params[3].get_str(), auth);
166 
167  if (dg.getProofId() != proofid) {
168  throw JSONRPCError(
170  "The delegation does not match the proof");
171  }
172 
173  if (key != auth) {
174  throw JSONRPCError(
176  "The public key does not match the delegation");
177  }
178  }
179 
180  if (!registerProofIfNeeded(proof)) {
182  "The proof has conflicting utxos");
183  }
184 
185  if (!node.connman->ForNode(nodeid, [&](CNode *pnode) {
186  LOCK(pnode->cs_avalanche_pubkey);
187  bool expected = false;
188  if (pnode->m_avalanche_enabled.compare_exchange_strong(
189  expected, true)) {
190  pnode->m_avalanche_pubkey = std::move(key);
191  }
192  return true;
193  })) {
194  throw JSONRPCError(
196  strprintf("The node does not exist: %d", nodeid));
197  }
198 
199  return g_avalanche->withPeerManager(
200  [&](avalanche::PeerManager &pm) {
201  if (!pm.addNode(nodeid, proofid)) {
202  return false;
203  }
204 
205  pm.addUnbroadcastProof(proofid);
206  return true;
207  });
208  },
209  };
210 }
211 
213  return RPCHelpMan{
214  "buildavalancheproof",
215  "Build a proof for avalanche's sybil resistance.\n",
216  {
218  "The proof's sequence"},
219  {"expiration", RPCArg::Type::NUM, RPCArg::Optional::NO,
220  "A timestamp indicating when the proof expire"},
222  "The master private key in base58-encoding"},
223  {
224  "stakes",
227  "The stakes to be signed and associated private keys",
228  {
229  {
230  "stake",
233  "A stake to be attached to this proof",
234  {
235  {"txid", RPCArg::Type::STR_HEX,
236  RPCArg::Optional::NO, "The transaction id"},
238  "The output number"},
239  {"amount", RPCArg::Type::AMOUNT,
240  RPCArg::Optional::NO, "The amount in this UTXO"},
242  "The height at which this UTXO was mined"},
243  {"iscoinbase", RPCArg::Type::BOOL,
244  /* default */ "false",
245  "Indicate wether the UTXO is a coinbase"},
246  {"privatekey", RPCArg::Type::STR,
248  "private key in base58-encoding"},
249  },
250  },
251  },
252  },
253  {"payoutAddress", RPCArg::Type::STR, RPCArg::Optional::NO,
254  "A payout address"},
255  },
257  "A string that is a serialized, hex-encoded proof data."},
258  RPCExamples{HelpExampleRpc("buildavalancheproof",
259  "0 1234567800 \"<master>\" []")},
260  [&](const RPCHelpMan &self, const Config &config,
261  const JSONRPCRequest &request) -> UniValue {
262  RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM,
263  UniValue::VSTR, UniValue::VARR});
264 
265  const uint64_t sequence = request.params[0].get_int64();
266  const int64_t expiration = request.params[1].get_int64();
267 
268  CKey masterKey = DecodeSecret(request.params[2].get_str());
269  if (!masterKey.IsValid()) {
270  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid master key");
271  }
272 
273  CTxDestination payoutAddress = DecodeDestination(
274  request.params[4].get_str(), config.GetChainParams());
275 
276  if (!IsValidDestination(payoutAddress)) {
278  "Invalid payout address");
279  }
280 
281  avalanche::ProofBuilder pb(sequence, expiration, masterKey,
282  GetScriptForDestination(payoutAddress));
283 
284  const UniValue &stakes = request.params[3].get_array();
285  for (size_t i = 0; i < stakes.size(); i++) {
286  const UniValue &stake = stakes[i];
288  stake,
289  {
290  {"txid", UniValue::VSTR},
291  {"vout", UniValue::VNUM},
292  // "amount" is also required but check is done below
293  // due to UniValue::VNUM erroneously not accepting
294  // quoted numerics (which are valid JSON)
295  {"height", UniValue::VNUM},
296  {"privatekey", UniValue::VSTR},
297  });
298 
299  int nOut = find_value(stake, "vout").get_int();
300  if (nOut < 0) {
302  "vout cannot be negative");
303  }
304 
305  const int height = find_value(stake, "height").get_int();
306  if (height < 1) {
308  "height must be positive");
309  }
310 
311  const TxId txid(ParseHashO(stake, "txid"));
312  const COutPoint utxo(txid, nOut);
313 
314  if (!stake.exists("amount")) {
315  throw JSONRPCError(RPC_INVALID_PARAMETER, "Missing amount");
316  }
317 
318  const Amount amount =
319  AmountFromValue(find_value(stake, "amount"));
320 
321  const UniValue &iscbparam = find_value(stake, "iscoinbase");
322  const bool iscoinbase =
323  iscbparam.isNull() ? false : iscbparam.get_bool();
324  CKey key =
325  DecodeSecret(find_value(stake, "privatekey").get_str());
326 
327  if (!key.IsValid()) {
329  "Invalid private key");
330  }
331 
332  if (!pb.addUTXO(utxo, amount, uint32_t(height), iscoinbase,
333  std::move(key))) {
335  "Duplicated stake");
336  }
337  }
338 
339  const avalanche::ProofRef proof = pb.build();
340 
341  return proof->ToHex();
342  },
343  };
344 }
345 
347  return RPCHelpMan{
348  "decodeavalancheproof",
349  "Convert a serialized, hex-encoded proof, into JSON object. "
350  "The validity of the proof is not verified.\n",
351  {
353  "The proof hex string"},
354  },
355  RPCResult{
357  "",
358  "",
359  {
360  {RPCResult::Type::NUM, "sequence",
361  "The proof's sequential number"},
362  {RPCResult::Type::NUM, "expiration",
363  "A timestamp indicating when the proof expires"},
364  {RPCResult::Type::STR_HEX, "master", "The master public key"},
365  {RPCResult::Type::STR, "signature",
366  "The proof signature (base64 encoded)"},
368  "payoutscript",
369  "The proof payout script",
370  {
371  {RPCResult::Type::STR, "asm", "Decoded payout script"},
372  {RPCResult::Type::STR_HEX, "hex",
373  "Raw payout script in hex format"},
374  {RPCResult::Type::STR, "type",
375  "The output type (e.g. " + GetAllOutputTypes() + ")"},
376  {RPCResult::Type::NUM, "reqSigs",
377  "The required signatures"},
379  "addresses",
380  "",
381  {
382  {RPCResult::Type::STR, "address", "eCash address"},
383  }},
384  }},
385  {RPCResult::Type::STR_HEX, "limitedid",
386  "A hash of the proof data excluding the master key."},
387  {RPCResult::Type::STR_HEX, "proofid",
388  "A hash of the limitedid and master key."},
389  {RPCResult::Type::STR_AMOUNT, "staked_amount",
390  "The total staked amount of this proof in " +
391  Currency::get().ticker + "."},
392  {RPCResult::Type::NUM, "score", "The score of this proof."},
394  "stakes",
395  "",
396  {
398  "",
399  "",
400  {
401  {RPCResult::Type::STR_HEX, "txid",
402  "The transaction id"},
403  {RPCResult::Type::NUM, "vout", "The output number"},
404  {RPCResult::Type::STR_AMOUNT, "amount",
405  "The amount in this UTXO"},
406  {RPCResult::Type::NUM, "height",
407  "The height at which this UTXO was mined"},
408  {RPCResult::Type::BOOL, "iscoinbase",
409  "Indicate whether the UTXO is a coinbase"},
410  {RPCResult::Type::STR_HEX, "pubkey",
411  "This UTXO's public key"},
412  {RPCResult::Type::STR, "signature",
413  "Signature of the proofid with this UTXO's private "
414  "key (base64 encoded)"},
415  }},
416  }},
417  }},
418  RPCExamples{HelpExampleCli("decodeavalancheproof", "\"<hex proof>\"") +
419  HelpExampleRpc("decodeavalancheproof", "\"<hex proof>\"")},
420  [&](const RPCHelpMan &self, const Config &config,
421  const JSONRPCRequest &request) -> UniValue {
422  RPCTypeCheck(request.params, {UniValue::VSTR});
423 
424  avalanche::Proof proof;
426  if (!avalanche::Proof::FromHex(proof, request.params[0].get_str(),
427  error)) {
429  }
430 
431  UniValue result(UniValue::VOBJ);
432  result.pushKV("sequence", proof.getSequence());
433  result.pushKV("expiration", proof.getExpirationTime());
434  result.pushKV("master", HexStr(proof.getMaster()));
435  result.pushKV("signature", EncodeBase64(proof.getSignature()));
436 
437  const auto payoutScript = proof.getPayoutScript();
438  UniValue payoutScriptObj(UniValue::VOBJ);
439  ScriptPubKeyToUniv(payoutScript, payoutScriptObj,
440  /* fIncludeHex */ true);
441  result.pushKV("payoutscript", payoutScriptObj);
442 
443  result.pushKV("limitedid", proof.getLimitedId().ToString());
444  result.pushKV("proofid", proof.getId().ToString());
445 
446  result.pushKV("staked_amount", proof.getStakedAmount());
447  result.pushKV("score", uint64_t(proof.getScore()));
448 
449  UniValue stakes(UniValue::VARR);
450  for (const avalanche::SignedStake &s : proof.getStakes()) {
451  const COutPoint &utxo = s.getStake().getUTXO();
452  UniValue stake(UniValue::VOBJ);
453  stake.pushKV("txid", utxo.GetTxId().ToString());
454  stake.pushKV("vout", uint64_t(utxo.GetN()));
455  stake.pushKV("amount", s.getStake().getAmount());
456  stake.pushKV("height", uint64_t(s.getStake().getHeight()));
457  stake.pushKV("iscoinbase", s.getStake().isCoinbase());
458  stake.pushKV("pubkey", HexStr(s.getStake().getPubkey()));
459  // Only PKHash destination is supported, so this is safe
460  stake.pushKV("address",
461  EncodeDestination(PKHash(s.getStake().getPubkey()),
462  config));
463  stake.pushKV("signature", EncodeBase64(s.getSignature()));
464  stakes.push_back(stake);
465  }
466  result.pushKV("stakes", stakes);
467 
468  return result;
469  },
470  };
471 }
472 
474  return RPCHelpMan{
475  "delegateavalancheproof",
476  "Delegate the avalanche proof to another public key.\n",
477  {
478  {"limitedproofid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO,
479  "The limited id of the proof to be delegated."},
480  {"privatekey", RPCArg::Type::STR, RPCArg::Optional::NO,
481  "The private key in base58-encoding. Must match the proof master "
482  "public key or the upper level parent delegation public key if "
483  " supplied."},
485  "The public key to delegate the proof to."},
487  "A string that is the serialized, hex-encoded delegation for the "
488  "proof and which is a parent for the delegation to build."},
489  },
490  RPCResult{RPCResult::Type::STR_HEX, "delegation",
491  "A string that is a serialized, hex-encoded delegation."},
492  RPCExamples{
493  HelpExampleRpc("delegateavalancheproof",
494  "\"<limitedproofid>\" \"<privkey>\" \"<pubkey>\"")},
495  [&](const RPCHelpMan &self, const Config &config,
496  const JSONRPCRequest &request) -> UniValue {
497  RPCTypeCheck(request.params,
498  {UniValue::VSTR, UniValue::VSTR, UniValue::VSTR});
499 
500  if (!g_avalanche) {
502  "Avalanche is not initialized");
503  }
504 
505  avalanche::LimitedProofId limitedProofId{
506  ParseHashV(request.params[0], "limitedproofid")};
507 
508  const CKey privkey = DecodeSecret(request.params[1].get_str());
509  if (!privkey.IsValid()) {
511  "The private key is invalid");
512  }
513 
514  const CPubKey pubkey = ParsePubKey(request.params[2]);
515 
516  std::unique_ptr<avalanche::DelegationBuilder> dgb;
517  if (request.params.size() >= 4 && !request.params[3].isNull()) {
519  CPubKey auth;
520  verifyDelegationOrThrow(dg, request.params[3].get_str(), auth);
521 
522  if (dg.getProofId() !=
523  limitedProofId.computeProofId(dg.getProofMaster())) {
524  throw JSONRPCError(
526  "The delegation does not match the proof");
527  }
528 
529  if (privkey.GetPubKey() != auth) {
530  throw JSONRPCError(
532  "The private key does not match the delegation");
533  }
534 
535  dgb = std::make_unique<avalanche::DelegationBuilder>(dg);
536  } else {
537  dgb = std::make_unique<avalanche::DelegationBuilder>(
538  limitedProofId, privkey.GetPubKey());
539  }
540 
541  if (!dgb->addLevel(privkey, pubkey)) {
543  "Unable to build the delegation");
544  }
545 
547  ss << dgb->build();
548  return HexStr(ss);
549  },
550  };
551 }
552 
554  return RPCHelpMan{
555  "decodeavalanchedelegation",
556  "Convert a serialized, hex-encoded avalanche proof delegation, into "
557  "JSON object. \n"
558  "The validity of the delegation is not verified.\n",
559  {
561  "The delegation hex string"},
562  },
563  RPCResult{
565  "",
566  "",
567  {
568  {RPCResult::Type::STR_HEX, "pubkey",
569  "The public key the proof is delegated to."},
570  {RPCResult::Type::STR_HEX, "proofmaster",
571  "The delegated proof master public key."},
572  {RPCResult::Type::STR_HEX, "delegationid",
573  "The identifier of this delegation."},
574  {RPCResult::Type::STR_HEX, "limitedid",
575  "A delegated proof data hash excluding the master key."},
576  {RPCResult::Type::STR_HEX, "proofid",
577  "A hash of the delegated proof limitedid and master key."},
578  {RPCResult::Type::NUM, "depth",
579  "The number of delegation levels."},
581  "levels",
582  "",
583  {
585  "",
586  "",
587  {
588  {RPCResult::Type::NUM, "index",
589  "The index of this delegation level."},
590  {RPCResult::Type::STR_HEX, "pubkey",
591  "This delegated public key for this level"},
592  {RPCResult::Type::STR, "signature",
593  "Signature of this delegation level (base64 "
594  "encoded)"},
595  }},
596  }},
597  }},
598  RPCExamples{HelpExampleCli("decodeavalanchedelegation",
599  "\"<hex delegation>\"") +
600  HelpExampleRpc("decodeavalanchedelegation",
601  "\"<hex delegation>\"")},
602  [&](const RPCHelpMan &self, const Config &config,
603  const JSONRPCRequest &request) -> UniValue {
604  RPCTypeCheck(request.params, {UniValue::VSTR});
605 
606  avalanche::Delegation delegation;
609  delegation, request.params[0].get_str(), error)) {
611  }
612 
613  UniValue result(UniValue::VOBJ);
614  result.pushKV("pubkey", HexStr(delegation.getDelegatedPubkey()));
615  result.pushKV("proofmaster", HexStr(delegation.getProofMaster()));
616  result.pushKV("delegationid", delegation.getId().ToString());
617  result.pushKV("limitedid",
618  delegation.getLimitedProofId().ToString());
619  result.pushKV("proofid", delegation.getProofId().ToString());
620 
621  auto levels = delegation.getLevels();
622  result.pushKV("depth", uint64_t(levels.size()));
623 
624  UniValue levelsArray(UniValue::VARR);
625  for (auto &level : levels) {
627  obj.pushKV("pubkey", HexStr(level.pubkey));
628  obj.pushKV("signature", EncodeBase64(level.sig));
629  levelsArray.push_back(std::move(obj));
630  }
631  result.pushKV("levels", levelsArray);
632 
633  return result;
634  },
635  };
636 }
637 
639  return RPCHelpMan{
640  "getavalancheinfo",
641  "Returns an object containing various state info regarding avalanche "
642  "networking.\n",
643  {},
644  RPCResult{
646  "",
647  "",
648  {
649  {RPCResult::Type::BOOL, "ready_to_poll",
650  "Whether the node is ready to start polling and voting."},
652  "local",
653  "Only available if -avaproof has been supplied to the node",
654  {
655  {RPCResult::Type::BOOL, "verified",
656  "Whether the node local proof has been locally verified "
657  "or not."},
658  {RPCResult::Type::STR, "verification_status",
659  "The proof verification status. Only available if the "
660  "\"verified\" flag is false."},
661  {RPCResult::Type::BOOL, "sharing",
662  "Whether the node local proof is being advertised on the "
663  "network or not."},
664  {RPCResult::Type::STR_HEX, "proofid",
665  "The node local proof id."},
666  {RPCResult::Type::STR_HEX, "limited_proofid",
667  "The node local limited proof id."},
668  {RPCResult::Type::STR_HEX, "master",
669  "The node local proof master public key."},
670  {RPCResult::Type::STR, "payout_address",
671  "The node local proof payout address. This might be "
672  "omitted if the payout script is not one of P2PK, P2PKH "
673  "or P2SH, in which case decodeavalancheproof can be used "
674  "to get more details."},
675  {RPCResult::Type::STR_AMOUNT, "stake_amount",
676  "The node local proof staked amount."},
677  }},
679  "network",
680  "",
681  {
682  {RPCResult::Type::NUM, "proof_count",
683  "The number of valid avalanche proofs we know exist "
684  "(including this node's local proof if applicable)."},
685  {RPCResult::Type::NUM, "connected_proof_count",
686  "The number of avalanche proofs with at least one node "
687  "we are connected to (including this node's local proof "
688  "if applicable)."},
689  {RPCResult::Type::NUM, "dangling_proof_count",
690  "The number of avalanche proofs with no node attached."},
691  {RPCResult::Type::NUM, "finalized_proof_count",
692  "The number of known avalanche proofs that have been "
693  "finalized by avalanche."},
694  {RPCResult::Type::NUM, "conflicting_proof_count",
695  "The number of known avalanche proofs that conflict with "
696  "valid proofs."},
697  {RPCResult::Type::NUM, "immature_proof_count",
698  "The number of known avalanche proofs that have immature "
699  "utxos."},
700  {RPCResult::Type::STR_AMOUNT, "total_stake_amount",
701  "The total staked amount over all the valid proofs in " +
703  " (including this node's local proof if "
704  "applicable)."},
705  {RPCResult::Type::STR_AMOUNT, "connected_stake_amount",
706  "The total staked amount over all the connected proofs "
707  "in " +
709  " (including this node's local proof if "
710  "applicable)."},
711  {RPCResult::Type::STR_AMOUNT, "dangling_stake_amount",
712  "The total staked amount over all the dangling proofs "
713  "in " +
715  " (including this node's local proof if "
716  "applicable)."},
717  {RPCResult::Type::STR_AMOUNT, "immature_stake_amount",
718  "The total staked amount over all the immature proofs "
719  "in " +
721  " (including this node's local proof if "
722  "applicable)."},
723  {RPCResult::Type::NUM, "node_count",
724  "The number of avalanche nodes we are connected to "
725  "(including this node if a local proof is set)."},
726  {RPCResult::Type::NUM, "connected_node_count",
727  "The number of avalanche nodes associated with an "
728  "avalanche proof (including this node if a local proof "
729  "is set)."},
730  {RPCResult::Type::NUM, "pending_node_count",
731  "The number of avalanche nodes pending for a proof."},
732  }},
733  },
734  },
735  RPCExamples{HelpExampleCli("getavalancheinfo", "") +
736  HelpExampleRpc("getavalancheinfo", "")},
737  [&](const RPCHelpMan &self, const Config &config,
738  const JSONRPCRequest &request) -> UniValue {
739  if (!g_avalanche) {
741  "Avalanche is not initialized");
742  }
743 
745  ret.pushKV("ready_to_poll", g_avalanche->isQuorumEstablished());
746 
747  auto localProof = g_avalanche->getLocalProof();
748  if (localProof != nullptr) {
749  UniValue local(UniValue::VOBJ);
750  const bool verified = g_avalanche->withPeerManager(
751  [&](const avalanche::PeerManager &pm) {
752  const avalanche::ProofId &proofid = localProof->getId();
753  return pm.isBoundToPeer(proofid);
754  });
755  local.pushKV("verified", verified);
756  if (!verified) {
758  g_avalanche->getLocalProofRegistrationState();
759  // If the local proof is not registered but the state is
760  // valid, no registration attempt occurred yet.
761  local.pushKV("verification_status",
762  state.IsValid() ? "pending"
763  : state.GetRejectReason());
764  }
765  local.pushKV("sharing", g_avalanche->canShareLocalProof());
766  local.pushKV("proofid", localProof->getId().ToString());
767  local.pushKV("limited_proofid",
768  localProof->getLimitedId().ToString());
769  local.pushKV("master", HexStr(localProof->getMaster()));
770  CTxDestination destination;
771  if (ExtractDestination(localProof->getPayoutScript(),
772  destination)) {
773  local.pushKV("payout_address",
774  EncodeDestination(destination, config));
775  }
776  local.pushKV("stake_amount", localProof->getStakedAmount());
777  ret.pushKV("local", local);
778  }
779 
780  g_avalanche->withPeerManager([&](avalanche::PeerManager &pm) {
781  UniValue network(UniValue::VOBJ);
782 
783  uint64_t proofCount{0};
784  uint64_t connectedProofCount{0};
785  uint64_t finalizedProofCount{0};
786  uint64_t connectedNodeCount{0};
787  Amount totalStakes = Amount::zero();
788  Amount connectedStakes = Amount::zero();
789 
790  pm.forEachPeer([&](const avalanche::Peer &peer) {
791  CHECK_NONFATAL(peer.proof != nullptr);
792 
793  const bool isLocalProof = peer.proof == localProof;
794 
795  ++proofCount;
796  const Amount proofStake = peer.proof->getStakedAmount();
797 
798  totalStakes += proofStake;
799 
800  if (peer.hasFinalized) {
801  ++finalizedProofCount;
802  }
803 
804  if (peer.node_count > 0 || isLocalProof) {
805  ++connectedProofCount;
806  connectedStakes += proofStake;
807  }
808 
809  connectedNodeCount += peer.node_count + isLocalProof;
810  });
811 
812  Amount immatureStakes = Amount::zero();
814  [&](const avalanche::ProofRef &proof) {
815  immatureStakes += proof->getStakedAmount();
816  });
817 
818  network.pushKV("proof_count", proofCount);
819  network.pushKV("connected_proof_count", connectedProofCount);
820  network.pushKV("dangling_proof_count",
821  proofCount - connectedProofCount);
822 
823  network.pushKV("finalized_proof_count", finalizedProofCount);
824  network.pushKV(
825  "conflicting_proof_count",
826  uint64_t(pm.getConflictingProofPool().countProofs()));
827  network.pushKV(
828  "immature_proof_count",
829  uint64_t(pm.getImmatureProofPool().countProofs()));
830 
831  network.pushKV("total_stake_amount", totalStakes);
832  network.pushKV("connected_stake_amount", connectedStakes);
833  network.pushKV("dangling_stake_amount",
834  totalStakes - connectedStakes);
835  network.pushKV("immature_stake_amount", immatureStakes);
836 
837  const uint64_t pendingNodes = pm.getPendingNodeCount();
838  network.pushKV("node_count", connectedNodeCount + pendingNodes);
839  network.pushKV("connected_node_count", connectedNodeCount);
840  network.pushKV("pending_node_count", pendingNodes);
841 
842  ret.pushKV("network", network);
843  });
844 
845  return ret;
846  },
847  };
848 }
849 
851  return RPCHelpMan{
852  "getavalanchepeerinfo",
853  "Returns data about an avalanche peer as a json array of objects. If "
854  "no proofid is provided, returns data about all the peers.\n",
855  {
857  "The hex encoded avalanche proof identifier."},
858  },
859  RPCResult{
861  "",
862  "",
863  {{
865  "",
866  "",
867  {{
868  {RPCResult::Type::NUM, "avalanche_peerid",
869  "The avalanche internal peer identifier"},
870  {RPCResult::Type::STR_HEX, "proofid",
871  "The avalanche proof id used by this peer"},
872  {RPCResult::Type::STR_HEX, "proof",
873  "The avalanche proof used by this peer"},
874  {RPCResult::Type::NUM, "nodecount",
875  "The number of nodes for this peer"},
877  "node_list",
878  "",
879  {
880  {RPCResult::Type::NUM, "nodeid",
881  "Node id, as returned by getpeerinfo"},
882  }},
883  }},
884  }},
885  },
886  RPCExamples{HelpExampleCli("getavalanchepeerinfo", "") +
887  HelpExampleCli("getavalanchepeerinfo", "\"proofid\"") +
888  HelpExampleRpc("getavalanchepeerinfo", "") +
889  HelpExampleRpc("getavalanchepeerinfo", "\"proofid\"")},
890  [&](const RPCHelpMan &self, const Config &config,
891  const JSONRPCRequest &request) -> UniValue {
892  RPCTypeCheck(request.params, {UniValue::VSTR});
893 
894  if (!g_avalanche) {
896  "Avalanche is not initialized");
897  }
898 
899  auto peerToUniv = [](const avalanche::PeerManager &pm,
900  const avalanche::Peer &peer) {
902 
903  obj.pushKV("avalanche_peerid", uint64_t(peer.peerid));
904  obj.pushKV("proofid", peer.getProofId().ToString());
905  obj.pushKV("proof", peer.proof->ToHex());
906 
907  UniValue nodes(UniValue::VARR);
908  pm.forEachNode(peer, [&](const avalanche::Node &n) {
909  nodes.push_back(n.nodeid);
910  });
911 
912  obj.pushKV("nodecount", uint64_t(peer.node_count));
913  obj.pushKV("node_list", nodes);
914 
915  return obj;
916  };
917 
919 
920  g_avalanche->withPeerManager([&](const avalanche::PeerManager &pm) {
921  // If a proofid is provided, only return the associated peer
922  if (!request.params[0].isNull()) {
923  const avalanche::ProofId proofid =
924  avalanche::ProofId::fromHex(
925  request.params[0].get_str());
926  if (!pm.isBoundToPeer(proofid)) {
927  throw JSONRPCError(RPC_INVALID_PARAMETER,
928  "Proofid not found");
929  }
930 
931  pm.forPeer(proofid, [&](const avalanche::Peer &peer) {
932  return ret.push_back(peerToUniv(pm, peer));
933  });
934 
935  return;
936  }
937 
938  // If no proofid is provided, return all the peers
939  pm.forEachPeer([&](const avalanche::Peer &peer) {
940  ret.push_back(peerToUniv(pm, peer));
941  });
942  });
943 
944  return ret;
945  },
946  };
947 }
948 
950  return RPCHelpMan{
951  "getavalancheproofs",
952  "Returns an object containing all tracked proofids.\n",
953  {},
954  RPCResult{
956  "",
957  "",
958  {
960  "valid",
961  "",
962  {
963  {RPCResult::Type::STR_HEX, "proofid",
964  "Avalanche proof id"},
965  }},
967  "conflicting",
968  "",
969  {
970  {RPCResult::Type::STR_HEX, "proofid",
971  "Avalanche proof id"},
972  }},
974  "immature",
975  "",
976  {
977  {RPCResult::Type::STR_HEX, "proofid",
978  "Avalanche proof id"},
979  }},
980  },
981  },
982  RPCExamples{HelpExampleCli("getavalancheproofs", "") +
983  HelpExampleRpc("getavalancheproofs", "")},
984  [&](const RPCHelpMan &self, const Config &config,
985  const JSONRPCRequest &request) -> UniValue {
986  if (!g_avalanche) {
988  "Avalanche is not initialized");
989  }
990 
992  g_avalanche->withPeerManager([&](avalanche::PeerManager &pm) {
993  auto appendProofIds = [&ret](const avalanche::ProofPool &pool,
994  const std::string &key) {
995  UniValue arrOut(UniValue::VARR);
996  for (const avalanche::ProofId &proofid :
997  pool.getProofIds()) {
998  arrOut.push_back(proofid.ToString());
999  }
1000  ret.pushKV(key, arrOut);
1001  };
1002 
1003  appendProofIds(pm.getValidProofPool(), "valid");
1004  appendProofIds(pm.getConflictingProofPool(), "conflicting");
1005  appendProofIds(pm.getImmatureProofPool(), "immature");
1006  });
1007 
1008  return ret;
1009  },
1010  };
1011 }
1012 
1014  return RPCHelpMan{
1015  "getrawavalancheproof",
1016  "Lookup for a known avalanche proof by id.\n",
1017  {
1019  "The hex encoded avalanche proof identifier."},
1020  },
1021  RPCResult{
1023  "",
1024  "",
1025  {{
1026  {RPCResult::Type::STR_HEX, "proof",
1027  "The hex encoded proof matching the identifier."},
1028  {RPCResult::Type::BOOL, "immature",
1029  "Whether the proof has immature utxos."},
1030  {RPCResult::Type::BOOL, "boundToPeer",
1031  "Whether the proof is bound to an avalanche peer."},
1032  {RPCResult::Type::BOOL, "conflicting",
1033  "Whether the proof has a conflicting UTXO with an avalanche "
1034  "peer."},
1035  {RPCResult::Type::BOOL, "finalized",
1036  "Whether the proof is finalized by vote."},
1037  }},
1038  },
1039  RPCExamples{HelpExampleRpc("getrawavalancheproof", "<proofid>")},
1040  [&](const RPCHelpMan &self, const Config &config,
1041  const JSONRPCRequest &request) -> UniValue {
1042  if (!g_avalanche) {
1044  "Avalanche is not initialized");
1045  }
1046 
1047  const avalanche::ProofId proofid =
1048  avalanche::ProofId::fromHex(request.params[0].get_str());
1049 
1050  bool isImmature = false;
1051  bool isBoundToPeer = false;
1052  bool conflicting = false;
1053  bool finalized = false;
1054  auto proof = g_avalanche->withPeerManager(
1055  [&](const avalanche::PeerManager &pm) {
1056  isImmature = pm.isImmature(proofid);
1057  isBoundToPeer = pm.isBoundToPeer(proofid);
1058  conflicting = pm.isInConflictingPool(proofid);
1059  finalized =
1060  pm.forPeer(proofid, [&](const avalanche::Peer &p) {
1061  return p.hasFinalized;
1062  });
1063  return pm.getProof(proofid);
1064  });
1065 
1066  if (!proof) {
1067  throw JSONRPCError(RPC_INVALID_PARAMETER, "Proof not found");
1068  }
1069 
1070  UniValue ret(UniValue::VOBJ);
1071 
1073  ss << *proof;
1074  ret.pushKV("proof", HexStr(ss));
1075  ret.pushKV("immature", isImmature);
1076  ret.pushKV("boundToPeer", isBoundToPeer);
1077  ret.pushKV("conflicting", conflicting);
1078  ret.pushKV("finalized", finalized);
1079 
1080  return ret;
1081  },
1082  };
1083 }
1084 
1086  return RPCHelpMan{
1087  "isfinalblock",
1088  "Check if a block has been finalized by avalanche votes.\n",
1089  {
1091  "The hash of the block."},
1092  },
1093  RPCResult{RPCResult::Type::BOOL, "success",
1094  "Whether the block has been finalized by avalanche votes."},
1095  RPCExamples{HelpExampleRpc("isfinalblock", "<block hash>") +
1096  HelpExampleCli("isfinalblock", "<block hash>")},
1097  [&](const RPCHelpMan &self, const Config &config,
1098  const JSONRPCRequest &request) -> UniValue {
1099  if (!g_avalanche) {
1101  "Avalanche is not initialized");
1102  }
1103 
1104  // Deprecated since 0.26.2
1105  if (!IsDeprecatedRPCEnabled(gArgs, "isfinalblock_noerror") &&
1106  !g_avalanche->isQuorumEstablished()) {
1108  "Avalanche is not ready to poll yet.");
1109  }
1110 
1111  ChainstateManager &chainman = EnsureAnyChainman(request.context);
1112  const BlockHash blockhash(
1113  ParseHashV(request.params[0], "blockhash"));
1114  const CBlockIndex *pindex;
1115 
1116  {
1117  LOCK(cs_main);
1118  pindex = chainman.m_blockman.LookupBlockIndex(blockhash);
1119 
1120  if (!pindex) {
1122  "Block not found");
1123  }
1124  }
1125 
1126  return chainman.ActiveChainstate().IsBlockAvalancheFinalized(
1127  pindex);
1128  },
1129  };
1130 }
1131 
1133  return RPCHelpMan{
1134  "isfinaltransaction",
1135  "Check if a transaction has been finalized by avalanche votes.\n",
1136  {
1138  "The id of the transaction."},
1140  "The block in which to look for the transaction"},
1141  },
1142  RPCResult{
1143  RPCResult::Type::BOOL, "success",
1144  "Whether the transaction has been finalized by avalanche votes."},
1145  RPCExamples{HelpExampleRpc("isfinaltransaction", "<txid> <blockhash>") +
1146  HelpExampleCli("isfinaltransaction", "<txid> <blockhash>")},
1147  [&](const RPCHelpMan &self, const Config &config,
1148  const JSONRPCRequest &request) -> UniValue {
1149  if (!g_avalanche) {
1151  "Avalanche is not initialized");
1152  }
1153 
1154  const NodeContext &node = EnsureAnyNodeContext(request.context);
1155  ChainstateManager &chainman = EnsureChainman(node);
1156  const TxId txid = TxId(ParseHashV(request.params[0], "txid"));
1157  CBlockIndex *pindex = nullptr;
1158 
1159  if (!request.params[1].isNull()) {
1160  const BlockHash blockhash(
1161  ParseHashV(request.params[1], "blockhash"));
1162 
1163  LOCK(cs_main);
1164  pindex = chainman.m_blockman.LookupBlockIndex(blockhash);
1165  if (!pindex) {
1167  "Block not found");
1168  }
1169  }
1170 
1171  bool f_txindex_ready = false;
1172  if (g_txindex && !pindex) {
1173  f_txindex_ready = g_txindex->BlockUntilSyncedToCurrentChain();
1174  }
1175 
1176  BlockHash hash_block;
1177  const CTransactionRef tx = GetTransaction(
1178  pindex, node.mempool.get(), txid,
1179  config.GetChainParams().GetConsensus(), hash_block);
1180 
1181  // Deprecated since 0.26.2
1182  if (!IsDeprecatedRPCEnabled(gArgs, "isfinaltransaction_noerror")) {
1183  if (!g_avalanche->isQuorumEstablished()) {
1185  "Avalanche is not ready to poll yet.");
1186  }
1187 
1188  if (!tx) {
1189  std::string errmsg;
1190  if (pindex) {
1191  if (WITH_LOCK(::cs_main,
1192  return !pindex->nStatus.hasData())) {
1193  throw JSONRPCError(
1195  "Block data not downloaded yet.");
1196  }
1197  errmsg =
1198  "No such transaction found in the provided block.";
1199  } else if (!g_txindex) {
1200  errmsg =
1201  "No such transaction. Use -txindex or provide a "
1202  "block "
1203  "hash to enable blockchain transaction queries.";
1204  } else if (!f_txindex_ready) {
1205  errmsg =
1206  "No such transaction. Blockchain transactions are "
1207  "still in the process of being indexed.";
1208  } else {
1209  errmsg = "No such mempool or blockchain transaction.";
1210  }
1212  }
1213  }
1214 
1215  if (!pindex) {
1216  LOCK(cs_main);
1217  pindex = chainman.m_blockman.LookupBlockIndex(hash_block);
1218  }
1219 
1220  // The first 2 checks are redundant as we expect to throw a JSON RPC
1221  // error for these cases, but they are almost free so they are kept
1222  // as a safety net.
1223  return tx != nullptr && !node.mempool->exists(txid) &&
1225  pindex);
1226  },
1227  };
1228 }
1229 
1231  return RPCHelpMan{
1232  "sendavalancheproof",
1233  "Broadcast an avalanche proof.\n",
1234  {
1236  "The avalanche proof to broadcast."},
1237  },
1238  RPCResult{RPCResult::Type::BOOL, "success",
1239  "Whether the proof was sent successfully or not."},
1240  RPCExamples{HelpExampleRpc("sendavalancheproof", "<proof>")},
1241  [&](const RPCHelpMan &self, const Config &config,
1242  const JSONRPCRequest &request) -> UniValue {
1243  if (!g_avalanche) {
1245  "Avalanche is not initialized");
1246  }
1247 
1248  auto proof = RCUPtr<avalanche::Proof>::make();
1249  NodeContext &node = EnsureAnyNodeContext(request.context);
1250 
1251  // Verify the proof. Note that this is redundant with the
1252  // verification done when adding the proof to the pool, but we get a
1253  // chance to give a better error message.
1254  verifyProofOrThrow(node, *proof, request.params[0].get_str());
1255 
1256  // Add the proof to the pool if we don't have it already. Since the
1257  // proof verification has already been done, a failure likely
1258  // indicates that there already is a proof with conflicting utxos.
1259  const avalanche::ProofId &proofid = proof->getId();
1261  if (!registerProofIfNeeded(proof, state)) {
1263  strprintf("%s (%s)\n",
1264  state.GetRejectReason(),
1265  state.GetDebugMessage()));
1266  }
1267 
1268  g_avalanche->withPeerManager([&](avalanche::PeerManager &pm) {
1269  pm.addUnbroadcastProof(proofid);
1270  });
1271 
1272  if (node.peerman) {
1273  node.peerman->RelayProof(proofid);
1274  }
1275 
1276  return true;
1277  },
1278  };
1279 }
1280 
1282  return RPCHelpMan{
1283  "verifyavalancheproof",
1284  "Verify an avalanche proof is valid and return the error otherwise.\n",
1285  {
1287  "Proof to verify."},
1288  },
1289  RPCResult{RPCResult::Type::BOOL, "success",
1290  "Whether the proof is valid or not."},
1291  RPCExamples{HelpExampleRpc("verifyavalancheproof", "\"<proof>\"")},
1292  [&](const RPCHelpMan &self, const Config &config,
1293  const JSONRPCRequest &request) -> UniValue {
1294  RPCTypeCheck(request.params, {UniValue::VSTR});
1295 
1296  avalanche::Proof proof;
1297  verifyProofOrThrow(EnsureAnyNodeContext(request.context), proof,
1298  request.params[0].get_str());
1299 
1300  return true;
1301  },
1302  };
1303 }
1304 
1306  return RPCHelpMan{
1307  "verifyavalanchedelegation",
1308  "Verify an avalanche delegation is valid and return the error "
1309  "otherwise.\n",
1310  {
1312  "The avalanche proof delegation to verify."},
1313  },
1314  RPCResult{RPCResult::Type::BOOL, "success",
1315  "Whether the delegation is valid or not."},
1316  RPCExamples{HelpExampleRpc("verifyavalanchedelegation", "\"<proof>\"")},
1317  [&](const RPCHelpMan &self, const Config &config,
1318  const JSONRPCRequest &request) -> UniValue {
1319  RPCTypeCheck(request.params, {UniValue::VSTR});
1320 
1321  avalanche::Delegation delegation;
1322  CPubKey dummy;
1323  verifyDelegationOrThrow(delegation, request.params[0].get_str(),
1324  dummy);
1325 
1326  return true;
1327  },
1328  };
1329 }
1330 
1332  // clang-format off
1333  static const CRPCCommand commands[] = {
1334  // category actor (function)
1335  // ----------------- --------------------
1336  { "avalanche", getavalanchekey, },
1337  { "avalanche", addavalanchenode, },
1338  { "avalanche", buildavalancheproof, },
1339  { "avalanche", decodeavalancheproof, },
1340  { "avalanche", delegateavalancheproof, },
1341  { "avalanche", decodeavalanchedelegation, },
1342  { "avalanche", getavalancheinfo, },
1343  { "avalanche", getavalanchepeerinfo, },
1344  { "avalanche", getavalancheproofs, },
1345  { "avalanche", getrawavalancheproof, },
1346  { "avalanche", isfinalblock, },
1347  { "avalanche", isfinaltransaction, },
1348  { "avalanche", sendavalancheproof, },
1349  { "avalanche", verifyavalancheproof, },
1350  { "avalanche", verifyavalanchedelegation, },
1351  };
1352  // clang-format on
1353 
1354  for (const auto &c : commands) {
1355  t.appendCommand(c.name, &c);
1356  }
1357 }
std::unique_ptr< avalanche::Processor > g_avalanche
Global avalanche instance.
Definition: processor.cpp:34
RecursiveMutex cs_main
Global state.
Definition: validation.cpp:111
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:52
#define Assert(val)
Identity function.
Definition: check.h:65
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: blockindex.h:26
bool IsBlockAvalancheFinalized(const CBlockIndex *pindex) const
Checks if a block is finalized by avalanche voting.
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:197
An encapsulated secp256k1 private key.
Definition: key.h:28
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:94
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:210
Information about a peer.
Definition: net.h:443
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:22
uint32_t GetN() const
Definition: transaction.h:38
const TxId & GetTxId() const
Definition: transaction.h:37
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:183
void appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
Definition: server.cpp:325
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
Definition: validation.h:1046
CChainState & ActiveChainstate() const
The most-work chain.
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Definition: validation.h:1113
Definition: config.h:17
static RCUPtr make(Args &&...args)
Construct a new object that is owned by the pointer.
Definition: rcu.h:112
const std::string & get_str() const
@ VOBJ
Definition: univalue.h:27
@ VSTR
Definition: univalue.h:27
@ VARR
Definition: univalue.h:27
@ VNUM
Definition: univalue.h:27
bool isNull() const
Definition: univalue.h:89
size_t size() const
Definition: univalue.h:80
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
const UniValue & get_array() const
bool exists(const std::string &key) const
Definition: univalue.h:87
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
bool get_bool() const
int get_int() const
bool IsValid() const
Definition: validation.h:120
std::string GetRejectReason() const
Definition: validation.h:124
std::string GetDebugMessage() const
Definition: validation.h:125
std::string ToString() const
Definition: validation.h:126
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 LimitedProofId & getLimitedProofId() const
Definition: delegation.h:61
const CPubKey & getDelegatedPubkey() const
Definition: delegation.cpp:60
const DelegationId & getId() const
Definition: delegation.h:60
const CPubKey & getProofMaster() const
Definition: delegation.h:62
bool forPeer(const ProofId &proofid, Callable &&func) const
Definition: peermanager.h:351
bool addNode(NodeId nodeid, const ProofId &proofid)
Node API.
Definition: peermanager.cpp:18
void addUnbroadcastProof(const ProofId &proofid)
Proof broadcast API.
bool isBoundToPeer(const ProofId &proofid) const
const ProofPool & getConflictingProofPool() const
Definition: peermanager.h:411
size_t getPendingNodeCount() const
Definition: peermanager.h:256
void forEachPeer(Callable &&func) const
Definition: peermanager.h:357
const ProofPool & getValidProofPool() const
Definition: peermanager.h:410
void forEachNode(const Peer &peer, Callable &&func) const
Definition: peermanager.h:282
const Amount & getStakeUtxoDustThreshold() const
Definition: peermanager.h:425
const ProofPool & getImmatureProofPool() const
Definition: peermanager.h:414
bool isImmature(const ProofId &proofid) const
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:163
static bool FromHex(Proof &proof, const std::string &hexProof, bilingual_str &errorOut)
Definition: proof.cpp:50
const ProofId & getId() const
Definition: proof.h:169
const std::vector< SignedStake > & getStakes() const
Definition: proof.h:165
bool verify(const Amount &stakeUtxoDustThreshold, ProofValidationState &state) const
Definition: proof.cpp:110
Amount getStakedAmount() const
Definition: proof.cpp:103
uint64_t getSequence() const
Definition: proof.h:162
const CScript & getPayoutScript() const
Definition: proof.h:166
const CPubKey & getMaster() const
Definition: proof.h:164
const SchnorrSig & getSignature() const
Definition: proof.h:167
uint32_t getScore() const
Definition: proof.h:174
const LimitedProofId & getLimitedId() const
Definition: proof.h:170
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:78
CBlockIndex * LookupBlockIndex(const BlockHash &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
void ScriptPubKeyToUniv(const CScript &scriptPubKey, UniValue &out, bool fIncludeHex)
Definition: core_write.cpp:190
std::string EncodeDestination(const CTxDestination &dest, const Config &config)
Definition: key_io.cpp:170
CTxDestination DecodeDestination(const std::string &addr, const CChainParams &params)
Definition: key_io.cpp:177
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:80
static constexpr Amount PROOF_DUST_THRESHOLD
Minimum amount per utxo.
Definition: proof.h:40
Definition: init.h:28
CTransactionRef GetTransaction(const CBlockIndex *const block_index, const CTxMemPool *const mempool, const TxId &txid, const Consensus::Params &consensusParams, BlockHash &hashBlock)
Return transaction with a given txid.
int64_t NodeId
Definition: nodeid.h:10
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:319
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:52
static RPCHelpMan buildavalancheproof()
Definition: avalanche.cpp:212
static RPCHelpMan delegateavalancheproof()
Definition: avalanche.cpp:473
static RPCHelpMan decodeavalanchedelegation()
Definition: avalanche.cpp:553
static RPCHelpMan sendavalancheproof()
Definition: avalanche.cpp:1230
static RPCHelpMan getavalancheproofs()
Definition: avalanche.cpp:949
static void verifyDelegationOrThrow(avalanche::Delegation &dg, const std::string &dgHex, CPubKey &auth)
Definition: avalanche.cpp:80
static RPCHelpMan getrawavalancheproof()
Definition: avalanche.cpp:1013
static void verifyProofOrThrow(const NodeContext &node, avalanche::Proof &proof, const std::string &proofHex)
Definition: avalanche.cpp:94
void RegisterAvalancheRPCCommands(CRPCTable &t)
Definition: avalanche.cpp:1331
static RPCHelpMan getavalanchekey()
Definition: avalanche.cpp:31
static RPCHelpMan addavalanchenode()
Definition: avalanche.cpp:120
static bool registerProofIfNeeded(avalanche::ProofRef proof, avalanche::ProofRegistrationState &state)
Definition: avalanche.cpp:62
static CPubKey ParsePubKey(const UniValue &param)
Definition: avalanche.cpp:50
static RPCHelpMan verifyavalanchedelegation()
Definition: avalanche.cpp:1305
static RPCHelpMan isfinalblock()
Definition: avalanche.cpp:1085
static RPCHelpMan isfinaltransaction()
Definition: avalanche.cpp:1132
static RPCHelpMan getavalanchepeerinfo()
Definition: avalanche.cpp:850
static RPCHelpMan verifyavalancheproof()
Definition: avalanche.cpp:1281
static RPCHelpMan getavalancheinfo()
Definition: avalanche.cpp:638
static RPCHelpMan decodeavalancheproof()
Definition: avalanche.cpp:346
@ 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
void RPCTypeCheck(const UniValue &params, const std::list< UniValueType > &typesExpected, bool fAllowNull)
Type-check arguments; throws JSONRPCError if wrong type given.
Definition: util.cpp:27
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:178
Amount AmountFromValue(const UniValue &value)
Definition: util.cpp:83
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:195
std::string GetAllOutputTypes()
Definition: util.cpp:333
CPubKey HexToPubKey(const std::string &hex_in)
Definition: util.cpp:219
uint256 ParseHashO(const UniValue &o, std::string strKey)
Definition: util.cpp:118
uint256 ParseHashV(const UniValue &v, std::string strName)
Utilities: convert hex-encoded values (throws error if not hex).
Definition: util.cpp:101
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:54
@ SER_NETWORK
Definition: serialize.h:166
bool IsDeprecatedRPCEnabled(const ArgsManager &args, const std::string &method)
Definition: server.cpp:405
ChainstateManager & EnsureAnyChainman(const std::any &context)
Definition: server_util.cpp:46
NodeContext & EnsureAnyNodeContext(const std::any &context)
Definition: server_util.cpp:19
ChainstateManager & EnsureChainman(const NodeContext &node)
Definition: server_util.cpp:39
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:161
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:263
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:243
boost::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:93
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)
bool IsHex(const std::string &str)
Returns true if each character in str is a hex character, and has an even number of hex digits.
Definition: amount.h:19
static constexpr Amount zero()
Definition: amount.h:42
A BlockHash is a unqiue identifier for a block.
Definition: blockhash.h:13
static const Currency & get()
Definition: amount.cpp:18
std::string ticker
Definition: amount.h:160
@ 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 with default value omitted because they are implicitly clear.
@ 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:22
uint32_t node_count
Definition: peermanager.h:87
ProofRef proof
Definition: peermanager.h:89
static ProofId fromHex(const std::string &str)
Definition: proofid.h:21
Bilingual messages:
Definition: translation.h:17
NodeContext struct containing references to chain state and connection state.
Definition: context.h:38
#define LOCK(cs)
Definition: sync.h:243
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:276
ArgsManager gArgs
Definition: system.cpp:77
bool error(const char *fmt, const Args &...args)
Definition: system.h:46
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1201
std::unique_ptr< TxIndex > g_txindex
The global transaction index, used in GetTransaction. May be null.
Definition: txindex.cpp:17
const UniValue & find_value(const UniValue &obj, const std::string &name)
Definition: univalue.cpp:234
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:11