mirror of
https://github.com/jmcorgan/fips.git
synced 2026-07-22 07:48:26 +00:00
Restructure design docs around protocol layers
Reorganize FIPS design documentation from implementation-centric structure (routing, gossip protocol, wire protocol, transports) to protocol-layer organization with clear service boundaries. New documents (8): - fips-transport-layer.md — transport layer spec - fips-link-layer.md — FLP spec (peer auth, link encryption, forwarding) - fips-session-layer.md — FSP spec (end-to-end encryption, sessions) - fips-ipv6-adapter.md — IPv6 adaptation (TUN, DNS, MTU enforcement) - fips-mesh-operation.md — routing, discovery, error recovery - fips-wire-formats.md — consolidated wire format reference - fips-spanning-tree.md — tree algorithm reference - fips-bloom-filters.md — bloom filter math reference Rewritten (2): - fips-intro.md — breadth-first intro with layer model diagrams - fips-software-architecture.md — slimmed to stable decisions Updated (3): - spanning-tree-dynamics.md — removed stale root refresh, aligned terminology - fips-configuration.md — fixed priority type (u16 → u8) - fips-state-machines.md — synced code examples with codebase Deleted (6): fips-transports.md, fips-wire-protocol.md, fips-gossip-protocol.md, fips-session-protocol.md, fips-routing.md, fips-tun-driver.md (content absorbed into new structure)
This commit is contained in:
@@ -3,9 +3,9 @@
|
||||
## What is FIPS?
|
||||
|
||||
FIPS is a self-organizing mesh network that can operate over any transport
|
||||
medium—radio, serial links, Tor, local networks, or the existing internet as
|
||||
an overlay. The long-term goal is infrastructure that can function alongside
|
||||
or ultimately replace dependence on the Internet.
|
||||
medium — radio, serial links, Tor, local networks, or the existing internet as
|
||||
an overlay. The long-term goal is infrastructure that can function alongside or
|
||||
ultimately replace dependence on the Internet.
|
||||
|
||||
Nodes in the mesh route traffic for each other using Nostr identities (npubs)
|
||||
as network addresses. Applications can access the mesh through a native FIPS
|
||||
@@ -15,7 +15,7 @@ as an IPv6 endpoint for compatibility with existing IP-based applications.
|
||||
## Why FIPS?
|
||||
|
||||
**Infrastructure independence**: The internet depends on centralized
|
||||
infrastructure—ISPs, backbone providers, DNS, certificate authorities. FIPS
|
||||
infrastructure — ISPs, backbone providers, DNS, certificate authorities. FIPS
|
||||
works over any transport that can carry packets: a LoRa radio link between
|
||||
mountain towns, a serial cable between air-gapped systems, onion-routed
|
||||
connections through Tor, or the existing internet as an overlay. When the
|
||||
@@ -38,80 +38,185 @@ and security credentials without coordination with any central authority. The
|
||||
identity system uses Nostr keypairs (secp256k1), so existing npub/nsec pairs
|
||||
work directly.
|
||||
|
||||
## How It Works (Overview)
|
||||
## A Self-Organizing Mesh
|
||||
|
||||
Each FIPS node selects which transports to use (Ethernet, radio links, internet
|
||||
overlay, etc.) and which peer nodes to connect to. From these local peering
|
||||
decisions, the distributed spanning tree and bloom filter propagation algorithms
|
||||
self-organize reachability and path information throughout the mesh.
|
||||
Traditional networks are built top-down. A central authority assigns addresses,
|
||||
configures routing tables, provisions hardware, and manages the topology. If the
|
||||
authority disappears or the infrastructure fails, the network fails with it.
|
||||
Nodes cannot reach each other without infrastructure mediating the connection.
|
||||
|
||||
Nodes form a spanning tree rooted at a deterministically-elected node. Each
|
||||
node knows its path to the root, enabling shortest-path routing to be
|
||||
calculated between any two nodes (not necessarily through the root). Bloom filters propagate reachability information so nodes can find
|
||||
each other. Traffic flows via greedy routing toward destinations, encrypted
|
||||
end-to-end.
|
||||
FIPS inverts this model. There is no central authority, no address assignment
|
||||
service, no routing table pushed from above. Each node generates its own
|
||||
identity from a cryptographic keypair. Each node independently decides which
|
||||
peers to connect to and which transports to use. From these local decisions
|
||||
alone, the network self-organizes:
|
||||
|
||||
Nodes with multiple transports automatically bridge between networks—the same
|
||||
routing logic works regardless of the underlying transport mix.
|
||||
- A **spanning tree** forms through distributed parent selection, giving every
|
||||
node a coordinate in the network without any node knowing the full topology
|
||||
- **Bloom filters** propagate through gossip, so each node learns which peers
|
||||
can reach which destinations — again without global knowledge
|
||||
- **Routing decisions** are made locally at each hop, using only the node's
|
||||
immediate peers and cached coordinate information
|
||||
|
||||
The result is a network that builds itself from the bottom up, heals around
|
||||
failures automatically, and scales without central coordination. Adding a node
|
||||
is as simple as connecting to one existing peer — the network integrates the
|
||||
new node through its normal gossip protocols.
|
||||
|
||||
## Design Goals
|
||||
|
||||
1. **Nostr-native identity** - Use Nostr keypairs as node identities
|
||||
2. **Transport agnostic** - Support IP, wireless, serial, onion, and other link types
|
||||
3. **Self-organizing** - Automatic topology discovery and route optimization
|
||||
4. **Privacy preserving** - Minimize metadata leakage across untrusted links
|
||||
5. **Resilient** - Self-healing with graceful degradation
|
||||
6. **Reuse Nostr primitives** - Leverage secp256k1, Schnorr signatures, and SHA-256
|
||||
1. **Nostr-native identity** — Use Nostr keypairs as node identities
|
||||
2. **Transport agnostic** — Support IP, wireless, serial, onion, and other
|
||||
link types
|
||||
3. **Self-organizing** — Automatic topology discovery and route optimization
|
||||
4. **Privacy preserving** — Minimize metadata leakage across untrusted links
|
||||
5. **Resilient** — Self-healing with graceful degradation
|
||||
6. **Reuse Nostr primitives** — Leverage secp256k1, Schnorr signatures, and
|
||||
SHA-256
|
||||
|
||||
---
|
||||
|
||||
## Protocol Architecture
|
||||
|
||||
FIPS is organized in three protocol layers, each with distinct responsibilities
|
||||
and clean service boundaries. Understanding these layers is key to understanding
|
||||
how FIPS works.
|
||||
|
||||
```text
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Applications │
|
||||
│ (native FIPS API / IPv6 adapter) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ FIPS Session Protocol (FSP) │
|
||||
│ End-to-end authenticated encryption between endpoints │
|
||||
│ Session lifecycle, coordinate caching, replay protection │
|
||||
│ │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ FIPS Link Protocol (FLP) │
|
||||
│ Hop-by-hop link encryption, peer authentication │
|
||||
│ Spanning tree, bloom filters, routing, forwarding │
|
||||
│ │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Transport Layer │
|
||||
│ Datagram delivery over arbitrary media │
|
||||
│ UDP, Ethernet, LoRa, Tor, serial, ... │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Mapping to Traditional Networking
|
||||
|
||||
Readers familiar with the OSI model or TCP/IP networking may find it helpful to
|
||||
see how FIPS concepts relate to traditional layers:
|
||||
|
||||
```text
|
||||
Traditional FIPS Key Difference
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
Application Applications Same role — user-facing
|
||||
(IPv6 adapter) software
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
Transport (TCP/UDP) (not present) FIPS provides datagrams,
|
||||
not reliable streams
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
Session FSP End-to-end encryption
|
||||
and session management
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
Network (IP) FLP Routing, forwarding,
|
||||
address resolution —
|
||||
but self-organizing
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
Link (Ethernet/WiFi) FLP (link encryption) Peer authentication
|
||||
and hop-by-hop crypto
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
Physical (PHY) Transport layer Abstracted — FIPS
|
||||
(UDP, radio, serial) treats all media the
|
||||
same way
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
```
|
||||
|
||||
Note that FLP spans what would traditionally be separate link and network
|
||||
layers. This is intentional — in a self-organizing mesh, the same layer that
|
||||
authenticates peers also makes routing decisions, because routing depends on
|
||||
authenticated peer state (spanning tree positions, bloom filters).
|
||||
|
||||
### Layer Responsibilities
|
||||
|
||||
**Transport layer**: Delivers datagrams between endpoints over a specific
|
||||
medium. Each transport type (UDP socket, Ethernet interface, radio modem)
|
||||
implements the same abstract interface: send and receive datagrams, report MTU.
|
||||
The transport layer knows nothing about FIPS identities, routing, or encryption.
|
||||
It provides raw datagram delivery to FLP above.
|
||||
|
||||
See [fips-transport-layer.md](fips-transport-layer.md) for the transport layer
|
||||
specification.
|
||||
|
||||
**FIPS Link Protocol (FLP)**: Manages peer connections, authenticates peers via
|
||||
Noise IK handshakes, and encrypts all traffic on each link. FLP is where the
|
||||
mesh organizes itself — nodes exchange spanning tree announcements and bloom
|
||||
filters with their direct peers, and FLP makes forwarding decisions for transit
|
||||
traffic. FLP provides authenticated, encrypted forwarding to FSP above.
|
||||
|
||||
See [fips-link-layer.md](fips-link-layer.md) for the FLP specification and
|
||||
[fips-mesh-operation.md](fips-mesh-operation.md) for how FLP's routing and
|
||||
self-organization work in practice.
|
||||
|
||||
**FIPS Session Protocol (FSP)**: Provides end-to-end authenticated encryption
|
||||
between any two nodes, regardless of how many intermediate hops separate them.
|
||||
FSP manages session lifecycle (setup, data transfer, teardown), caches
|
||||
destination coordinates for efficient routing, and handles the warmup strategy
|
||||
that keeps transit node caches populated. FSP provides a datagram service to
|
||||
applications above.
|
||||
|
||||
See [fips-session-layer.md](fips-session-layer.md) for the FSP specification.
|
||||
|
||||
**IPv6 adaptation layer**: Sits above FSP and adapts the FIPS datagram service
|
||||
for unmodified IPv6 applications. Provides DNS resolution (npub → fd::/8
|
||||
address), identity cache management, MTU enforcement, and a TUN interface.
|
||||
This is the primary way existing applications use the FIPS mesh.
|
||||
|
||||
See [fips-ipv6-adapter.md](fips-ipv6-adapter.md) for the IPv6 adapter.
|
||||
|
||||
---
|
||||
|
||||
## Architecture Overview
|
||||
|
||||

|
||||
|
||||
Each link uses a different transport, but the end-to-end session encryption
|
||||
is independent of the transport mix. Intermediate nodes decrypt the link
|
||||
layer to make routing decisions, then re-encrypt for the next hop. They
|
||||
cannot read the session-layer payload.
|
||||
Each link uses a different transport, but the end-to-end session encryption is
|
||||
independent of the transport mix. Intermediate nodes decrypt the link layer to
|
||||
make routing decisions, then re-encrypt for the next hop. They cannot read the
|
||||
session-layer payload.
|
||||
|
||||
Applications can use the native FIPS datagram service directly, or access the
|
||||
mesh through an IPv6 adaptation layer (TUN device) for compatibility with
|
||||
existing IP-based applications. The router handles discovery, routing, and
|
||||
encryption transparently in either case.
|
||||
```text
|
||||
Application ──────────── End-to-end FSP session ──────────── Application
|
||||
│ │
|
||||
▼ ▼
|
||||
┌─────────┐ FLP link ┌─────────┐ FLP link ┌─────────┐
|
||||
│ Node A │◄──────────────►│ Node B │◄──────────────►│ Node C │
|
||||
└────┬────┘ (Noise IK) └────┬────┘ (Noise IK) └────┬────┘
|
||||
│ │ │
|
||||
UDP/IP Ethernet LoRa
|
||||
transport transport transport
|
||||
```
|
||||
|
||||
See [fips-transports.md](fips-transports.md) for transport options and characteristics.
|
||||
Each FLP link operates over its own transport type, with independent link-layer
|
||||
encryption. The FSP session spans the entire path, providing end-to-end
|
||||
confidentiality that is independent of the transport mix along the route.
|
||||
|
||||

|
||||
|
||||
Internally, each node is organized in three layers. At the top, two application
|
||||
interfaces provide access to the mesh: a native datagram API addressed by npub,
|
||||
and an IPv6 TUN adapter that maps npubs to `fd::/8` addresses so unmodified
|
||||
IP applications can use the network transparently. The router core in the middle
|
||||
implements spanning tree maintenance, bloom filter exchange, greedy routing,
|
||||
session management, and Noise IK encryption. At the bottom, transport plugins
|
||||
handle the physical diversity — each plugin implements the same interface, so the
|
||||
router treats UDP, Ethernet, LoRa, Tor, and serial links identically. Adding a
|
||||
new transport requires no changes to the routing or session layers.
|
||||
|
||||
## Prior Work
|
||||
|
||||
FIPS builds on proven designs rather than inventing new cryptography or routing
|
||||
algorithms.
|
||||
|
||||
**Routing**: The spanning tree coordinates, bloom filter discovery, and greedy
|
||||
routing algorithms are adapted from [Yggdrasil v0.5](https://yggdrasil-network.github.io/2023/10/22/upcoming-v05-release.html)
|
||||
and its [Ironwood](https://github.com/Arceliar/ironwood) routing library. FIPS
|
||||
adapts these for multi-transport operation and Nostr identity integration.
|
||||
|
||||
**Encryption**: Link and session encryption use the [Noise Protocol
|
||||
Framework](https://noiseprotocol.org/), the same foundation used by WireGuard,
|
||||
Lightning Network, and other production systems. FIPS uses the IK pattern for
|
||||
link authentication and end-to-end sessions.
|
||||
|
||||
**Cryptographic primitives**: FIPS reuses Nostr's cryptographic stack—secp256k1
|
||||
for keys, Schnorr signatures, SHA-256 for hashing, and ChaCha20-Poly1305 for
|
||||
authenticated encryption. No novel cryptography.
|
||||
|
||||
**Session management**: The index-based session dispatch follows WireGuard's
|
||||
approach, enabling O(1) packet routing without relying on source addresses.
|
||||
Internally, each node is organized in the three protocol layers. At the top,
|
||||
two application interfaces provide access to the mesh: a native datagram API
|
||||
addressed by npub, and an IPv6 TUN adapter that maps npubs to `fd::/8`
|
||||
addresses so unmodified IP applications can use the network transparently. The
|
||||
FSP and FLP layers in the middle implement session management, routing, and
|
||||
encryption. At the bottom, transport plugins handle the physical diversity —
|
||||
each plugin implements the same interface, so the router treats UDP, Ethernet,
|
||||
LoRa, Tor, and serial links identically. Adding a new transport requires no
|
||||
changes to the routing or session layers.
|
||||
|
||||
---
|
||||
|
||||
@@ -125,7 +230,7 @@ The FIPS address (synonymous with the pubkey) is the primary means for
|
||||
application-layer software to identify communication endpoints. The
|
||||
bech32-encoded npub can be used interchangeably for user interface purposes.
|
||||
The FIPS datagram service is exposed to the application layer either via a
|
||||
native API to the FIPS node software, or through an IPv6 shim driver that
|
||||
native API to the FIPS node software, or through an IPv6 adaptation layer that
|
||||
converts the node identity into an IPv6 address and provides DNS resolution
|
||||
from npub to this address for traditional software.
|
||||
|
||||
@@ -133,70 +238,70 @@ from npub to this address for traditional software.
|
||||
|
||||

|
||||
|
||||
The pubkey is the node's cryptographic identity, used in Noise IK handshakes for
|
||||
both link and session encryption. It is never exposed beyond the endpoints of an
|
||||
encrypted channel. The node_addr, a one-way SHA-256 hash truncated to 16 bytes,
|
||||
serves as the routing identifier in packet headers and bloom filters. Intermediate
|
||||
routers see only node_addrs — they can forward traffic without learning the Nostr
|
||||
identities of the endpoints. An observer can verify "does this node_addr belong
|
||||
to pubkey X?" but cannot enumerate which pubkeys are communicating by inspecting
|
||||
traffic. The IPv6 address prepends `fd` to the first 15 bytes of the node_addr,
|
||||
providing an overlay address for unmodified IP applications via the TUN interface.
|
||||
The pubkey is the node's cryptographic identity, used in Noise IK handshakes
|
||||
for both link and session encryption. It is never exposed beyond the endpoints
|
||||
of an encrypted channel. The node_addr, a one-way SHA-256 hash truncated to
|
||||
16 bytes, serves as the routing identifier in packet headers and bloom filters.
|
||||
Intermediate routers see only node_addrs — they can forward traffic without
|
||||
learning the Nostr identities of the endpoints. An observer can verify "does
|
||||
this node_addr belong to pubkey X?" but cannot enumerate which pubkeys are
|
||||
communicating by inspecting traffic. The IPv6 address prepends `fd` to the
|
||||
first 15 bytes of the node_addr, providing an overlay address for unmodified
|
||||
IP applications via the TUN interface.
|
||||
|
||||
### Address Format
|
||||
|
||||
When using the IPv6 protocol adapter, FIPS addresses use the IPv6 Unique Local
|
||||
When using the IPv6 adaptation layer, FIPS addresses use the IPv6 Unique Local
|
||||
Address (ULA) prefix `fd00::/8`, providing 120 bits from the node_addr hash.
|
||||
These are overlay identifiers—they appear in the TUN interface for application
|
||||
These are overlay identifiers — they appear in the TUN interface for application
|
||||
compatibility but are not routable on the underlying transport. The fd prefix
|
||||
ensures no collision with addresses that may be in use on the transport network.
|
||||
FIPS provides a local DNS service that maps npub bech32 names to IPv6 addresses
|
||||
for this purpose.
|
||||
|
||||
### Identity Verification
|
||||
|
||||
The Noise Protocol Framework is used to mutually authenticate both peer-to-peer
|
||||
link connections and end-to-end session traffic, proving each party controls
|
||||
the private key for their claimed identity.
|
||||
link connections (at FLP) and end-to-end session traffic (at FSP), proving each
|
||||
party controls the private key for their claimed identity.
|
||||
|
||||
See [fips-wire-protocol.md](fips-wire-protocol.md) for the Noise IK handshake
|
||||
and [fips-session-protocol.md](fips-session-protocol.md) for end-to-end
|
||||
session establishment.
|
||||
See [fips-link-layer.md](fips-link-layer.md) for peer authentication and
|
||||
[fips-session-layer.md](fips-session-layer.md) for end-to-end session
|
||||
establishment.
|
||||
|
||||
### Terminology: Addresses and Identifiers
|
||||
|
||||
FIPS uses several related but distinct identifiers at different protocol layers:
|
||||
|
||||
| Term | Layer | Visible To | Description |
|
||||
|----------------------------|---------------------|----------------|----------------------------------------------------------------------|
|
||||
| **FIPS address / pubkey** | Application/Session | Endpoints only | 32-byte secp256k1 public key - the endpoint identity |
|
||||
| **npub** | (encoding) | Human readers | Bech32 encoding of pubkey for display/config |
|
||||
| **node_addr** | Routing | Routing nodes | SHA-256(pubkey) truncated to 128 bits - cannot be reversed to pubkey |
|
||||
| **link_addr** | Transport | Direct peers | IP:port, MAC, .onion - transport-specific |
|
||||
| **IPv6 address** | IPv6 shim | Applications | fd::/8 derived from node_addr - optional compatibility |
|
||||
| Term | Layer | Visible To | Description |
|
||||
| ---- | ----- | ---------- | ----------- |
|
||||
| **FIPS address / pubkey** | Application/FSP | Endpoints only | 32-byte secp256k1 public key — the endpoint identity |
|
||||
| **npub** | (encoding) | Human readers | Bech32 encoding of pubkey for display/config |
|
||||
| **node_addr** | FLP (routing) | Routing nodes | SHA-256(pubkey) truncated to 128 bits — cannot be reversed to pubkey |
|
||||
| **link_addr** | Transport | Direct peers | IP:port, MAC, .onion — transport-specific |
|
||||
| **IPv6 address** | IPv6 adapter | Applications | fd::/8 derived from node_addr — optional compatibility |
|
||||
|
||||
**Privacy property**: The pubkey (FIPS address / Nostr identity) is never exposed to
|
||||
intermediate routing nodes. They see only the node_addr, a one-way hash. An observer
|
||||
can verify "does this node_addr belong to pubkey X?" but cannot derive the pubkey from
|
||||
traffic.
|
||||
**Privacy property**: The pubkey (FIPS address / Nostr identity) is never
|
||||
exposed to intermediate routing nodes. They see only the node_addr, a one-way
|
||||
hash. An observer can verify "does this node_addr belong to pubkey X?" but
|
||||
cannot derive the pubkey from traffic.
|
||||
|
||||
---
|
||||
|
||||
## Two-Layer Encryption
|
||||
|
||||
FIPS uses independent encryption at two layers:
|
||||
FIPS uses independent encryption at two protocol layers:
|
||||
|
||||
| Layer | Scope | Pattern | Purpose |
|
||||
|-------------|-------------|----------|------------------------------------------------|
|
||||
| **Link** | Hop-by-hop | Noise IK | Encrypt all traffic on each link |
|
||||
| **Session** | End-to-end | Noise IK | Encrypt application payload between endpoints |
|
||||
| Layer | Scope | Pattern | Purpose |
|
||||
| ----- | ----- | ------- | ------- |
|
||||
| **FLP (Link)** | Hop-by-hop | Noise IK | Encrypt all traffic on each peer link |
|
||||
| **FSP (Session)** | End-to-end | Noise IK | Encrypt application payload between endpoints |
|
||||
|
||||
### Link Layer (Hop-by-Hop)
|
||||
|
||||
When two nodes establish a direct connection, they perform a Noise IK handshake.
|
||||
This authenticates both parties and establishes symmetric keys for encrypting
|
||||
all traffic on that link. Every packet between direct peers is encrypted—gossip
|
||||
messages, routing queries, and forwarded session datagrams alike.
|
||||
When two nodes establish a direct connection, they perform a Noise IK
|
||||
handshake. This authenticates both parties and establishes symmetric keys for
|
||||
encrypting all traffic on that link. Every packet between direct peers is
|
||||
encrypted — gossip messages, routing queries, and forwarded session datagrams
|
||||
alike.
|
||||
|
||||
The IK pattern is used because outbound connections know the peer's npub from
|
||||
configuration, while inbound connections learn the initiator's identity from
|
||||
@@ -207,188 +312,130 @@ the first handshake message.
|
||||
FIPS establishes end-to-end encrypted sessions between any two communicating
|
||||
nodes using Noise IK, regardless of whether they are direct peers or separated
|
||||
by intermediate routers. The initiator knows the destination's npub; the
|
||||
responder learns the initiator's identity from the handshake—the same asymmetry
|
||||
as link-layer connections.
|
||||
responder learns the initiator's identity from the handshake — the same
|
||||
asymmetry as link-layer connections.
|
||||
|
||||
Both layers always apply. For adjacent peers, application traffic is encrypted
|
||||
twice: once by the session layer (end-to-end) and once by the link layer
|
||||
(hop-by-hop). This uniform model means:
|
||||
|
||||
- No special case for "local peer" vs "remote destination"
|
||||
- Topology changes (a direct peer becomes reachable only through intermediaries)
|
||||
don't affect sessions
|
||||
- Topology changes (a direct peer becomes reachable only through
|
||||
intermediaries) don't affect sessions
|
||||
- The link layer remains purely a transport concern
|
||||
|
||||
A packet from A to adjacent peer B:
|
||||
|
||||
1. A encrypts payload with A↔B session key
|
||||
2. A wraps in SessionDatagram, encrypts with A↔B link key, sends to B
|
||||
1. A encrypts payload with A↔B session key (FSP)
|
||||
2. A wraps in SessionDatagram, encrypts with A↔B link key (FLP), sends to B
|
||||
3. B decrypts link layer, then decrypts session layer to get payload
|
||||
|
||||
A packet from A to D through intermediate node B:
|
||||
|
||||
1. A encrypts payload with A↔D session key
|
||||
2. A wraps in SessionDatagram, encrypts with A↔B link key, sends to B
|
||||
3. B decrypts link layer, sees destination, re-encrypts with B↔D link key
|
||||
1. A encrypts payload with A↔D session key (FSP)
|
||||
2. A wraps in SessionDatagram, encrypts with A↔B link key (FLP), sends to B
|
||||
3. B decrypts link layer, reads destination, re-encrypts with B↔D link key
|
||||
4. D decrypts link layer, then decrypts session layer to get payload
|
||||
|
||||
Intermediate nodes can route based on destination address but cannot read
|
||||
Intermediate nodes can route based on destination node_addr but cannot read
|
||||
session-layer payloads.
|
||||
|
||||
FIPS session setup also warms up route caches along the path between the
|
||||
endpoints, so that when application traffic flows the network is already ready.
|
||||
|
||||
See [fips-wire-protocol.md](fips-wire-protocol.md) for link encryption and
|
||||
[fips-session-protocol.md](fips-session-protocol.md) for session encryption.
|
||||
See [fips-link-layer.md](fips-link-layer.md) for link encryption and
|
||||
[fips-session-layer.md](fips-session-layer.md) for session encryption.
|
||||
|
||||
---
|
||||
|
||||
## Spanning Tree Protocol
|
||||
## Routing and Mesh Operation
|
||||
|
||||
FIPS routing is entirely distributed — each node makes forwarding decisions
|
||||
using only local information. There are no routing tables pushed from above, no
|
||||
link-state floods, and no distance-vector exchanges. Instead, two complementary
|
||||
mechanisms provide the information each node needs.
|
||||
|
||||
### Spanning Tree: The Coordinate System
|
||||
|
||||

|
||||
|
||||
The spanning tree is a subset of the full mesh network that connects all nodes,
|
||||
forming a tree structure rooted at a deterministically-elected node. Each node
|
||||
selects a single parent, and the resulting tree serves as the routing backbone.
|
||||
This enables routing without global routing tables.
|
||||
Nodes self-organize into a spanning tree rooted at a deterministically-elected
|
||||
node (the one with the smallest node_addr). Each node selects a single parent
|
||||
from among its direct peers, and the resulting tree gives every node a
|
||||
**coordinate** — its path from itself to the root.
|
||||
|
||||
### Why a Spanning Tree?
|
||||
These coordinates enable distance calculations between any two nodes: the
|
||||
distance is the number of hops from each node to their lowest common ancestor
|
||||
in the tree. This provides a metric for routing decisions without any node
|
||||
needing to know the full network topology.
|
||||
|
||||
A spanning tree has useful properties:
|
||||
The tree maintains itself through gossip — nodes exchange TreeAnnounce messages
|
||||
with their peers, propagating parent selections and ancestry chains. Changes
|
||||
cascade through the tree proportional to depth, not network size. If the
|
||||
network partitions, each segment elects its own root and reconverges
|
||||
automatically when segments rejoin.
|
||||
|
||||
- **Unique paths**: Exactly one path exists between any two nodes
|
||||
- **Minimal state**: Nodes only track their parent and immediate peers
|
||||
- **Coordinates**: A node's position in the tree enables distance calculations
|
||||
See [fips-spanning-tree.md](fips-spanning-tree.md) for the tree algorithms and
|
||||
[spanning-tree-dynamics.md](spanning-tree-dynamics.md) for detailed convergence
|
||||
walkthroughs.
|
||||
|
||||
The tree provides structure for routing while bloom filters provide reachability
|
||||
information. Together they enable efficient packet delivery without requiring
|
||||
nodes to know the full network topology.
|
||||
### Bloom Filters: Candidate Selection
|
||||
|
||||
### Tree Coordinates
|
||||
Each node maintains bloom filters summarizing which destinations are reachable
|
||||
through each of its peers. Bloom filters propagate via gossip, with each node
|
||||
computing outbound filters by merging the filters received from its other
|
||||
peers. At steady state, filters represent the entire reachable network.
|
||||
|
||||
A node's coordinate is its path from itself to the root. The distance between
|
||||
two nodes is the sum of hops from each to their lowest common ancestor (LCA).
|
||||
This distance metric enables greedy routing: forward packets to the peer that
|
||||
minimizes distance to the destination.
|
||||
Bloom filters answer a single question: "can peer P possibly reach destination
|
||||
D?" The answer is either "no" (definitive) or "maybe" (probabilistic — false
|
||||
positives are possible). This is **candidate selection**, not routing — bloom
|
||||
filters identify which peers are worth considering, but the actual forwarding
|
||||
decision requires tree coordinates to rank those candidates by distance.
|
||||
|
||||
### Root Election
|
||||
See [fips-bloom-filters.md](fips-bloom-filters.md) for filter parameters and
|
||||
mathematical properties.
|
||||
|
||||
The root is the node with the lexicographically smallest node_addr among all
|
||||
reachable nodes. This election is deterministic and requires no coordination—
|
||||
each node independently examines its view of the network and reaches the same
|
||||
conclusion.
|
||||
### Routing Decisions
|
||||
|
||||
The root provides a coordinate reference point but does not participate in
|
||||
routing unless the paths from source and destination to the root share no
|
||||
common ancestors (i.e., the root is their lowest common ancestor).
|
||||
At each hop, FLP makes a local forwarding decision using the following priority
|
||||
chain:
|
||||
|
||||
### Parent Selection
|
||||
1. **Local delivery** — the destination is this node
|
||||
2. **Direct peer** — the destination is an authenticated neighbor
|
||||
3. **Bloom-guided candidate selection** — bloom filters identify peers that can
|
||||
reach the destination; tree coordinates rank them by distance
|
||||
4. **Greedy tree routing** — fallback when bloom filters haven't converged;
|
||||
forward to the peer that minimizes tree distance to the destination
|
||||
5. **No route** — destination unreachable; send error signal to source
|
||||
|
||||
Each node selects a parent that provides the best path to root, considering:
|
||||
All multi-hop routing depends on knowing the destination's tree coordinates.
|
||||
These are cached at each node after being learned through discovery
|
||||
(LookupRequest/LookupResponse) or session establishment (SessionSetup). The
|
||||
coordinate cache is the critical piece that enables efficient forwarding.
|
||||
|
||||
- Reachability (the parent must have a path to root)
|
||||
- Link quality (latency, packet loss, bandwidth)
|
||||
- Stability (hysteresis prevents flapping on minor changes)
|
||||
### Coordinate Caching and Discovery
|
||||
|
||||
The parent must be a direct peer—nodes cannot select non-peers as parents.
|
||||
When a node first needs to reach an unknown destination, it sends a
|
||||
LookupRequest that floods through the network guided by bloom filters. The
|
||||
destination responds with its coordinates, which the source caches. Subsequent
|
||||
traffic routes efficiently using the cached coordinates.
|
||||
|
||||
### Tree Gossip
|
||||
Session establishment (SessionSetup) also carries coordinates, warming transit
|
||||
node caches along the path so that data packets can be forwarded without
|
||||
individual discovery at each hop.
|
||||
|
||||
Nodes exchange TreeAnnounce messages containing their parent selection and
|
||||
ancestry chain (path to root). When a node changes its parent, it announces the
|
||||
change; peers propagate relevant updates. The tree converges through this
|
||||
gossip without centralized coordination.
|
||||
### Error Recovery
|
||||
|
||||
Changes propagate only as far as they need to—distantly connected nodes are
|
||||
unaffected by local path changes and don't receive updates for them.
|
||||
When routing fails — because cached coordinates are stale or a path has
|
||||
broken — transit nodes signal the source:
|
||||
|
||||
### Partition Handling
|
||||
- **CoordsRequired**: A transit node lacks the destination's coordinates.
|
||||
The source re-initiates discovery and resets its coordinate warmup strategy.
|
||||
- **PathBroken**: Greedy routing reached a dead end. The source re-discovers
|
||||
the destination's current coordinates.
|
||||
|
||||
If the network partitions, each isolated segment elects its own root (the
|
||||
smallest node_addr within that segment). When partitions merge, nodes in the
|
||||
segment with the larger root discover the globally smaller root and re-parent.
|
||||
The tree reconverges automatically.
|
||||
Both signals trigger active recovery, and are rate-limited to prevent storms
|
||||
during topology changes.
|
||||
|
||||
See [fips-routing.md](fips-routing.md) for routing concepts,
|
||||
[fips-gossip-protocol.md](fips-gossip-protocol.md) for message formats, and
|
||||
[spanning-tree-dynamics.md](spanning-tree-dynamics.md) for convergence behavior.
|
||||
|
||||
---
|
||||
|
||||
## Bloom Filter Routing
|
||||
|
||||
Tree coordinates enable routing once you know a destination's position. Bloom
|
||||
filters enable finding that position in the first place.
|
||||
|
||||
A bloom filter is a space-efficient probabilistic data structure that can test
|
||||
whether an element is a member of a set. It may produce false positives (saying
|
||||
an element is present when it isn't) but never false negatives. This makes it
|
||||
ideal for routing: a node can quickly check if a destination might be reachable
|
||||
through a given peer, with occasional false positives handled by backtracking.
|
||||
|
||||
### How It Works
|
||||
|
||||
Each node maintains bloom filters summarizing which node_addrs are reachable
|
||||
through each of its peers. These filters propagate through the tree: a node
|
||||
aggregates filters from its children and announces the combined filter to its
|
||||
parent (and vice versa).
|
||||
|
||||
When a node needs to reach an unknown destination:
|
||||
|
||||
1. Check local bloom filters—which peers might be able to reach this node_addr?
|
||||
2. Send a LookupRequest to peers whose filters indicate "maybe"
|
||||
3. The request propagates through the tree toward matching subtrees
|
||||
4. The destination responds with a LookupResponse containing its coordinates
|
||||
5. The sender caches the coordinates and routes directly via greedy forwarding
|
||||
|
||||
Bloom filters have false positives (a filter may indicate "maybe" when the node
|
||||
isn't actually reachable through that path) but no false negatives. Extra
|
||||
queries are harmless; missing a reachable node is not.
|
||||
|
||||
### Filter Propagation
|
||||
|
||||
Filters propagate in the opposite direction from tree announcements:
|
||||
|
||||
- Tree state propagates upward (toward root) via ancestry chains
|
||||
- Bloom filters propagate downward (toward leaves) via subtree aggregation
|
||||
|
||||
A node's filter contains all node_addrs reachable through its subtree. The root's
|
||||
filter contains everyone; leaf nodes have empty outbound filters.
|
||||
|
||||
See [fips-routing.md](fips-routing.md) for bloom filter design and
|
||||
[fips-gossip-protocol.md](fips-gossip-protocol.md) for FilterAnnounce format.
|
||||
|
||||
---
|
||||
|
||||
## Greedy Routing
|
||||
|
||||
Once a destination's tree coordinates are known, packets are forwarded using
|
||||
greedy routing: at each hop, forward to the peer that minimizes tree distance
|
||||
to the destination.
|
||||
|
||||
### The Algorithm
|
||||
|
||||
1. If I am the destination, deliver the packet locally
|
||||
2. Calculate my tree distance to the destination
|
||||
3. For each peer, calculate their tree distance to the destination
|
||||
4. Forward to the peer with the smallest distance (must be less than mine)
|
||||
5. If no peer is closer, routing has failed (local minimum)
|
||||
|
||||
### Path-Broken Recovery
|
||||
|
||||
Greedy routing can fail if the destination has moved or the cached coordinates
|
||||
are stale. When this happens, the node that cannot make progress sends a
|
||||
PathBroken notification back to the source. The source then initiates a fresh
|
||||
bloom filter lookup to find the destination's current coordinates.
|
||||
|
||||
### Session Establishment
|
||||
|
||||
For efficiency, FIPS establishes routing sessions that cache coordinate
|
||||
information at intermediate routers. The first packet (SessionSetup) carries
|
||||
full coordinates; subsequent packets use cached state for minimal overhead.
|
||||
|
||||
See [fips-routing.md](fips-routing.md) for the complete routing design and
|
||||
[fips-session-protocol.md](fips-session-protocol.md) for session establishment.
|
||||
See [fips-mesh-operation.md](fips-mesh-operation.md) for the complete routing
|
||||
and mesh behavior description.
|
||||
|
||||
---
|
||||
|
||||
@@ -397,84 +444,33 @@ See [fips-routing.md](fips-routing.md) for the complete routing design and
|
||||
FIPS is transport-agnostic. The protocol operates identically whether peers
|
||||
connect over UDP, Ethernet, LoRa radio, serial cables, or Tor hidden services.
|
||||
|
||||
### Transports and Links
|
||||
|
||||
A **transport** is a physical or logical interface: a UDP socket, an Ethernet
|
||||
NIC, a Tor client, a radio modem. A **link** is a connection instance to a
|
||||
specific peer over a transport.
|
||||
|
||||
### Multi-Transport Bridging
|
||||
NIC, a Tor client, a radio modem. A **link** is a peer connection established
|
||||
over a transport. Transport addresses (IP:port, MAC address, .onion) are opaque
|
||||
to all layers above FLP — they are used only to deliver datagrams and are
|
||||
discarded once FLP has authenticated the peer.
|
||||
|
||||
A node with multiple transports automatically bridges between networks. Peers
|
||||
from all transports feed into a single spanning tree; the router selects the
|
||||
best path regardless of transport type. If one transport fails, traffic
|
||||
automatically routes through alternatives.
|
||||
|
||||
### Transport Types
|
||||
|
||||
| Category | Examples | Characteristics |
|
||||
|----------|----------|-----------------|
|
||||
| Overlay | UDP/IP, TCP/TLS, QUIC, WebSocket | Internet connectivity, NAT considerations |
|
||||
| Shared medium | Ethernet, WiFi, Bluetooth, LoRa | Broadcast/multicast discovery |
|
||||
| Point-to-point | Serial, dialup | No discovery needed, static config |
|
||||
| -------- | -------- | --------------- |
|
||||
| Overlay | UDP/IP, TCP/TLS, WebSocket | Internet connectivity, NAT traversal |
|
||||
| Shared medium | Ethernet, WiFi, Bluetooth, LoRa | Local discovery, broadcast |
|
||||
| Point-to-point | Serial, dialup | Static config, no discovery |
|
||||
| Anonymity | Tor, I2P | High latency, strong privacy |
|
||||
|
||||
UDP over IP is expected to be the most common transport for internet-connected
|
||||
nodes. Radio transports enable connectivity where internet infrastructure is
|
||||
unavailable.
|
||||
> **Implementation status**: UDP/IP is the only implemented transport. All
|
||||
> others are future directions.
|
||||
|
||||
See [fips-transports.md](fips-transports.md) for transport characteristics.
|
||||
See [fips-transport-layer.md](fips-transport-layer.md) for transport layer
|
||||
design.
|
||||
|
||||
---
|
||||
|
||||
## Protocol Messages
|
||||
|
||||
FIPS uses a discriminator-based wire format for efficient message dispatch.
|
||||
|
||||
### Link Layer Messages
|
||||
|
||||
Exchanged between directly connected peers, encrypted with link session keys:
|
||||
|
||||
| Type | Name | Purpose |
|
||||
|------|----------------|------------------------------------------------------|
|
||||
| 0x10 | TreeAnnounce | Spanning tree state (parent, ancestry) |
|
||||
| 0x20 | FilterAnnounce | Bloom filter reachability update |
|
||||
| 0x30 | LookupRequest | Query for node's tree coordinates |
|
||||
| 0x31 | LookupResponse | Response with coordinates and proof |
|
||||
| 0x40 | SessionDatagram| Carries session-layer payloads through the mesh |
|
||||
| 0x50 | Disconnect | Orderly disconnect notification |
|
||||
|
||||
### SessionDatagram Payload Messages
|
||||
|
||||
Carried inside SessionDatagram (0x40), which provides src_addr, dest_addr, and
|
||||
hop_limit for multi-hop forwarding.
|
||||
|
||||
**Session-layer messages** (end-to-end encrypted between source and destination):
|
||||
|
||||
| Type | Name | Purpose |
|
||||
|------|----------------|--------------------------------------------|
|
||||
| 0x00 | SessionSetup | Establish routing session with coordinates |
|
||||
| 0x01 | SessionAck | Acknowledge session establishment |
|
||||
| 0x10 | DataPacket | Encrypted application data (IPv6 payload) |
|
||||
|
||||
**Link-layer error signals** (plaintext, generated by transit routers):
|
||||
|
||||
| Type | Name | Purpose |
|
||||
|------|----------------|--------------------------------------------|
|
||||
| 0x20 | CoordsRequired | Router cache miss—need fresh coordinates |
|
||||
| 0x21 | PathBroken | Greedy routing failed—need re-lookup |
|
||||
|
||||
Error signals are sent back to the original source using the `src_addr` from
|
||||
the SessionDatagram that triggered the error. They are plaintext because the
|
||||
transit router has no end-to-end session with the source; link-layer encryption
|
||||
protects them hop-by-hop.
|
||||
|
||||
See [fips-wire-protocol.md](fips-wire-protocol.md) for wire format details and
|
||||
[fips-gossip-protocol.md](fips-gossip-protocol.md) for gossip message formats.
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
## Security
|
||||
|
||||
### Threat Model
|
||||
|
||||
@@ -493,79 +489,105 @@ sees only encrypted packets.
|
||||
**End-to-end encryption**: Session-layer Noise IK encrypts payloads between
|
||||
endpoints. Intermediate routers cannot read application data.
|
||||
|
||||
**Signature verification**: All protocol messages (TreeAnnounce, LookupResponse)
|
||||
are signed. The full ancestry chain in TreeAnnounce includes signatures from
|
||||
each node, preventing forged tree positions.
|
||||
**Signature verification**: TreeAnnounce messages carry signed parent
|
||||
declarations. Direct peers verify signatures using keys established during
|
||||
the Noise IK handshake; ancestry beyond direct peers uses transitive trust
|
||||
in the v1 protocol.
|
||||
|
||||
**Replay protection**: Sequence numbers and timestamps on announcements.
|
||||
Counter-based nonces with sliding window for encrypted packets.
|
||||
**Replay protection**: Counter-based nonces with sliding window for encrypted
|
||||
packets at both the link and session layers. Sequence numbers on protocol
|
||||
announcements prevent replay of stale state.
|
||||
|
||||
### Sybil Resistance
|
||||
|
||||
Creating many identities is cheap, but exploiting them is constrained:
|
||||
|
||||
- **Discretionary peering**: Node operators choose who to peer with. An attacker
|
||||
with many identities still needs real nodes to accept their connections.
|
||||
- **Discretionary peering**: Node operators choose who to peer with. An
|
||||
attacker with many identities still needs real nodes to accept their
|
||||
connections.
|
||||
- **Tree coordinate verification**: Nodes cannot claim arbitrary tree positions
|
||||
without valid signed ancestry chains from real nodes
|
||||
without valid signed ancestry chains from real nodes.
|
||||
- **Rate limiting**: Handshake rate limiting constrains how fast attackers can
|
||||
establish connections
|
||||
establish connections.
|
||||
|
||||
### Metadata Exposure
|
||||
|
||||
Each entity in the network sees different information:
|
||||
|
||||
| Entity | Can See |
|
||||
|--------|---------|
|
||||
| ------ | ------- |
|
||||
| Transport observer | Encrypted packets, timing, packet sizes |
|
||||
| Direct peer | Your npub (identity), traffic volume, timing |
|
||||
| Intermediate router | Source and destination node_addrs, packet size |
|
||||
| Destination | Your npub (identity), payload content |
|
||||
|
||||
Intermediate routers see node_addrs, not npubs. Since node_addrs are derived from
|
||||
pubkeys via one-way SHA-256 hash, routers cannot determine the actual identities
|
||||
of the endpoints they route for.
|
||||
Intermediate routers see node_addrs, not npubs. Since node_addrs are derived
|
||||
from pubkeys via one-way SHA-256 hash, routers cannot determine the actual
|
||||
identities of the endpoints they route for.
|
||||
|
||||
The session layer hides payload content from intermediate routers. The link
|
||||
layer hides everything from passive observers on the underlying transport.
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
## Prior Work
|
||||
|
||||
FIPS combines these elements into a cohesive system that achieves its design
|
||||
goals:
|
||||
FIPS builds on proven designs rather than inventing new cryptography or routing
|
||||
algorithms.
|
||||
|
||||
- **Self-sovereign identity** through Nostr keypairs, with node_addrs providing
|
||||
routing-level privacy
|
||||
- **Transport agnosticism** via the transport abstraction layer, enabling the
|
||||
same routing logic across UDP, Ethernet/WiFi, Tor, and other link types
|
||||
- **Self-organization** through distributed spanning tree formation and bloom
|
||||
filter propagation, requiring no central coordination
|
||||
- **Privacy preservation** with two-layer encryption that hides payloads from
|
||||
intermediate routers and hides everything from transport observers
|
||||
- **Resilience** through automatic partition detection, re-election, and tree
|
||||
reconvergence when the network topology changes
|
||||
**Routing**: The spanning tree coordinates, bloom filter candidate selection,
|
||||
and greedy routing algorithms are adapted from
|
||||
[Yggdrasil v0.5](https://yggdrasil-network.github.io/2023/10/22/upcoming-v05-release.html)
|
||||
and its [Ironwood](https://github.com/Arceliar/ironwood) routing library. FIPS
|
||||
adapts these for multi-transport operation and Nostr identity integration.
|
||||
|
||||
The result is a mesh network where nodes can find and communicate with each
|
||||
other securely, regardless of the underlying transport infrastructure, while
|
||||
maintaining control over their own identities and peering relationships.
|
||||
**Encryption**: Link and session encryption use the
|
||||
[Noise Protocol Framework](https://noiseprotocol.org/), the same foundation
|
||||
used by WireGuard, Lightning Network, and other production systems. FIPS uses
|
||||
the IK pattern for both link authentication and end-to-end sessions.
|
||||
|
||||
**Cryptographic primitives**: FIPS reuses Nostr's cryptographic stack —
|
||||
secp256k1 for keys, Schnorr signatures, SHA-256 for hashing, and
|
||||
ChaCha20-Poly1305 for authenticated encryption. No novel cryptography.
|
||||
|
||||
**Session management**: The index-based session dispatch follows WireGuard's
|
||||
approach, enabling O(1) packet routing without relying on source addresses.
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
## Further Reading
|
||||
|
||||
### FIPS Design Documents
|
||||
### Protocol Layers
|
||||
|
||||
| Document | Description |
|
||||
|----------|-------------|
|
||||
| [fips-session-protocol.md](fips-session-protocol.md) | End-to-end session flow, Noise IK encryption |
|
||||
| [fips-wire-protocol.md](fips-wire-protocol.md) | Link-layer transport, Noise IK handshake |
|
||||
| [fips-gossip-protocol.md](fips-gossip-protocol.md) | TreeAnnounce, FilterAnnounce, Lookup formats |
|
||||
| [fips-routing.md](fips-routing.md) | Bloom filters, discovery, greedy routing |
|
||||
| [spanning-tree-dynamics.md](spanning-tree-dynamics.md) | Tree protocol dynamics and convergence |
|
||||
| [fips-transports.md](fips-transports.md) | Transport protocol characteristics |
|
||||
| [fips-software-architecture.md](fips-software-architecture.md) | Software architecture, configuration |
|
||||
| -------- | ----------- |
|
||||
| [fips-transport-layer.md](fips-transport-layer.md) | Transport layer: abstraction, types, services provided to FLP |
|
||||
| [fips-link-layer.md](fips-link-layer.md) | FLP: peer authentication, link encryption, forwarding |
|
||||
| [fips-session-layer.md](fips-session-layer.md) | FSP: end-to-end encryption, session lifecycle |
|
||||
| [fips-ipv6-adapter.md](fips-ipv6-adapter.md) | IPv6 adaptation: DNS, TUN interface, MTU enforcement |
|
||||
|
||||
### Mesh Behavior and Wire Formats
|
||||
|
||||
| Document | Description |
|
||||
| -------- | ----------- |
|
||||
| [fips-mesh-operation.md](fips-mesh-operation.md) | How the mesh operates: routing, discovery, error recovery |
|
||||
| [fips-wire-formats.md](fips-wire-formats.md) | Complete wire format reference for all protocol layers |
|
||||
|
||||
### Supporting References
|
||||
|
||||
| Document | Description |
|
||||
| -------- | ----------- |
|
||||
| [fips-spanning-tree.md](fips-spanning-tree.md) | Spanning tree algorithms and data structures |
|
||||
| [fips-bloom-filters.md](fips-bloom-filters.md) | Bloom filter parameters, math, and computation |
|
||||
| [spanning-tree-dynamics.md](spanning-tree-dynamics.md) | Scenario walkthroughs: convergence, partitions, recovery |
|
||||
|
||||
### Implementation
|
||||
|
||||
| Document | Description |
|
||||
| -------- | ----------- |
|
||||
| [fips-software-architecture.md](fips-software-architecture.md) | Stable architectural decisions guiding the codebase |
|
||||
| [fips-state-machines.md](fips-state-machines.md) | Phase-based state machine pattern (Rust) |
|
||||
| [fips-configuration.md](fips-configuration.md) | YAML configuration reference |
|
||||
|
||||
### External References
|
||||
|
||||
|
||||
Reference in New Issue
Block a user