mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-25 10:43:19 -03:00
net: add short message encoding/decoding support to V2Transport
This commit is contained in:
parent
8da8642062
commit
0be752d9f8
1 changed files with 91 additions and 6 deletions
97
src/net.cpp
97
src/net.cpp
|
@ -913,6 +913,74 @@ size_t V1Transport::GetSendMemoryUsage() const noexcept
|
||||||
return m_message_to_send.GetMemoryUsage();
|
return m_message_to_send.GetMemoryUsage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
/** List of short messages as defined in BIP324, in order.
|
||||||
|
*
|
||||||
|
* Only message types that are actually implemented in this codebase need to be listed, as other
|
||||||
|
* messages get ignored anyway - whether we know how to decode them or not.
|
||||||
|
*/
|
||||||
|
const std::array<std::string, 33> V2_MESSAGE_IDS = {
|
||||||
|
"", // 12 bytes follow encoding the message type like in V1
|
||||||
|
NetMsgType::ADDR,
|
||||||
|
NetMsgType::BLOCK,
|
||||||
|
NetMsgType::BLOCKTXN,
|
||||||
|
NetMsgType::CMPCTBLOCK,
|
||||||
|
NetMsgType::FEEFILTER,
|
||||||
|
NetMsgType::FILTERADD,
|
||||||
|
NetMsgType::FILTERCLEAR,
|
||||||
|
NetMsgType::FILTERLOAD,
|
||||||
|
NetMsgType::GETBLOCKS,
|
||||||
|
NetMsgType::GETBLOCKTXN,
|
||||||
|
NetMsgType::GETDATA,
|
||||||
|
NetMsgType::GETHEADERS,
|
||||||
|
NetMsgType::HEADERS,
|
||||||
|
NetMsgType::INV,
|
||||||
|
NetMsgType::MEMPOOL,
|
||||||
|
NetMsgType::MERKLEBLOCK,
|
||||||
|
NetMsgType::NOTFOUND,
|
||||||
|
NetMsgType::PING,
|
||||||
|
NetMsgType::PONG,
|
||||||
|
NetMsgType::SENDCMPCT,
|
||||||
|
NetMsgType::TX,
|
||||||
|
NetMsgType::GETCFILTERS,
|
||||||
|
NetMsgType::CFILTER,
|
||||||
|
NetMsgType::GETCFHEADERS,
|
||||||
|
NetMsgType::CFHEADERS,
|
||||||
|
NetMsgType::GETCFCHECKPT,
|
||||||
|
NetMsgType::CFCHECKPT,
|
||||||
|
NetMsgType::ADDRV2,
|
||||||
|
// Unimplemented message types that are assigned in BIP324:
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
};
|
||||||
|
|
||||||
|
class V2MessageMap
|
||||||
|
{
|
||||||
|
std::unordered_map<std::string, uint8_t> m_map;
|
||||||
|
|
||||||
|
public:
|
||||||
|
V2MessageMap() noexcept
|
||||||
|
{
|
||||||
|
for (size_t i = 1; i < std::size(V2_MESSAGE_IDS); ++i) {
|
||||||
|
m_map.emplace(V2_MESSAGE_IDS[i], i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<uint8_t> operator()(const std::string& message_name) const noexcept
|
||||||
|
{
|
||||||
|
auto it = m_map.find(message_name);
|
||||||
|
if (it == m_map.end()) return std::nullopt;
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const V2MessageMap V2_MESSAGE_MAP;
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
V2Transport::V2Transport(NodeId nodeid, bool initiating, int type_in, int version_in) noexcept :
|
V2Transport::V2Transport(NodeId nodeid, bool initiating, int type_in, int version_in) noexcept :
|
||||||
m_cipher{}, m_initiating{initiating}, m_nodeid{nodeid},
|
m_cipher{}, m_initiating{initiating}, m_nodeid{nodeid},
|
||||||
m_v1_fallback{nodeid, type_in, version_in}, m_recv_type{type_in}, m_recv_version{version_in},
|
m_v1_fallback{nodeid, type_in, version_in}, m_recv_type{type_in}, m_recv_version{version_in},
|
||||||
|
@ -1299,7 +1367,16 @@ std::optional<std::string> V2Transport::GetMessageType(Span<const uint8_t>& cont
|
||||||
uint8_t first_byte = contents[0];
|
uint8_t first_byte = contents[0];
|
||||||
contents = contents.subspan(1); // Strip first byte.
|
contents = contents.subspan(1); // Strip first byte.
|
||||||
|
|
||||||
if (first_byte != 0) return std::nullopt; // TODO: implement short encoding
|
if (first_byte != 0) {
|
||||||
|
// Short (1 byte) encoding.
|
||||||
|
if (first_byte < std::size(V2_MESSAGE_IDS)) {
|
||||||
|
// Valid short message id.
|
||||||
|
return V2_MESSAGE_IDS[first_byte];
|
||||||
|
} else {
|
||||||
|
// Unknown short message id.
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (contents.size() < CMessageHeader::COMMAND_SIZE) {
|
if (contents.size() < CMessageHeader::COMMAND_SIZE) {
|
||||||
return std::nullopt; // Long encoding needs 12 message type bytes.
|
return std::nullopt; // Long encoding needs 12 message type bytes.
|
||||||
|
@ -1364,11 +1441,19 @@ bool V2Transport::SetMessageToSend(CSerializedNetMsg& msg) noexcept
|
||||||
// buffer to just one, and leaves the responsibility for queueing them up to the caller.
|
// buffer to just one, and leaves the responsibility for queueing them up to the caller.
|
||||||
if (!(m_send_state == SendState::READY && m_send_buffer.empty())) return false;
|
if (!(m_send_state == SendState::READY && m_send_buffer.empty())) return false;
|
||||||
// Construct contents (encoding message type + payload).
|
// Construct contents (encoding message type + payload).
|
||||||
// Initialize with zeroes, and then write the message type string starting at offset 1.
|
std::vector<uint8_t> contents;
|
||||||
// This means contents[0] and the unused positions in contents[1..13] remain 0x00.
|
auto short_message_id = V2_MESSAGE_MAP(msg.m_type);
|
||||||
std::vector<uint8_t> contents(1 + CMessageHeader::COMMAND_SIZE + msg.data.size(), 0);
|
if (short_message_id) {
|
||||||
std::copy(msg.m_type.begin(), msg.m_type.end(), contents.data() + 1);
|
contents.resize(1 + msg.data.size());
|
||||||
std::copy(msg.data.begin(), msg.data.end(), contents.begin() + 1 + CMessageHeader::COMMAND_SIZE);
|
contents[0] = *short_message_id;
|
||||||
|
std::copy(msg.data.begin(), msg.data.end(), contents.begin() + 1);
|
||||||
|
} else {
|
||||||
|
// Initialize with zeroes, and then write the message type string starting at offset 1.
|
||||||
|
// This means contents[0] and the unused positions in contents[1..13] remain 0x00.
|
||||||
|
contents.resize(1 + CMessageHeader::COMMAND_SIZE + msg.data.size(), 0);
|
||||||
|
std::copy(msg.m_type.begin(), msg.m_type.end(), contents.data() + 1);
|
||||||
|
std::copy(msg.data.begin(), msg.data.end(), contents.begin() + 1 + CMessageHeader::COMMAND_SIZE);
|
||||||
|
}
|
||||||
// Construct ciphertext in send buffer.
|
// Construct ciphertext in send buffer.
|
||||||
m_send_buffer.resize(contents.size() + BIP324Cipher::EXPANSION);
|
m_send_buffer.resize(contents.size() + BIP324Cipher::EXPANSION);
|
||||||
m_cipher.Encrypt(MakeByteSpan(contents), {}, false, MakeWritableByteSpan(m_send_buffer));
|
m_cipher.Encrypt(MakeByteSpan(contents), {}, false, MakeWritableByteSpan(m_send_buffer));
|
||||||
|
|
Loading…
Add table
Reference in a new issue