# Nostr Core Protocol - Production Reference

**Verzió:** 1.0  
**Mélység:** Core/Architecture  
**Cél:** Production-ready implementációs útmutató

---

## 1. Protokoll Architektúra

### 1.1 A Nostr Stack

```
┌─────────────────────────────────────────────────────────────┐
│                      APPLICATION LAYER                       │
│  ┌──────────────┐ ┌──────────────┐ ┌─────────────────────┐  │
│  │   Client     │ │   Client     │ │      Client         │  │
│  │   (Damus)    │ │ (Amethyst)   │ │    (Web/Browser)    │  │
│  └──────┬───────┘ └──────┬───────┘ └──────────┬──────────┘  │
└─────────┼────────────────┼────────────────────┼─────────────┘
          │                │                    │
          ▼                ▼                    ▼
┌─────────────────────────────────────────────────────────────┐
│                     NOSTR PROTOCOL LAYER                     │
│  ┌──────────────┐ ┌──────────────┐ ┌─────────────────────┐  │
│  │   Events     │ │   Filters    │ │   Subscription      │  │
│  │   (Kinds)    │ │   (Queries)  │ │   Management        │  │
│  └──────────────┘ └──────────────┘ └─────────────────────┘  │
│  ┌──────────────┐ ┌──────────────┐ ┌─────────────────────┐  │
│  │  Cryptography│ │   NIP Impl   │ │   Identity          │  │
│  │(Schnorr/sigs)│ │   (Extended) │ │   (Keys/NIP-05)     │  │
│  └──────────────┘ └──────────────┘ └─────────────────────┘  │
└─────────────────────────────────────────────────────────────┘
          │                │                    │
          ▼                ▼                    ▼
┌─────────────────────────────────────────────────────────────┐
│                      TRANSPORT LAYER                         │
│  ┌──────────────┐ ┌──────────────┐ ┌─────────────────────┐  │
│  │  WebSocket   │ │   WebSocket  │ │    WebSocket        │  │
│  │  Connection  │ │  Connection  │ │   Connection        │  │
│  │   (Relay 1)  │ │   (Relay 2)  │ │    (Relay N)        │  │
│  └──────────────┘ └──────────────┘ └─────────────────────┘  │
└─────────────────────────────────────────────────────────────┘
          │                │                    │
          ▼                ▼                    ▼
┌─────────────────────────────────────────────────────────────┐
│                       RELAY LAYER                            │
│  ┌──────────────┐ ┌──────────────┐ ┌─────────────────────┐  │
│  │    strfry    │ │ nostr-rs-re│ │    Other            │  │
│  │    (C++)     │ │    lay      │ │   Relay Impl        │  │
│  └──────────────┘ └──────────────┘ └─────────────────────┘  │
└─────────────────────────────────────────────────────────────┘
```

### 1.2 Event Lifecycle (Részletes)

```
┌─────────────┐     ┌──────────────┐     ┌──────────────┐
│   CREATE    │────▶│    SIGN      │────▶│   SERIALIZE  │
│  (Content)  │     │ (Schnorr)    │     │  (JSON)      │
└─────────────┘     └──────────────┘     └──────┬───────┘
                                                  │
                    ┌─────────────────────────────┘
                    │
                    ▼
┌─────────────┐     ┌──────────────┐     ┌──────────────┐
│   STORE     │◀────│   VALIDATE   │◀────│   HASH       │
│  (Relay DB) │     │ (Signature + │     │  (SHA256)    │
│             │     │  Structure)  │     │              │
└─────────────┘     └──────────────┘     └──────────────┘
       │
       │ WebSocket Broadcast
       ▼
┌─────────────┐     ┌──────────────┐     ┌──────────────┐
│  SUBSCRIBE  │────▶│    MATCH     │────▶│   DELIVER    │
│  (Filters)  │     │  (Filter OK?)│     │   (Clients)  │
└─────────────┘     └──────────────┘     └──────────────┘
```

**Event Structure Validation:**
1. JSON parsing valid?
2. Required fields present? (id, pubkey, created_at, kind, tags, content, sig)
3. `id` matches SHA256 of serialized content?
4. `sig` valid Schnorr signature over `id`?
5. `created_at` within acceptable window (anti-spam)?
6. `kind` in allowed range?

---

## 2. WebSocket Management

