@@ -915,9 +915,9 @@ size_t V1Transport::GetSendMemoryUsage() const noexcept
915
915
916
916
V2Transport::V2Transport (NodeId nodeid, bool initiating, int type_in, int version_in) noexcept :
917
917
m_cipher{}, m_initiating{initiating}, m_nodeid{nodeid},
918
- m_recv_type{type_in}, m_recv_version{version_in},
919
- m_recv_state{RecvState::KEY},
920
- m_send_state{SendState::AWAITING_KEY}
918
+ m_v1_fallback{nodeid, type_in, version_in}, m_recv_type{type_in}, m_recv_version{version_in},
919
+ m_recv_state{initiating ? RecvState::KEY : RecvState::KEY_MAYBE_V1 },
920
+ m_send_state{initiating ? SendState::AWAITING_KEY : SendState::MAYBE_V1 }
921
921
{
922
922
// Initialize the send buffer with ellswift pubkey.
923
923
m_send_buffer.resize (EllSwiftPubKey::size ());
@@ -926,9 +926,9 @@ V2Transport::V2Transport(NodeId nodeid, bool initiating, int type_in, int versio
926
926
927
927
V2Transport::V2Transport (NodeId nodeid, bool initiating, int type_in, int version_in, const CKey& key, Span<const std::byte> ent32) noexcept :
928
928
m_cipher{key, ent32}, m_initiating{initiating}, m_nodeid{nodeid},
929
- m_recv_type{type_in}, m_recv_version{version_in},
930
- m_recv_state{RecvState::KEY},
931
- m_send_state{SendState::AWAITING_KEY}
929
+ m_v1_fallback{nodeid, type_in, version_in}, m_recv_type{type_in}, m_recv_version{version_in},
930
+ m_recv_state{initiating ? RecvState::KEY : RecvState::KEY_MAYBE_V1 },
931
+ m_send_state{initiating ? SendState::AWAITING_KEY : SendState::MAYBE_V1 }
932
932
{
933
933
// Initialize the send buffer with ellswift pubkey.
934
934
m_send_buffer.resize (EllSwiftPubKey::size ());
@@ -940,6 +940,9 @@ void V2Transport::SetReceiveState(RecvState recv_state) noexcept
940
940
AssertLockHeld (m_recv_mutex);
941
941
// Enforce allowed state transitions.
942
942
switch (m_recv_state) {
943
+ case RecvState::KEY_MAYBE_V1:
944
+ Assume (recv_state == RecvState::KEY || recv_state == RecvState::V1);
945
+ break ;
943
946
case RecvState::KEY:
944
947
Assume (recv_state == RecvState::GARB_GARBTERM);
945
948
break ;
@@ -958,6 +961,9 @@ void V2Transport::SetReceiveState(RecvState recv_state) noexcept
958
961
case RecvState::APP_READY:
959
962
Assume (recv_state == RecvState::APP);
960
963
break ;
964
+ case RecvState::V1:
965
+ Assume (false ); // V1 state cannot be left
966
+ break ;
961
967
}
962
968
// Change state.
963
969
m_recv_state = recv_state;
@@ -968,11 +974,15 @@ void V2Transport::SetSendState(SendState send_state) noexcept
968
974
AssertLockHeld (m_send_mutex);
969
975
// Enforce allowed state transitions.
970
976
switch (m_send_state) {
977
+ case SendState::MAYBE_V1:
978
+ Assume (send_state == SendState::V1 || send_state == SendState::AWAITING_KEY);
979
+ break ;
971
980
case SendState::AWAITING_KEY:
972
981
Assume (send_state == SendState::READY);
973
982
break ;
974
983
case SendState::READY:
975
- Assume (false ); // Final state
984
+ case SendState::V1:
985
+ Assume (false ); // Final states
976
986
break ;
977
987
}
978
988
// Change state.
@@ -983,9 +993,48 @@ bool V2Transport::ReceivedMessageComplete() const noexcept
983
993
{
984
994
AssertLockNotHeld (m_recv_mutex);
985
995
LOCK (m_recv_mutex);
996
+ if (m_recv_state == RecvState::V1) return m_v1_fallback.ReceivedMessageComplete ();
997
+
986
998
return m_recv_state == RecvState::APP_READY;
987
999
}
988
1000
1001
+ void V2Transport::ProcessReceivedMaybeV1Bytes () noexcept
1002
+ {
1003
+ AssertLockHeld (m_recv_mutex);
1004
+ AssertLockNotHeld (m_send_mutex);
1005
+ Assume (m_recv_state == RecvState::KEY_MAYBE_V1);
1006
+ // We still have to determine if this is a v1 or v2 connection. The bytes being received could
1007
+ // be the beginning of either a v1 packet (network magic + "version\x00"), or of a v2 public
1008
+ // key. BIP324 specifies that a mismatch with this 12-byte string should trigger sending of the
1009
+ // key.
1010
+ std::array<uint8_t , V1_PREFIX_LEN> v1_prefix = {0 , 0 , 0 , 0 , ' v' , ' e' , ' r' , ' s' , ' i' , ' o' , ' n' , 0 };
1011
+ std::copy (std::begin (Params ().MessageStart ()), std::end (Params ().MessageStart ()), v1_prefix.begin ());
1012
+ Assume (m_recv_buffer.size () <= v1_prefix.size ());
1013
+ if (!std::equal (m_recv_buffer.begin (), m_recv_buffer.end (), v1_prefix.begin ())) {
1014
+ // Mismatch with v1 prefix, so we can assume a v2 connection.
1015
+ SetReceiveState (RecvState::KEY); // Convert to KEY state, leaving received bytes around.
1016
+ // Transition the sender to AWAITING_KEY state (if not already).
1017
+ LOCK (m_send_mutex);
1018
+ SetSendState (SendState::AWAITING_KEY);
1019
+ } else if (m_recv_buffer.size () == v1_prefix.size ()) {
1020
+ // Full match with the v1 prefix, so fall back to v1 behavior.
1021
+ LOCK (m_send_mutex);
1022
+ Span<const uint8_t > feedback{m_recv_buffer};
1023
+ // Feed already received bytes to v1 transport. It should always accept these, because it's
1024
+ // less than the size of a v1 header, and these are the first bytes fed to m_v1_fallback.
1025
+ bool ret = m_v1_fallback.ReceivedBytes (feedback);
1026
+ Assume (feedback.empty ());
1027
+ Assume (ret);
1028
+ SetReceiveState (RecvState::V1);
1029
+ SetSendState (SendState::V1);
1030
+ // Reset v2 transport buffers to save memory.
1031
+ m_recv_buffer = {};
1032
+ m_send_buffer = {};
1033
+ } else {
1034
+ // We have not received enough to distinguish v1 from v2 yet. Wait until more bytes come.
1035
+ }
1036
+ }
1037
+
989
1038
void V2Transport::ProcessReceivedKeyBytes () noexcept
990
1039
{
991
1040
AssertLockHeld (m_recv_mutex);
@@ -1143,6 +1192,15 @@ size_t V2Transport::GetMaxBytesToProcess() noexcept
1143
1192
{
1144
1193
AssertLockHeld (m_recv_mutex);
1145
1194
switch (m_recv_state) {
1195
+ case RecvState::KEY_MAYBE_V1:
1196
+ // During the KEY_MAYBE_V1 state we do not allow more than the length of v1 prefix into the
1197
+ // receive buffer.
1198
+ Assume (m_recv_buffer.size () <= V1_PREFIX_LEN);
1199
+ // As long as we're not sure if this is a v1 or v2 connection, don't receive more than what
1200
+ // is strictly necessary to distinguish the two (12 bytes). If we permitted more than
1201
+ // the v1 header size (24 bytes), we may not be able to feed the already-received bytes
1202
+ // back into the m_v1_fallback V1 transport.
1203
+ return V1_PREFIX_LEN - m_recv_buffer.size ();
1146
1204
case RecvState::KEY:
1147
1205
// During the KEY state, we only allow the 64-byte key into the receive buffer.
1148
1206
Assume (m_recv_buffer.size () <= EllSwiftPubKey::size ());
@@ -1171,6 +1229,10 @@ size_t V2Transport::GetMaxBytesToProcess() noexcept
1171
1229
case RecvState::APP_READY:
1172
1230
// No bytes can be processed until GetMessage() is called.
1173
1231
return 0 ;
1232
+ case RecvState::V1:
1233
+ // Not allowed (must be dealt with by the caller).
1234
+ Assume (false );
1235
+ return 0 ;
1174
1236
}
1175
1237
Assume (false ); // unreachable
1176
1238
return 0 ;
@@ -1180,6 +1242,8 @@ bool V2Transport::ReceivedBytes(Span<const uint8_t>& msg_bytes) noexcept
1180
1242
{
1181
1243
AssertLockNotHeld (m_recv_mutex);
1182
1244
LOCK (m_recv_mutex);
1245
+ if (m_recv_state == RecvState::V1) return m_v1_fallback.ReceivedBytes (msg_bytes);
1246
+
1183
1247
// Process the provided bytes in msg_bytes in a loop. In each iteration a nonzero number of
1184
1248
// bytes (decided by GetMaxBytesToProcess) are taken from the beginning om msg_bytes, and
1185
1249
// appended to m_recv_buffer. Then, depending on the receiver state, one of the
@@ -1195,6 +1259,11 @@ bool V2Transport::ReceivedBytes(Span<const uint8_t>& msg_bytes) noexcept
1195
1259
1196
1260
// Process data in the buffer.
1197
1261
switch (m_recv_state) {
1262
+ case RecvState::KEY_MAYBE_V1:
1263
+ ProcessReceivedMaybeV1Bytes ();
1264
+ if (m_recv_state == RecvState::V1) return true ;
1265
+ break ;
1266
+
1198
1267
case RecvState::KEY:
1199
1268
ProcessReceivedKeyBytes ();
1200
1269
break ;
@@ -1211,6 +1280,11 @@ bool V2Transport::ReceivedBytes(Span<const uint8_t>& msg_bytes) noexcept
1211
1280
1212
1281
case RecvState::APP_READY:
1213
1282
return true ;
1283
+
1284
+ case RecvState::V1:
1285
+ // We should have bailed out before.
1286
+ Assume (false );
1287
+ break ;
1214
1288
}
1215
1289
// Make sure we have made progress before continuing.
1216
1290
Assume (max_read > 0 );
@@ -1254,6 +1328,8 @@ CNetMessage V2Transport::GetReceivedMessage(std::chrono::microseconds time, bool
1254
1328
{
1255
1329
AssertLockNotHeld (m_recv_mutex);
1256
1330
LOCK (m_recv_mutex);
1331
+ if (m_recv_state == RecvState::V1) return m_v1_fallback.GetReceivedMessage (time , reject_message);
1332
+
1257
1333
Assume (m_recv_state == RecvState::APP_READY);
1258
1334
Span<const uint8_t > contents{m_recv_decode_buffer};
1259
1335
auto msg_type = GetMessageType (contents);
@@ -1282,6 +1358,7 @@ bool V2Transport::SetMessageToSend(CSerializedNetMsg& msg) noexcept
1282
1358
{
1283
1359
AssertLockNotHeld (m_send_mutex);
1284
1360
LOCK (m_send_mutex);
1361
+ if (m_send_state == SendState::V1) return m_v1_fallback.SetMessageToSend (msg);
1285
1362
// We only allow adding a new message to be sent when in the READY state (so the packet cipher
1286
1363
// is available) and the send buffer is empty. This limits the number of messages in the send
1287
1364
// buffer to just one, and leaves the responsibility for queueing them up to the caller.
@@ -1305,6 +1382,11 @@ Transport::BytesToSend V2Transport::GetBytesToSend(bool have_next_message) const
1305
1382
{
1306
1383
AssertLockNotHeld (m_send_mutex);
1307
1384
LOCK (m_send_mutex);
1385
+ if (m_send_state == SendState::V1) return m_v1_fallback.GetBytesToSend (have_next_message);
1386
+
1387
+ // We do not send anything in MAYBE_V1 state (as we don't know if the peer is v1 or v2),
1388
+ // despite there being data in the send buffer in that state.
1389
+ if (m_send_state == SendState::MAYBE_V1) return {{}, false , m_send_type};
1308
1390
Assume (m_send_pos <= m_send_buffer.size ());
1309
1391
return {
1310
1392
Span{m_send_buffer}.subspan (m_send_pos),
@@ -1319,6 +1401,8 @@ void V2Transport::MarkBytesSent(size_t bytes_sent) noexcept
1319
1401
{
1320
1402
AssertLockNotHeld (m_send_mutex);
1321
1403
LOCK (m_send_mutex);
1404
+ if (m_send_state == SendState::V1) return m_v1_fallback.MarkBytesSent (bytes_sent);
1405
+
1322
1406
m_send_pos += bytes_sent;
1323
1407
Assume (m_send_pos <= m_send_buffer.size ());
1324
1408
if (m_send_pos == m_send_buffer.size ()) {
@@ -1331,6 +1415,8 @@ size_t V2Transport::GetSendMemoryUsage() const noexcept
1331
1415
{
1332
1416
AssertLockNotHeld (m_send_mutex);
1333
1417
LOCK (m_send_mutex);
1418
+ if (m_send_state == SendState::V1) return m_v1_fallback.GetSendMemoryUsage ();
1419
+
1334
1420
return sizeof (m_send_buffer) + memusage::DynamicUsage (m_send_buffer);
1335
1421
}
1336
1422
0 commit comments