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.
501* This is the initial state for initiators, during which the other side's public key is502* received. When that information arrives, the ciphers get initialized and the state503* becomes GARB_GARBTERM. */504KEY,506/** Garbage and garbage terminator.507*508* Whenever a byte is received, the last 16 bytes are compared with the expected garbage509* terminator. When that happens, the state becomes VERSION. If no matching terminator is510* received in 4111 bytes (4095 for the maximum garbage length, and 16 bytes for the511* terminator), the connection aborts. */512GARB_GARBTERM,514/** Version packet.515*516* A packet is received, and decrypted/verified. If that fails, the connection aborts. The517* first received packet in this state (whether it's a decoy or not) is expected to518* authenticate the garbage received during the GARB_GARBTERM state as associated519* authenticated data (AAD). The first non-decoy packet in this state is interpreted as520* version negotiation (currently, that means ignoring the contents, but it can be used for521* negotiating future extensions), and afterwards the state becomes APP. */522VERSION,524/** Application packet.525*526* A packet is received, and decrypted/verified. If that succeeds, the state becomes527* APP_READY and the decrypted contents is kept in m_recv_decode_buffer until it is528* retrieved as a message by GetMessage(). */529APP,531/** Nothing (an application packet is available for GetMessage()).532*533* Nothing can be received in this state. When the message is retrieved by GetMessage,534* the state becomes APP again. */535APP_READY,537/** Nothing (this transport is using v1 fallback).538*539* All receive operations are redirected to m_v1_fallback. */540V1,541};543/** State type that controls the sender side.544*545* Diagram:546*547* start(responder)548* |549* | start(initiator)550* | |551* v v552* MAYBE_V1 -> AWAITING_KEY -> READY553* |554* \-----> V1555*/556enum class SendState : uint8_t {557/** (Responder only) Not sending until v1 or v2 is detected.558*559* This is the initial state for responders. The send buffer is empty.560* When the receiver determines whether this561* is a V1 or V2 connection, the sender state becomes AWAITING_KEY (for v2) or V1 (for v1).562*/563MAYBE_V1,565/** Waiting for the other side's public key.566*567* This is the initial state for initiators. The public key and garbage is sent out. When568* the receiver receives the other side's public key and transitions to GARB_GARBTERM, the569* sender state becomes READY. */570AWAITING_KEY,572/** Normal sending state.573*574* In this state, the ciphers are initialized, so packets can be sent. When this state is575* entered, the garbage terminator and version packet are appended to the send buffer (in576* addition to the key and garbage which may still be there). In this state a message can be577* provided if the send buffer is empty. */578READY,580/** This transport is using v1 fallback.581*582* All send operations are redirected to m_v1_fallback. */583V1,584};586/** Cipher state. */587BIP324Cipher m_cipher;588/** Whether we are the initiator side. */589const bool m_initiating;590/** NodeId (for debug logging). */591const NodeId m_nodeid;592/** Encapsulate a V1Transport to fall back to. */593V1Transport m_v1_fallback;595/** Lock for receiver-side fields. */596mutable Mutex m_recv_mutex ACQUIRED_BEFORE(m_send_mutex);597/** In {VERSION, APP}, the decrypted packet length, if m_recv_buffer.size() >=598* BIP324Cipher::LENGTH_LEN. Unspecified otherwise. */599uint32_t m_recv_len GUARDED_BY(m_recv_mutex) {0};600/** Receive buffer; meaning is determined by m_recv_state. */601std::vector<uint8_t> m_recv_buffer GUARDED_BY(m_recv_mutex);602/** AAD expected in next received packet (currently used only for garbage). */603std::vector<uint8_t> m_recv_aad GUARDED_BY(m_recv_mutex);604/** Buffer to put decrypted contents in, for converting to CNetMessage. */605std::vector<uint8_t> m_recv_decode_buffer GUARDED_BY(m_recv_mutex);606/** Current receiver state. */607RecvState m_recv_state GUARDED_BY(m_recv_mutex);609/** Lock for sending-side fields. If both sending and receiving fields are accessed,610* m_recv_mutex must be acquired before m_send_mutex. */611mutable Mutex m_send_mutex ACQUIRED_AFTER(m_recv_mutex);612/** The send buffer; meaning is determined by m_send_state. */613std::vector<uint8_t> m_send_buffer GUARDED_BY(m_send_mutex);614/** How many bytes from the send buffer have been sent so far. */615uint32_t m_send_pos GUARDED_BY(m_send_mutex) {0};616/** The garbage sent, or to be sent (MAYBE_V1 and AWAITING_KEY state only). */617std::vector<uint8_t> m_send_garbage GUARDED_BY(m_send_mutex);618/** Type of the message being sent. */619std::string m_send_type GUARDED_BY(m_send_mutex);620/** Current sender state. */621SendState m_send_state GUARDED_BY(m_send_mutex);622/** Whether we've sent at least 24 bytes (which would trigger disconnect for V1 peers). */623bool m_sent_v1_header_worth GUARDED_BY(m_send_mutex) {false};625/** Change the receive state. */626void SetReceiveState(RecvState recv_state) noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex);627/** Change the send state. */628void SetSendState(SendState send_state) noexcept EXCLUSIVE_LOCKS_REQUIRED(m_send_mutex);629/** Given a packet's contents, find the message type (if valid), and strip it from contents. */630static std::optional<std::string> GetMessageType(std::span<const uint8_t>& contents) noexcept;631/** Determine how many received bytes can be processed in one go (not allowed in V1 state). */632size_t GetMaxBytesToProcess() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex);633/** Put our public key + garbage in the send buffer. */634void StartSendingHandshake() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_send_mutex);635/** Process bytes in m_recv_buffer, while in KEY_MAYBE_V1 state. */636void ProcessReceivedMaybeV1Bytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex, !m_send_mutex);637/** Process bytes in m_recv_buffer, while in KEY state. */638bool ProcessReceivedKeyBytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex, !m_send_mutex);639/** Process bytes in m_recv_buffer, while in GARB_GARBTERM state. */640bool ProcessReceivedGarbageBytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex);641/** Process bytes in m_recv_buffer, while in VERSION/APP state. */642bool ProcessReceivedPacketBytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex);644public:645static constexpr uint32_t MAX_GARBAGE_LEN = 4095;647/** Construct a V2 transport with securely generated random keys.648*649* @param[in] nodeid the node's NodeId (only for debug log output).650* @param[in] initiating whether we are the initiator side.651*/652V2Transport(NodeId nodeid, bool initiating) noexcept;654/** Construct a V2 transport with specified keys and garbage (test use only). */655V2Transport(NodeId nodeid, bool initiating, const CKey& key, std::span<const std::byte> ent32, std::vector<uint8_t> garbage) noexcept;657// Receive side functions.658bool ReceivedMessageComplete() const noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex);659bool ReceivedBytes(std::span<const uint8_t>& msg_bytes) noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex, !m_send_mutex);660CNetMessage GetReceivedMessage(NodeClock::time_point time, bool& reject_message) noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex);662// Send side functions.663bool SetMessageToSend(CSerializedNetMsg& msg) noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex);664BytesToSend GetBytesToSend(bool have_next_message) const noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex);665void MarkBytesSent(size_t bytes_sent) noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex);666size_t GetSendMemoryUsage() const noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex);668// Miscellaneous functions.669bool ShouldReconnectV1() const noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex, !m_send_mutex);670Info GetInfo() const noexcept override EXCLUSIVE_LOCKS_REQUIRED(!m_recv_mutex);671};673struct CNodeOptions674{675NetPermissionFlags permission_flags = NetPermissionFlags::None;676std::optional<Proxy> proxy_override = {};677std::unique_ptr<i2p::sam::Session> i2p_sam_session = nullptr;678bool prefer_evict = false;679size_t recv_flood_size{DEFAULT_MAXRECEIVEBUFFER * 1000};680bool use_v2transport = false;681};683/** Information about a peer */684class CNode685{686public:687/** Transport serializer/deserializer. The receive side functions are only called under cs_vRecv, while688* the sending side functions are only called under cs_vSend. */689const std::unique_ptr<Transport> m_transport;691const NetPermissionFlags m_permission_flags;693/**694* Socket used for communication with the node.695* May not own a Sock object (after `CloseSocketDisconnect()` or during tests).696* `shared_ptr` (instead of `unique_ptr`) is used to avoid premature close of697* the underlying file descriptor by one thread while another thread is698* poll(2)-ing it for activity.699* @see https://github.com/bitcoin/bitcoin/issues/21744 for details.700*/701std::shared_ptr<Sock> m_sock GUARDED_BY(m_sock_mutex);703/** Sum of GetMemoryUsage of all vSendMsg entries. */704size_t m_send_memusage GUARDED_BY(cs_vSend){0};705/** Total number of bytes sent on the wire to this peer. */706uint64_t nSendBytes GUARDED_BY(cs_vSend){0};707/** Messages still to be fed to m_transport->SetMessageToSend. */708std::deque<CSerializedNetMsg> vSendMsg GUARDED_BY(cs_vSend);709Mutex cs_vSend;710Mutex m_sock_mutex;711Mutex cs_vRecv;713uint64_t nRecvBytes GUARDED_BY(cs_vRecv){0};715std::atomic<NodeClock::time_point> m_last_send{NodeClock::epoch};716std::atomic<NodeClock::time_point> m_last_recv{NodeClock::epoch};717//! Unix epoch time at peer connection718const NodeClock::time_point m_connected;720//! Proxy to use regardless of global proxy settings if reconnecting to this node.721const std::optional<Proxy> m_proxy_override;723// Address of this peer724const CAddress addr;725// Bind address of our side of the connection726const CService addrBind;727const std::string m_addr_name;728/** The pszDest argument provided to ConnectNode(). Only used for reconnections. */729const std::string m_dest;730//! Whether this peer is an inbound onion, i.e. connected via our Tor onion service.731const bool m_inbound_onion;732std::atomic<int> nVersion{0};733Mutex m_subver_mutex;734/**735* cleanSubVer is a sanitized string of the user agent byte array we read736* from the wire. This cleaned string can safely be logged or displayed.737*/738std::string cleanSubVer GUARDED_BY(m_subver_mutex){};739const bool m_prefer_evict{false}; // This peer is preferred for eviction.740bool HasPermission(NetPermissionFlags permission) const {741return NetPermissions::HasFlag(m_permission_flags, permission);742}743/** fSuccessfullyConnected is set to true on receiving VERACK from the peer. */744std::atomic_bool fSuccessfullyConnected{false};745// Setting fDisconnect to true will cause the node to be disconnected the746// next time DisconnectNodes() runs747std::atomic_bool fDisconnect{false};748CountingSemaphoreGrant<> grantOutbound;749std::atomic<int> nRefCount{0};
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.