@@ -913,6 +913,74 @@ size_t V1Transport::GetSendMemoryUsage() const noexcept
913
913
return m_message_to_send.GetMemoryUsage ();
914
914
}
915
915
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
+
916
984
V2Transport::V2Transport (NodeId nodeid, bool initiating, int type_in, int version_in) noexcept :
917
985
m_cipher{}, m_initiating{initiating}, m_nodeid{nodeid},
918
986
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
1299
1367
uint8_t first_byte = contents[0 ];
1300
1368
contents = contents.subspan (1 ); // Strip first byte.
1301
1369
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
+ }
1303
1380
1304
1381
if (contents.size () < CMessageHeader::COMMAND_SIZE) {
1305
1382
return std::nullopt; // Long encoding needs 12 message type bytes.
@@ -1364,11 +1441,19 @@ bool V2Transport::SetMessageToSend(CSerializedNetMsg& msg) noexcept
1364
1441
// buffer to just one, and leaves the responsibility for queueing them up to the caller.
1365
1442
if (!(m_send_state == SendState::READY && m_send_buffer.empty ())) return false ;
1366
1443
// 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
+ }
1372
1457
// Construct ciphertext in send buffer.
1373
1458
m_send_buffer.resize (contents.size () + BIP324Cipher::EXPANSION);
1374
1459
m_cipher.Encrypt (MakeByteSpan (contents), {}, false , MakeWritableByteSpan (m_send_buffer));
0 commit comments