### 2.1 Connection State Machine

```
                    ┌──────────────┐
                    │   DISCONNECTED│
                    └───────┬──────┘
                            │ connect()
                            ▼
                    ┌──────────────┐
                    │  CONNECTING   │
                    └───────┬──────┘
                            │ onopen
                            ▼
        ┌──────────────────────────────────────┐
        │              CONNECTED                │
        │  ┌──────────────┐ ┌──────────────┐  │
        │  │   IDLE       │ │  AUTHENTICATING│  │
        │  │              │ │  (NIP-42)      │  │
        │  └───────┬──────┘ └───────┬──────┘  │
        │          │                │         │
        │          ▼                ▼         │
        │  ┌──────────────────────────────┐  │
        │  │        SUBSCRIBED             │  │
        │  │  (Active REQ/CLOSE cycle)    │  │
        │  └──────────────────────────────┘  │
        └──────────────────────────────────────┘
                            │
              ┌─────────────┼─────────────┐
              │             │             │
              ▼             ▼             ▼
        ┌─────────┐   ┌─────────┐   ┌─────────┐
        │ onclose │   │ onerror │   │ close() │
        └────┬────┘   └────┬────┘   └────┬────┘
             └─────────────┴─────────────┘
                            │
                            ▼
                    ┌──────────────┐
                    │  DISCONNECTED │
                    └──────────────┘
```

### 2.2 Relay Pool Architecture

```rust
// Conceptual Rust implementation
pub struct RelayPool {
    relays: HashMap<RelayUrl, RelayConnection>,
    global_subscription_id: Arc<AtomicU64>,
    event_handler: Box<dyn Fn(RelayMessage) + Send + Sync>,
    connection_timeout: Duration,
    retry_policy: RetryPolicy,
}

pub struct RelayConnection {
    url: RelayUrl,
    socket: WebSocket,
    state: ConnectionState,
    subscriptions: HashMap<SubscriptionId, Filter>,
    last_ping: Instant,
    retry_count: u32,
    backoff: Duration,
    write_queue: VecDeque<ClientMessage>,
    stats: RelayStats,
}

impl RelayPool {
    // Connection management
    pub async fn add_relay(&mut self, url: RelayUrl) -> Result<(), Error>;
    pub async fn remove_relay(&mut self, url: RelayUrl);
    pub async fn reconnect_all(&mut self);
    
    // Broadcasting
    pub async fn broadcast_event(&self, event: Event) -> Vec<(RelayUrl, Result<(), Error>)>;
    pub async fn subscribe(&self, filter: Filter) -> SubscriptionId;
    pub async fn unsubscribe(&self, id: SubscriptionId);
    
    // Query interface
    pub async fn query(&self, filter: Filter, timeout: Duration) -> Vec<Event>;
}
```

**Connection Health Monitoring:**
- Ping/pong every 30 seconds
- Reconnection with exponential backoff (1s, 2s, 4s, 8s... max 60s)
- Connection quality metrics (latency, success rate, timeout rate)
- Automatic failover for dead relays

---

## 3. Subscription Management

### 3.1 Subscription Lifecycle

```
Client                                    Relay
  │                                         │
  │  ["REQ", "sub-123", {"kinds": [1]}]     │
  │────────────────────────────────────────▶│
  │                                         │
  │  ["EVENT", "sub-123", {event1}]         │
  │◀────────────────────────────────────────│
  │  ["EVENT", "sub-123", {event2}]         │
  │◀────────────────────────────────────────│
  │       ... (real-time events) ...        │
  │◀────────────────────────────────────────│
  │                                         │
  │  ["CLOSE", "sub-123"]                   │
  │────────────────────────────────────────▶│
  │         [Connection stays open]          │
```

### 3.2 Filter Matching Logic

