> subsystem-summary-of-overlay
read this skill for a token-efficient summary of the overlay subsystem
curl "https://skillshub.wtf/stellar/stellar-core/subsystem-summary-of-overlay?format=md"Overlay Subsystem — Technical Summary
Overview
The overlay subsystem implements stellar-core's peer-to-peer network layer. It manages TCP connections to other nodes, authenticates peers via ECDH+HMAC, floods broadcast messages (transactions, SCP messages) across the network, fetches missing data (tx sets, quorum sets) via anycast requests, and performs network surveys. The subsystem supports optional background thread processing for I/O-heavy operations (reads/writes on TCP sockets) to keep the main thread responsive.
Key Files
- OverlayManager.h / OverlayManagerImpl.h/.cpp — Central manager; owns peer lists, Floodgate, TxDemandsManager, SurveyManager, PeerManager, PeerAuth, PeerDoor.
- Peer.h / Peer.cpp — Abstract base class for a connected peer; handles message dispatch, HMAC auth, flow control, pull-mode adverts.
- TCPPeer.h / TCPPeer.cpp — Concrete
Peersubclass; async TCP read/write via Asio, framing with RFC5531 record marking. - FlowControl.h / FlowControl.cpp — Per-peer flow control for flood traffic; outbound queuing with priority and load shedding.
- FlowControlCapacity.h / FlowControlCapacity.cpp — Tracks message-count and byte-count capacity for reading/writing flood data.
- Floodgate.h / Floodgate.cpp — Tracks which peers have seen which broadcast messages; ensures each message is sent/received at most once per peer.
- ItemFetcher.h / ItemFetcher.cpp — Manages anycast fetch requests for tx sets and quorum sets via Tracker instances.
- Tracker.h / Tracker.cpp — Tracks a single fetch request; tries peers sequentially with timeout-based retries.
- TxAdverts.h / TxAdverts.cpp — Per-peer incoming/outgoing transaction hash advertisement queues (pull mode).
- TxDemandsManager.h / TxDemandsManager.cpp — Global transaction demand scheduling; issues FLOOD_DEMAND messages based on received adverts.
- PeerManager.h / PeerManager.cpp — Persists peer records (address, type, failure count, next-attempt time) in the database.
- PeerDoor.h / PeerDoor.cpp — Listens on the configured TCP port; accepts incoming connections and hands them to OverlayManager.
- PeerAuth.h / PeerAuth.cpp — ECDH key exchange and HMAC key derivation for peer authentication.
- Hmac.h / Hmac.cpp — Per-peer HMAC state for message authentication (send/recv MAC keys, sequence numbers).
- PeerBareAddress.h / PeerBareAddress.cpp — Value type for an IPv4 address + port, with DNS resolution.
- PeerSharedKeyId.h / PeerSharedKeyId.cpp — Cache key type for shared ECDH keys (remote public key + role).
- RandomPeerSource.h / RandomPeerSource.cpp — Loads random peers from PeerManager matching a query, with local caching.
- BanManager.h / BanManagerImpl.h/.cpp — Manages a persistent ban list of NodeIDs in the database.
- SurveyManager.h / SurveyManager.cpp — Orchestrates time-sliced overlay network surveys.
- SurveyDataManager.h / SurveyDataManager.cpp — Collects and finalizes per-node and per-peer survey data.
- SurveyMessageLimiter.h / SurveyMessageLimiter.cpp — Rate-limits and deduplicates survey messages.
- OverlayMetrics.h / OverlayMetrics.cpp — Central cache of medida metrics for the overlay (meters, timers, counters).
- OverlayUtils.h / OverlayUtils.cpp — Utility:
logErrorOrThrowfor error handling in overlay code. - StellarXDR.h — Convenience include aggregating all XDR headers used by overlay.
Key Classes and Data Structures
OverlayManager (abstract interface)
Defines the public API for managing the overlay network. Created via OverlayManager::create(app). Key pure virtual methods:
broadcastMessage(msg, hash)— Flood a message to all authenticated peers.recvFloodedMsgID(peer, msgID)— Record that a peer sent us a flooded message.recvTransaction(tx, peer, index)— Process incoming transaction, pass to Herder.recvTxDemand(dmd, peer)— Process incoming demand for a transaction.connectTo(address)— Initiate outbound connection.acceptAuthenticatedPeer(peer)— Promote peer from pending to authenticated.removePeer(peer)— Remove a peer in CLOSING state.clearLedgersBelow(ledgerSeq, lclSeq)— Purge old Floodgate/ItemFetcher data.start()/shutdown()— Lifecycle control.checkScheduledAndCache(tracker)— Deduplicate messages already scheduled for processing.getOverlayThreadSnapshot()— Get/create a bucket list snapshot for the overlay background thread.
Static helpers: isFloodMessage(msg), createTxBatch(), getFlowControlBytesBatch(cfg).
OverlayManagerImpl (concrete implementation)
Owns all major overlay components:
mInboundPeers,mOutboundPeers—PeersListstructs holding pending (vector) and authenticated (map by NodeID) peer collections, plus amDroppedset to extend lifetime until background I/O completes.mFloodGate(Floodgate) — Broadcast deduplication.mTxDemandsManager(TxDemandsManager) — Pull-mode demand scheduling.mSurveyManager(shared_ptr<SurveyManager>) — Network survey orchestration.mPeerManager(PeerManager) — Persistent peer record storage.mDoor(PeerDoor) — TCP listener.mAuth(PeerAuth) — Authentication key management.mOverlayMetrics(OverlayMetrics) — Metrics cache.mMessageCache(RandomEvictionCache<uint64_t, bool>) — Deduplicates received messages for metrics.mScheduledMessages(RandomEvictionCache<Hash, weak_ptr<CapacityTrackedMessage>>) — Tracks messages currently scheduled for processing to avoid duplicates.mPeerSources(map<PeerType, unique_ptr<RandomPeerSource>>) — Peer sources for INBOUND, OUTBOUND, PREFERRED types.mResolvedPeers(future<ResolvedPeers>) — Async DNS resolution result.mOverlayThreadSnapshot— Bucket list snapshot for overlay thread use only.
Inner struct PeersList:
mPending(vector<Peer::pointer>) — Peers that have connected but not yet authenticated.mAuthenticated(map<NodeID, Peer::pointer>) — Fully authenticated peers.mDropped(unordered_set<Peer::pointer>) — Dropped peers kept alive until background I/O finishes.- Methods:
byAddress(),removePeer(),moveToAuthenticated(),acceptAuthenticatedPeer(),shutdown().
Peer (abstract base class)
Represents a single connected peer. Inherits enable_shared_from_this. Key state:
mState—CONNECTING,CONNECTED,GOT_HELLO,GOT_AUTH,CLOSING. Protected bymStateMutex(recursive mutex).mRole—WE_CALLED_REMOTEorREMOTE_CALLED_US(const after construction).mFlowControl(shared_ptr<FlowControl>) — Per-peer flow control instance.mTxAdverts(shared_ptr<TxAdverts>) — Per-peer transaction advertisement state.mHmac(Hmac) — Per-connection HMAC keys and sequence counters.mPeerMetrics(PeerMetrics) — Atomic counters for per-peer statistics.mSendNonce/mRecvNonce— Random nonces for key derivation.mPeerID(NodeID) — Remote node's public key (set during HELLO).mAddress(PeerBareAddress) — Remote address.mRecurringTimer— Fires every 5s for ping, idle timeout, straggler checks.mDelayedExecutionTimer— One-shot timer for delayed operations.
Key methods:
sendMessage(msg)— Enqueue a message for sending. Flood messages go through FlowControl; non-flood messages are sent directly viasendAuthenticatedMessage().recvRawMessage(tracker)— Entry point for processing a received message from the background thread. Posts to main thread.recvMessage(tracker)— Main-thread message dispatch (called from main). Dispatches torecvHello,recvAuth,recvTransaction,recvSCPMessage,recvFloodAdvert,recvFloodDemand, etc.beginMessageProcessing(msg)/endMessageProcessing(msg)— Bracket message processing to track flow control capacity.endMessageProcessingmay sendSEND_MORE_EXTENDEDto request more data.sendHello()/sendAuth()— Handshake messages.shutdownAndRemovePeer(reason, direction)— Set state to CLOSING, remove from OverlayManager.maybeExecuteInBackground(name, f)— Post work to overlay thread if background processing is enabled.- Pull mode facade:
sendAdvert(hash),sendTxDemand(demands),retryAdvert(hashes),hasAdvert(),popAdvert(). recurrentTimerExpired()— Checks idle timeout, straggler timeout, and no-outbound-capacity timeout.
CapacityTrackedMessage
RAII wrapper for a received StellarMessage. On construction, calls Peer::beginMessageProcessing to lock flow control capacity. On destruction, calls Peer::endMessageProcessing to release capacity and potentially send SEND_MORE. Also pre-computes BLAKE2 hash for SCP/TX messages and optionally pre-populates signature cache on the overlay thread.
Members:
mWeakPeer— Weak reference to the owning Peer.mMsg— The StellarMessage.mMaybeHash— Optional BLAKE2 hash (for SCP_MESSAGE and TRANSACTION types).mTxsMap— Map from hash to pre-constructedTransactionFrameBasePtr(with pre-cached hashes).
TCPPeer (concrete Peer subclass)
Implements TCP socket I/O using Asio's buffered_read_stream. Key details:
mSocket(shared_ptr<SocketType>) — The Asio TCP socket with 256KB buffer.ThreadRestrictedVars— Inner class ensuring write queue, write buffers, and incoming header/body vectors are only accessed from the correct thread (overlay thread when background processing is enabled).mWriteQueue(deque<TimestampedMessage>) — Outgoing message queue.mDropStarted(atomic<bool>) — Ensures drop is initiated only once across threads.mLiveInboundPeersCounter(shared_ptr<int>) — Shared counter tracking live inbound TCPPeers for load shedding.
Static factory methods:
initiate(app, address)— Create outbound connection; resolves address, callsasync_connect.accept(app, socket)— Create from an accepted inbound socket; starts reading immediately.
Key methods:
sendMessage(xdrBytes, msg)— Enqueues XDR bytes intomWriteQueue, callsmessageSender().messageSender()— Batches queued messages intomWriteBuffers, callsasync_write.scheduleRead()/startRead()— Initiates async read of 4-byte header, then body.readHeaderHandler()/readBodyHandler()— Process received data; constructCapacityTrackedMessage, callrecvRawMessage.writeHandler()— Completes write, processes sent messages viaFlowControl::processSentMessages, sends next batch.drop(reason, direction)— Atomic drop initiation; shuts down socket, posts cleanup to main thread.
FlowControl (thread-safe)
Per-peer flow control managing both inbound capacity tracking and outbound message queuing. Protected by mFlowControlMutex.
Key state:
mFlowControlCapacity(FlowControlMessageCapacity) — Tracks message-count capacity.mFlowControlBytesCapacity(FlowControlByteCapacity) — Tracks byte-count capacity.mOutboundQueues(FloodQueues<QueuedOutboundMessage>, array of 4 deques) — Priority-ordered: [0] SCP, [1] transactions, [2] demands, [3] adverts.mTxQueueByteCount,mAdvertQueueTxHashCount,mDemandQueueTxHashCount— Size trackers for load shedding.mFloodDataProcessed/mFloodDataProcessedBytes— Counters since last SEND_MORE.mLastThrottle— Timestamp when reading was last throttled.mNoOutboundCapacity— Timestamp when outbound capacity was last exhausted.
Key methods:
addMsgAndMaybeTrimQueue(msg)— Add flood message to appropriate priority queue; shed oldest transactions if byte limit exceeded; shed excess adverts/demands.getNextBatchToSend()— Dequeue messages across all priorities while outbound capacity is available; lock capacity for each sent message.beginMessageProcessing(msg)— Lock local reading capacity for an incoming message.endMessageProcessing(msg)— Release local capacity; returnSendMoreCapacityindicating how much to request from the peer.maybeThrottleRead()— If local capacity is exhausted, mark peer as throttled.stopThrottling()— Resume reading from a throttled peer.processSentMessages(sentMessages)— After async_write completes, remove sent messages from front of queues and update size trackers.isSendMoreValid(msg, errorMsg)— Validate a received SEND_MORE message.
FlowControlCapacity (abstract base)
Base class for capacity tracking. Two subclasses:
FlowControlMessageCapacity— Tracks by message count. Capacity limits come from config (PEER_FLOOD_READING_CAPACITY).FlowControlByteCapacity— Tracks by byte count. Limits come fromOverlayManager::getFlowControlBytesTotal(). SupportshandleTxSizeIncrease()for protocol upgrades that increase max tx size.
Both track:
mCapacity.mFloodCapacity— Local reading capacity for flood messages.mCapacity.mTotalCapacity— Optional total capacity (flood + non-flood).mOutboundCapacity— How much the remote peer has allowed us to send.
Floodgate
Ensures each broadcast message is sent/received at most once per peer. Uses a FloodRecord per message hash.
Key state:
mFloodMap(map<Hash, FloodRecord::pointer>) — Hash ofStellarMessage→ record of which peers have been told.
Key methods:
addRecord(peer, msgID)— Record thatpeersent us message with hashmsgID. Returns true if new.broadcast(msg, hash)— Send message to all authenticated peers that haven't been told. For transactions (pull mode), sends adverts instead of the full message.clearBelow(maxLedger)— Remove records for ledgers older thanmaxLedger.getPeersKnows(msgID)— Return set of peers that have seen a given message.forgetRecord(msgID)— Remove a record (e.g., when tx is rejected).
ItemFetcher
Manages fetching of tx sets and quorum sets via anycast. One ItemFetcher per item type, each with a configurable AskPeer delegate (e.g., sendGetTxSet or sendGetQuorumSet).
Key state:
mTrackers(map<Hash, shared_ptr<Tracker>>) — One Tracker per item hash being fetched.
Key methods:
fetch(hash, envelope)— Start or join fetching of itemhashneeded by SCPenvelope.stopFetch(hash, envelope)— Remove interest from a specific envelope.recv(hash, timer)— Item received; cancel tracker, re-process waiting envelopes via Herder.doesntHave(hash, peer)— Peer reported DONT_HAVE; try next peer.stopFetchingBelow(slotIndex, slotToKeep)— Cleanup old trackers.
Tracker
Tracks a single item fetch across multiple peers. Tries peers sequentially with 1.5s timeout per attempt.
Key state:
mPeersAsked(map<Peer::pointer, bool>) — Which peers have been tried.mWaitingEnvelopes(vector<pair<Hash, SCPEnvelope>>) — Envelopes waiting for this data.mTimer— Timeout timer for current fetch attempt.mNumListRebuild— Number of times the peer list has been rebuilt (max 20 tries).
Key methods:
tryNextPeer()— Pick an authenticated peer that hasn't been tried (or rebuild list), send request viamAskPeerdelegate, start timeout timer.doesntHave(peer)— Mark peer and try next.listen(env)/discard(env)— Add/remove envelopes from wait list.cancel()— Stop timer and fetching.
TxAdverts
Per-peer transaction advertisement management. Handles both incoming adverts (hashes to demand) and outgoing adverts (hashes to advertise).
Key state:
mIncomingTxHashes(deque<Hash>) — FIFO queue of hashes received from this peer.mTxHashesToRetry(list<Hash>) — Hashes to retry demanding.mAdvertHistory(RandomEvictionCache<Hash, uint32_t>) — Seen hash cache (50k entries).mOutgoingTxHashes(TxAdvertVector) — Batch of hashes to advertise to this peer.mAdvertTimer— Periodic flush timer.mSendCb— Callback to send the advert message.
Key methods:
queueOutgoingAdvert(hash)— Add hash to outgoing batch; flush if batch is full or timer fires.queueIncomingAdvert(hashes, seq)— Deduplicate and enqueue incoming hashes.popIncomingAdvert()— Pop next hash (retries first, then incoming queue).retryIncomingAdvert(list)— Re-queue hashes for retry after failed demand.seenAdvert(hash)— Check if hash was already seen.clearBelow(ledgerSeq)— Remove stale advert history entries.
TxDemandsManager
Global demand scheduling for pull-mode transactions. Runs on a periodic timer (FLOOD_DEMAND_PERIOD_MS, default 200ms).
Key state:
mDemandHistoryMap(UnorderedMap<Hash, DemandHistory>) — Tracks per-hash demand history (peers tried, timestamps, retry count).mPendingDemands(queue<Hash>) — FIFO of all demanded hashes for cleanup.mDemandTimer— Periodic demand timer.
Key methods:
demand()— Main demand loop: iterates over authenticated peers with pending adverts, determines demand status per hash (DEMAND / RETRY_LATER / DISCARD), batches demands, sendsFLOOD_DEMANDmessages. Uses linear backoff up to 2s between retries, max 15 retry attempts.recvTxDemand(dmd, peer)— Process incoming demand: look up transactions in Herder, send back if available; track metrics for fulfilled/unfulfilled demands.recordTxPullLatency(hash, peer)— Record latency from first demand to receipt.
PeerManager
Persists peer records in the database. Each peer record stores: address (IP:port), number of failures, next attempt time, type (inbound/outbound/preferred).
Key methods:
ensureExists(address)— Insert if not present.update(address, type, preferredTypeKnown, backOff)— Update type and/or backoff. Type transitions: outbound→preferred (upgrade), preferred→outbound (downgrade only if definitely not preferred).loadRandomPeers(query, size)— Load random peers matching criteria from DB.removePeersWithManyFailures(minFailures)— Purge dead peers.getPeersToSend(size, address)— Select peers to recommend to a requesting peer.
PeerDoor
TCP listener using Asio acceptor. Calls TCPPeer::accept() to create inbound peers, then OverlayManager::maybeAddInboundConnection() to register them.
PeerAuth
Handles per-connection authentication key derivation:
- Generates ephemeral Curve25519 keypair on startup.
- Creates
AuthCert(signed ephemeral public key with expiration). - Derives shared HMAC keys via:
HKDF(ECDH(local_secret, remote_public) || local_pub || remote_pub), then per-session send/recv keys viaHKDF_expandwith nonces. - Uses
RandomEvictionCachefor shared key caching.
Hmac
Per-connection HMAC state (thread-safe via mutex):
mSendMacKey/mRecvMacKey— HMAC-SHA256 keys.mSendMacSeq/mRecvMacSeq— Monotonic sequence numbers preventing replay.checkAuthenticatedMessage()— Verify incoming message MAC and sequence.setAuthenticatedMessageBody()— Compute and set MAC on outgoing message.
SurveyManager
Orchestrates time-sliced network surveys. Supports two phases: Collecting (gathering data) and Reporting (answering queries).
Key state:
mSurveyDataManager(SurveyDataManager) — Manages collected data.mMessageLimiter(SurveyMessageLimiter) — Rate-limits survey messages.mPeersToSurveyQueue— Queue of nodes to survey.mRunningSurveyReportingPhase— Whether in reporting phase.mCurve25519SecretKey/PublicKey— Keys for encrypting survey responses.
Key methods:
broadcastStartSurveyCollecting(nonce)/broadcastStopSurveyCollecting()— Start/stop collecting phase.startSurveyReporting()/stopSurveyReporting()— Start/stop reporting phase.addNodeToRunningSurveyBacklog(node, inIdx, outIdx)— Queue a node for surveying.relayOrProcessRequest/Response(msg, peer)— Route survey messages.updateSurveyPhase(...)— Called from OverlayManager tick to check phase transitions/timeouts.
SurveyDataManager
Thread-safe data collection for time-sliced surveys.
Key state:
mCollectingNodeData(optional<CollectingNodeData>) — Node-level stats during collecting.mCollectingInboundPeerData/mCollectingOutboundPeerData(unordered_map<NodeID, CollectingPeerData>) — Per-peer stats during collecting.mFinalNodeData,mFinalInboundPeerData,mFinalOutboundPeerData— Finalized data for reporting.mPhase—COLLECTING,REPORTING, orINACTIVE.
RandomPeerSource
Loads random peers from PeerManager matching a query. Maintains a local cache that is refreshed from the database when exhausted.
BanManager / BanManagerImpl
Persistent ban list stored in the database. Methods: banNode(id), unbanNode(id), isBanned(id), getBans().
OverlayMetrics
Centralized cache of medida metrics for the overlay. Thread-safe (medida is thread-safe). Groups meters/timers/counters for: message read/write, byte read/write, async I/O, per-message-type recv/send timers, connection latency, flow control throttle, outbound queue delays/drops, flood bytes (unique/duplicate), demand/pull metrics.
Key Control Loops, Threads, and Tasks
Main Thread (tick() loop)
OverlayManagerImpl::tick() runs every PEER_AUTHENTICATION_TIMEOUT + 1 seconds (default 3s):
- Cleans up unreferenced dropped peers (use_count == 1).
- Checks if DNS resolution future is ready; stores resolved peers, schedules next resolution.
- Updates survey phase via
SurveyManager::updateSurveyPhase(). - Connects to preferred peers (highest priority).
- If out of sync, may randomly drop a non-preferred outbound peer.
- Connects to outbound peers (from DB).
- Attempts to promote inbound peers to outbound.
Overlay Background Thread
When BACKGROUND_OVERLAY_PROCESSING is enabled, TCP socket I/O (async_read, async_write) runs on a dedicated overlay thread (Application::getOverlayIOContext()). Key operations on overlay thread:
TCPPeer::readHeaderHandler()/readBodyHandler()— Read messages from socket.TCPPeer::writeHandler()— Process write completions, callFlowControl::processSentMessages().TCPPeer::messageSender()— Batch and send queued messages.CapacityTrackedMessageconstructor — Pre-parses transactions, optionally verifies signatures in background.Peer::recvRawMessage()— Posts received message to main thread for processing.
Peer Recurrent Timer
Each Peer runs a 5-second recurring timer (startRecurrentTimer()) checking:
- Idle timeout: no read/write for
PEER_TIMEOUTseconds (authenticated) orPEER_AUTHENTICATION_TIMEOUT(pending). - Straggler timeout: last write enqueue too old (
PEER_STRAGGLER_TIMEOUT). - Flow control timeout: no outbound capacity for
PEER_SEND_MODE_IDLE_TIMEOUT(60s).
Demand Timer
TxDemandsManager::demand() fires every FLOOD_DEMAND_PERIOD_MS (default 200ms):
- Purges obsolete demand history entries.
- Iterates over authenticated peers with pending adverts.
- For each hash, checks demand status (demand/retry/discard).
- Batches demands up to
getMaxDemandSize(), sendsFLOOD_DEMANDto peer. - Handles retry failures by requeueing hashes via
peer->retryAdvert().
Advert Timer
Per-peer TxAdverts::flushAdvert() fires after FLOOD_ADVERT_PERIOD_MS or when batch is full. Sends accumulated outgoing adverts as a single FLOOD_ADVERT message.
DNS Resolution
triggerPeerResolution() resolves KNOWN_PEERS and PREFERRED_PEERS on a background thread. Results are picked up in tick() and stored via storePeerList(). Retry with backoff on failure; resolves again every 600s on success.
Ownership Relationships
Application
└─ OverlayManagerImpl (unique_ptr)
├─ PeerDoor (value) — TCP acceptor
├─ PeerAuth (value) — authentication key manager
├─ PeerManager (value) — database peer records
├─ Floodgate (value) — broadcast deduplication
├─ TxDemandsManager (value) — demand scheduling
├─ SurveyManager (shared_ptr)
│ ├─ SurveyDataManager (value)
│ └─ SurveyMessageLimiter (value)
├─ OverlayMetrics (value)
├─ PeersList mInboundPeers (value)
│ ├─ mPending: vector<Peer::pointer>
│ ├─ mAuthenticated: map<NodeID, Peer::pointer>
│ └─ mDropped: unordered_set<Peer::pointer>
├─ PeersList mOutboundPeers (value) — same structure
└─ RandomPeerSource[3] (unique_ptr per PeerType)
Peer (shared_ptr, TCPPeer concrete)
├─ FlowControl (shared_ptr)
│ ├─ FlowControlMessageCapacity (value)
│ └─ FlowControlByteCapacity (value)
├─ TxAdverts (shared_ptr)
├─ Hmac (value)
├─ PeerMetrics (value)
└─ TCPPeer::SocketType (shared_ptr) — Asio socket
Key Data Flows
Connection Handshake
- Initiator calls
TCPPeer::initiate()→async_connect→connectHandler→sendHello(). - Responder:
PeerDoor::acceptNextPeer()→TCPPeer::accept()→maybeAddInboundConnection()→startRead(). - Both sides:
recvHello()validates version, network ID, addresses →recvAuth()sets up HMAC keys viaPeerAuth, callsacceptAuthenticatedPeer()→moveToAuthenticated(). - After auth: peers send
SEND_MORE_EXTENDEDto indicate initial reading capacity, exchange peer lists, start adverts.
Transaction Flooding (Pull Mode)
- Herder calls
OverlayManager::broadcastMessage(tx_msg, hash). Floodgate::broadcast()sendsFLOOD_ADVERT(hash only) to each peer not already told.- Per-peer
TxAdverts::queueOutgoingAdvert()batches hashes; flushed on timer or batch full. - Remote peer receives advert →
Peer::recvFloodAdvert()→TxAdverts::queueIncomingAdvert(). TxDemandsManager::demand()timer fires → picks hashes from peers → sendsFLOOD_DEMAND.- Remote peer receives demand →
TxDemandsManager::recvTxDemand()→ looks up tx in Herder → sends fullTRANSACTIONmessage back. Peer::recvTransaction()→OverlayManager::recvTransaction()→Herder::recvTransaction().
SCP Message Flooding (Push Mode)
- Herder calls
broadcastMessage(scp_msg). Floodgate::broadcast()sends fullSCP_MESSAGEto all peers not yet told.- Messages go through
FlowControl::addMsgAndMaybeTrimQueue()with priority 0 (highest). - Remote peer receives →
recvSCPMessage()→ posted to main thread → dispatched to Herder.
Anycast Fetch (TX Sets / Quorum Sets)
- Herder needs a tx set or quorum set → calls
ItemFetcher::fetch(hash, envelope). ItemFetchercreates/reuses aTrackerfor the hash.Tracker::tryNextPeer()picks a peer, sendsGET_TX_SETorGET_SCP_QUORUMSET.- Remote peer responds with the data, or
DONT_HAVE. - On
DONT_HAVE:Tracker::doesntHave()→ try next peer. - On receipt:
ItemFetcher::recv()→ cancel tracker → re-submit waiting envelopes to Herder.
Flow Control
- On connection, both sides start with initial flood reading capacity (messages + bytes).
- When peer sends flood data, it consumes outbound capacity (
lockOutboundCapacity). - Receiver processes message, releasing local capacity via
endMessageProcessing(). - When enough capacity freed (batch threshold), receiver sends
SEND_MORE_EXTENDED(numMessages, numBytes). - Sender receives
SEND_MORE_EXTENDED→FlowControl::maybeReleaseCapacity()→ unlocks outbound capacity → can send more. - If outbound capacity exhausted, messages queue up. Oldest tx messages are shed if byte limit exceeded.
- If reading capacity exhausted,
maybeThrottleRead()stops scheduling reads until capacity is freed.
> related_skills --same-repo
> validating-a-change
comprehensive validation of a change to ensure it is correct and ready for a pull request
> regenerating a technical summary of stellar-core
Instructions for regenerating the full set of subsystem and whole-system technical summary skill documents for stellar-core
> subsystem-summary-of-work
read this skill for a token-efficient summary of the work subsystem
> subsystem-summary-of-util
read this skill for a token-efficient summary of the util subsystem