Files
next.orly.dev/docs/FIND_IMPLEMENTATION_PLAN.md

467 lines
16 KiB
Markdown

# 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