Mix Cover Traffic
| Field | Value |
|---|---|
| Name | Mix Cover Traffic |
| Slug | 161 |
| Status | raw |
| Category | Standards Track |
| Editor | Prem Prathi [email protected] |
| Contributors |
Timeline
- 2026-05-11 —
2aa2bcd— feat: Mix Cover Traffic specification (#311)
Abstract
This document specifies the cover traffic architecture for the libp2p Mix Protocol. The architecture ensures that an observer cannot distinguish cover traffic from locally originated messages by observing a node's emission pattern. It defines how cover packets are generated and emitted, how the rate-limit budget is shared across cover and non-cover traffic, and specifies the Constant-Rate cover traffic strategy, with Poisson-Rate as a future consideration in §11.5.
1. Introduction
The Mix Protocol provides sender anonymity through layered encryption and per-hop delays. However, without cover traffic, an adversary observing a mix node's emission rate can mount several attacks:
- Traffic analysis: by correlating emission bursts with known events, an adversary can link a node's activity periods to specific senders or recipients.
- Intersection attack: by observing which nodes are active each time a message reaches its destination, an adversary can progressively narrow down the set of possible senders across multiple messages.
- Timing correlation: by matching idle and active periods across mix nodes, an adversary can correlate ingress and egress packets.
All three attacks rely on the same weakness: a node's emission pattern leaks information about whether it is carrying non-cover traffic.
Cover traffic addresses this by ensuring a node's emission pattern does not depend on non-cover traffic volume, making it indistinguishable to an observer whether the node is sending locally originated messages or none at all.
The Mix Protocol defines cover traffic as a pluggable component (see Mix Protocol §6.4). This specification provides a concrete instantiation of that component, defining the cover traffic architecture, the rate-limit budget model, and two concrete scheduling strategies. The architecture is designed to be compatible with the DoS protection mechanism defined in Mix DoS Protection and specifically with the Mix RLN DoS Protection mechanism.
2. Terminology
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
Other terms used in this document are as defined in the libp2p Mix Protocol and Mix DoS Protection.
The following additional terms are used throughout this specification:
-
Cover Packet A dummy Sphinx packet that carries no application payload and is indistinguishable from non-cover Sphinx packets in structure, size, and routing behavior.
-
Slot A single rate-limit token within an epoch's budget of
Rtokens, as defined by the DoS protection mechanism. Each outgoing packet — whether cover or non-cover — consumes exactly one slot. -
Slot Pool The collection of rate-limit slots available for a given epoch.
-
Epoch A fixed time window of duration
Pseconds during which each mix node is permitted to emit at mostRpackets, as enforced by the DoS protection mechanism.
3. Design Principles
The cover traffic architecture is guided by the following principles:
- Sender unobservability: A node's emission pattern must not depend on non-cover traffic volume, making it indistinguishable to an observer whether the node is carrying non-cover traffic or not.
- Indistinguishability: Cover packets are structurally identical to non-cover Sphinx packets in size and routing behavior, preventing packet-level classification. (Mix Protocol §6.4)
- Self-exit: Cover packets SHOULD use loop paths where the originating node is also the exit node. This ensures the dummy payload is never decrypted by an external party, eliminating the risk of cover classification at the exit.
- DoS protection compliance: All cover traffic operates within the rate-limit budget
Renforced per epoch. Proofs are epoch-bound and unused slots are discarded at epoch boundaries. (Mix DoS Protection) - Slot integrity: Each rate-limit slot is consumed at most once on the wire per epoch. When a non-cover claim reclaims a slot held by a queued cover packet, that packet's pre-computed proof is discarded before the slot is reused.
- Mix node only: Cover traffic is generated only for mix nodes that act as intermediate nodes forwarding mix traffic and participate continuously in the network. Initiating-only nodes are mostly short-lived with dynamic identifiers and do not forward traffic, making cover traffic neither practical nor beneficial for them.
- Pre-computation: As an optimization, cover packets and their proofs MAY be generated during epoch
N-1, so they are ready to emit at the start of epochNwithout any cryptographic work at emission time.
Overview
A mix node plays multiple roles at once: it sends its own messages, relays messages for other nodes, and ideally hides which of these it is doing. Without protection, an observer watching the node's outgoing packets can tell when it is active, how busy it is, and when it is idle — enough to link users to their messages through traffic patterns.
Cover traffic addresses this by emitting additional dummy packets that look identical to real mix traffic from the outside. An observer still sees packets leaving the node, but can no longer tell from the pattern alone whether those packets are real or dummy.
The node operates under a rate limit that bounds total packets emitted per epoch (§4). Every packet — cover, locally originated, or forwarded — consumes one slot from this shared budget. Forwarding typically takes a large share of the budget because each originated packet traverses multiple hops, so the maximum cover rate is naturally bounded below the total.
Cover is emitted at a steady configurable rate, up to this bound (§7.1).
A cover_rate_fraction parameter scales cover down from the maximum,
leaving headroom in the budget for spikes in real traffic.
Real traffic (locally originated and forwarded) claims slots from the same pool as it arrives;
cover yields whatever slots remain.
Cover packets follow round-trip paths — the sender is also the final destination, so the dummy payload is never decrypted by another party (§5.1). For efficiency, cover packets and their rate-limit proofs MAY be pre-built during the previous epoch (§6.1) and revalidated at send time in case the underlying state has changed (§6.5).
Each epoch begins by discarding previous state and initializing a fresh slot budget, loading any pre-built cover packets prepared during the prior epoch. Throughout the epoch, cover, locally originated, and forwarded packets independently claim slots. Near the midpoint, the node starts pre-computing cover packets for the next epoch. At epoch end, unused slots are discarded and the cycle repeats.
The specification focuses on the Constant-Rate strategy. An alternative Poisson-Rate strategy, where cover emission times are randomized, is kept for future consideration in §11.5.
4. Rate Limit Budget Model
Each mix node receives a budget of R slots per epoch from the DoS protection mechanism.
Cover emission, locally originated message sending, and packet forwarding all draw from the same pool.
Since each originated packet traverses L forwarding hops — where L is the mix path length
as defined in Mix Protocol §6 —
forwarding traffic naturally consumes a significant portion of the budget.
If every node originates at rate C packets per epoch (cover plus locally originated combined),
each node forwards approximately C * L packets per epoch.
Since origination and forwarding share the same budget R:
C + C * L ≤ R
C ≤ R / (1 + L)
R / (1 + L) is therefore the upper bound on total origination,
not a target for cover emission alone.
Cover rate does not need to be explicitly reduced by a node's locally originated rate,
because the slot pool is self-balancing (see below).
This means the actual cover traffic emitted by a node is always less than R and depends on:
- Path length
L: longer paths consume more forwarding slots, leaving fewer for cover. ForL=3, approximately 25% of slots are available for cover and locally originated message sending. - Network size
Nand forwarding variance: with random path selection, forwarding load is not uniform. Some nodes receive more forwarding traffic than the equilibrium average, leaving even fewer slots for cover. The actual cover output per node therefore varies with network conditions.
The slot pool is self-balancing — no explicit origination rate constraint is needed. Heavier forwarding load automatically leaves fewer slots for cover; lighter load leaves more.
Note on DoS protection architecture:
The self-balancing pool model assumes per-hop generated proofs
(Mix DoS Protection §4.2),
where forwarding consumes slots from the node's own R budget.
With sender-generated proofs (Mix DoS Protection §4.1),
forwarding nodes only verify proofs and do not consume their own R,
but cover emission must still account for forwarding load to maintain constant total output.
The budget model and slot pool semantics for sender-generated proofs require separate analysis
and are deferred to §11.4.
5. Integration with the Mix Protocol
The cover traffic mechanism integrates with the Mix Protocol at four points in packet processing.
Cover packets are identified by the reserved protocol codec "/mix/cover/1.0.0".
This codec is used as the origin protocol codec during Sphinx packet construction
and is checked during exit processing to distinguish cover packets from application traffic.
All mix nodes in a deployment SHOULD use the same strategy type and parameters
to ensure uniform emission patterns across the anonymity set.
The configured path length L for cover packets
MUST match the path length used for locally originated messages
as defined in Mix Protocol §6.
5.1 Cover Packet Transmission
Trigger: The configured strategy schedules a cover emission.
During Sphinx packet construction: The mechanism constructs a cover Sphinx packet following the same construction procedure as a locally originated message, with the following differences:
- The mix path is a loop path — the final hop routes the packet back to the originating node.
- The origin protocol codec MUST be set to the cover traffic codec defined in §5. This codec is recognized by the Mix Protocol during exit processing to identify returning cover packets (see §5.4).
- The application message content SHOULD be filled with cryptographically random bytes. Random payloads provide defense-in-depth against partial path compromise and ensure that cover packets remain indistinguishable from non-cover traffic if the design evolves to support non-loop cover paths in the future.
- If pre-computation is enabled, the pre-built cover packet is used directly without re-construction.
Wire format: Cover packets use the exact Sphinx packet format defined in Mix Protocol §8. No additional fields or framing are introduced. A cover packet on the wire is indistinguishable from a non-cover traffic packet, ensuring that intermediary nodes and external observers cannot classify packets as cover or non-cover.
The cover packet is then transmitted to the first hop following the standard Mix Protocol transmission procedure.
5.2 Non-Cover Slot Claim
Procedure: ClaimSlot() -> success
Trigger: The Mix Protocol needs to send a message or forward a packet and requires a slot from the budget.
The mechanism atomically claims a slot from the pool using the following procedure:
- If
slots_remaining == 0, the claim fails. - If
slots_remaining == len(cover_queue), the only way to free a slot is to reclaim one held by a queued cover packet: dequeue the head ofcover_queueand discard it. Its pre-computed proof MUST NOT be sent on the wire. - Decrement
slots_remainingand return success.
Free (unreserved) slots are taken first; a queued cover packet is reclaimed only when no free slots remain (i.e., when every remaining slot is committed to either non-cover claims already on the wire or pre-built cover in the queue).
On success, the caller then generates a DoS protection proof
via GenerateProof(binding_data) (Mix DoS Protection §8.2.1),
where binding_data is the packet-specific data as defined by the DoS protection mechanism.
If the claim fails, the packet SHOULD be handled as follows to avoid hitting DoS protection limits:
- Locally originated messages: queued for the next epoch.
- Forwarded packets: dropped.
5.3 Epoch Boundary
Procedure: ResetEpoch(epoch) -> void
Trigger: The DoS protection mechanism signals the start of a new epoch
via OnEpochChange (Mix DoS Protection §8.2.3).
The Mix Protocol MUST call ResetEpoch before processing any packets in the new epoch.
The mechanism refreshes the slot pool for the new epoch:
all remaining slots from the previous epoch are discarded,
and a new pool of R slots is initialized.
If pre-computation is enabled, the pre-built cover packets prepared during the previous epoch
are loaded into the new pool.
Cover packets emitted near epoch end may arrive at later hops in a subsequent epoch.
The DoS protection mechanism is responsible for accepting proofs within a configurable epoch window
(e.g., the max_epoch_gap parameter in Mix RLN DoS Protection).
5.4 Cover Packet Reception
Trigger: The Mix Protocol completes exit processing on a received Sphinx packet and extracts the origin protocol codec from the decrypted payload.
If the codec matches the cover traffic codec (see §5), the Mix Protocol MUST handle the packet internally without handing off to the Mix Exit Layer. The packet SHOULD be silently discarded. Implementations MAY use this reception event for diagnostics such as path health monitoring (see §11.2).
This is handled by the cover traffic codec check in Mix Protocol §8.6.4 step 4, which intercepts cover packets before handing off to the Mix Exit Layer.
Since cover packets use loop paths (see the self-exit principle in §3), the exit node is always the originating node itself. The cover traffic codec is therefore never visible to any external party. If a cover packet were routed to a different exit node, that node would detect the cover traffic codec during exit processing and classify the packet as cover traffic. Although the Sphinx construction prevents the exit from identifying the sender, a malicious exit could accumulate cover-to-non-cover traffic ratios over time, leaking information about network-wide cover strategy and volume.
5.5 Data Structures
PrebuiltCoverPacket {
slot_id: bytes // Slot identifier within the epoch
packet: bytes // Pre-built wire-format packet (Sphinx packet + DoS protection proof), ready to transmit
path: []bytes // Ordered list of mix node identifiers on the cover path
created_at: uint64 // Unix timestamp (seconds) when this packet was constructed
}
SlotPool {
epoch: uint64 // The epoch this pool belongs to
cover_queue: []PrebuiltCoverPacket // Pre-built cover packets, dequeued on emission or reclaimed by non-cover claims
slots_remaining: uint32 // Slots still spendable in this epoch (R minus what's already on the wire);
// invariant: slots_remaining >= len(cover_queue)
}
CoverTrafficConfig {
strategy_type: enum { CONSTANT_RATE, POISSON, NONE }
cover_rate_fraction: float64 // f ∈ (0.0, 1.0], scales cover rate relative to the maximum safe rate (see §7); RECOMMENDED default 0.7
// Strategy-specific parameters (see §7):
// For CONSTANT_RATE: emission_rate (float64, packets per second)
// For POISSON: lambda_cover (float64, packets per second)
}
6. Node Responsibilities
This section defines what each mix node MUST do at each integration point.
The slot pool (SlotPool) is a token bucket of R slots per epoch.
Each outgoing packet — cover or non-cover — atomically claims one slot.
Slot claim operations MUST be atomic.
6.1 At Epoch Boundary
When the DoS protection mechanism signals the start of a new epoch,
the Mix Protocol instance MUST invoke ResetEpoch (§5.3) on the cover traffic mechanism
to discard previous epoch state and initialize a new slot pool.
If pre-computation is enabled (RECOMMENDED):
The cover traffic mechanism pre-builds cover packets during epoch N-1 for use in epoch N.
For each slot to be pre-computed (at most R; see §9.1 for sizing guidance),
construct a cover Sphinx packet following the procedure in §5.1
and generate a DoS protection proof for the next epoch
via GenerateProof(binding_data) (Mix DoS Protection §8.2.1).
Store the result as a PrebuiltCoverPacket.
Slots without a pre-built packet will require on-demand generation if selected for cover emission.
Pre-computed proofs are bound to a specific epoch and MUST NOT be reused in subsequent epochs.
Proof validity over time:
Pre-computed proofs may be invalidated within their target epoch, not just across epochs.
For example, in Mix RLN DoS Protection,
accumulating membership updates can push the root used at generation time
out of the current acceptable_root_window_size before the epoch ends.
Implementations MUST therefore validate pre-computed proofs at send time
(see §6.5).
Fallback caveat: On-demand generation when pre-computation falls behind introduces timing jitter, which shifts emissions off-grid for deterministic strategies (e.g., §7.1) and weakens timing unobservability. Implementations SHOULD size the pre-computation pipeline (§9.1) to avoid the fallback path in steady state.
6.2 Cover Emission
The cover emission loop runs continuously as a background process.
Emission timing is governed by the configured strategy (CoverTrafficConfig).
Cover emission consumes from cover_queue.
Slots are deducted from slots_remaining at claim time, not at wire transmission:
forwarded packets within their mixing delay (see §6.4)
have already been deducted, so their slots are unavailable to any later claim.
Algorithm: Cover Emission
The following steps repeat continuously throughout each epoch:
- Wait for the next emission event as determined by the configured strategy.
- If the strategy schedules an emission and
cover_queueis non-empty:
- a. Dequeue the head of
cover_queueand decrementslots_remaining.- b. Validate the proof per §6.5.
- c. Transmit the
packetfield ofPrebuiltCoverPacketto the first hop (other fields are internal and MUST NOT be sent).- If
cover_queueis empty for the remainder of the epoch (because pre-built packets were exhausted by emission or reclaimed under heavy non-cover load), cover emission is suppressed until the next epoch boundary.
6.3 Locally Originated Message Sending
During Sphinx packet construction:
When the Mix Entry Layer submits a locally originated message for mixification,
the Mix Protocol instance MUST first call ClaimSlot() (§5.2).
If no slot can be claimed, the message is queued for the next epoch.
Otherwise, the Mix Protocol instance proceeds with
Sphinx packet construction.
6.4 Packet Forwarding
During Sphinx packet handling:
When the Mix Protocol instance acts as an intermediary and receives a Sphinx packet to forward,
it MUST first call ClaimSlot() (§5.2) before applying the mixing delay.
This ensures no two forwarded packets consume the same slot regardless of how their mixing delays overlap.
If no slot can be claimed, the packet is dropped.
Otherwise, the Mix Protocol instance proceeds with
intermediary processing.
Slot consumption:
The slot is consumed on successful ClaimSlot(), not on transmission (see §6.2).
Send timing: The packet is dispatched when its mixing delay elapses, independently of the cover emission schedule.
6.5 Pre-Computed Proof Validation at Send Time
Before transmitting a pre-built cover packet,
the mechanism MUST validate the carried DoS protection proof against the current state
(see §6.1 for rationale).
For Mix RLN DoS Protection,
this means verifying the merkle_root bound into the proof
is still within the node's acceptable_root_window_size.
If validation fails, implementations MUST either:
- Regenerate the proof against the current anchor, keeping the Sphinx packet body unchanged; or
- Skip the emission if regeneration is infeasible.
A pre-built packet with a stale proof MUST NOT be sent. When regenerating, implementations MAY reuse the message identifier bound to the cover packet where the DoS protection mechanism permits (see Mix RLN DoS Protection).
7. Recommended Strategy
This section defines the Constant-Rate cover emission strategy, which is the normative strategy for this specification.
An alternative Poisson-Rate strategy is documented as a future consideration in §11.5.
Cover emission operates over the R-slot pool and produces irregular total output
because forwarding traffic claims slots at unpredictable times.
Cover is emitted at up to R / (1 + L) packets per epoch —
a maximum, not a target;
the self-balancing pool (§4)
accommodates locally originated messages without explicit adjustment.
Cover rate fraction f:
The strategy takes a configurable cover_rate_fraction f ∈ (0.0, 1.0] (§5.5)
that scales the configured cover rate relative to the maximum safe rate R / ((1 + L) × P).
A value of f = 1.0 emits cover at the maximum; lower values reduce cover output
and leave more headroom in the slot budget for locally originated messages and forwarded traffic.
The RECOMMENDED default is f = 0.7,
which reserves roughly 30% of the per-node slot budget as headroom against forwarding variance.
All mix nodes in a deployment SHOULD use the same f to preserve a uniform anonymity set across the network.
7.1 Constant-Rate Cover Traffic
The cover traffic mechanism emits cover packets at a fixed interval of 1 / emission_rate seconds,
where emission_rate = f × R / ((1 + L) × P) packets per second.
f is the configured cover_rate_fraction (§5.5),
and R / ((1 + L) × P) is the maximum safe cover rate (achieved at f = 1.0).
Non-cover traffic claims slots via ClaimSlot() (§5.2) as it arrives,
making total output inherently irregular even though the cover emission rate is constant.
At the configured rate, up to f × R / (1 + L) cover packets are emitted per epoch;
the actual count is lower when locally originated messages or forwarding variance claim slots first.
The originated cover emission rate is perfectly constant,
so an adversary cannot distinguish epochs with heavy locally originated traffic from idle epochs
by observing cover timing alone.
Tradeoff — timing separability: Cover packets fire on a fixed grid, while forwarded packets fire at arrival time plus mixing delay — always off-grid relative to the cover schedule. Over enough observations, an adversary can separate cover from non-cover by timing alone, regardless of forwarding load. Constant-Rate therefore provides volume unobservability (the node's emission count does not leak non-cover activity) but not timing unobservability (individual packets remain classifiable by timing).
Full timing unobservability requires the pre-scheduled emission timing enhancement (§11.3), where all traffic types share the same timing grid. Constant-Rate is the only strategy compatible with this upgrade path, as it requires deterministic emission times known at epoch start.
Characteristics:
Constant-Rate emits up to N = f × R / (1 + L) cover packets per epoch.
The count is exact when forwarding does not exhaust the pool —
the design intent behind the RECOMMENDED cover_rate_fraction = 0.7 (§7),
which reserves roughly 30% of the per-node slot budget as headroom against forwarding spikes.
Pre-computation sizing matches N; no further safety margin beyond f is needed.
Under exhaustion, cover emission is suppressed for the remainder of the epoch
(§6.2, §10.5),
and per-epoch cover output drops below N.
An observer who knows f can upper-bound the per-epoch forwarding count as total_emissions - N,
so volume unobservability holds only against observers unaware of f or watching aggregate rates.
8. Initiating-Only Node Considerations
Initiating-only nodes are short-lived with dynamic identifiers and do not forward traffic. They SHOULD NOT generate cover traffic, as cover traffic is only meaningful for nodes that participate continuously in the network with a stable identity — a briefly connected node has no sustained emission pattern to protect or contribute.
Residual privacy for initiating-only nodes: Without cover traffic, initiating-only nodes still retain:
- Path anonymity: Sphinx layered encryption prevents any single intermediary or exit from learning both sender and recipient.
- Identity unlinkability: dynamic identifiers prevent cross-session linking.
However, an adversary on the link to the first hop — or a malicious first hop itself — can directly observe session volume and timing, since no cover or forwarded packets are blended with originated traffic.
Deployments where this matters SHOULD route initiating-only traffic through trusted first hops.
If an initiating-only node is promoted to a mix node and becomes long-lived, it SHOULD activate cover traffic using the Constant-Rate strategy. During the first epoch after promotion, pre-computed cover packets are unavailable; the node SHOULD fall back to on-demand cover packet generation for that epoch and begin pre-computation immediately upon promotion.
9. Implementation Recommendations
This section provides non-normative guidance for implementers.
9.1 Pre-computation Scheduling
The pre-computation pipeline SHOULD be initiated at the midpoint of the current epoch to allow sufficient time for slots to be processed before the next epoch begins. Implementations SHOULD interleave pre-computation with normal packet processing (e.g., yielding to non-cover traffic between slot generations) to avoid contention with ongoing packet handling.
Rather than pre-computing all cover packets in the previous epoch,
implementations MAY batch pre-computation across epochs:
an initial batch during epoch N-1 to ensure cover packets are available at the start of epoch N,
with subsequent batches computed incrementally during epoch N itself, staying ahead of the emission schedule.
This reduces peak computational load and memory usage.
9.2 Pool Status Tracking
Implementations SHOULD maintain runtime counters for available slots, cover emissions, and non-cover consumptions. These aid in diagnostics, monitoring, and tuning the emission strategy.
Exposure restrictions: The non-cover consumption counter reveals the exact per-epoch count of real traffic, which is what traffic analysis aims to recover.
Implementations MUST keep this counter (and any derived per-epoch breakdowns) in-memory only and MUST NOT export it via metrics endpoints, structured logs, or any monitoring interface.
9.3 Slot Exhaustion Logging
When a forwarded packet is dropped due to slot exhaustion, implementations SHOULD log a warning.
Persistent slot exhaustion may indicate that R is too low for the network's forwarding load,
or that the node is under a traffic flooding attack.
9.4 Synchronization
Slot claim operations MUST be atomic. Implementations may enforce this using mutexes, lock-free atomic operations, or single-threaded event loops, depending on the concurrency model.
10. Security Considerations
The design principles motivating slot integrity and DoS protection compliance are described in §3. This section discusses the threat context behind those principles.
10.1 Proof Reuse via Proof Leakage
If a pre-computed cover proof and a freshly generated non-cover proof for the same slot are both sent on the wire, the DoS protection mechanism detects a reuse. Depending on the mechanism, this may result in slashing or reputation loss for the node. The slot integrity principle (§3) prevents this by ensuring the cover proof is discarded before the slot is reused.
10.2 Slot Exhaustion Under Heavy Non-Cover Traffic
If non-cover traffic consumes all R slots before the epoch ends,
the node cannot emit further cover traffic.
This is a natural consequence of DoS protection compliance (§3).
Locally originated messages that arrive after slot exhaustion MUST be queued for the next epoch.
Cover emission ceases when no slots remain.
10.3 Network-Wide Cover-Rate Correlation
When a message traverses multiple mix nodes, each node on the path claims one slot for forwarding, slightly reducing its available cover capacity for the remainder of the epoch. A global passive adversary observing all nodes simultaneously could in principle detect correlated cover-rate perturbations across nodes and use them to trace message paths.
In practice, each forwarded message consumes only one slot out of R,
making the perturbation negligible for sufficiently large R.
The pre-scheduled emission timing enhancement (§11.3)
would eliminate this concern entirely by fixing all emission times at epoch start,
making individual slot consumption events unobservable.
10.4 Timing Separability of Cover and Non-Cover Packets
The default Constant-Rate strategy (§7.1) emits cover packets on a fixed grid while forwarded packets are dispatched at arrival time plus mixing delay. With enough observations, a passive adversary can classify individual packets by timing alone, regardless of forwarding load.
Constant-Rate therefore provides volume unobservability but not timing unobservability. Under Constant-Rate, the pre-scheduled emission timing enhancement (§11.3) is the only design that closes this gap, by assigning all outgoing packets — cover, locally originated, and forwarded — to a shared fixed-time grid determined at epoch start.
10.5 Cover Priority and Forwarded Packet Drops
Cover emissions occur on a schedule independent of forwarding load,
so slots consumed by cover early in an epoch are unavailable to forwarded packets arriving later.
Under uneven forwarding load, this can cause honest forwards to be dropped (§6.4)
even when total traffic stays within the R budget.
The cover_rate_fraction f (§7) reduces this risk
by holding back a fraction of the per-node slot budget from cover emission,
leaving headroom for forwarding spikes.
With the RECOMMENDED f = 0.7, approximately 30% of the budget is reserved as headroom.
Deployments SHOULD adjust f based on observed network behavior;
see §11.1 for adaptive tuning as a future enhancement.
11. Future Work
11.1 Adaptive Cover Rate Fraction
The cover_rate_fraction f (§7) is currently a static deployment-wide configuration.
A future enhancement MAY define a method for nodes to adapt f based on observed forwarding load,
network size N, and path length L,
allowing cover rate to be tuned closer to the node's actual available budget
and reducing unnecessary cryptographic work.
Any adaptive scheme MUST preserve uniformity of f across the anonymity set
to avoid leaking per-node load through emission rate differences.
11.2 Path Health Monitoring
When cover packets are implemented as loop packets — dummy Sphinx packets that follow a valid mix path and return to the originating node — their return confirms path liveness. Failures to return indicate potential node failures or active attacks along the path. A future revision of this specification MAY define an interface for exposing loop return status to enable path health monitoring.
11.3 Pre-Scheduled Emission Timing
Inspired by the Blend Protocol, a future enhancement MAY define pre-scheduled emission slots where all outgoing packets — cover, locally originated, and forwarded — are assigned to fixed time slots determined at epoch start. All traffic types would share the same timing grid, producing a perfectly periodic total output regardless of traffic mix. This would eliminate the periodic emission pattern tradeoff noted in §7.1, as an observer would see uniform intervals with no way to classify individual packets. When using Constant-Rate, this is the only design path to full timing unobservability (see §10.4).
This approach is only compatible with the Constant-Rate strategy, which provides deterministic emission times known at epoch start. Poisson-Rate, where emission times are sampled at runtime, cannot support pre-scheduled slots. Note that pre-scheduled slots would require changes to the mixing delay strategy in the Mix Protocol, as forwarded packets would need to be held until their assigned slot time rather than forwarded after the sampled delay elapses.
11.4 Budget Model for Sender-Generated Proofs
The rate-limit budget model in §4 assumes per-hop generated proofs,
where forwarding consumes from the node's own R budget and the slot pool self-balances.
With sender-generated proofs, the initiating node generates L proofs per originated packet from its own R,
while forwarding nodes only verify and do not consume their own budget.
A future revision MAY define an adapted budget model for this architecture,
including revised slot pool semantics, an explicit emission rate target that accounts for observed forwarding load,
and updated pre-computation sizing.
11.5 Poisson-Rate Cover Traffic
Poisson-Rate is a candidate alternative strategy retained here for future consideration.
The node emits cover packets according to a Poisson process with rate λ_cover packets per second,
producing random memoryless inter-emission gaps.
λ_cover would be set to f × R / ((1 + L) × P) packets per second,
where f is the configured cover_rate_fraction (§5.5).
Emissions are suppressed when no slots are available.
Potential strengths:
- Timing unobservability: both cover and forwarded emissions are exp-distributed, making it statistically hard for an observer to classify individual packets by timing (addressing the separability concern in §10.4).
- Short-window volume unobservability: per-epoch cover count is
Poisson(N)rather than deterministic, so forwarding-count estimates from total emissions carry at least±√Nuncertainty per epoch.
Costs:
- Per-epoch variance: cover emissions per epoch are
Poisson(N)— some epochs are thin and weaken in-epoch mixing. - Front-loading: random clustering can consume cover budget early, starving late-arriving non-cover traffic.
- Pre-computation margin: pipelines need a safety margin (e.g.,
N + 3√N) to avoid running dry. - Budget coupling: cover rate drops with non-cover load as the pool nears exhaustion.
Interaction with R:
Poisson-Rate's per-epoch variance shrinks relative to its mean as R grows (√N / N → 0).
At small R, front-loading and thin-cover epochs are pronounced.
At large R, these effects become negligible.
Simulation of real traffic distributions is required before adopting Poisson-Rate as a normative option.
Copyright
Copyright and related rights waived via CC0.