Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1252// At this point we have a valid packet decrypted into m_recv_decode_buffer. If it's not a1253// decoy, which we simply ignore, use the current state to decide what to do with it.1254if (!ignore) {1255switch (m_recv_state) {1256case RecvState::VERSION:1257// Version message received; transition to application phase. The contents is1258// ignored, but can be used for future extensions.1259SetReceiveState(RecvState::APP);1260break;1261case RecvState::APP:1262// Application message decrypted correctly. It can be extracted using GetMessage().1263SetReceiveState(RecvState::APP_READY);1264break;1265default:1266// Any other state is invalid (this function should not have been called).1267Assume(false);1268}1269}1270// Wipe the receive buffer where the next packet will be received into.1271ClearShrink(m_recv_buffer);1272// In all but APP_READY state, we can wipe the decoded contents.1273if (m_recv_state != RecvState::APP_READY) ClearShrink(m_recv_decode_buffer);1274} else {1275// We either have less than 3 bytes, so we don't know the packet's length yet, or more1276// than 3 bytes but less than the packet's full ciphertext. Wait until those arrive.1277}1278return true;1279}1281size_t V2Transport::GetMaxBytesToProcess() noexcept1282{1283AssertLockHeld(m_recv_mutex);1284switch (m_recv_state) {1285case RecvState::KEY_MAYBE_V1:1286// During the KEY_MAYBE_V1 state we do not allow more than the length of v1 prefix into the1287// receive buffer.1288Assume(m_recv_buffer.size() <= V1_PREFIX_LEN);1289// As long as we're not sure if this is a v1 or v2 connection, don't receive more than what1290// is strictly necessary to distinguish the two (16 bytes). If we permitted more than1291// the v1 header size (24 bytes), we may not be able to feed the already-received bytes1292// back into the m_v1_fallback V1 transport.1293return V1_PREFIX_LEN - m_recv_buffer.size();1294case RecvState::KEY:1295// During the KEY state, we only allow the 64-byte key into the receive buffer.1296Assume(m_recv_buffer.size() <= EllSwiftPubKey::size());1297// As long as we have not received the other side's public key, don't receive more than1298// that (64 bytes), as garbage follows, and locating the garbage terminator requires the1299// key exchange first.1300return EllSwiftPubKey::size() - m_recv_buffer.size();1301case RecvState::GARB_GARBTERM:1302// Process garbage bytes one by one (because terminator may appear anywhere).1303return 1;1304case RecvState::VERSION:1305case RecvState::APP:1306// These three states all involve decoding a packet. Process the length descriptor first,1307// so that we know where the current packet ends (and we don't process bytes from the next1308// packet or decoy yet). Then, process the ciphertext bytes of the current packet.1309if (m_recv_buffer.size() < BIP324Cipher::LENGTH_LEN) {1310return BIP324Cipher::LENGTH_LEN - m_recv_buffer.size();1311} else {1312// Note that BIP324Cipher::EXPANSION is the total difference between contents size1313// and encoded packet size, which includes the 3 bytes due to the packet length.1314// When transitioning from receiving the packet length to receiving its ciphertext,1315// the encrypted packet length is left in the receive buffer.1316return BIP324Cipher::EXPANSION + m_recv_len - m_recv_buffer.size();1317}1318case RecvState::APP_READY:1319// No bytes can be processed until GetMessage() is called.1320return 0;1321case RecvState::V1:1322// Not allowed (must be dealt with by the caller).1323Assume(false);1324return 0;1325}1326Assume(false); // unreachable1327return 0;1328}1330bool V2Transport::ReceivedBytes(std::span<const uint8_t>& msg_bytes) noexcept1331{1332AssertLockNotHeld(m_recv_mutex);1333/** How many bytes to allocate in the receive buffer at most above what is received so far. */1334static constexpr size_t MAX_RESERVE_AHEAD = 256 * 1024;1336LOCK(m_recv_mutex);1337if (m_recv_state == RecvState::V1) return m_v1_fallback.ReceivedBytes(msg_bytes);1339// Process the provided bytes in msg_bytes in a loop. In each iteration a nonzero number of1340// bytes (decided by GetMaxBytesToProcess) are taken from the beginning om msg_bytes, and1341// appended to m_recv_buffer. Then, depending on the receiver state, one of the1342// ProcessReceived*Bytes functions is called to process the bytes in that buffer.1343while (!msg_bytes.empty()) {1344// Decide how many bytes to copy from msg_bytes to m_recv_buffer.1345size_t max_read = GetMaxBytesToProcess();1347// Reserve space in the buffer if there is not enough.1348if (m_recv_buffer.size() + std::min(msg_bytes.size(), max_read) > m_recv_buffer.capacity()) {1349switch (m_recv_state) {1350case RecvState::KEY_MAYBE_V1:1351case RecvState::KEY:1352case RecvState::GARB_GARBTERM:1353// During the initial states (key/garbage), allocate once to fit the maximum (41111354// bytes).1355m_recv_buffer.reserve(MAX_GARBAGE_LEN + BIP324Cipher::GARBAGE_TERMINATOR_LEN);1356break;1357case RecvState::VERSION:1358case RecvState::APP: {1359// During states where a packet is being received, as much as is expected but never1360// more than MAX_RESERVE_AHEAD bytes in addition to what is received so far.1361// This means attackers that want to cause us to waste allocated memory are limited1362// to MAX_RESERVE_AHEAD above the largest allowed message contents size, and to1363// MAX_RESERVE_AHEAD more than they've actually sent us.1364size_t alloc_add = std::min(max_read, msg_bytes.size() + MAX_RESERVE_AHEAD);1365m_recv_buffer.reserve(m_recv_buffer.size() + alloc_add);1366break;1367}1368case RecvState::APP_READY:1369// The buffer is empty in this state.1370Assume(m_recv_buffer.empty());1371break;1372case RecvState::V1:1373// Should have bailed out above.1374Assume(false);1375break;1376}1377}1379// Can't read more than provided input.1380max_read = std::min(msg_bytes.size(), max_read);1381// Copy data to buffer.1382m_recv_buffer.insert(m_recv_buffer.end(), UCharCast(msg_bytes.data()), UCharCast(msg_bytes.data() + max_read));1383msg_bytes = msg_bytes.subspan(max_read);1385// Process data in the buffer.1386switch (m_recv_state) {1387case RecvState::KEY_MAYBE_V1:1388ProcessReceivedMaybeV1Bytes();1389if (m_recv_state == RecvState::V1) return true;1390break;1392case RecvState::KEY:1393if (!ProcessReceivedKeyBytes()) return false;1394break;1396case RecvState::GARB_GARBTERM:1397if (!ProcessReceivedGarbageBytes()) return false;1398break;1400case RecvState::VERSION:1401case RecvState::APP:1402if (!ProcessReceivedPacketBytes()) return false;1403break;1405case RecvState::APP_READY:1406return true;1408case RecvState::V1:1409// We should have bailed out before.1410Assume(false);1411break;1412}1413// Make sure we have made progress before continuing.1414Assume(max_read > 0);1415}1417return true;1418}1420std::optional<std::string> V2Transport::GetMessageType(std::span<const uint8_t>& contents) noexcept1421{1422if (contents.size() == 0) return std::nullopt; // Empty contents1423uint8_t first_byte = contents[0];1424contents = contents.subspan(1); // Strip first byte.1426if (first_byte != 0) {1427// Short (1 byte) encoding.1428if (first_byte < std::size(V2_MESSAGE_IDS)) {1429// Valid short message id.1430return V2_MESSAGE_IDS[first_byte];1431} else {1432// Unknown short message id.1433return std::nullopt;1434}1435}1437if (contents.size() < CMessageHeader::MESSAGE_TYPE_SIZE) {1438return std::nullopt; // Long encoding needs 12 message type bytes.1439}1441size_t msg_type_len{0};1442while (msg_type_len < CMessageHeader::MESSAGE_TYPE_SIZE && contents[msg_type_len] != 0) {1443// Verify that message type bytes before the first 0x00 are in range. BIP324 specifies the1444// long message type encoding as "an ASCII message type (as in the v1 P2P protocol)".1445if (contents[msg_type_len] < ' ' || contents[msg_type_len] > 0x7E) {1446return {};1447}1448++msg_type_len;1449}1450std::string ret{reinterpret_cast<const char*>(contents.data()), msg_type_len};1451while (msg_type_len < CMessageHeader::MESSAGE_TYPE_SIZE) {1452// Verify that message type bytes after the first 0x00 are also 0x00.1453if (contents[msg_type_len] != 0) return {};1454++msg_type_len;1455}1456// Strip message type bytes of contents.1457contents = contents.subspan(CMessageHeader::MESSAGE_TYPE_SIZE);1458return ret;1459}1461CNetMessage V2Transport::GetReceivedMessage(NodeClock::time_point time, bool& reject_message) noexcept1462{1463AssertLockNotHeld(m_recv_mutex);1464LOCK(m_recv_mutex);1465if (m_recv_state == RecvState::V1) return m_v1_fallback.GetReceivedMessage(time, reject_message);1467Assume(m_recv_state == RecvState::APP_READY);1468std::span<const uint8_t> contents{m_recv_decode_buffer};1469auto msg_type = GetMessageType(contents);1470CNetMessage msg{DataStream{}};1471// Note that BIP324Cipher::EXPANSION also includes the length descriptor size.1472msg.m_raw_message_size = m_recv_decode_buffer.size() + BIP324Cipher::EXPANSION;1473if (msg_type) {1474reject_message = false;1475msg.m_type = std::move(*msg_type);1476msg.m_time = time;1477msg.m_message_size = contents.size();1478msg.m_recv.resize(contents.size());1479std::copy(contents.begin(), contents.end(), UCharCast(msg.m_recv.data()));1480} else {1481LogDebug(BCLog::NET, "V2 transport error: invalid message type (%u bytes contents), peer=%d\n", m_recv_decode_buffer.size(), m_nodeid);1482reject_message = true;1483}1484ClearShrink(m_recv_decode_buffer);1485SetReceiveState(RecvState::APP);1487return msg;1488}1490bool V2Transport::SetMessageToSend(CSerializedNetMsg& msg) noexcept1491{1492AssertLockNotHeld(m_send_mutex);1493LOCK(m_send_mutex);1494if (m_send_state == SendState::V1) return m_v1_fallback.SetMessageToSend(msg);1495// We only allow adding a new message to be sent when in the READY state (so the packet cipher1496// is available) and the send buffer is empty. This limits the number of messages in the send1497// buffer to just one, and leaves the responsibility for queueing them up to the caller.1498if (!(m_send_state == SendState::READY && m_send_buffer.empty())) return false;1499// Construct contents (encoding message type + payload).1500std::vector<uint8_t> contents;