The protocol handshake and how messages (proposals, validations, transactions) are relayed and squelched — plus a look at proposed protocol extensions.
What you'll learn
≈30 min · Advanced · builds on Peer discovery & connection lifecycle
Now let's watch messages actually move. In this module you'll learn the HTTP-upgrade handshake that starts a peer session, how proposals, validations and transactions are relayed across the mesh, and how squelching and reduce-relay cut the redundant traffic that would otherwise drown a large network. You'll also get a glimpse of where the protocol is heading next.
In brief: what the protocol handshake has to establish before two peers exchange data.
The handshake accomplishes several essential goals:
Authentication: Each node proves its identity using cryptographic signatures. This prevents impersonation attacks where a malicious node pretends to be a trusted validator.
Protocol Negotiation: Nodes agree on the protocol version and features they will use for communication. This enables the network to evolve while maintaining backward compatibility.
Trust Establishment: Both parties verify that the other is a legitimate participant running compatible software. This ensures network integrity.
Capability Exchange: Nodes share information about their supported features, enabling peers to optimize their communication strategies.
In brief: a peer session starts as an HTTP Upgrade request, then switches to the peer protocol.
(README)
Key idea. Relaying uses squelching and reduce-relay so a node does not forward the same proposal or validation from every peer. That is what keeps a large network's traffic manageable.
In brief: the code that accepts a connection and starts relaying messages.
PeerImp::run (PeerImp.cpp):
doAccept(). If outbound, calls doProtocolStart().PeerImp::doAccept (PeerImp.cpp):
overlay_.activate(shared_from_this()) to register the peer as active.doProtocolStart().The handshake protocol establishes secure, authenticated connections between XRP Ledger nodes. Through TLS encryption, cryptographic signatures, and careful protocol negotiation, it ensures that only legitimate nodes can participate in the network while maintaining compatibility across different software versions. Understanding this process is essential for diagnosing connection issues and implementing protocol enhancements.
Title: Quantum-Resistant Signatures
Revision: 1 (2025-07-08)
Type: Draft
Author:
Atharva Lele, Trinity College Dublin
Denis Angell, XRPL Labs
This proposal introduces quantum-resistant digital signatures to the XRP Ledger (XRPL) using the Dilithium post-quantum cryptographic algorithm. The amendment provides accounts with the ability to use quantum-resistant signatures for enhanced security against future quantum computing threats while maintaining backward compatibility with existing signature schemes.
As quantum computing advances, current cryptographic signatures (secp256k1, ed25519) may become vulnerable to quantum attacks. This proposal adds support for Dilithium, a NIST-standardized post-quantum signature algorithm, ensuring long-term security for XRPL accounts.
This feature enables accounts to use quantum-resistant signatures with an optional enforcement mechanism.
The amendment adds:
KeyType::dilithium = 2)lsfForceQuantum to enforce quantum-resistant signaturesThe quantum-resistant signatures implementation is currently under active development in the following branch:
Repository: Transia-RnD/rippled
Branch: dilithium-full
This branch contains the working implementation of the quantum-resistant signature system, including:
lsfForceQuantum flag enforcement mechanismsThe dilithium-full branch includes:
Developers interested in contributing to the quantum-resistant signatures implementation should:
dilithium-full branchdilithium-full branch| Aspect | secp256k1 | ed25519 | Dilithium |
|---|---|---|---|
| Public Key Size | 33 bytes | 33 bytes | 1312 bytes |
| Secret Key Size | 32 bytes | 32 bytes | 2528 bytes |
| Signature Size | ~70 bytes | 64 bytes | ~2420 bytes |
| Security Level | 128-bit | 128-bit | 128-bit (quantum-resistant) |
// Generate quantum-resistant keys
auto keyPair = generateKeyPair(KeyType::dilithium, seed);
auto secretKey = randomSecretKey(KeyType::dilithium);
std::optional<KeyType> publicKeyType(Slice const& slice) {
if (slice.size() == 33) {
if (slice[0] == 0xED) return KeyType::ed25519;
if (slice[0] == 0x02 || slice[0] == 0x03) return KeyType::secp256k1;
}
else if (slice.size() == CRYPTO_PUBLICKEYBYTES) {
return KeyType::dilithium; // 1312 bytes
}
return std::nullopt;
}
lsfForceQuantum Flag| Field | Value | Description |
|---|---|---|
lsfForceQuantum |
0x02000000 |
When set, account requires quantum-resistant signatures |
asfForceQuantum |
11 |
AccountSet flag to enable/disable quantum requirement |
{
"TransactionType": "AccountSet",
"Account": "rAccount...",
"SetFlag": 11 // Enable quantum-only signatures
}
if (account.isFlag(lsfForceQuantum) && publicKey.size() != DILITHIUM_PK_SIZE)
return telBAD_PUBLIC_KEY;
case KeyType::dilithium: {
uint8_t sig[CRYPTO_BYTES];
size_t len;
crypto_sign_signature(sig, &len, message.data(), message.size(), secretKey.data());
return Buffer{sig, len};
}
if (keyType == KeyType::dilithium) {
return crypto_sign_verify(
sig.data(), sig.size(),
message.data(), message.size(),
publicKey.data()) == 0;
}
lsfForceQuantum| Error Code | Description |
|---|---|
telBAD_PUBLIC_KEY |
Non-quantum signature used with lsfForceQuantum account |
As quantum-resistant signatures become standard, several validator-related components will require updates:
// From seed
auto seed = generateSeed("masterpassphrase");
auto keyPair = generateKeyPair(KeyType::dilithium, seed);
// Random generation
auto secretKey = randomSecretKey(KeyType::dilithium);
auto publicKey = derivePublicKey(KeyType::dilithium, secretKey);
{
"TransactionType": "AccountSet",
"Account": "rQuantumAccount...",
"SetFlag": 11
}
auto signature = sign(publicKey, secretKey, transactionData);
bool isValid = verify(publicKey, transactionData, signature);
Efficient message propagation is essential for a decentralized ledger. Transactions must reach validators quickly, proposals must spread to enable consensus, and validations must propagate to finalize ledgers. The overlay network's message relaying system ensures information flows efficiently while preventing network overload through intelligent squelching.
This lesson explores how messages propagate through the network and how Rippled optimizes this process to handle high-throughput scenarios.
OverlayImpl::relay(protocol::TMProposeSet& m, uint256 const& uid, PublicKey const& validator) (OverlayImpl.cpp):
app_.getHashRouter().shouldRelay(uid) to determine if the proposal should be relayed.Slot::update (Slot.h):
OverlayImpl::unsquelch (OverlayImpl.cpp):
squelch=false for the validator.This module showed messages actually moving across the mesh. A peer session begins as an HTTP Upgrade request, then proposals, validations, and transactions are relayed between peers, and squelching and reduce-relay suppress redundant duplicates so a large network's traffic stays manageable. You also glimpsed a proposed protocol extension for quantum-resistant signatures.
To remember:
PeerImp::run / doAccept)src/xrpld/overlay/detailNext up. Peers talk to peers; everyone else knocks on a different door. New phase: the RPC architecture, from port to handler and back.
Resources
Assignments
0 of 2 complete