Skip to content

IFM Frequency Model

Overview

A frequency in IFM is a human-friendly namespace that maps to a 256-bit network identifier (Topic ID). This separation allows the protocol to evolve beyond the FM radio metaphor while maintaining backward compatibility.


Frequency Representation

Human-Friendly Frequency

91.700
chat.general
music.lofi
weather.tokyo
sensor.greenhouse.3
game.room.42
private.team
team.alpha

Canonical Identifier

ifm://public/91.700
ifm://public/chat.general
ifm://public/music.lofi
ifm://public/weather.tokyo
ifm://public/sensor.greenhouse.3
ifm://public/game.room.42
ifm://protected/private.team
ifm://hidden/team.alpha

Network Identifier (Topic ID)

BLAKE3("ifm://public/91.700")        = 0xabcdef...
BLAKE3("ifm://public/chat.general")  = 0x123456...
BLAKE3("ifm://protected/private.team") = 0x789abc...
BLAKE3("ifm://hidden/team.alpha")    = 0xfedcba...

Frequency Structure

rust
struct Frequency {
    namespace: Namespace,    // public | protected | hidden
    channel: String,         // human-readable channel name
    version: u8,             // protocol version for this frequency
}

Namespace Types

NamespacePrefixEncryptionDiscoveryUse Case
Publicifm://public/None (plaintext)DHT + GossipSubOpen broadcast, chat, streaming
Protectedifm://protected/ChaCha20-Poly1305DHT + GossipSub (key required to decrypt)Private groups, team comms
Hiddenifm://hidden/ChaCha20-Poly1305Invite-only (not in DHT)Secret channels, secure comms

Frequency Resolution

Parsing Human Frequency

Resolution Algorithm

rust
fn resolve_frequency(input: &str) -> Result<Frequency> {
    // 1. Try parsing as canonical URI
    if input.starts_with("ifm://") {
        return parse_canonical(input);
    }
    
    // 2. Check for explicit namespace prefixes
    if input.starts_with("public:") {
        return Ok(Frequency { namespace: Public, channel: input[7..].into(), version: 1 });
    }
    if input.starts_with("protected:") || input.starts_with("private:") {
        return Ok(Frequency { namespace: Protected, channel: input.split(':').nth(1).unwrap().into(), version: 1 });
    }
    if input.starts_with("hidden:") {
        return Ok(Frequency { namespace: Hidden, channel: input[7..].into(), version: 1 });
    }
    
    // 3. Heuristic: FM-like frequencies (digits + optional dot)
    if input.chars().all(|c| c.is_ascii_digit() || c == '.') {
        return Ok(Frequency { namespace: Public, channel: input.into(), version: 1 });
    }
    
    // 4. Default: public namespace
    Ok(Frequency { namespace: Public, channel: input.into(), version: 1 })
}

Frequency Hash (Topic ID)

rust
fn frequency_to_topic_id(freq: &Frequency) -> [u8; 32] {
    let canonical = freq.to_canonical_string(); // e.g., "ifm://public/91.700"
    BLAKE3::hash(canonical.as_bytes()).into()
}

Properties:

  • Deterministic: same frequency always → same Topic ID
  • Uniform distribution: suitable for DHT keyspace
  • 256-bit: collision-resistant
  • Used as: GossipSub topic, DHT key, cache key

Frequency Metadata

Optional metadata attached to frequencies (broadcast via ANNOUNCE packets):

rust
struct FrequencyMetadata {
    name: Option<String>,           // "General Chat"
    description: Option<String>,    // "Main discussion channel"
    language: Option<String>,       // "en", "es", "ja"
    encryption: EncryptionType,     // None | ChaCha20Poly1305
    listener_count: u32,            // Current peers tuned in
    capabilities: Vec<Capability>,  // Voice, Chat, File, Video, etc.
    created_at: u64,                // Unix timestamp
    owner: Option<PeerId>,          // For protected/hidden frequencies
}

Capabilities

CapabilityDescription
voiceReal-time voice communication
chatText messaging
videoVideo streaming
fileFile transfer
telemetryIoT sensor data
gamingMultiplayer game sync
aiAI agent communication

Frequency Operations

Tune (Join Frequency)

Leave Frequency

1. GossipSub: UNSUBSCRIBE from Topic ID
2. Send LEAVE packet (optional, graceful)
3. Close frequency-specific connections
4. Clean up local state, emit "left" event

Scan (Discover Frequencies)

1. DHT: Iterate known frequency announcements
2. Local: mDNS/UDP multicast for LAN frequencies
3. Return list of (Frequency, Metadata, PeerCount)

Protected Frequencies

Key Derivation

Encryption

  • Algorithm: ChaCha20-Poly1305 (AEAD)
  • Nonce: 12-byte prefix + 4-byte packet sequence (big-endian)
  • AAD: Canonical frequency string
  • Applied: At packet payload level (before signing)
rust
fn encrypt_payload(payload: &[u8], key: &[u8; 32], nonce_prefix: &[u8; 12], sequence: u64, aad: &[u8]) -> Vec<u8> {
    let mut nonce = [0u8; 12];
    nonce[..8].copy_from_slice(nonce_prefix);
    nonce[8..].copy_from_slice(&sequence.to_be_bytes());
    
    chacha20_poly1305_encrypt(key, &nonce, payload, aad)
}

Hidden Frequencies

  • Not advertised in DHT
  • Not announced via ANNOUNCE packets
  • Joined only via direct invitation (QR code, secure link, out-of-band)
  • Same encryption as protected frequencies
  • Topic ID still derived from canonical form (but canonical form never published)

Frequency Naming Conventions

Public Frequencies

PatternExampleUse Case
FM-style91.700, 88.5, 107.9Radio-like broadcast
Category.namechat.general, music.lofi, news.worldOrganized channels
Location.categoryweather.tokyo, traffic.la, alerts.sfGeo-specific
Sensor.typesensor.temperature, sensor.humidityIoT telemetry

Protected Frequencies

PatternExampleUse Case
private.nameprivate.team, private.familyPrivate groups
org.nameacme.engineering, acme.salesOrganization channels
project.nameproject.alpha, project.launchProject rooms

Hidden Frequencies

PatternExampleUse Case
secret.namesecret.op, secret.meetingCovert comms
game.room.idgame.room.42, game.lobby.7Game sessions
device.iddevice.camera.1, device.drone.3Device control

Frequency Lifecycle


Mermaid: Frequency Resolution Flow


Examples

Public Frequency

json
{
  "human": "91.700",
  "canonical": "ifm://public/91.700",
  "topic_id": "0xabcdef1234567890...",
  "encryption": "none",
  "discoverable": true
}

Protected Frequency

json
{
  "human": "private.team",
  "canonical": "ifm://protected/team",
  "topic_id": "0x1234567890abcdef...",
  "encryption": "ChaCha20-Poly1305",
  "discoverable": true,
  "key_required": true
}

Hidden Frequency

json
{
  "human": "team.alpha",
  "canonical": "ifm://hidden/team.alpha",
  "topic_id": "0xfedcba0987654321...",
  "encryption": "ChaCha20-Poly1305",
  "discoverable": false,
  "invite_only": true
}

Custom Canonical Form

json
{
  "human": "ifm://protected/acme.engineering",
  "canonical": "ifm://protected/acme.engineering",
  "topic_id": "0x9988776655443322...",
  "encryption": "ChaCha20-Poly1305",
  "discoverable": true
}

Released under the MIT License.