# FIND Name Binding Implementation Plan ## Overview This document outlines the implementation plan for integrating the Free Internet Name Daemon (FIND) protocol with the ORLY relay. The FIND protocol provides decentralized name-to-npub bindings that are discoverable by any client using standard Nostr queries. ## Architecture ### System Components ``` ┌─────────────────────────────────────────────────────────────┐ │ ORLY Relay │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │ │ │ WebSocket │ │ FIND Daemon │ │ HTTP API │ │ │ │ Handler │ │ (Registry │ │ (NIP-11, Web) │ │ │ │ │ │ Service) │ │ │ │ │ └──────┬───────┘ └──────┬───────┘ └────────┬─────────┘ │ │ │ │ │ │ │ └─────────────────┼────────────────────┘ │ │ │ │ │ ┌───────▼────────┐ │ │ │ Database │ │ │ │ (Badger/ │ │ │ │ DGraph) │ │ │ └────────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ ▲ │ Publish FIND events │ Query FIND events │ (kinds 30100-30105) │ (kinds 30102, 30103) ▼ │ ┌─────────────────────────────────────────────────────────────┐ │ Nostr Network │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │ │ │ Other │ │ Other │ │ Clients │ │ │ │ Relays │ │ Registry │ │ │ │ │ │ │ │ Services │ │ │ │ │ └──────────────┘ └──────────────┘ └──────────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` ### Event Flow 1. **Name Registration:** ``` User → FIND CLI → Registration Proposal (kind 30100) → Relay → Database ↓ Registry Service (attestation) ↓ Attestation (kind 20100) → Other Registry Services ↓ Consensus → Name State (kind 30102) ``` 2. **Name Resolution:** ``` Client → Query kind 30102 (name state) → Relay → Database → Response Client → Query kind 30103 (records) → Relay → Database → Response ``` ## Implementation Phases ### Phase 1: Database Storage for FIND Events ✓ (Already Supported) The relay already stores all parameterized replaceable events (kind 30xxx) and ephemeral events (kind 20xxx), which includes all FIND event types: - ✓ Kind 30100: Registration Proposals - ✓ Kind 20100: Attestations (ephemeral) - ✓ Kind 30101: Trust Graphs - ✓ Kind 30102: Name State - ✓ Kind 30103: Name Records - ✓ Kind 30104: Certificates - ✓ Kind 30105: Witness Services **Status:** No changes needed. The existing event storage system handles these automatically. ### Phase 2: Registry Service Implementation Create a new registry service that runs within the ORLY relay process (optional, can be enabled via config). **New Files:** - `pkg/find/registry.go` - Core registry service - `pkg/find/consensus.go` - Consensus algorithm implementation - `pkg/find/trust.go` - Trust graph calculation - `app/find-service.go` - Integration with relay server **Key Components:** ```go // Registry service that monitors proposals and computes consensus type RegistryService struct { db database.Database pubkey []byte // Registry service identity trustGraph *TrustGraph pendingProposals map[string]*ProposalState config *RegistryConfig } type RegistryConfig struct { Enabled bool ServicePubkey string AttestationDelay time.Duration // Default: 60s SparseAttestation bool SamplingRate int // For sparse attestation } // Proposal state tracking during attestation window type ProposalState struct { Proposal *RegistrationProposal Attestations []*Attestation ReceivedAt time.Time ProcessedAt *time.Time } ``` **Responsibilities:** 1. Subscribe to kind 30100 (registration proposals) from database 2. Validate proposals (name format, ownership, renewal window) 3. Check for conflicts (competing proposals) 4. After attestation window (60-120s): - Fetch attestations (kind 20100) from other registry services - Compute trust-weighted consensus - Publish name state (kind 30102) if consensus reached ### Phase 3: Client Query Handlers Enhance existing query handlers to optimize FIND event queries. **Enhancements:** - Add specialized indexes for FIND events (already exists via `d` tag indexes) - Implement name resolution helper functions - Cache frequently queried name states **New Helper Functions:** ```go // Query name state for a given name func (d *Database) QueryNameState(name string) (*find.NameState, error) // Query all records for a name func (d *Database) QueryNameRecords(name string, recordType string) ([]*find.NameRecord, error) // Check if name is available for registration func (d *Database) IsNameAvailable(name string) (bool, error) // Get parent domain owner (for subdomain validation) func (d *Database) GetParentDomainOwner(name string) (string, error) ``` ### Phase 4: Configuration Integration Add FIND-specific configuration options to `app/config/config.go`: ```go type C struct { // ... existing fields ... // FIND registry service settings FindEnabled bool `env:"ORLY_FIND_ENABLED" default:"false" usage:"enable FIND registry service for name consensus"` FindServicePubkey string `env:"ORLY_FIND_SERVICE_PUBKEY" usage:"public key for this registry service (hex)"` FindServicePrivkey string `env:"ORLY_FIND_SERVICE_PRIVKEY" usage:"private key for signing attestations (hex)"` FindAttestationDelay string `env:"ORLY_FIND_ATTESTATION_DELAY" default:"60s" usage:"delay before publishing attestations"` FindSparseEnabled bool `env:"ORLY_FIND_SPARSE_ENABLED" default:"false" usage:"use sparse attestation (probabilistic)"` FindSamplingRate int `env:"ORLY_FIND_SAMPLING_RATE" default:"10" usage:"sampling rate for sparse attestation (1/K)"` FindBootstrapServices []string `env:"ORLY_FIND_BOOTSTRAP_SERVICES" usage:"comma-separated list of bootstrap registry service pubkeys"` } ``` ### Phase 5: FIND Daemon HTTP API Add HTTP API endpoints for FIND operations (optional, for user convenience): **New Endpoints:** - `GET /api/find/names/:name` - Query name state - `GET /api/find/names/:name/records` - Query all records for a name - `GET /api/find/names/:name/records/:type` - Query specific record type - `POST /api/find/register` - Submit registration proposal - `POST /api/find/transfer` - Submit transfer proposal - `GET /api/find/trust-graph` - Query this relay's trust graph **Implementation:** ```go // app/handle-find-api.go func (s *Server) handleFindNameQuery(w http.ResponseWriter, r *http.Request) { name := r.PathValue("name") // Validate name format if err := find.ValidateName(name); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // Query name state from database nameState, err := s.DB.QueryNameState(name) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } if nameState == nil { http.Error(w, "name not found", http.StatusNotFound) return } // Return as JSON w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(nameState) } ``` ### Phase 6: Client Integration Examples Provide example code for clients to use FIND: **Example: Query name ownership** ```javascript // JavaScript/TypeScript example using nostr-tools import { SimplePool } from 'nostr-tools' async function queryNameOwner(relays, name) { const pool = new SimplePool() // Query kind 30102 events with d tag = name const events = await pool.list(relays, [{ kinds: [30102], '#d': [name], limit: 5 }]) if (events.length === 0) { return null // Name not registered } // Check for majority consensus among registry services const ownerCounts = {} for (const event of events) { const ownerTag = event.tags.find(t => t[0] === 'owner') if (ownerTag) { const owner = ownerTag[1] ownerCounts[owner] = (ownerCounts[owner] || 0) + 1 } } // Return owner with most attestations let maxCount = 0 let consensusOwner = null for (const [owner, count] of Object.entries(ownerCounts)) { if (count > maxCount) { maxCount = count consensusOwner = owner } } return consensusOwner } // Example: Resolve name to IP address async function resolveNameToIP(relays, name) { const owner = await queryNameOwner(relays, name) if (!owner) { throw new Error('Name not registered') } // Query kind 30103 events for A records const pool = new SimplePool() const records = await pool.list(relays, [{ kinds: [30103], '#name': [name], '#type': ['A'], authors: [owner], // Only records from name owner are valid limit: 5 }]) if (records.length === 0) { throw new Error('No A records found') } // Extract IP addresses from value tags const ips = records.map(event => { const valueTag = event.tags.find(t => t[0] === 'value') return valueTag ? valueTag[1] : null }).filter(Boolean) return ips } ``` **Example: Register a name** ```javascript import { finalizeEvent, getPublicKey } from 'nostr-tools' import { find } from './find-helpers' async function registerName(relays, privkey, name) { // Validate name format if (!find.validateName(name)) { throw new Error('Invalid name format') } const pubkey = getPublicKey(privkey) // Create registration proposal (kind 30100) const event = { kind: 30100, created_at: Math.floor(Date.now() / 1000), tags: [ ['d', name], ['action', 'register'], ['expiration', String(Math.floor(Date.now() / 1000) + 300)] // 5 min expiry ], content: '' } const signedEvent = finalizeEvent(event, privkey) // Publish to relays const pool = new SimplePool() await Promise.all(relays.map(relay => pool.publish(relay, signedEvent))) // Wait for consensus (typically 1-2 minutes) console.log('Registration proposal submitted. Waiting for consensus...') await new Promise(resolve => setTimeout(resolve, 120000)) // Check if registration succeeded const owner = await queryNameOwner(relays, name) if (owner === pubkey) { console.log('Registration successful!') return true } else { console.log('Registration failed - another proposal may have won consensus') return false } } ``` ## Testing Plan ### Unit Tests 1. **Name Validation Tests** (`pkg/find/validation_test.go` - already exists) - Valid names - Invalid names (too long, invalid characters, etc.) - Subdomain authority validation 2. **Consensus Algorithm Tests** (`pkg/find/consensus_test.go` - new) - Single proposal scenario - Competing proposals - Trust-weighted scoring - Attestation window expiry 3. **Trust Graph Tests** (`pkg/find/trust_test.go` - new) - Direct trust relationships - Multi-hop trust inheritance - Trust decay calculation ### Integration Tests 1. **End-to-End Registration** (`pkg/find/integration_test.go` - new) - Submit proposal - Generate attestations - Compute consensus - Verify name state 2. **Name Renewal** (`pkg/find/renewal_test.go` - new) - Renewal during preferential window - Rejection outside renewal window - Expiration handling 3. **Record Management** (`pkg/find/records_test.go` - new) - Publish DNS-style records - Verify owner authorization - Query records by type ### Performance Tests 1. **Concurrent Proposals** - Benchmark handling 1000+ simultaneous proposals 2. **Trust Graph Calculation** - Test with 10,000+ registry services 3. **Query Performance** - Measure name resolution latency ## Deployment Strategy ### Development Phase 1. Implement core registry service (Phase 2) 2. Add unit tests 3. Test with local relay and simulated registry services ### Testnet Phase 1. Deploy 5-10 test relays with FIND enabled 2. Simulate various attack scenarios (Sybil, censorship, etc.) 3. Tune consensus parameters based on results ### Production Rollout 1. Documentation and client libraries 2. Enable FIND on select relays (opt-in) 3. Monitor for issues and gather feedback 4. Gradual adoption across relay network ## Security Considerations ### Attack Mitigations 1. **Sybil Attacks** - Trust-weighted consensus prevents new services from dominating - Age-weighted trust (new services have reduced influence) 2. **Censorship** - Diverse trust graphs make network-wide censorship difficult - Users can query different registry services aligned with their values 3. **Name Squatting** - Mandatory 1-year expiration - Preferential 30-day renewal window - No indefinite holding 4. **Renewal Window DoS** - 30-day window reduces attack surface - Owner can submit multiple renewal attempts - Registry services filter by pubkey during renewal window ### Privacy Considerations - Registration proposals are public (necessary for consensus) - Ownership history is permanently visible - Clients can use Tor or private relays for sensitive queries ## Documentation Updates 1. **User Guide** (`docs/FIND_USER_GUIDE.md` - new) - How to register a name - How to manage DNS records - How to renew registrations - Client integration examples 2. **Operator Guide** (`docs/FIND_OPERATOR_GUIDE.md` - new) - How to enable FIND registry service - Trust graph configuration - Monitoring and troubleshooting - Bootstrap recommendations 3. **Developer Guide** (`docs/FIND_DEVELOPER_GUIDE.md` - new) - API reference - Client library examples (JS, Python, Go) - Event schemas and validation - Consensus algorithm details 4. **Update CLAUDE.md** - Add FIND sections to project overview - Document new configuration options - Add testing instructions ## Success Metrics - **Registration Finality:** < 2 minutes for 95% of registrations - **Query Latency:** < 100ms for name lookups - **Consensus Agreement:** > 99% agreement among honest registry services - **Uptime:** Registry service availability > 99.9% - **Adoption:** 100+ registered names within first month of testnet ## Future Enhancements 1. **Economic Incentives** - Optional registration fees via Lightning 2. **Reputation System** - Track registry service quality metrics 3. **Certificate System** - Implement NIP-XX certificate witnessing 4. **Noise Protocol** - Secure transport layer for TLS replacement 5. **Client Libraries** - Official libraries for popular languages 6. **Browser Integration** - Browser extension for name resolution 7. **DNS Gateway** - Traditional DNS server that queries FIND