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.
251// Only one CNetMessage object will exist for the same message on either252// the receive or processing queue. For performance reasons we therefore253// delete the copy constructor and assignment operator to avoid the254// possibility of copying CNetMessage objects.255CNetMessage(CNetMessage&&) = default;256CNetMessage(const CNetMessage&) = delete;257CNetMessage& operator=(CNetMessage&&) = default;258CNetMessage& operator=(const CNetMessage&) = delete;260/** Compute total memory usage of this object (own memory + any dynamic memory). */261size_t GetMemoryUsage() const noexcept;262};264/** The Transport converts one connection's sent messages to wire bytes, and received bytes back. */265class Transport {266public:267virtual ~Transport() = default;269struct Info270{271TransportProtocolType transport_type;272std::optional<uint256> session_id;273};275/** Retrieve information about this transport. */276virtual Info GetInfo() const noexcept = 0;278// 1. Receiver side functions, for decoding bytes received on the wire into transport protocol279// agnostic CNetMessage (message type & payload) objects.281/** Returns true if the current message is complete (so GetReceivedMessage can be called). */282virtual bool ReceivedMessageComplete() const = 0;284/** Feed wire bytes to the transport.285*286* @return false if some bytes were invalid, in which case the transport can't be used anymore.287*288* Consumed bytes are chopped off the front of msg_bytes.289*/290virtual bool ReceivedBytes(std::span<const uint8_t>& msg_bytes) = 0;292/** Retrieve a completed message from transport.293*294* This can only be called when ReceivedMessageComplete() is true.295*296* If reject_message=true is returned the message itself is invalid, but (other than false297* returned by ReceivedBytes) the transport is not in an inconsistent state.298*/299virtual CNetMessage GetReceivedMessage(NodeClock::time_point time, bool& reject_message) = 0;301// 2. Sending side functions, for converting messages into bytes to be sent over the wire.303/** Set the next message to send.304*305* If no message can currently be set (perhaps because the previous one is not yet done being306* sent), returns false, and msg will be unmodified. Otherwise msg is enqueued (and307* possibly moved-from) and true is returned.308*/309virtual bool SetMessageToSend(CSerializedNetMsg& msg) noexcept = 0;311/** Return type for GetBytesToSend, consisting of:312* - std::span<const uint8_t> to_send: span of bytes to be sent over the wire (possibly empty).313* - bool more: whether there will be more bytes to be sent after the ones in to_send are314* all sent (as signaled by MarkBytesSent()).315* - const std::string& m_type: message type on behalf of which this is being sent316* ("" for bytes that are not on behalf of any message).317*/318using BytesToSend = std::tuple<319std::span<const uint8_t> /*to_send*/,320bool /*more*/,321const std::string& /*m_type*/322>;324/** Get bytes to send on the wire, if any, along with other information about it.325*326* As a const function, it does not modify the transport's observable state, and is thus safe327* to be called multiple times.328*329* @param[in] have_next_message If true, the "more" return value reports whether more will330* be sendable after a SetMessageToSend call. It is set by the caller when they know331* they have another message ready to send, and only care about what happens332* after that. The have_next_message argument only affects this "more" return value333* and nothing else.334*335* Effectively, there are three possible outcomes about whether there are more bytes336* to send:337* - Yes: the transport itself has more bytes to send later. For example, for338* V1Transport this happens during the sending of the header of a339* message, when there is a non-empty payload that follows.340* - No: the transport itself has no more bytes to send, but will have bytes to341* send if handed a message through SetMessageToSend. In V1Transport this342* happens when sending the payload of a message.343* - Blocked: the transport itself has no more bytes to send, and is also incapable344* of sending anything more at all now, if it were handed another345* message to send. This occurs in V2Transport before the handshake is346* complete, as the encryption ciphers are not set up for sending347* messages before that point.348*349* The boolean 'more' is true for Yes, false for Blocked, and have_next_message350* controls what is returned for No.351*352* @return a BytesToSend object. The to_send member returned acts as a stream which is only353* ever appended to. This means that with the exception of MarkBytesSent (which pops354* bytes off the front of later to_sends), operations on the transport can only append355* to what is being returned. Also note that m_type and to_send refer to data that is356* internal to the transport, and calling any non-const function on this object may357* invalidate them.358*/359virtual BytesToSend GetBytesToSend(bool have_next_message) const noexcept = 0;361/** Report how many bytes returned by the last GetBytesToSend() have been sent.362*363* bytes_sent cannot exceed to_send.size() of the last GetBytesToSend() result.364*365* If bytes_sent=0, this call has no effect.366*/367virtual void MarkBytesSent(size_t bytes_sent) noexcept = 0;369/** Return the memory usage of this transport attributable to buffered data to send. */370virtual size_t GetSendMemoryUsage() const noexcept = 0;372// 3. Miscellaneous functions.374/** Whether upon disconnections, a reconnect with V1 is warranted. */375virtual bool ShouldReconnectV1() const noexcept = 0;376};378class V1Transport final : public Transport379{380private:381const MessageStartChars m_magic_bytes;382const NodeId m_node_id; // Only for logging383mutable Mutex m_recv_mutex; //!< Lock for receive state384mutable CHash256 hasher GUARDED_BY(m_recv_mutex);385mutable uint256 data_hash GUARDED_BY(m_recv_mutex);386bool in_data GUARDED_BY(m_recv_mutex); // parsing header (false) or data (true)387DataStream hdrbuf GUARDED_BY(m_recv_mutex){}; // partially received header388CMessageHeader hdr GUARDED_BY(m_recv_mutex); // complete header389DataStream vRecv GUARDED_BY(m_recv_mutex){}; // received message data390unsigned int nHdrPos GUARDED_BY(m_recv_mutex);391unsigned int nDataPos GUARDED_BY(m_recv_mutex);393const uint256& GetMessageHash() const EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex);394int readHeader(std::span<const uint8_t> msg_bytes) EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex);395int readData(std::span<const uint8_t> msg_bytes) EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex);397void Reset() EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex) {398AssertLockHeld(m_recv_mutex);399vRecv.clear();400hdrbuf.clear();401hdrbuf.resize(24);402in_data = false;403nHdrPos = 0;404nDataPos = 0;405data_hash.SetNull();406hasher.Reset();407}409bool CompleteInternal() const noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex)410{411AssertLockHeld(m_recv_mutex);412if (!in_data) return false;413return hdr.nMessageSize == nDataPos;414}416/** Lock for sending state. */417mutable Mutex m_send_mutex;418/** The header of the message currently being sent. */419std::vector<uint8_t> m_header_to_send GUARDED_BY(m_send_mutex);420/** The data of the message currently being sent. */421CSerializedNetMsg m_message_to_send GUARDED_BY(m_send_mutex);422/** Whether we're currently sending header bytes or message bytes. */423bool m_sending_header GUARDED_BY(m_send_mutex) {false};424/** How many bytes have been sent so far (from m_header_to_send, or from m_message_to_send.data). */425size_t m_bytes_sent GUARDED_BY(m_send_mutex) {0};427public:428explicit V1Transport(NodeId node_id) noexcept;430bool ReceivedMessageComplete() const override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex)431{432AssertLockNotHeld(m_recv_mutex);433return WITH_LOCK(m_recv_mutex, return CompleteInternal());434}436Info GetInfo() const noexcept override;438bool ReceivedBytes(std::span<const uint8_t>& msg_bytes) override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex)439{440AssertLockNotHeld(m_recv_mutex);441LOCK(m_recv_mutex);442int ret = in_data ? readData(msg_bytes) : readHeader(msg_bytes);443if (ret < 0) {444Reset();445} else {446msg_bytes = msg_bytes.subspan(ret);447}448return ret >= 0;449}451CNetMessage GetReceivedMessage(NodeClock::time_point time, bool& reject_message) override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex);453bool SetMessageToSend(CSerializedNetMsg& msg) noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex);454BytesToSend GetBytesToSend(bool have_next_message) const noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex);455void MarkBytesSent(size_t bytes_sent) noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex);456size_t GetSendMemoryUsage() const noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex);457bool ShouldReconnectV1() const noexcept override { return false; }458};460class V2Transport final : public Transport461{462private:463/** Contents of the version packet to send. BIP324 stipulates that senders should leave this464* empty, and receivers should ignore it. Future extensions can change what is sent as long as465* an empty version packet contents is interpreted as no extensions supported. */466static constexpr std::array<std::byte, 0> VERSION_CONTENTS = {};468/** The length of the V1 prefix to match bytes initially received by responders with to469* determine if their peer is speaking V1 or V2. */470static constexpr size_t V1_PREFIX_LEN = 16;472// The sender side and receiver side of V2Transport are state machines that are transitioned473// through, based on what has been received. The receive state corresponds to the contents of,474// and bytes received to, the receive buffer. The send state controls what can be appended to475// the send buffer and what can be sent from it.477/** State type that defines the current contents of the receive buffer and/or how the next478* received bytes added to it will be interpreted.479*480* Diagram:481*482* start(responder)483* |484* | start(initiator) /---------\485* | | | |486* v v v |487* KEY_MAYBE_V1 -> KEY -> GARB_GARBTERM -> VERSION -> APP -> APP_READY488* |489* \-------> V1490*/491enum class RecvState : uint8_t {492/** (Responder only) either v2 public key or v1 header.493*494* This is the initial state for responders, before data has been received to distinguish495* v1 from v2 connections. When that happens, the state becomes either KEY (for v2) or V1496* (for v1). */497KEY_MAYBE_V1,499/** Public key.500*
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.