Files
c-relay/README.md
2025-09-25 11:25:50 -04:00

351 lines
10 KiB
Markdown

# C Nostr Relay - Event-Based Configuration System
A high-performance Nostr relay implemented in C with SQLite backend, featuring a revolutionary **zero-configuration** approach using event-based configuration management.
## 📜 Supported NIPs
<!--
NOTE FOR ASSISTANTS: When updating the NIPs checklist below, ONLY change [ ] to [x] to mark as complete.
Do NOT modify the formatting, add emojis, or change the text. Keep the simple format consistent.
-->
- [x] NIP-01: Basic protocol flow implementation
- [x] NIP-09: Event deletion
- [x] NIP-11: Relay information document
- [x] NIP-13: Proof of Work
- [x] NIP-15: End of Stored Events Notice
- [x] NIP-20: Command Results
- [x] NIP-33: Parameterized Replaceable Events
- [x] NIP-40: Expiration Timestamp
- [x] NIP-42: Authentication of clients to relays
- [ ] NIP-45: Counting results
- [ ] NIP-50: Keywords filter
- [ ] NIP-70: Protected Events
## 🔧 Administrator API
C-Relay uses an innovative **event-based administration system** where all configuration and management commands are sent as signed Nostr events using the admin private key generated during first startup. Admin commands use ephemeral kinds 23455 and 23456 with **optional NIP-44 encryption** for enhanced security.
### Authentication
All admin commands require signing with the admin private key displayed during first-time startup. **Save this key securely** - it cannot be recovered and is needed for all administrative operations.
### Security Options
**Standard Mode (Plaintext):** Commands sent in tags as normal
**Encrypted Mode (NIP-44):** Commands encrypted in content field, no tags used
### Kind 23455: Configuration Management (Ephemeral)
Update relay configuration parameters or query available settings.
**Configuration Update:**
```json
{
"kind": 23455,
"content": "<optional nip-44 encrypted tags>",
"tags": [
["config_key1", "config_value1"],
["config_key2", "config_value2"]
]
}
```
**Query Available Config Keys:**
```json
{
"kind": 23455,
"content": "<optional nip-44 encrypted tags>",
"tags": [
["config_query", "list_all_keys"]
]
}
```
**Get Current Configuration:**
```json
{
"kind": 23455,
"content": "<optional nip-44 encrypted tags>",
"tags": [
["config_query", "get_current_config"]
]
}
```
**Available Configuration Keys:**
**Basic Relay Settings:**
- `relay_description`: Relay description text
- `relay_contact`: Contact information
- `max_connections`: Maximum concurrent connections
- `max_subscriptions_per_client`: Max subscriptions per client
- `max_event_tags`: Maximum tags per event
- `max_content_length`: Maximum event content length
**Authentication & Access Control:**
- `auth_enabled`: Enable whitelist/blacklist auth rules (`true`/`false`)
- `nip42_auth_required`: Enable NIP-42 cryptographic authentication (`true`/`false`)
- `nip42_auth_required_kinds`: Event kinds requiring NIP-42 auth (comma-separated)
- `nip42_challenge_timeout`: NIP-42 challenge expiration seconds
**Proof of Work & Validation:**
- `pow_min_difficulty`: Minimum proof-of-work difficulty
- `nip40_expiration_enabled`: Enable event expiration (`true`/`false`)
### Kind 23456: Auth Rules & System Management (Ephemeral)
Manage whitelist/blacklist rules and system administration commands.
**Add Blacklist Rule:**
```json
{
"kind": 23456,
"content": "<optional nip-44 encrypted tags>",
"tags": [
["blacklist", "pubkey", "deadbeef1234abcd..."]
]
}
```
**Add Whitelist Rule:**
```json
{
"kind": 23456,
"content": "<optional nip-44 encrypted tags>",
"tags": [
["whitelist", "pubkey", "cafebabe5678efgh..."]
]
}
```
**Remove Rule:**
```json
{
"kind": 23456,
"content": "<optional nip-44 encrypted tags>",
"tags": [
["blacklist", "pubkey", "deadbeef1234abcd..."]
]
}
```
**Query Auth Rules:**
```json
{
"kind": 23456,
"content": "<optional nip-44 encrypted tags>",
"tags": [
["auth_query", "all"]
]
}
```
**Query Specific Rule Type:**
```json
{
"kind": 23456,
"content": "<optional nip-44 encrypted tags>",
"tags": [
["auth_query", "whitelist"]
]
}
```
**Query Specific Pattern:**
```json
{
"kind": 23456,
"content": "<optional nip-44 encrypted tags>",
"tags": [
["auth_query", "pattern", "deadbeef1234abcd..."]
]
}
```
**Clear All Auth Rules:**
```json
{
"kind": 23456,
"content": "<optional nip-44 encrypted tags>",
"tags": [
["system_command", "clear_all_auth_rules"]
]
}
```
### Response Format
All admin commands return JSON responses via WebSocket:
**Success Response:**
```json
["OK", "event_id", true, "Operation completed successfully"]
```
**Error Response:**
```json
["OK", "event_id", false, "Error: invalid configuration value"]
```
### Command Examples
**Using `nak` CLI tool:**
```bash
# Set environment variables
ADMIN_PRIVKEY="your_admin_private_key_here"
RELAY_PUBKEY="your_relay_public_key_here"
RELAY_URL="ws://localhost:8888"
# List all available configuration keys
nak event -k 23455 --content "Discovery query" \
-t "config_query=list_all_keys" \
--sec $ADMIN_PRIVKEY | nak event $RELAY_URL
# Enable whitelist/blacklist auth rules
nak event -k 23455 --content "Enable auth rules" \
-t "auth_enabled=true" \
--sec $ADMIN_PRIVKEY | nak event $RELAY_URL
# Add user to blacklist
nak event -k 23456 --content "Block spam user" \
-t "blacklist=pubkey;$SPAM_USER_PUBKEY" \
--sec $ADMIN_PRIVKEY | nak event $RELAY_URL
# Add user to whitelist
nak event -k 23456 --content "Allow trusted user" \
-t "whitelist=pubkey;$TRUSTED_USER_PUBKEY" \
--sec $ADMIN_PRIVKEY | nak event $RELAY_URL
# Query all current auth rules
nak event -k 23456 --content "Get all auth rules" \
-t "auth_query=all" \
--sec $ADMIN_PRIVKEY | nak event $RELAY_URL
# Query only whitelist rules
nak event -k 23456 --content "Get whitelist rules" \
-t "auth_query=whitelist" \
--sec $ADMIN_PRIVKEY | nak event $RELAY_URL
# Query only blacklist rules
nak event -k 23456 --content "Get blacklist rules" \
-t "auth_query=blacklist" \
--sec $ADMIN_PRIVKEY | nak event $RELAY_URL
# Check if specific pattern exists
nak event -k 23456 --content "Check user status" \
-t "auth_query=pattern;$CHECK_USER_PUBKEY" \
--sec $ADMIN_PRIVKEY | nak event $RELAY_URL
# Clear all auth rules (for testing)
nak event -k 23456 --content "Clear all rules" \
-t "system_command=clear_all_auth_rules" \
--sec $ADMIN_PRIVKEY | nak event $RELAY_URL
# Update relay description
nak event -k 23455 --content "Update description" \
-t "relay_description=My awesome relay" \
--sec $ADMIN_PRIVKEY | nak event $RELAY_URL
# Set connection limits
nak event -k 23455 --content "Update limits" \
-t "max_connections=500" \
-t "max_subscriptions_per_client=10" \
--sec $ADMIN_PRIVKEY | nak event $RELAY_URL
```
**For encrypted commands (NIP-44), use empty tags and encrypted content:**
```bash
# Enable auth rules (encrypted)
ENCRYPTED_TAGS=$(echo '[["auth_enabled","true"]]' | nip44_encrypt_with_relay_pubkey)
nak event -k 23455 --content "{\"encrypted_tags\":\"$ENCRYPTED_TAGS\"}" \
--sec $ADMIN_PRIVKEY | nak event $RELAY_URL
# Add user to blacklist (encrypted)
ENCRYPTED_TAGS=$(echo '[["blacklist","pubkey","'$SPAM_USER_PUBKEY'"]]' | nip44_encrypt_with_relay_pubkey)
nak event -k 23456 --content "{\"encrypted_tags\":\"$ENCRYPTED_TAGS\"}" \
--sec $ADMIN_PRIVKEY | nak event $RELAY_URL
```
### Authentication Systems
C-Relay supports **two independent authentication systems**:
#### 1. Auth Rules (Whitelist/Blacklist)
- **Config Key**: `auth_enabled=true`
- **Purpose**: Block or allow specific pubkeys from publishing events
- **Method**: Database-driven rules enforcement
- **Use Case**: Spam prevention, content moderation
#### 2. NIP-42 Cryptographic Authentication
- **Config Key**: `nip42_auth_required=true`
- **Purpose**: Require cryptographic proof of pubkey ownership
- **Method**: Challenge-response authentication protocol
- **Use Case**: Verified identity, premium features
**Important**: These systems can be used independently or together:
- `auth_enabled=true` + `nip42_auth_required=false`: Only whitelist/blacklist rules
- `auth_enabled=false` + `nip42_auth_required=true`: Only NIP-42 auth challenges
- Both `true`: Users must pass NIP-42 auth AND not be blacklisted
### Security Considerations
- **Private Key Protection**: Admin private key grants full relay control
- **Network Access**: Admin commands should only be sent over secure connections
- **Backup**: Keep secure backups of admin private key
- **Rotation**: Consider implementing admin key rotation for production deployments
### Troubleshooting
**Common Issues:**
- `auth-required: not authorized admin`: Verify you're using the correct admin private key
- `invalid: missing or invalid kind`: Ensure event kind is 23455 or 23456
- `error: failed to process configuration event`: Check configuration key/value validity
- `no valid auth rules found`: Verify tag format uses semicolon syntax for multi-element tags
**Debug Commands:**
```bash
# Check if relay is accepting connections
echo '["REQ","test",{}]' | websocat ws://localhost:8888
# Test admin authentication
nak event -k 23455 --content "Test auth" \
-t "test_config=true" \
--sec $ADMIN_PRIVKEY | nak event ws://localhost:8888
# Discover available configuration keys
nak event -k 23455 --content "Discovery query" \
-t "config_query=list_all_keys" \
--sec $ADMIN_PRIVKEY | nak event ws://localhost:8888
# Query current auth rules
nak event -k 23456 --content "Get auth rules" \
-t "auth_query=all" \
--sec $ADMIN_PRIVKEY | nak event ws://localhost:8888
```
### Configuration Discovery
Before making changes, admins can query the relay to discover all available configuration options:
```bash
# Get list of all editable configuration keys with descriptions
nak event -k 23455 --content '{"query":"list_config_keys","description":"Discovery"}' \
-t "config_query=list_all_keys" \
--sec $ADMIN_PRIVKEY | nak event $RELAY_URL
# Get current values of all configuration parameters
nak event -k 23455 --content '{"query":"get_config","description":"Current state"}' \
-t "config_query=get_current_config" \
--sec $ADMIN_PRIVKEY | nak event $RELAY_URL
```
**Expected Response Format:**
```json
["EVENT", "subscription_id", {
"kind": 23455,
"content": "{\"config_keys\": [\"auth_enabled\", \"max_connections\", ...], \"descriptions\": {...}}",
"tags": [["response_type", "config_keys_list"]]
}]
```