Skip to content

Commit 0be752d

Browse files
committed
net: add short message encoding/decoding support to V2Transport
1 parent 8da8642 commit 0be752d

File tree

1 file changed

+91
-6
lines changed

1 file changed

+91
-6
lines changed

src/net.cpp

Lines changed: 91 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -913,6 +913,74 @@ size_t V1Transport::GetSendMemoryUsage() const noexcept
913913
return m_message_to_send.GetMemoryUsage();
914914
}
915915

916+
namespace {
917+
918+
/** List of short messages as defined in BIP324, in order.
919+
*
920+
* Only message types that are actually implemented in this codebase need to be listed, as other
921+
* messages get ignored anyway - whether we know how to decode them or not.
922+
*/
923+
const std::array<std::string, 33> V2_MESSAGE_IDS = {
924+
"", // 12 bytes follow encoding the message type like in V1
925+
NetMsgType::ADDR,
926+
NetMsgType::BLOCK,
927+
NetMsgType::BLOCKTXN,
928+
NetMsgType::CMPCTBLOCK,
929+
NetMsgType::FEEFILTER,
930+
NetMsgType::FILTERADD,
931+
NetMsgType::FILTERCLEAR,
932+
NetMsgType::FILTERLOAD,
933+
NetMsgType::GETBLOCKS,
934+
NetMsgType::GETBLOCKTXN,
935+
NetMsgType::GETDATA,
936+
NetMsgType::GETHEADERS,
937+
NetMsgType::HEADERS,
938+
NetMsgType::INV,
939+
NetMsgType::MEMPOOL,
940+
NetMsgType::MERKLEBLOCK,
941+
NetMsgType::NOTFOUND,
942+
NetMsgType::PING,
943+
NetMsgType::PONG,
944+
NetMsgType::SENDCMPCT,
945+
NetMsgType::TX,
946+
NetMsgType::GETCFILTERS,
947+
NetMsgType::CFILTER,
948+
NetMsgType::GETCFHEADERS,
949+
NetMsgType::CFHEADERS,
950+
NetMsgType::GETCFCHECKPT,
951+
NetMsgType::CFCHECKPT,
952+
NetMsgType::ADDRV2,
953+
// Unimplemented message types that are assigned in BIP324:
954+
"",
955+
"",
956+
"",
957+
""
958+
};
959+
960+
class V2MessageMap
961+
{
962+
std::unordered_map<std::string, uint8_t> m_map;
963+
964+
public:
965+
V2MessageMap() noexcept
966+
{
967+
for (size_t i = 1; i < std::size(V2_MESSAGE_IDS); ++i) {
968+
m_map.emplace(V2_MESSAGE_IDS[i], i);
969+
}
970+
}
971+
972+
std::optional<uint8_t> operator()(const std::string& message_name) const noexcept
973+
{
974+
auto it = m_map.find(message_name);
975+
if (it == m_map.end()) return std::nullopt;
976+
return it->second;
977+
}
978+
};
979+
980+
const V2MessageMap V2_MESSAGE_MAP;
981+
982+
} // namespace
983+
916984
V2Transport::V2Transport(NodeId nodeid, bool initiating, int type_in, int version_in) noexcept :
917985
m_cipher{}, m_initiating{initiating}, m_nodeid{nodeid},
918986
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
12991367
uint8_t first_byte = contents[0];
13001368
contents = contents.subspan(1); // Strip first byte.
13011369

1302-
if (first_byte != 0) return std::nullopt; // TODO: implement short encoding
1370+
if (first_byte != 0) {
1371+
// Short (1 byte) encoding.
1372+
if (first_byte < std::size(V2_MESSAGE_IDS)) {
1373+
// Valid short message id.
1374+
return V2_MESSAGE_IDS[first_byte];
1375+
} else {
1376+
// Unknown short message id.
1377+
return std::nullopt;
1378+
}
1379+
}
13031380

13041381
if (contents.size() < CMessageHeader::COMMAND_SIZE) {
13051382
return std::nullopt; // Long encoding needs 12 message type bytes.
@@ -1364,11 +1441,19 @@ bool V2Transport::SetMessageToSend(CSerializedNetMsg& msg) noexcept
13641441
// buffer to just one, and leaves the responsibility for queueing them up to the caller.
13651442
if (!(m_send_state == SendState::READY && m_send_buffer.empty())) return false;
13661443
// Construct contents (encoding message type + payload).
1367-
// Initialize with zeroes, and then write the message type string starting at offset 1.
1368-
// This means contents[0] and the unused positions in contents[1..13] remain 0x00.
1369-
std::vector<uint8_t> contents(1 + CMessageHeader::COMMAND_SIZE + msg.data.size(), 0);
1370-
std::copy(msg.m_type.begin(), msg.m_type.end(), contents.data() + 1);
1371-
std::copy(msg.data.begin(), msg.data.end(), contents.begin() + 1 + CMessageHeader::COMMAND_SIZE);
1444+
std::vector<uint8_t> contents;
1445+
auto short_message_id = V2_MESSAGE_MAP(msg.m_type);
1446+
if (short_message_id) {
1447+
contents.resize(1 + msg.data.size());
1448+
contents[0] = *short_message_id;
1449+
std::copy(msg.data.begin(), msg.data.end(), contents.begin() + 1);
1450+
} else {
1451+
// Initialize with zeroes, and then write the message type string starting at offset 1.
1452+
// This means contents[0] and the unused positions in contents[1..13] remain 0x00.
1453+
contents.resize(1 + CMessageHeader::COMMAND_SIZE + msg.data.size(), 0);
1454+
std::copy(msg.m_type.begin(), msg.m_type.end(), contents.data() + 1);
1455+
std::copy(msg.data.begin(), msg.data.end(), contents.begin() + 1 + CMessageHeader::COMMAND_SIZE);
1456+
}
13721457
// Construct ciphertext in send buffer.
13731458
m_send_buffer.resize(contents.size() + BIP324Cipher::EXPANSION);
13741459
m_cipher.Encrypt(MakeByteSpan(contents), {}, false, MakeWritableByteSpan(m_send_buffer));

0 commit comments

Comments
 (0)