@@ -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+
916984V2Transport::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