super_ball/THROWER.md

6.8 KiB

Thrower Rules

What I Am

I am a Thrower - an anonymizing node that provides location privacy for Nostr users by catching, unwrapping, rewrapping and throwing Superballs (wrapped encrypted events) with timing delays and size obfuscation.

What I Look For

1. Routing Events (Kind 22222)

  • Monitor all relays I'm connected to
  • Look for events with kind: 22222
  • Check if tags contains ["p", "<my_pubkey>"]
  • These are events meant for me to process

2. Event Structure I Expect

{
  "kind": 22222,
  "pubkey": "<some_ephemeral_key>", // Not important to me
  "content": "<nip44_encrypted_payload>", // This is what I need
  "tags": [["p", "<my_pubkey>"]],
  "created_at": <timestamp>,
  "id": "<event_id>",
  "sig": "<signature>"
}

What I Do When I Receive An Event

1. Validate

  • Verify the event signature is valid
  • Confirm the p tag contains my pubkey
  • Ensure it's kind 22222

2. Decrypt and Identify Payload Type

  • Use my private key with NIP-44 to decrypt the content
  • Check payload structure to determine type:

Type 1: Routing Payload (Created by Builder)

{
  "event": { /* Final event or inner wrapped event */ },
  "routing": { /* My routing instructions from builder */
    "relays": ["wss://relay1.com", "wss://relay2.com"],
    "delay": 30,
    "p": "next_thrower_pubkey", // Optional - missing means final posting
    "audit": "audit_tag", // Required audit tag
    "payment": "eCash_token", // Optional
    "add_padding_bytes": 256 // Optional
  }
}

Type 2: Padding Payload (Created by Previous Thrower)

{
  "event": { /* Still-encrypted inner event */ },
  "padding": "01234567890123" // Padding data to discard
}

3. Handle Payload Type

If Padding Payload:

  1. Discard padding - Ignore padding field completely
  2. Decrypt again - The "event" field contains another encrypted payload
  3. Process the inner payload - This will be a routing payload meant for me

If Routing Payload:

  1. Process routing instructions - These were created by the builder specifically for me
  2. Continue with normal processing

4. Process Routing Instructions

Delay

  • Wait the specified number of seconds before forwarding
  • Add random jitter (±10%) to prevent timing analysis
  • Queue the event for delayed processing

Relays

  • Post to ALL relays in the relays array that don't require AUTH
  • Skip AUTH-required relays when posting final events (can't authenticate as original author)
  • Validate all relay URLs are properly formatted
  • Provides redundancy and availability within AUTH constraints

Next Hop Logic

  • p field present: Forward to next Thrower with padding-only wrapper
  • p field missing: Post inner event directly to relays (end chain)

Audit Tag Processing

  • audit field: Always present - include as ["p", "<audit_tag>"] in routing event
  • Camouflage: Audit tag looks identical to real next-hop pubkeys
  • Security: Enables user detection of dropped/delayed/modified events

Payment Processing

  • payment field present: Process eCash token for service payment
  • payment field missing: Process for free (if thrower allows)

5. Forward Event

Two-Path Processing

Path 1: Forward to Next Thrower (p field present)

  • Create padding-only wrapper (never create routing instructions)
  • Generate fresh ephemeral keypair
  • Create padding payload:
{
  "event": { /* The still-encrypted inner event */ },
  "padding": "random_padding_data_123456789"
}
  • Encrypt to next Thrower's pubkey
  • Create routing event with next hop's pubkey in p tag

Path 2: Final Posting (p field missing)

  • Extract inner event from payload
  • Post directly to all relays in routing.relays array
  • No wrapping or encryption needed
  • End of chain

Critical Rules

  1. Throwers NEVER create routing instructions - Only padding
  2. Routing instructions come ONLY from the builder - Pre-encrypted for each hop
  3. Always use fresh ephemeral keys when forwarding
  4. Include audit tag in routing event p tags for camouflage

My Rules

Security Rules

  1. Never log sensitive data - Don't store decrypted content or routing info
  2. Generate new keys - Use fresh ephemeral keys for each forward
  3. Validate everything - Check signatures, event structure, relay URLs
  4. Rate limiting - Don't process more than X events per minute from same source

Privacy Rules

  1. No correlation - Don't link input events to output events in logs
  2. Clear memory - Immediately clear decrypted data after processing
  3. Random timing - Add jitter to specified delays
  4. Mix traffic - Send decoy traffic when idle (optional)

Processing Rules

  1. First come, first served - Process events in order received
  2. Fail silently - Drop invalid events without response
  3. Retry logic - Attempt to post 3 times before giving up
  4. Resource limits - Drop oldest queued events if memory/queue full

Network Rules

  1. Multiple relays - Connect to diverse set of relays
  2. Separate connections - Use different connections for input/output
  3. AUTH constraint - Can only write to relays that do NOT require AUTH (since I post events I didn't sign)
  4. Read capability - Can read from any relay (AUTH or non-AUTH) to monitor for Superballs
  5. NIP-65 compliance - Maintain accurate relay list marking read-only vs write-capable relays
  6. Authentication testing - Regularly test relays to determine AUTH requirements
  7. Rotate connections - Periodically reconnect to prevent fingerprinting

What I Never Do

  1. Never modify final signatures - Only remove padding tags, never add to signed events
  2. Never store routing paths - Process and forget
  3. Never respond to clients - Silent operation only
  4. Never correlate users - Each Superball is independent
  5. Never log destinations - Only log operational metrics

Example Processing Flow

Single Unwrapping (Routing Payload)

  1. Receive: Kind 22222 event with my pubkey in p tag
  2. Decrypt: Get payload with routing instructions
  3. Process: These routing instructions were created for me by builder
  4. Forward or Post: Based on routing.p field

Double Unwrapping (Padding Payload)

  1. Receive: Kind 22222 event with my pubkey in p tag
  2. First Decrypt: Get padding payload - discard padding
  3. Second Decrypt: Decrypt the inner event to get my routing instructions
  4. Process: These routing instructions were created for me by builder
  5. Forward or Post: Based on routing.p field

Clean Up

  • Queue: Schedule for delayed processing (e.g., 30 seconds + jitter)
  • Clean: Clear all decrypted data from memory after processing

I am a privacy-preserving Thrower that helps users post content while hiding their location. I ask no questions, store no logs, and remember nothing about the Superballs that pass through me.