```rust
// Pseudocode for filter matching
fn event_matches_filter(event: &Event, filter: &Filter) -> bool {
    // Check IDs (if specified)
    if let Some(ids) = &filter.ids {
        if !ids.iter().any(|id| id.matches(&event.id)) {
            return false;
        }
    }
    
    // Check authors
    if let Some(authors) = &filter.authors {
        if !authors.contains(&event.pubkey) {
            return false;
        }
    }
    
    // Check kinds
    if let Some(kinds) = &filter.kinds {
        if !kinds.contains(&event.kind) {
            return false;
        }
    }
    
    // Check timestamp range
    if let Some(since) = filter.since {
        if event.created_at < since {
            return false;
        }
    }
    
    if let Some(until) = filter.until {
        if event.created_at > until {
            return false;
        }
    }
    
    // Check generic tags (#e, #p, #t, etc.)
    for (tag_name, values) in &filter.tags {
        let tag_char = tag_name.chars().nth(0).unwrap();
        let event_has_tag = event.tags.iter()
            .filter(|t| t.get(0) == Some(&tag_char.to_string()))
            .any(|t| t.get(1).map_or(false, |v| values.contains(v)));
        
        if !event_has_tag {
            return false;
        }
    }
    
    true
}
```

### 3.3 Subscription Strategies

**Outbox Model (Recommended for Censorship Resistance):**

```
User A writes to: wss://relay-a.com, wss://relay-b.com
User B follows User A
User B queries: wss://relay-a.com, wss://relay-b.com (User A's write relays)
+ wss://relay-c.com, wss://relay-d.com (User B's read relays for real-time)
```

**Hybrid Model:**
1. Fetch historical events from author's write relays (NIP-65)
2. Subscribe to real-time updates on user's preferred relays
3. Fan-out: post to N relays (typically 3-5)

---

## 4. Event Types Deep Dive

### 4.1 Replaceable Events

**Kinds 0, 3, 10000-19999:**
- Relay stores ONLY the latest per author
- Used for: metadata (profile), contacts, relay lists, mute lists
- Replacement key: `(kind, author)`

```json
// Kind 0 - Profile Metadata (Replaceable)
{
  "kind": 0,
  "content": "{\"name\":\"Alice\",\"about\":\"Nostr user\",\"picture\":\"https://...\"}",
  "created_at": 1234567890,
  // ... other fields
}

// Relay behavior: Replaces previous kind 0 from this author
```

### 4.2 Addressable Events

**Kinds 30000-39999:**
- Identified by `(kind, author, d-tag)`
- Used for: long-form articles, replaceable lists, parameterized replaceables
- Replacement key: `(kind, author, d-tag value)`

```json
// Kind 30023 - Long-form Article
{
  "kind": 30023,
  "tags": [
    ["d", "my-article-slug"],
    ["title", "My Article Title"],
    ["published_at", "1234567890"]
  ],
  "content": "# Markdown content...",
  // ...
}
```

### 4.3 Ephemeral Events

**Kinds 20000-29999:**
- Not stored by relays
- Used for: real-time indicators, typing notifications, presence

```json
// Kind 24242 - Typing indicator (Ephemeral)
{
  "kind": 24242,
  "tags": **"p", "recipient_pubkey"**,
  "content": "typing...",
  // Relay: Broadcast only, no storage
}
```

---

## 5. Message Protocol

### 5.1 Client-to-Relay Messages

```typescript
// TypeScript definitions for clarity
type ClientMessage = 
  | ["EVENT", Event]           // Publish event
  | ["REQ", string, Filter]  // Subscribe (id, filter)
  | ["REQ", string, Filter, Filter, ...]  // Subscribe with multiple filters
  | ["CLOSE", string]          // Unsubscribe
  | ["AUTH", SignedEvent];     // NIP-42 authentication
```

### 5.2 Relay-to-Client Messages

```typescript
type RelayMessage =
  | ["EVENT", string, Event]        // Subscription ID + Event
  | ["OK", string, boolean, string] // Event ID + Success + Message
  | ["EOSE", string]                // End of Stored Events (Subscription ID)
  | ["CLOSED", string, string]      // Subscription closed + Reason
  | ["NOTICE", string]              // Human-readable message
  | ["AUTH", string];               // NIP-42 challenge
```

### 5.3 AUTH Flow (NIP-42)

```
1. Relay sends:   ["AUTH", "challenge-string"]
2. Client creates kind 22242 event:
   {
     "kind": 22242,
     "content": "",
     "tags": [
       ["relay", "wss://relay.example.com"],
       ["challenge", "challenge-string"]
     ],
     "created_at": <current time>,
     // signed with client's key
   }
3. Client sends:  ["AUTH", <signed_event>]
4. Relay responds: ["OK", <event_id>, true, "auth success"]
```

---

## 6. Error Handling & Edge Cases

