34 "Returns the key used to sign avalanche messages.\n",
42 "Avalanche is not initialized");
51 const std::string keyHex = param.
get_str();
56 strprintf(
"Invalid public key: %s\n", keyHex));
65 if (localProof && localProof->getId() == proof->getId()) {
70 return pm.
getProof(proof->getId()) ||
81 const std::string &dgHex,
CPubKey &auth) {
88 if (!dg.
verify(state, auth)) {
90 "The delegation is invalid: " + state.
ToString());
95 const std::string &proofHex) {
115 "The proof is invalid: " + state.
ToString());
123 "Add a node in the set of peers to poll for avalanche.\n",
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"},
135 "Whether the addition succeeded or not."},
137 HelpExampleRpc(
"addavalanchenode",
"5, \"<pubkey>\", \"<proof>\"")},
141 {UniValue::VNUM, UniValue::VSTR, UniValue::VSTR});
145 "Avalanche is not initialized");
148 const NodeId nodeid = request.params[0].get_int64();
156 if (key != proof->getMaster()) {
157 if (request.params.size() < 4 || request.params[3].isNull()) {
160 "The public key does not match the proof");
170 "The delegation does not match the proof");
176 "The public key does not match the delegation");
182 "The proof has conflicting utxos");
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(
190 pnode->m_avalanche_pubkey = std::move(key);
196 strprintf(
"The node does not exist: %d", nodeid));
201 if (!pm.
addNode(nodeid, proofid)) {
214 "buildavalancheproof",
215 "Build a proof for avalanche's sybil resistance.\n",
218 "The proof's sequence"},
220 "A timestamp indicating when the proof expire"},
222 "The master private key in base58-encoding"},
227 "The stakes to be signed and associated private keys",
233 "A stake to be attached to this proof",
238 "The output number"},
242 "The height at which this UTXO was mined"},
245 "Indicate wether the UTXO is a coinbase"},
248 "private key in base58-encoding"},
257 "A string that is a serialized, hex-encoded proof data."},
259 "0 1234567800 \"<master>\" []")},
262 RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM,
263 UniValue::VSTR, UniValue::VARR});
265 const uint64_t sequence = request.params[0].get_int64();
266 const int64_t expiration = request.params[1].get_int64();
274 request.params[4].get_str(), config.GetChainParams());
278 "Invalid payout address");
285 for (
size_t i = 0; i < stakes.
size(); i++) {
302 "vout cannot be negative");
308 "height must be positive");
314 if (!stake.
exists(
"amount")) {
322 const bool iscoinbase =
329 "Invalid private key");
332 if (!pb.
addUTXO(utxo, amount, uint32_t(height), iscoinbase,
341 return proof->ToHex();
348 "decodeavalancheproof",
349 "Convert a serialized, hex-encoded proof, into JSON object. "
350 "The validity of the proof is not verified.\n",
353 "The proof hex string"},
361 "The proof's sequential number"},
363 "A timestamp indicating when the proof expires"},
366 "The proof signature (base64 encoded)"},
369 "The proof payout script",
373 "Raw payout script in hex format"},
377 "The required signatures"},
386 "A hash of the proof data excluding the master key."},
388 "A hash of the limitedid and master key."},
390 "The total staked amount of this proof in " +
402 "The transaction id"},
405 "The amount in this UTXO"},
407 "The height at which this UTXO was mined"},
409 "Indicate whether the UTXO is a coinbase"},
411 "This UTXO's public key"},
413 "Signature of the proofid with this UTXO's private "
414 "key (base64 encoded)"},
441 result.
pushKV(
"payoutscript", payoutScriptObj);
451 const COutPoint &utxo = s.getStake().getUTXO();
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()));
466 result.
pushKV(
"stakes", stakes);
475 "delegateavalancheproof",
476 "Delegate the avalanche proof to another public key.\n",
479 "The limited id of the proof to be delegated."},
481 "The private key in base58-encoding. Must match the proof master "
482 "public key or the upper level parent delegation public key if "
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."},
491 "A string that is a serialized, hex-encoded delegation."},
494 "\"<limitedproofid>\" \"<privkey>\" \"<pubkey>\"")},
498 {UniValue::VSTR, UniValue::VSTR, UniValue::VSTR});
502 "Avalanche is not initialized");
506 ParseHashV(request.params[0],
"limitedproofid")};
511 "The private key is invalid");
516 std::unique_ptr<avalanche::DelegationBuilder> dgb;
517 if (request.params.size() >= 4 && !request.params[3].isNull()) {
526 "The delegation does not match the proof");
532 "The private key does not match the delegation");
535 dgb = std::make_unique<avalanche::DelegationBuilder>(dg);
537 dgb = std::make_unique<avalanche::DelegationBuilder>(
541 if (!dgb->addLevel(privkey, pubkey)) {
543 "Unable to build the delegation");
555 "decodeavalanchedelegation",
556 "Convert a serialized, hex-encoded avalanche proof delegation, into "
558 "The validity of the delegation is not verified.\n",
561 "The delegation hex string"},
569 "The public key the proof is delegated to."},
571 "The delegated proof master public key."},
573 "The identifier of this delegation."},
575 "A delegated proof data hash excluding the master key."},
577 "A hash of the delegated proof limitedid and master key."},
579 "The number of delegation levels."},
589 "The index of this delegation level."},
591 "This delegated public key for this level"},
593 "Signature of this delegation level (base64 "
599 "\"<hex delegation>\"") +
601 "\"<hex delegation>\"")},
609 delegation, request.params[0].get_str(),
error)) {
617 result.
pushKV(
"limitedid",
622 result.
pushKV(
"depth", uint64_t(levels.size()));
625 for (
auto &level : levels) {
631 result.
pushKV(
"levels", levelsArray);
641 "Returns an object containing various state info regarding avalanche "
650 "Whether the node is ready to start polling and voting."},
653 "Only available if -avaproof has been supplied to the node",
656 "Whether the node local proof has been locally verified "
659 "The proof verification status. Only available if the "
660 "\"verified\" flag is false."},
662 "Whether the node local proof is being advertised on the "
665 "The node local proof id."},
667 "The node local limited proof id."},
669 "The node local proof master public key."},
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."},
676 "The node local proof staked amount."},
683 "The number of valid avalanche proofs we know exist "
684 "(including this node's local proof if applicable)."},
686 "The number of avalanche proofs with at least one node "
687 "we are connected to (including this node's local proof "
690 "The number of avalanche proofs with no node attached."},
692 "The number of known avalanche proofs that have been "
693 "finalized by avalanche."},
695 "The number of known avalanche proofs that conflict with "
698 "The number of known avalanche proofs that have immature "
701 "The total staked amount over all the valid proofs in " +
703 " (including this node's local proof if "
706 "The total staked amount over all the connected proofs "
709 " (including this node's local proof if "
712 "The total staked amount over all the dangling proofs "
715 " (including this node's local proof if "
718 "The total staked amount over all the immature proofs "
721 " (including this node's local proof if "
724 "The number of avalanche nodes we are connected to "
725 "(including this node if a local proof is set)."},
727 "The number of avalanche nodes associated with an "
728 "avalanche proof (including this node if a local proof "
731 "The number of avalanche nodes pending for a proof."},
741 "Avalanche is not initialized");
748 if (localProof !=
nullptr) {
750 const bool verified =
g_avalanche->withPeerManager(
755 local.
pushKV(
"verified", verified);
761 local.
pushKV(
"verification_status",
766 local.
pushKV(
"proofid", localProof->getId().ToString());
767 local.
pushKV(
"limited_proofid",
768 localProof->getLimitedId().ToString());
769 local.
pushKV(
"master",
HexStr(localProof->getMaster()));
773 local.
pushKV(
"payout_address",
776 local.
pushKV(
"stake_amount", localProof->getStakedAmount());
777 ret.
pushKV(
"local", local);
783 uint64_t proofCount{0};
784 uint64_t connectedProofCount{0};
785 uint64_t finalizedProofCount{0};
786 uint64_t connectedNodeCount{0};
793 const bool isLocalProof = peer.
proof == localProof;
796 const Amount proofStake = peer.
proof->getStakedAmount();
798 totalStakes += proofStake;
801 ++finalizedProofCount;
805 ++connectedProofCount;
806 connectedStakes += proofStake;
809 connectedNodeCount += peer.
node_count + isLocalProof;
815 immatureStakes += proof->getStakedAmount();
818 network.
pushKV(
"proof_count", proofCount);
819 network.
pushKV(
"connected_proof_count", connectedProofCount);
820 network.
pushKV(
"dangling_proof_count",
821 proofCount - connectedProofCount);
823 network.
pushKV(
"finalized_proof_count", finalizedProofCount);
825 "conflicting_proof_count",
828 "immature_proof_count",
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);
838 network.
pushKV(
"node_count", connectedNodeCount + pendingNodes);
839 network.
pushKV(
"connected_node_count", connectedNodeCount);
840 network.
pushKV(
"pending_node_count", pendingNodes);
842 ret.
pushKV(
"network", network);
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",
857 "The hex encoded avalanche proof identifier."},
869 "The avalanche internal peer identifier"},
871 "The avalanche proof id used by this peer"},
873 "The avalanche proof used by this peer"},
875 "The number of nodes for this peer"},
881 "Node id, as returned by getpeerinfo"},
896 "Avalanche is not initialized");
903 obj.
pushKV(
"avalanche_peerid", uint64_t(peer.peerid));
904 obj.
pushKV(
"proofid", peer.getProofId().ToString());
905 obj.
pushKV(
"proof", peer.proof->ToHex());
912 obj.
pushKV(
"nodecount", uint64_t(peer.node_count));
913 obj.
pushKV(
"node_list", nodes);
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");
932 return ret.push_back(peerToUniv(pm, peer));
951 "getavalancheproofs",
952 "Returns an object containing all tracked proofids.\n",
964 "Avalanche proof id"},
971 "Avalanche proof id"},
978 "Avalanche proof id"},
988 "Avalanche is not initialized");
994 const std::string &key) {
1015 "getrawavalancheproof",
1016 "Lookup for a known avalanche proof by id.\n",
1019 "The hex encoded avalanche proof identifier."},
1027 "The hex encoded proof matching the identifier."},
1029 "Whether the proof has immature utxos."},
1031 "Whether the proof is bound to an avalanche peer."},
1033 "Whether the proof has a conflicting UTXO with an avalanche "
1036 "Whether the proof is finalized by vote."},
1044 "Avalanche is not initialized");
1050 bool isImmature =
false;
1051 bool isBoundToPeer =
false;
1052 bool conflicting =
false;
1053 bool finalized =
false;
1075 ret.
pushKV(
"immature", isImmature);
1076 ret.
pushKV(
"boundToPeer", isBoundToPeer);
1077 ret.
pushKV(
"conflicting", conflicting);
1078 ret.
pushKV(
"finalized", finalized);
1088 "Check if a block has been finalized by avalanche votes.\n",
1091 "The hash of the block."},
1094 "Whether the block has been finalized by avalanche votes."},
1101 "Avalanche is not initialized");
1108 "Avalanche is not ready to poll yet.");
1134 "isfinaltransaction",
1135 "Check if a transaction has been finalized by avalanche votes.\n",
1138 "The id of the transaction."},
1140 "The block in which to look for the transaction"},
1144 "Whether the transaction has been finalized by avalanche votes."},
1151 "Avalanche is not initialized");
1159 if (!request.params[1].isNull()) {
1171 bool f_txindex_ready =
false;
1173 f_txindex_ready =
g_txindex->BlockUntilSyncedToCurrentChain();
1178 pindex,
node.mempool.get(), txid,
1179 config.GetChainParams().GetConsensus(), hash_block);
1185 "Avalanche is not ready to poll yet.");
1192 return !pindex->nStatus.hasData())) {
1195 "Block data not downloaded yet.");
1198 "No such transaction found in the provided block.";
1201 "No such transaction. Use -txindex or provide a "
1203 "hash to enable blockchain transaction queries.";
1204 }
else if (!f_txindex_ready) {
1206 "No such transaction. Blockchain transactions are "
1207 "still in the process of being indexed.";
1209 errmsg =
"No such mempool or blockchain transaction.";
1223 return tx !=
nullptr && !
node.mempool->exists(txid) &&
1232 "sendavalancheproof",
1233 "Broadcast an avalanche proof.\n",
1236 "The avalanche proof to broadcast."},
1239 "Whether the proof was sent successfully or not."},
1245 "Avalanche is not initialized");
1273 node.peerman->RelayProof(proofid);
1283 "verifyavalancheproof",
1284 "Verify an avalanche proof is valid and return the error otherwise.\n",
1287 "Proof to verify."},
1290 "Whether the proof is valid or not."},
1298 request.params[0].get_str());
1307 "verifyavalanchedelegation",
1308 "Verify an avalanche delegation is valid and return the error "
1312 "The avalanche proof delegation to verify."},
1315 "Whether the delegation is valid or not."},
1354 for (
const auto &c : commands) {
std::unique_ptr< avalanche::Processor > g_avalanche
Global avalanche instance.
RecursiveMutex cs_main
Global state.
#define CHECK_NONFATAL(condition)
Identity function.
#define Assert(val)
Identity function.
The block chain is a tree shaped structure starting with the genesis block at the root,...
bool IsBlockAvalancheFinalized(const CBlockIndex *pindex) const
Checks if a block is finalized by avalanche voting.
Double ended buffer combining vector and stream-like interfaces.
An encapsulated secp256k1 private key.
bool IsValid() const
Check whether this private key is valid.
CPubKey GetPubKey() const
Compute the public key from a private key.
Information about a peer.
An outpoint - a combination of a transaction hash and an index n into its vout.
const TxId & GetTxId() const
An encapsulated public key.
static constexpr unsigned int COMPRESSED_SIZE
static constexpr unsigned int SIZE
secp256k1:
void appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
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...
static RCUPtr make(Args &&...args)
Construct a new object that is owned by the pointer.
const std::string & get_str() const
bool push_back(const UniValue &val)
const UniValue & get_array() const
bool exists(const std::string &key) const
bool pushKV(const std::string &key, const UniValue &val)
std::string GetRejectReason() const
std::string GetDebugMessage() const
std::string ToString() const
ProofId getProofId() const
const std::vector< Level > & getLevels() const
static bool FromHex(Delegation &dg, const std::string &dgHex, bilingual_str &errorOut)
bool verify(DelegationState &state, CPubKey &auth) const
const LimitedProofId & getLimitedProofId() const
const CPubKey & getDelegatedPubkey() const
const DelegationId & getId() const
const CPubKey & getProofMaster() const
bool forPeer(const ProofId &proofid, Callable &&func) const
bool addNode(NodeId nodeid, const ProofId &proofid)
Node API.
void addUnbroadcastProof(const ProofId &proofid)
Proof broadcast API.
bool isBoundToPeer(const ProofId &proofid) const
const ProofPool & getConflictingProofPool() const
size_t getPendingNodeCount() const
void forEachPeer(Callable &&func) const
const ProofPool & getValidProofPool() const
void forEachNode(const Peer &peer, Callable &&func) const
const Amount & getStakeUtxoDustThreshold() const
const ProofPool & getImmatureProofPool() const
bool isImmature(const ProofId &proofid) const
bool isInConflictingPool(const ProofId &proofid) const
ProofRef getProof(const ProofId &proofid) const
bool registerProof(const ProofRef &proof, ProofRegistrationState ®istrationState, RegistrationMode mode=RegistrationMode::DEFAULT)
bool addUTXO(COutPoint utxo, Amount amount, uint32_t height, bool is_coinbase, CKey key)
int64_t getExpirationTime() const
static bool FromHex(Proof &proof, const std::string &hexProof, bilingual_str &errorOut)
const ProofId & getId() const
const std::vector< SignedStake > & getStakes() const
bool verify(const Amount &stakeUtxoDustThreshold, ProofValidationState &state) const
Amount getStakedAmount() const
uint64_t getSequence() const
const CScript & getPayoutScript() const
const CPubKey & getMaster() const
const SchnorrSig & getSignature() const
uint32_t getScore() const
const LimitedProofId & getLimitedId() const
Map a proof to each utxo.
size_t countProofs() const
void forEachProof(Callable &&func) const
ProofIdSet getProofIds() const
std::string ToString() const
CBlockIndex * LookupBlockIndex(const BlockHash &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
void ScriptPubKeyToUniv(const CScript &scriptPubKey, UniValue &out, bool fIncludeHex)
std::string EncodeDestination(const CTxDestination &dest, const Config &config)
CTxDestination DecodeDestination(const std::string &addr, const CChainParams ¶ms)
CKey DecodeSecret(const std::string &str)
static constexpr Amount PROOF_DUST_THRESHOLD
Minimum amount per utxo.
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.
std::shared_ptr< const CTransaction > CTransactionRef
UniValue JSONRPCError(int code, const std::string &message)
static RPCHelpMan buildavalancheproof()
static RPCHelpMan delegateavalancheproof()
static RPCHelpMan decodeavalanchedelegation()
static RPCHelpMan sendavalancheproof()
static RPCHelpMan getavalancheproofs()
static void verifyDelegationOrThrow(avalanche::Delegation &dg, const std::string &dgHex, CPubKey &auth)
static RPCHelpMan getrawavalancheproof()
static void verifyProofOrThrow(const NodeContext &node, avalanche::Proof &proof, const std::string &proofHex)
void RegisterAvalancheRPCCommands(CRPCTable &t)
static RPCHelpMan getavalanchekey()
static RPCHelpMan addavalanchenode()
static bool registerProofIfNeeded(avalanche::ProofRef proof, avalanche::ProofRegistrationState &state)
static CPubKey ParsePubKey(const UniValue ¶m)
static RPCHelpMan verifyavalanchedelegation()
static RPCHelpMan isfinalblock()
static RPCHelpMan isfinaltransaction()
static RPCHelpMan getavalanchepeerinfo()
static RPCHelpMan verifyavalancheproof()
static RPCHelpMan getavalancheinfo()
static RPCHelpMan decodeavalancheproof()
@ RPC_MISC_ERROR
General application defined errors std::exception thrown in command handling.
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
@ RPC_DESERIALIZATION_ERROR
Error parsing or validating structure in raw format.
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
void RPCTypeCheck(const UniValue ¶ms, const std::list< UniValueType > &typesExpected, bool fAllowNull)
Type-check arguments; throws JSONRPCError if wrong type given.
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Amount AmountFromValue(const UniValue &value)
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
std::string GetAllOutputTypes()
CPubKey HexToPubKey(const std::string &hex_in)
uint256 ParseHashO(const UniValue &o, std::string strKey)
uint256 ParseHashV(const UniValue &v, std::string strName)
Utilities: convert hex-encoded values (throws error if not hex).
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.
bool IsDeprecatedRPCEnabled(const ArgsManager &args, const std::string &method)
ChainstateManager & EnsureAnyChainman(const std::any &context)
NodeContext & EnsureAnyNodeContext(const std::any &context)
ChainstateManager & EnsureChainman(const NodeContext &node)
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
boost::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
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.
static constexpr Amount zero()
A BlockHash is a unqiue identifier for a block.
static const Currency & get()
@ 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.
@ 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.
static ProofId fromHex(const std::string &str)
NodeContext struct containing references to chain state and connection state.
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
bool error(const char *fmt, const Args &...args)
std::unique_ptr< TxIndex > g_txindex
The global transaction index, used in GetTransaction. May be null.
const UniValue & find_value(const UniValue &obj, const std::string &name)
static const int PROTOCOL_VERSION
network protocol versioning