153 lines
5.8 KiB
Markdown
153 lines
5.8 KiB
Markdown
# Superball Daemon Rules
|
|
|
|
## What I Am
|
|
I am Superball - an anonymizing node that provides location privacy for Nostr users by forwarding their encrypted events with timing delays and size obfuscation.
|
|
|
|
## What I Look For
|
|
|
|
### 1. Routing Events (Kind 30000)
|
|
- Monitor all relays I'm connected to
|
|
- Look for events with `kind: 30000`
|
|
- Check if `tags` contains `["p", "<my_pubkey>"]`
|
|
- These are events meant for me to process
|
|
|
|
### 2. Event Structure I Expect
|
|
```json
|
|
{
|
|
"kind": 30000,
|
|
"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 30000
|
|
|
|
### 2. Decrypt
|
|
- Use my private key with NIP-44 to decrypt the content
|
|
- Extract the payload which contains:
|
|
```json
|
|
{
|
|
"event": { /* The event to forward */ },
|
|
"routing": {
|
|
"relays": ["wss://relay1.com", "wss://relay2.com"],
|
|
"delay": 30,
|
|
"pad": "+150", // or "-50"
|
|
"p": "next_superball_pubkey", // Optional - missing means final posting
|
|
"audit": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456", // Required audit tag
|
|
"payment": "eCash_token" // Optional
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3. 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
|
|
|
|
#### Padding
|
|
- **Remove padding (`"pad": "-N"`)**: Delete N bytes worth of padding tags from the event
|
|
- **Add padding (`"pad": "+N"`)**: Create new routing wrapper with N bytes of padding tags
|
|
|
|
#### Relays
|
|
- Post to ALL relays in the `relays` array
|
|
- Validate all relay URLs are properly formatted
|
|
- Provides redundancy and availability
|
|
|
|
#### Next Hop Logic
|
|
- **`p` field present**: Create routing event for specified next Superball (can apply padding)
|
|
- **`p` field missing**: Extract inner event and post directly to relays (end chain, no padding changes)
|
|
|
|
#### Padding Logic
|
|
- **`p` field present + `pad` field**: Apply padding changes when creating routing wrapper
|
|
- **`p` field missing**: Ignore any `pad` field - cannot modify signed event
|
|
- **Final hop rule**: Never modify signed events, post exactly as received
|
|
|
|
#### 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 daemon allows)
|
|
|
|
### 4. Forward Event
|
|
|
|
#### Always Rewrap (Important for Privacy)
|
|
**ALWAYS** create a new routing event to hide whether padding was added or removed:
|
|
|
|
```json
|
|
{
|
|
"kind": 30000, // Always use routing event
|
|
"pubkey": "<my_ephemeral_key>", // Generate fresh ephemeral key
|
|
"content": "<encrypted_inner_event>", // Re-encrypt with my key
|
|
"tags": [
|
|
["p", "<next_hop_or_final_destination>"],
|
|
["p", "<audit_tag_from_routing>"], // Always include audit tag as p tag
|
|
["padding", "<random_data_1>"], // Adjusted padding
|
|
["padding", "<random_data_2>"] // May be more or less than before
|
|
]
|
|
}
|
|
```
|
|
|
|
#### Next Hop Handling
|
|
- **If `p` field in routing**: Create routing event with that pubkey in p tag
|
|
- **If no `p` field in routing**: Extract inner event and post directly to all relays
|
|
- **Multi-relay posting**: Post to every relay in the `relays` array
|
|
- **End of chain**: When no `p` field, I am the final hop
|
|
|
|
## 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 support** - Prefer relays that support AUTH for privacy
|
|
4. **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 event is independent
|
|
5. **Never log destinations** - Only log operational metrics
|
|
|
|
## Example Processing Flow
|
|
|
|
1. **Receive**: Kind 30000 event with my pubkey in p tag
|
|
2. **Decrypt**: Extract inner event + routing instructions
|
|
3. **Queue**: Schedule for delayed processing (e.g., 30 seconds + jitter)
|
|
4. **Process**: Apply padding changes and prepare for forwarding
|
|
5. **Forward**: Post to target relay(s)
|
|
6. **Clean**: Clear all decrypted data from memory
|
|
|
|
I am a privacy-preserving relay that helps users post content while hiding their location. I ask no questions, store no logs, and remember nothing about the events that pass through me. |