### 6.1 Relay Response Codes

| Code | Meaning | Action |
|------|---------|--------|
| `pow:20` | Proof of work required (20 bits) | Add nonce, retry |
| `rate-limited` | Too many requests | Backoff, retry later |
| `blocked` | User blocked | Switch relay |
| `invalid` | Invalid event | Fix and retry |
| `auth-required` | NIP-42 auth needed | Authenticate and retry |

### 6.2 Network Failure Recovery

```rust
pub enum ConnectionError {
    WebSocketError(tungstenite::Error),
    Timeout(Duration),
    AuthenticationFailed,
    RateLimited(Duration),
    UnexpectedClose(CloseCode),
}

impl RelayConnection {
    async fn handle_error(&mut self, err: ConnectionError) -> RecoveryAction {
        match err {
            ConnectionError::Timeout(_) => {
                self.backoff = min(self.backoff * 2, MAX_BACKOFF);
                RecoveryAction::RetryAfter(self.backoff)
            }
            ConnectionError::RateLimited(wait) => {
                RecoveryAction::RetryAfter(wait)
            }
            ConnectionError::AuthenticationFailed => {
                RecoveryAction::Reauthenticate
            }
            _ => RecoveryAction::Disconnect,
        }
    }
}
```

---

## 7. Performance Optimization

### 7.1 Batch Operations

```rust
// Multiple subscriptions in one REQ
let filter1 = Filter::new().kind(1).author(alice);
let filter2 = Filter::new().kind(0).author(bob);
let filter3 = Filter::new().kinds(vec![1, 6, 7]).limit(50);

relay.send_message(ClientMessage::ReqMulti {
    id: "batch-123".to_string(),
    filters: vec![filter1, filter2, filter3],
});
```

### 7.2 Event Deduplication

Clients MUST deduplicate events by ID across multiple relays:
```rust
use std::collections::HashSet;

pub struct EventDeduplicator {
    seen_ids: HashSet<EventId>,
    cache_size: usize,
}

impl EventDeduplicator {
    pub fn is_new(&mut self, event: &Event) -> bool {
        if self.seen_ids.contains(&event.id) {
            return false;
        }
        
        if self.seen_ids.len() >= self.cache_size {
            // LRU eviction or clear
            self.seen_ids.clear();
        }
        
        self.seen_ids.insert(event.id.clone());
        true
    }
}
```

### 7.3 Connection Pooling

- Max 100 concurrent subscriptions per relay (implementation dependent)
- Reuse connections for multiple subscriptions
- Implement backpressure for write-heavy operations

---

## 8. Security Considerations

### 8.1 Relay Trust Model

```
Threat Model:
┌─────────────────────────────────────────────────────┐
│  Relay can:                                         │
│  • Read all events (unless encrypted)                │
│  • Drop/censor events                              │
│  • Delay events                                    │
│  • Lie about EOSE                                  │
│  • Store events forever                            │
│                                                     │
│  Relay CANNOT:                                     │
│  • Forge valid signatures                          │
│  • Impersonate users                               │
│  • Decrypt NIP-04/17 messages (no key)            │
│  • Modify events without invalidating sig         │
└─────────────────────────────────────────────────────┘
```

**Mitigations:**
1. Post to multiple relays (redundancy)
2. Verify all signatures client-side
3. Use NIP-17 for sensitive content
4. Monitor relay behavior (health checks)

---

## 9. Implementation Checklist

### 9.1 Basic Client
- [ ] WebSocket connection management
- [ ] Event serialization/deserialization
- [ ] Signature verification (Schnorr)
- [ ] REQ/CLOSE subscription handling
- [ ] Event deduplication
- [ ] Relay pool management (3+ relays)

### 9.2 Advanced Client
- [ ] Outbox model implementation
- [ ] NIP-65 relay discovery
- [ ] Event caching/persistence
- [ ] Offline mode support
- [ ] Real-time sync
- [ ] Multi-account support

### 9.3 Production Hardening
- [ ] Connection health monitoring
- [ ] Automatic reconnection with backoff
- [ ] Rate limiting compliance
- [ ] Memory management (event cache eviction)
- [ ] Error telemetry
- [ ] Relay quality scoring

---

*Document Version: 1.0*  
*For: CreatorQuetzal*  
*By: Quetzalcoatl (OpenClaw)*