Changeset View
Changeset View
Standalone View
Standalone View
src/rpc/avalanche.cpp
Show First 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | |||||
static bool registerProofIfNeeded(std::shared_ptr<avalanche::Proof> proof) { | static bool registerProofIfNeeded(std::shared_ptr<avalanche::Proof> proof) { | ||||
return g_avalanche->withPeerManager([&](avalanche::PeerManager &pm) { | return g_avalanche->withPeerManager([&](avalanche::PeerManager &pm) { | ||||
return pm.getProof(proof->getId()) || | return pm.getProof(proof->getId()) || | ||||
pm.registerProof(std::move(proof)); | pm.registerProof(std::move(proof)); | ||||
}); | }); | ||||
} | } | ||||
static void verifyDelegationOrThrow(avalanche::Delegation &dg, | |||||
const std::string &dgHex, CPubKey &auth) { | |||||
bilingual_str error; | |||||
if (!avalanche::Delegation::FromHex(dg, dgHex, error)) { | |||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, error.original); | |||||
} | |||||
avalanche::DelegationState state; | |||||
if (!dg.verify(state, auth)) { | |||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | |||||
"The delegation is invalid: " + state.ToString()); | |||||
} | |||||
} | |||||
static UniValue addavalanchenode(const Config &config, | static UniValue addavalanchenode(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
RPCHelpMan{ | RPCHelpMan{ | ||||
"addavalanchenode", | "addavalanchenode", | ||||
"Add a node in the set of peers to poll for avalanche.\n", | "Add a node in the set of peers to poll for avalanche.\n", | ||||
{ | { | ||||
{"nodeid", RPCArg::Type::NUM, RPCArg::Optional::NO, | {"nodeid", RPCArg::Type::NUM, RPCArg::Optional::NO, | ||||
"Node to be added to avalanche."}, | "Node to be added to avalanche."}, | ||||
{"publickey", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | {"publickey", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | ||||
"The public key of the node."}, | "The public key of the node."}, | ||||
{"proof", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | {"proof", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | ||||
"Proof that the node is not a sybil."}, | "Proof that the node is not a sybil."}, | ||||
{"delegation", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, | |||||
"The proof delegation the the node public key"}, | |||||
}, | }, | ||||
RPCResult{RPCResult::Type::BOOL, "success", | RPCResult{RPCResult::Type::BOOL, "success", | ||||
"Whether the addition succeeded or not."}, | "Whether the addition succeeded or not."}, | ||||
RPCExamples{ | RPCExamples{ | ||||
HelpExampleRpc("addavalanchenode", "5, \"<pubkey>\", \"<proof>\"")}, | HelpExampleRpc("addavalanchenode", "5, \"<pubkey>\", \"<proof>\"")}, | ||||
} | } | ||||
.Check(request); | .Check(request); | ||||
Show All 9 Lines | static UniValue addavalanchenode(const Config &config, | ||||
auto proof = std::make_shared<avalanche::Proof>(); | auto proof = std::make_shared<avalanche::Proof>(); | ||||
bilingual_str error; | bilingual_str error; | ||||
if (!avalanche::Proof::FromHex(*proof, request.params[2].get_str(), | if (!avalanche::Proof::FromHex(*proof, request.params[2].get_str(), | ||||
error)) { | error)) { | ||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, error.original); | throw JSONRPCError(RPC_DESERIALIZATION_ERROR, error.original); | ||||
} | } | ||||
const avalanche::ProofId &proofid = proof->getId(); | |||||
if (key != proof->getMaster()) { | if (key != proof->getMaster()) { | ||||
// TODO: we want to provide a proper delegation. | if (request.params.size() < 4 || request.params[3].isNull()) { | ||||
return false; | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"The public key does not match the proof"); | |||||
} | |||||
avalanche::Delegation dg; | |||||
CPubKey auth; | |||||
verifyDelegationOrThrow(dg, request.params[3].get_str(), auth); | |||||
if (dg.getProofId() != proofid) { | |||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | |||||
"The delegation does not match the proof"); | |||||
} | |||||
if (key != auth) { | |||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | |||||
"The public key does not match the delegation"); | |||||
} | |||||
} | } | ||||
const avalanche::ProofId &proofid = proof->getId(); | |||||
if (!registerProofIfNeeded(proof)) { | if (!registerProofIfNeeded(proof)) { | ||||
return false; | return false; | ||||
} | } | ||||
NodeContext &node = EnsureNodeContext(request.context); | NodeContext &node = EnsureNodeContext(request.context); | ||||
if (!node.connman->ForNode(nodeid, [&](CNode *pnode) { | if (!node.connman->ForNode(nodeid, [&](CNode *pnode) { | ||||
// FIXME This is not thread safe, and might cause issues if the | // FIXME This is not thread safe, and might cause issues if the | ||||
// unlikely event the peer sends an avahello message at the same | // unlikely event the peer sends an avahello message at the same | ||||
▲ Show 20 Lines • Show All 258 Lines • ▼ Show 20 Lines | if (!privkey.IsValid()) { | ||||
"The private key is invalid"); | "The private key is invalid"); | ||||
} | } | ||||
const CPubKey pubkey = ParsePubKey(request.params[2]); | const CPubKey pubkey = ParsePubKey(request.params[2]); | ||||
std::unique_ptr<avalanche::DelegationBuilder> dgb; | std::unique_ptr<avalanche::DelegationBuilder> dgb; | ||||
if (request.params.size() >= 4 && !request.params[3].isNull()) { | if (request.params.size() >= 4 && !request.params[3].isNull()) { | ||||
avalanche::Delegation dg; | avalanche::Delegation dg; | ||||
bilingual_str error; | CPubKey auth; | ||||
if (!avalanche::Delegation::FromHex(dg, request.params[3].get_str(), | verifyDelegationOrThrow(dg, request.params[3].get_str(), auth); | ||||
error)) { | |||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, error.original); | |||||
} | |||||
if (dg.getProofId() != | if (dg.getProofId() != | ||||
limitedProofId.computeProofId(dg.getProofMaster())) { | limitedProofId.computeProofId(dg.getProofMaster())) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | throw JSONRPCError(RPC_INVALID_PARAMETER, | ||||
"The delegation does not match the proof"); | "The delegation does not match the proof"); | ||||
} | } | ||||
CPubKey auth; | |||||
avalanche::DelegationState dgState; | |||||
if (!dg.verify(dgState, auth)) { | |||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | |||||
"The delegation is invalid: " + | |||||
dgState.ToString()); | |||||
} | |||||
if (privkey.GetPubKey() != auth) { | if (privkey.GetPubKey() != auth) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"The private key does not match the delegation"); | "The private key does not match the delegation"); | ||||
} | } | ||||
dgb = std::make_unique<avalanche::DelegationBuilder>(dg); | dgb = std::make_unique<avalanche::DelegationBuilder>(dg); | ||||
} else { | } else { | ||||
dgb = std::make_unique<avalanche::DelegationBuilder>( | dgb = std::make_unique<avalanche::DelegationBuilder>( | ||||
▲ Show 20 Lines • Show All 240 Lines • Show Last 20 Lines |