mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-05 14:06:27 -05:00
rpc: add test-only sendmsgtopeer rpc
This rpc can be used when we want a node to send a message, but cannot use a python P2P object, for example for testing of low-level net transport behavior.
This commit is contained in:
parent
6ce5e8f475
commit
a9a1d69391
3 changed files with 51 additions and 0 deletions
|
@ -299,6 +299,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
||||||
{ "getnodeaddresses", 0, "count"},
|
{ "getnodeaddresses", 0, "count"},
|
||||||
{ "addpeeraddress", 1, "port"},
|
{ "addpeeraddress", 1, "port"},
|
||||||
{ "addpeeraddress", 2, "tried"},
|
{ "addpeeraddress", 2, "tried"},
|
||||||
|
{ "sendmsgtopeer", 0, "peer_id" },
|
||||||
{ "stop", 0, "wait" },
|
{ "stop", 0, "wait" },
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
|
@ -968,6 +968,54 @@ static RPCHelpMan addpeeraddress()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static RPCHelpMan sendmsgtopeer()
|
||||||
|
{
|
||||||
|
return RPCHelpMan{
|
||||||
|
"sendmsgtopeer",
|
||||||
|
"Send a p2p message to a peer specified by id.\n"
|
||||||
|
"The message type and body must be provided, the message header will be generated.\n"
|
||||||
|
"This RPC is for testing only.",
|
||||||
|
{
|
||||||
|
{"peer_id", RPCArg::Type::NUM, RPCArg::Optional::NO, "The peer to send the message to."},
|
||||||
|
{"msg_type", RPCArg::Type::STR, RPCArg::Optional::NO, strprintf("The message type (maximum length %i)", CMessageHeader::COMMAND_SIZE)},
|
||||||
|
{"msg", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The serialized message body to send, in hex, without a message header"},
|
||||||
|
},
|
||||||
|
RPCResult{RPCResult::Type::OBJ, "", "", std::vector<RPCResult>{}},
|
||||||
|
RPCExamples{
|
||||||
|
HelpExampleCli("sendmsgtopeer", "0 \"addr\" \"ffffff\"") + HelpExampleRpc("sendmsgtopeer", "0 \"addr\" \"ffffff\"")},
|
||||||
|
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
|
||||||
|
const NodeId peer_id{request.params[0].getInt<int64_t>()};
|
||||||
|
const std::string& msg_type{request.params[1].get_str()};
|
||||||
|
if (msg_type.size() > CMessageHeader::COMMAND_SIZE) {
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Error: msg_type too long, max length is %i", CMessageHeader::COMMAND_SIZE));
|
||||||
|
}
|
||||||
|
auto msg{TryParseHex<unsigned char>(request.params[2].get_str())};
|
||||||
|
if (!msg.has_value()) {
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Error parsing input for msg");
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||||
|
CConnman& connman = EnsureConnman(node);
|
||||||
|
|
||||||
|
CSerializedNetMsg msg_ser;
|
||||||
|
msg_ser.data = msg.value();
|
||||||
|
msg_ser.m_type = msg_type;
|
||||||
|
|
||||||
|
bool success = connman.ForNode(peer_id, [&](CNode* node) {
|
||||||
|
connman.PushMessage(node, std::move(msg_ser));
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
throw JSONRPCError(RPC_MISC_ERROR, "Error: Could not send message to peer");
|
||||||
|
}
|
||||||
|
|
||||||
|
UniValue ret{UniValue::VOBJ};
|
||||||
|
return ret;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
void RegisterNetRPCCommands(CRPCTable& t)
|
void RegisterNetRPCCommands(CRPCTable& t)
|
||||||
{
|
{
|
||||||
static const CRPCCommand commands[]{
|
static const CRPCCommand commands[]{
|
||||||
|
@ -986,6 +1034,7 @@ void RegisterNetRPCCommands(CRPCTable& t)
|
||||||
{"network", &getnodeaddresses},
|
{"network", &getnodeaddresses},
|
||||||
{"hidden", &addconnection},
|
{"hidden", &addconnection},
|
||||||
{"hidden", &addpeeraddress},
|
{"hidden", &addpeeraddress},
|
||||||
|
{"hidden", &sendmsgtopeer},
|
||||||
};
|
};
|
||||||
for (const auto& c : commands) {
|
for (const auto& c : commands) {
|
||||||
t.appendCommand(c.name, &c);
|
t.appendCommand(c.name, &c);
|
||||||
|
|
|
@ -158,6 +158,7 @@ const std::vector<std::string> RPC_COMMANDS_SAFE_FOR_FUZZING{
|
||||||
"reconsiderblock",
|
"reconsiderblock",
|
||||||
"scanblocks",
|
"scanblocks",
|
||||||
"scantxoutset",
|
"scantxoutset",
|
||||||
|
"sendmsgtopeer", // when no peers are connected, no p2p message is sent
|
||||||
"sendrawtransaction",
|
"sendrawtransaction",
|
||||||
"setmocktime",
|
"setmocktime",
|
||||||
"setnetworkactive",
|
"setnetworkactive",
|
||||||
|
|
Loading…
Add table
Reference in a new issue