summaryrefslogtreecommitdiffstats
path: root/timing/src/obfuscation.rs
diff options
context:
space:
mode:
authorgabrix73 <gabriel1@frozenstar.info>2026-06-01 18:41:36 +0200
committergabrix73 <gabriel1@frozenstar.info>2026-06-01 18:41:36 +0200
commit9f5d864d533ce86459e654f5d78212933c0269ea (patch)
tree4b71e8c7ab4e78da93e5f3164803da4de68c7031 /timing/src/obfuscation.rs
downloadonioncoin-main.tar.gz
onioncoin-main.tar.xz
onioncoin-main.zip
Initial commit: OnionCoin prototype with Proof-of-Relay consensusHEADv0.1.0main
OnionCoin is a privacy cryptocurrency that rewards Tor relay operators through a unique Proof-of-Contribution consensus mechanism. Core Features: - Proof-of-Relay: 30% of block rewards go to Tor operators - Native .onion node identity (no IP exposure) - Temporal obfuscation protocols - Dandelion++ over Tor propagation - Native inheritance system with dead man's switch Technical Stack: - Rust workspace with 8 crates - Ed25519/X25519 cryptography - arti (Rust Tor client) integration planned - 10 minute block time, 5-10 TPS design Status: Prototype - Consensus logic complete with passing tests (30/33) - Network layer conceptual design complete - Tor integration pending - Testnet launch planned Q3 2026 License: MIT Author: Gabriele Salati (virebent) Contact: g48rix@gmail.com Website: https://www.gabrielesalati.eu Repository: https://git.virebent.art/virebent/onioncoin
Diffstat (limited to 'timing/src/obfuscation.rs')
-rw-r--r--timing/src/obfuscation.rs243
1 files changed, 243 insertions, 0 deletions
diff --git a/timing/src/obfuscation.rs b/timing/src/obfuscation.rs
new file mode 100644
index 0000000..b48ea82
--- /dev/null
+++ b/timing/src/obfuscation.rs
@@ -0,0 +1,243 @@
+use crate::{TimeRange, TimeRangeProof, DelayStrategy, MixingPool};
+use chrono::{DateTime, Utc};
+use serde::{Deserialize, Serialize};
+use std::time::Duration;
+
+/// Orchestrates all timing obfuscation strategies
+#[derive(Debug)]
+pub struct TimingObfuscator<T> {
+ /// Mixing pool for batch releases
+ mixing_pool: MixingPool<T>,
+
+ /// Strategy for adding delays
+ delay_strategy: DelayStrategy,
+
+ /// Configuration
+ config: ObfuscationConfig,
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct ObfuscationConfig {
+ /// Enable mixing pool batching
+ pub use_mixing_pool: bool,
+
+ /// Enable random delays
+ pub use_delays: bool,
+
+ /// Enable fuzzy timestamps
+ pub use_fuzzy_timestamps: bool,
+
+ /// Ratio of fake items to inject (0.0 - 1.0)
+ pub fake_item_ratio: f32,
+}
+
+impl Default for ObfuscationConfig {
+ fn default() -> Self {
+ Self {
+ use_mixing_pool: true,
+ use_delays: true,
+ use_fuzzy_timestamps: true,
+ fake_item_ratio: 0.3, // 30% fake traffic
+ }
+ }
+}
+
+impl<T> TimingObfuscator<T> {
+ pub fn new(config: ObfuscationConfig) -> Self {
+ Self {
+ mixing_pool: MixingPool::default(),
+ delay_strategy: DelayStrategy::node_rebroadcast(),
+ config,
+ }
+ }
+
+ /// Add item to mixing pool
+ pub fn add_to_pool(&mut self, item: T) {
+ if self.config.use_mixing_pool {
+ self.mixing_pool.add(item);
+ }
+ }
+
+ /// Check if should release batch
+ pub fn should_release_batch(&self) -> bool {
+ if !self.config.use_mixing_pool {
+ return false;
+ }
+ self.mixing_pool.should_release()
+ }
+
+ /// Release shuffled batch
+ pub fn release_batch(&mut self) -> Vec<T> {
+ self.mixing_pool.release_batch()
+ }
+
+ /// Apply delay strategy
+ pub async fn apply_delay(&self) {
+ if self.config.use_delays {
+ self.delay_strategy.sleep().await;
+ }
+ }
+
+ /// Get current pool size
+ pub fn pool_size(&self) -> usize {
+ self.mixing_pool.len()
+ }
+}
+
+/// Transaction timing metadata
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct TimingMetadata {
+ /// Fuzzy time range
+ pub time_range: TimeRange,
+
+ /// Zero-knowledge proof of creation time
+ pub time_proof: TimeRangeProof,
+
+ /// Optional: observed network delay (for adaptive strategies)
+ pub network_delay_hint: Option<Duration>,
+}
+
+impl TimingMetadata {
+ /// Create timing metadata for a transaction
+ pub fn new(real_time: DateTime<Utc>, seed: &[u8; 32]) -> Result<Self, crate::timerange::TimeRangeError> {
+ let time_range = TimeRange::new_fuzzy(real_time);
+ let time_proof = TimeRangeProof::generate(seed, real_time, &time_range)?;
+
+ Ok(Self {
+ time_range,
+ time_proof,
+ network_delay_hint: None,
+ })
+ }
+
+ /// Validate timing metadata
+ pub fn validate(&self, current_time: DateTime<Utc>) -> bool {
+ // Check time range is valid
+ if !self.time_range.is_valid(current_time) {
+ return false;
+ }
+
+ // Verify time proof
+ if !self.time_proof.verify(&self.time_range) {
+ return false;
+ }
+
+ true
+ }
+
+ /// Set network delay hint for adaptive strategies
+ pub fn with_network_delay(mut self, delay: Duration) -> Self {
+ self.network_delay_hint = Some(delay);
+ self
+ }
+}
+
+/// Strategies for transaction propagation
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
+pub enum PropagationPhase {
+ /// Dandelion STEM phase (anonymity)
+ Stem,
+
+ /// Dandelion FLUFF phase (broadcast)
+ Fluff,
+}
+
+/// Transaction wrapper with timing information
+#[derive(Debug, Clone)]
+pub struct TimedItem<T> {
+ pub item: T,
+ pub timing: TimingMetadata,
+ pub phase: PropagationPhase,
+}
+
+impl<T> TimedItem<T> {
+ pub fn new(item: T, timing: TimingMetadata) -> Self {
+ Self {
+ item,
+ timing,
+ phase: PropagationPhase::Stem,
+ }
+ }
+
+ pub fn transition_to_fluff(mut self) -> Self {
+ self.phase = PropagationPhase::Fluff;
+ self
+ }
+
+ pub fn is_stem(&self) -> bool {
+ self.phase == PropagationPhase::Stem
+ }
+
+ pub fn is_fluff(&self) -> bool {
+ self.phase == PropagationPhase::Fluff
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_timing_metadata_creation() {
+ let now = Utc::now();
+ let seed = [42u8; 32];
+
+ let metadata = TimingMetadata::new(now, &seed).unwrap();
+ assert!(metadata.validate(now));
+ }
+
+ #[test]
+ fn test_timing_metadata_validation() {
+ let now = Utc::now();
+ let seed = [42u8; 32];
+
+ let metadata = TimingMetadata::new(now, &seed).unwrap();
+
+ // Should validate at current time
+ assert!(metadata.validate(now));
+
+ // Should validate slightly in the future
+ let future = now + chrono::Duration::hours(1);
+ assert!(metadata.validate(future));
+ }
+
+ #[test]
+ fn test_obfuscator_pool() {
+ let config = ObfuscationConfig::default();
+ let mut obfuscator = TimingObfuscator::<u32>::new(config);
+
+ obfuscator.add_to_pool(1);
+ obfuscator.add_to_pool(2);
+ obfuscator.add_to_pool(3);
+
+ assert_eq!(obfuscator.pool_size(), 3);
+ }
+
+ #[test]
+ fn test_timed_item_phases() {
+ let now = Utc::now();
+ let seed = [42u8; 32];
+ let timing = TimingMetadata::new(now, &seed).unwrap();
+
+ let item = TimedItem::new(42u32, timing);
+ assert!(item.is_stem());
+ assert!(!item.is_fluff());
+
+ let item = item.transition_to_fluff();
+ assert!(!item.is_stem());
+ assert!(item.is_fluff());
+ }
+
+ #[tokio::test]
+ async fn test_apply_delay() {
+ let config = ObfuscationConfig::default();
+ let obfuscator = TimingObfuscator::<u32>::new(config);
+
+ let start = std::time::Instant::now();
+ obfuscator.apply_delay().await;
+ let elapsed = start.elapsed();
+
+ // Should have some delay (at least 10s from node_rebroadcast strategy)
+ assert!(elapsed >= Duration::from_secs(10));
+ }
+}