Temporal Obfuscation
Temporal obfuscation is ZEclipse’s defense against timing-based blockchain analysis, based on the design in docs/TEMPORAL_OBFUSCATION.md.
It adds controlled randomness to when hops and transfers execute, so observers cannot correlate incoming and outgoing transactions purely by time.
Components
- TemporalObfuscationManager – low-level scheduler that decides when to send transactions.
- TimeObfuscator – convenience wrapper for obfuscating single and multi-transfer flows.
- TimingEnhancedConnector – SDK connector that combines anonymous transfers with timing privacy.
These live in the TypeScript SDK (app/src/timing and connector modules).
Timing Features
Random Execution Delays
Each hop is executed with a random delay:
- Delay range depends on the hop index and selected strategy.
- Prevents easy mapping of “in” and “out” transactions across hops.
// Conceptual example from the SDK
const obfuscator = new TimeObfuscator(connection)
const executeAt = await obfuscator.obfuscateTransfer(transaction, hopIndex)
Time-Sliced Execution
For multi-recipient transfers, ZEclipse spreads transactions across time slices within a configurable window:
- Avoids bursts of related transfers.
- Makes outputs appear as independent events.
const schedule = await obfuscator.obfuscateMultiTransfer(transactions, hopIndex)
// schedule maps each transaction to a specific execution time slice
Timing Strategies
From TEMPORAL_OBFUSCATION.md, strategies roughly behave as:
| Strategy | Min Delay | Max Delay | Window | Privacy Level | Typical Use Case |
|---|---|---|---|---|---|
MINIMAL | 200 ms | 2 s | 30 s | ★★☆☆☆ | Small transfers, testing |
STANDARD | 500 ms | 8 s | 60 s | ★★★☆☆ | General-purpose transfers |
BALANCED | 1 s | 10 s | 60 s | ★★★★☆ | Medium-value transfers |
MAXIMUM_PRIVACY | 2 s | 30 s | 180 s | ★★★★★ | High-value / sensitive txs |
CUSTOM | configurable | configurable | configurable | depends on config | Advanced users only |
Programmatically, you typically configure this via the connector:
connector.setTimingStrategy(TimingStrategy.MAXIMUM_PRIVACY)
Configuration
The core configuration interface is:
export interface TemporalObfuscationConfig {
minDelay: number // ms
maxDelay: number // ms
randomBatchOrder: boolean
timeSlicedExecution: boolean
timeWindowSize: number // ms
timeSliceInterval: number // ms
}
Strategies map to concrete configs, which you can override if you need more control.
Diagnostics & Entropy
The timing system exposes diagnostics so you can quantify privacy:
const stats = connector.getTimingStats()
/*
{
averageHopDelay: 2543,
timeDistribution: [25, 30, 10, 85, 40, ...],
entropyScore: 87,
correlationResistance: 79,
}
*/
Key ideas:
- Entropy score measures how unpredictable the timing distribution is.
- Correlation resistance approximates resistance to hop-to-hop timing correlation.
For high-value transfers, the docs recommend:
- Entropy score > 75.
- Correlation resistance > 80.
Effect on Anonymity
Base ZEclipse already achieves about 5.3M possible paths from the multi-hop split graph.
Temporal obfuscation:
- Multiplies this effective anonymity set by roughly 1–5× (strategy dependent).
- Makes it difficult to confidently rule out candidate paths using timing alone.
The tradeoff is straightforward:
- More delay ⇒ more privacy.
- Less delay ⇒ faster UX.
For most DApps, BALANCED or STANDARD strategies offer a good middle ground.