How rippled nodes talk on the wire — the peer protocol, protobuf message types, and where message handling lives.
What you'll learn
≈60 min · Advanced · builds on Development & debugging techniques
Watch this short video by XRPL Commons first, then dive into the details below.
Nodes don't speak JSON to each other, they speak a compact binary protocol. In this module you'll learn how peers talk on the wire: the Protocol Buffers definitions in xrpl.proto, the message types that carry transactions, proposals and validations (tmTRANSACTION, tmVALIDATION…), and where that message handling lives in the code. It's the vocabulary behind everything the network does.
In brief: how peers connect and form the overlay that carries all traffic.
The XRP Ledger operates as a decentralized network of Rippled servers (nodes) that communicate through peer-to-peer connections. Each node maintains connections with multiple peers, forming an overlay network on top of the internet infrastructure. This architecture ensures no single point of failure and enables the network to remain operational even if individual nodes go offline.
Unlike traditional client-server architectures where clients connect to centralized servers, the XRP Ledger uses a mesh topology where every node can communicate with multiple other nodes. This design provides:
Nodes discover peers through several complementary mechanisms, ensuring robust network connectivity:
1. Configured Peer Lists
Administrators can specify fixed peers in the xrpld.cfg configuration file:
[ips_fixed]
r.ripple.com 51235
s1.ripple.com 51235
s2.ripple.com 51235
These peers are trusted connections that the node will always attempt to maintain. Fixed peers are particularly important for validators and high-availability servers.
2. DNS Seeds
Rippled uses DNS to discover bootstrap nodes:
3. Peer Gossip
Once connected, nodes share information about other available peers:
This multi-layered approach ensures that even if some discovery mechanisms fail, nodes can still find and connect to peers, maintaining network connectivity.
Each Rippled node actively manages its peer connections:
Connection Limits: Nodes maintain a configured number of active connections (typically 10-20 peers) to balance network visibility with resource usage.
Peer Quality Assessment: Nodes continuously evaluate peer behavior:
Connection Pruning: Poor-quality peers are disconnected and replaced with better alternatives.
Connection Diversity: Nodes prefer geographically and administratively diverse peers to improve network resilience.
In brief: every peer message is a Protocol Buffers type defined in xrpl.proto.
Rippled uses Protocol Buffers (protobuf) for efficient binary serialization of messages exchanged between nodes. This choice provides several advantages:
Compact Message Sizes: Binary encoding is more efficient than text-based formats like JSON, reducing bandwidth usage.
Fast Serialization: Protobuf libraries provide high-performance encoding and decoding, critical for high-throughput systems.
Forward/Backward Compatibility: Protocol Buffers support schema evolution, allowing the protocol to evolve without breaking existing nodes.
Strong Typing: Protocol definitions provide clear contracts for message formats, reducing errors.
Cross-Language Support: Protobuf supports multiple languages, facilitating development of diverse XRPL tools.
Protocol messages are defined in .proto files located in the Rippled codebase. These definitions are compiled into C++ classes used throughout the application.
Example Structure:
message TMTransaction {
required bytes raw_transaction = 1;
required uint32 status = 2;
optional bytes signature = 3;
}
The compiled classes provide methods for:
Key idea. Peers do not exchange JSON. Every message is a compact protobuf defined in
xrpl.proto, which is the single source of truth for the wire format.
In brief: the handful of messages that matter most: transactions, proposals, validations, ledger data.
Understanding message types is essential for debugging network issues and implementing protocol improvements. Each message type serves a specific purpose in maintaining network consensus and ledger synchronization.
Purpose: Validator key rotation and identity verification
Validators use manifests to announce their identity and key rotation information. This allows validators to change their signing keys without losing their identity, improving security by enabling regular key rotation.
Key Information:
When Sent:
Purpose: Transaction propagation across the network
When a transaction is submitted to any node, it needs to reach all validators to be considered for inclusion in the next ledger. The tmTRANSACTION message broadcasts transactions throughout the network.
Key Information:
Routing Logic:
Purpose: Consensus proposals from validators
During the consensus process, validators broadcast their proposed transaction sets. These proposals inform other validators about which transactions should be included in the next ledger.
Key Information:
Consensus Flow:
Purpose: Ledger validations signaling agreement
After a ledger closes, validators broadcast validations confirming their agreement on the ledger state. A ledger becomes fully validated when it receives validations from a supermajority of trusted validators.
Key Information:
Validation Process:
Purpose: Request and response for ledger synchronization
When a node is behind or missing ledger data, it requests information from peers. These messages enable ledger history synchronization.
tmGET_LEDGER Fields:
tmLEDGER_DATA Fields:
Use Cases:
Purpose: Notifications about ledger close events
Nodes broadcast status changes to inform peers about important events, particularly ledger closures. This helps the network stay synchronized on the current ledger state.
Key Information:
In brief: how a message spreads across the mesh without flooding it.
When a node receives a message, it must decide whether to relay it to other peers. Rippled implements intelligent routing to prevent message flooding while ensuring necessary information reaches all relevant nodes.
1. Duplicate Suppression (Echo Prevention)
Problem: Without duplicate suppression, messages would bounce back to their sender, creating infinite loops. (Note: "squelching" is a different, specific mechanism, the reduce-relay muting of redundant validator-message senders via TMSquelch; see the Handshake & message relaying module.)
Solution: When node A sends a message to node B, node B remembers that A already has this message and won't send it back to A.
Implementation: Each message carries an originator identifier, and nodes track which peers already have which messages.
2. Deduplication
Problem: The same message might arrive from multiple peers, wasting processing resources.
Solution: Nodes track recently seen messages using a hash-based cache. If a message hash is already in the cache, it's discarded without reprocessing.
Cache Management:
3. Selective Relay
Problem: Not all peers need all messages. Broadcasting everything wastes bandwidth.
Solution: Messages are only relayed to peers that are likely to need them based on:
4. Priority Queuing
Problem: Under high load, important messages might be delayed behind less critical ones.
Solution: Messages are categorized by importance and processed in priority order:
High Priority:
Medium Priority:
Low Priority:
Let's trace how a transaction propagates through the network:
Total time: Typically 3-5 seconds from submission to ledger inclusion.
The process of two Rippled nodes establishing a connection involves multiple steps, each verifying compatibility and authenticity:
The protocol implementation is primarily located in src/xrpld/overlay. Understanding this directory structure is essential for working with networking code.
Primary Files
src/xrpld/overlay/detail/OverlayImpl.h and .cpp
src/xrpld/overlay/detail/PeerImp.h and .cpp
Finding Message Handlers:
// Look in PeerImp.cpp for message processing
void PeerImp::onMessage(std::shared_ptr<Message> const& m)
{
switch(m->getType())
{
case protocol::mtTRANSACTION:
onTransaction(m);
break;
case protocol::mtVALIDATION:
onValidation(m);
break;
// ... other message types
}
}
Understanding Peer Connection State:
// Peer states (simplified)
enum class State
{
connecting, // TCP connection in progress
connected, // TCP connected, handshake in progress
active, // Fully connected and operational
closing, // Graceful shutdown in progress
closed // Connection terminated
};
Message Creation Example:
// Creating and sending a transaction message
protocol::TMTransaction tx;
tx.set_rawtransaction(serializedTx);
tx.set_status(protocol::tsCURRENT);
send(std::make_shared<Message>(tx, protocol::mtTRANSACTION));
xrpld log_level Overlay trace
This will produce very detailed logs showing every message sent and received.
**Step 2**: Set up two Rippled instances in standalone mode
```bash
# Terminal 1 - Node A
xrpld --conf=/path/to/rippled-node1.cfg --standalone
# Terminal 2 - Node B
xrpld --conf=/path/to/rippled-node2.cfg --standalone
Step 3: Configure nodes to peer with each other
In rippled-node1.cfg:
[ips_fixed]
127.0.0.1 51236
In rippled-node2.cfg:
[port_peer]
port = 51236
ip = 127.0.0.1
[ips_fixed]
127.0.0.1 51235
Observation Tasks
Task 1: Observe connection establishment
Watch the logs as the nodes connect. You should see:
Task 2: Submit a transaction
# Submit to Node A
xrpld submit <signed_transaction>
Watch the logs to see:
tmTRANSACTION message created on Node ATask 3: Trigger a ledger close
# In standalone mode
xrpld ledger_accept
Observe:
Analysis Questions
Answer these questions based on your observations:
You should gain practical understanding of:
src/xrpld/overlay - Overlay network implementationinclude/xrpl/proto/xrpl.proto - Protocol Buffer message definitionssrc/xrpld/overlay/detail/OverlayImpl.cpp - Core networking logicsrc/xrpld/overlay/detail/PeerImp.cpp - Peer connection handlingThis module covered how nodes talk on the wire. Peers exchange compact Protocol Buffers messages defined in xrpl.proto, each type (tmTRANSACTION, tmVALIDATION, tmPROPOSE_LEDGER, and so on) serving a specific role, and those messages spread across the mesh through intelligent routing rather than naive flooding. You also saw where message handling lives in the overlay code.
To remember:
include/xrpl/proto/xrpl.prototmTRANSACTION, tmVALIDATION, tmPROPOSE_LEDGER, tmGET_LEDGER / tmLEDGER_DATA, tmMANIFESTS, tmSTATUS_CHANGEprotocol::TMTransaction etc.; dispatch lives in PeerImp (src/xrpld/overlay)Next up. Nodes exchange messages about state; but what IS that state, exactly? Next you meet the ideas behind XRPL's state management, and the tree that makes tampering impossible.
Resources
Assignments
0 of 2 complete