develop registration ratelimit mechanism
This commit is contained in:
495
docs/FIND_INTEGRATION_SUMMARY.md
Normal file
495
docs/FIND_INTEGRATION_SUMMARY.md
Normal file
@@ -0,0 +1,495 @@
|
||||
# FIND Name Binding System - Integration Summary
|
||||
|
||||
## Overview
|
||||
|
||||
The Free Internet Name Daemon (FIND) protocol has been integrated into ORLY, enabling human-readable name-to-npub bindings that are discoverable through standard Nostr queries. This document summarizes the implementation and provides guidance for using the system.
|
||||
|
||||
## What Was Implemented
|
||||
|
||||
### Core Components
|
||||
|
||||
1. **Consensus Engine** ([pkg/find/consensus.go](../pkg/find/consensus.go))
|
||||
- Implements trust-weighted consensus algorithm for name registrations
|
||||
- Validates proposals against renewal windows and ownership rules
|
||||
- Computes consensus scores from attestations
|
||||
- Enforces mandatory 1-year registration period with 30-day preferential renewal
|
||||
|
||||
2. **Trust Graph Manager** ([pkg/find/trust.go](../pkg/find/trust.go))
|
||||
- Manages web-of-trust relationships between registry services
|
||||
- Calculates direct and inherited trust (0-3 hops)
|
||||
- Applies hop-based decay factors (1.0, 0.8, 0.6, 0.4)
|
||||
- Provides metrics and analytics
|
||||
|
||||
3. **Registry Service** ([pkg/find/registry.go](../pkg/find/registry.go))
|
||||
- Monitors registration proposals (kind 30100)
|
||||
- Collects attestations from other registry services (kind 20100)
|
||||
- Publishes name state after consensus (kind 30102)
|
||||
- Manages pending proposals and attestation windows
|
||||
|
||||
4. **Event Parsers** ([pkg/find/parser.go](../pkg/find/parser.go))
|
||||
- Parses all FIND event types (30100-30105)
|
||||
- Validates event structure and required tags
|
||||
- Already complete - no changes needed
|
||||
|
||||
5. **Event Builders** ([pkg/find/builder.go](../pkg/find/builder.go))
|
||||
- Creates FIND events (registration proposals, attestations, name states, records)
|
||||
- Already complete - no changes needed
|
||||
|
||||
6. **Validators** ([pkg/find/validation.go](../pkg/find/validation.go))
|
||||
- DNS-style name format validation
|
||||
- IPv4/IPv6 address validation
|
||||
- Record type and value validation
|
||||
- Already complete - no changes needed
|
||||
|
||||
### Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ ORLY Relay │
|
||||
│ │
|
||||
│ ┌────────────────┐ ┌────────────────┐ ┌──────────────┐ │
|
||||
│ │ WebSocket │ │ Registry │ │ Database │ │
|
||||
│ │ Handler │ │ Service │ │ (Badger/ │ │
|
||||
│ │ │ │ │ │ DGraph) │ │
|
||||
│ │ - Receives │ │ - Monitors │ │ │ │
|
||||
│ │ proposals │ │ proposals │ │ - Stores │ │
|
||||
│ │ - Stores │──│ - Computes │──│ all FIND │ │
|
||||
│ │ events │ │ consensus │ │ events │ │
|
||||
│ │ │ │ - Publishes │ │ │ │
|
||||
│ │ │ │ name state │ │ │ │
|
||||
│ └────────────────┘ └────────────────┘ └──────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
│ Nostr Events
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ Clients & Other Registry Services │
|
||||
│ │
|
||||
│ - Query name state (kind 30102) │
|
||||
│ - Query records (kind 30103) │
|
||||
│ - Submit proposals (kind 30100) │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
### Name Registration Flow
|
||||
|
||||
1. **User submits registration proposal**
|
||||
```
|
||||
User → Create kind 30100 event → Publish to relay
|
||||
```
|
||||
|
||||
2. **Relay stores proposal**
|
||||
```
|
||||
Relay → Database → Store event
|
||||
```
|
||||
|
||||
3. **Registry service processes proposal**
|
||||
```
|
||||
Registry Service → Validate proposal
|
||||
→ Wait for attestation window (60-120s)
|
||||
→ Collect attestations from other services
|
||||
→ Compute trust-weighted consensus
|
||||
```
|
||||
|
||||
4. **Consensus reached**
|
||||
```
|
||||
Registry Service → Create name state (kind 30102)
|
||||
→ Publish to database
|
||||
```
|
||||
|
||||
5. **Clients query ownership**
|
||||
```
|
||||
Client → Query kind 30102 for name → Relay returns name state
|
||||
```
|
||||
|
||||
### Name Resolution Flow
|
||||
|
||||
1. **Client queries name state**
|
||||
```javascript
|
||||
// Query kind 30102 events with d tag = name
|
||||
const nameStates = await relay.list([{
|
||||
kinds: [30102],
|
||||
'#d': ['example.nostr']
|
||||
}])
|
||||
```
|
||||
|
||||
2. **Client queries DNS records**
|
||||
```javascript
|
||||
// Query kind 30103 events for records
|
||||
const records = await relay.list([{
|
||||
kinds: [30103],
|
||||
'#name': ['example.nostr'],
|
||||
'#type': ['A'],
|
||||
authors: [nameOwnerPubkey]
|
||||
}])
|
||||
```
|
||||
|
||||
3. **Client uses resolved data**
|
||||
```javascript
|
||||
// Extract IP addresses
|
||||
const ips = records.map(e =>
|
||||
e.tags.find(t => t[0] === 'value')[1]
|
||||
)
|
||||
// Connect to service at IP
|
||||
```
|
||||
|
||||
## Event Types
|
||||
|
||||
| Kind | Name | Description | Persistence |
|
||||
|------|------|-------------|-------------|
|
||||
| 30100 | Registration Proposal | User submits name claim | Parameterized replaceable |
|
||||
| 20100 | Attestation | Registry service votes | Ephemeral (3 min) |
|
||||
| 30101 | Trust Graph | Service trust relationships | Parameterized replaceable (30 days) |
|
||||
| 30102 | Name State | Current ownership | Parameterized replaceable (1 year) |
|
||||
| 30103 | Name Records | DNS-style records | Parameterized replaceable (tied to name) |
|
||||
| 30104 | Certificate | TLS-style certificates | Parameterized replaceable (90 days) |
|
||||
| 30105 | Witness Service | Certificate witnesses | Parameterized replaceable (180 days) |
|
||||
|
||||
## Integration Status
|
||||
|
||||
### ✅ Completed
|
||||
|
||||
- [x] Consensus algorithm implementation
|
||||
- [x] Trust graph calculation with multi-hop support
|
||||
- [x] Registry service core logic
|
||||
- [x] Event parsers for all FIND types
|
||||
- [x] Event builders for creating FIND events
|
||||
- [x] Validation functions (DNS names, IPs, etc.)
|
||||
- [x] Implementation documentation
|
||||
- [x] Client integration examples
|
||||
|
||||
### 🔨 Integration Points (Next Steps)
|
||||
|
||||
To complete the integration, the following work remains:
|
||||
|
||||
1. **Configuration** ([app/config/config.go](../app/config/config.go))
|
||||
```go
|
||||
// Add these fields to config.C:
|
||||
FindEnabled bool `env:"ORLY_FIND_ENABLED" default:"false"`
|
||||
FindServicePubkey string `env:"ORLY_FIND_SERVICE_PUBKEY"`
|
||||
FindServicePrivkey string `env:"ORLY_FIND_SERVICE_PRIVKEY"`
|
||||
FindAttestationDelay string `env:"ORLY_FIND_ATTESTATION_DELAY" default:"60s"`
|
||||
FindBootstrapServices []string `env:"ORLY_FIND_BOOTSTRAP_SERVICES"`
|
||||
```
|
||||
|
||||
2. **Database Query Helpers** ([pkg/database/](../pkg/database/))
|
||||
```go
|
||||
// Add helper methods:
|
||||
func (d *Database) QueryNameState(name string) (*find.NameState, error)
|
||||
func (d *Database) QueryNameRecords(name, recordType string) ([]*find.NameRecord, error)
|
||||
func (d *Database) IsNameAvailable(name string) (bool, error)
|
||||
```
|
||||
|
||||
3. **Server Integration** ([app/main.go](../app/main.go))
|
||||
```go
|
||||
// Initialize registry service if enabled:
|
||||
if cfg.FindEnabled {
|
||||
registryService, err := find.NewRegistryService(ctx, db, signer, &find.RegistryConfig{
|
||||
Enabled: true,
|
||||
AttestationDelay: 60 * time.Second,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := registryService.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer registryService.Stop()
|
||||
}
|
||||
```
|
||||
|
||||
4. **HTTP API Endpoints** ([app/handle-find-api.go](../app/handle-find-api.go) - new file)
|
||||
```go
|
||||
// Add REST endpoints:
|
||||
GET /api/find/names/:name // Query name state
|
||||
GET /api/find/names/:name/records // Query all records
|
||||
POST /api/find/register // Submit proposal
|
||||
```
|
||||
|
||||
5. **WebSocket Event Routing** ([app/handle-websocket.go](../app/handle-websocket.go))
|
||||
```go
|
||||
// Route FIND events to registry service:
|
||||
if cfg.FindEnabled && registryService != nil {
|
||||
if ev.Kind >= 30100 && ev.Kind <= 30105 {
|
||||
registryService.HandleEvent(ev)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Register a Name (Client)
|
||||
|
||||
```javascript
|
||||
import { finalizeEvent, getPublicKey } from 'nostr-tools'
|
||||
|
||||
async function registerName(relay, privkey, name) {
|
||||
const pubkey = getPublicKey(privkey)
|
||||
|
||||
// Create registration proposal
|
||||
const event = {
|
||||
kind: 30100,
|
||||
pubkey,
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
tags: [
|
||||
['d', name],
|
||||
['action', 'register'],
|
||||
['expiration', String(Math.floor(Date.now() / 1000) + 300)]
|
||||
],
|
||||
content: ''
|
||||
}
|
||||
|
||||
const signedEvent = finalizeEvent(event, privkey)
|
||||
await relay.publish(signedEvent)
|
||||
|
||||
console.log('Proposal submitted, waiting for consensus...')
|
||||
|
||||
// Wait 2 minutes for consensus
|
||||
await new Promise(r => setTimeout(r, 120000))
|
||||
|
||||
// Check if registration succeeded
|
||||
const nameState = await relay.get({
|
||||
kinds: [30102],
|
||||
'#d': [name]
|
||||
})
|
||||
|
||||
if (nameState && nameState.tags.find(t => t[0] === 'owner')[1] === pubkey) {
|
||||
console.log('Registration successful!')
|
||||
return true
|
||||
} else {
|
||||
console.log('Registration failed')
|
||||
return false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Publish DNS Records (Client)
|
||||
|
||||
```javascript
|
||||
async function publishARecord(relay, privkey, name, ipAddress) {
|
||||
const pubkey = getPublicKey(privkey)
|
||||
|
||||
// Verify we own the name first
|
||||
const nameState = await relay.get({
|
||||
kinds: [30102],
|
||||
'#d': [name]
|
||||
})
|
||||
|
||||
if (!nameState || nameState.tags.find(t => t[0] === 'owner')[1] !== pubkey) {
|
||||
throw new Error('You do not own this name')
|
||||
}
|
||||
|
||||
// Create A record
|
||||
const event = {
|
||||
kind: 30103,
|
||||
pubkey,
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
tags: [
|
||||
['d', `${name}:A:1`],
|
||||
['name', name],
|
||||
['type', 'A'],
|
||||
['value', ipAddress],
|
||||
['ttl', '3600']
|
||||
],
|
||||
content: ''
|
||||
}
|
||||
|
||||
const signedEvent = finalizeEvent(event, privkey)
|
||||
await relay.publish(signedEvent)
|
||||
|
||||
console.log(`Published A record: ${name} → ${ipAddress}`)
|
||||
}
|
||||
```
|
||||
|
||||
### Resolve Name to IP (Client)
|
||||
|
||||
```javascript
|
||||
async function resolveNameToIP(relay, name) {
|
||||
// 1. Get name state (ownership info)
|
||||
const nameState = await relay.get({
|
||||
kinds: [30102],
|
||||
'#d': [name]
|
||||
})
|
||||
|
||||
if (!nameState) {
|
||||
throw new Error('Name not registered')
|
||||
}
|
||||
|
||||
// Check if expired
|
||||
const expirationTag = nameState.tags.find(t => t[0] === 'expiration')
|
||||
if (expirationTag) {
|
||||
const expiration = parseInt(expirationTag[1])
|
||||
if (Date.now() / 1000 > expiration) {
|
||||
throw new Error('Name expired')
|
||||
}
|
||||
}
|
||||
|
||||
const owner = nameState.tags.find(t => t[0] === 'owner')[1]
|
||||
|
||||
// 2. Get A records
|
||||
const records = await relay.list([{
|
||||
kinds: [30103],
|
||||
'#name': [name],
|
||||
'#type': ['A'],
|
||||
authors: [owner]
|
||||
}])
|
||||
|
||||
if (records.length === 0) {
|
||||
throw new Error('No A records found')
|
||||
}
|
||||
|
||||
// 3. Extract IP addresses
|
||||
const ips = records.map(event => {
|
||||
return event.tags.find(t => t[0] === 'value')[1]
|
||||
})
|
||||
|
||||
console.log(`${name} → ${ips.join(', ')}`)
|
||||
return ips
|
||||
}
|
||||
```
|
||||
|
||||
### Run Registry Service (Operator)
|
||||
|
||||
```bash
|
||||
# Set environment variables
|
||||
export ORLY_FIND_ENABLED=true
|
||||
export ORLY_FIND_SERVICE_PUBKEY="your_service_pubkey_hex"
|
||||
export ORLY_FIND_SERVICE_PRIVKEY="your_service_privkey_hex"
|
||||
export ORLY_FIND_ATTESTATION_DELAY="60s"
|
||||
export ORLY_FIND_BOOTSTRAP_SERVICES="pubkey1,pubkey2,pubkey3"
|
||||
|
||||
# Start relay
|
||||
./orly
|
||||
```
|
||||
|
||||
The registry service will:
|
||||
- Monitor for registration proposals
|
||||
- Validate proposals against rules
|
||||
- Publish attestations for valid proposals
|
||||
- Compute consensus with other services
|
||||
- Publish name state events
|
||||
|
||||
## Key Features
|
||||
|
||||
### ✅ Implemented
|
||||
|
||||
1. **Trust-Weighted Consensus**
|
||||
- Services vote on proposals with weighted attestations
|
||||
- Multi-hop trust inheritance (0-3 hops)
|
||||
- Hop-based decay factors prevent infinite trust chains
|
||||
|
||||
2. **Renewal Window Enforcement**
|
||||
- Names expire after exactly 1 year
|
||||
- 30-day preferential renewal window for owners
|
||||
- Automatic expiration handling
|
||||
|
||||
3. **Subdomain Authority**
|
||||
- Only parent domain owners can register subdomains
|
||||
- TLDs can be registered by anyone (first-come-first-served)
|
||||
- Hierarchical ownership validation
|
||||
|
||||
4. **DNS-Compatible Records**
|
||||
- A, AAAA, CNAME, MX, TXT, NS, SRV record types
|
||||
- Per-type record limits
|
||||
- TTL-based caching
|
||||
|
||||
5. **Sparse Attestation**
|
||||
- Optional probabilistic attestation to reduce network load
|
||||
- Deterministic sampling based on proposal hash
|
||||
- Configurable sampling rates
|
||||
|
||||
### 🔮 Future Enhancements
|
||||
|
||||
1. **Certificate System** (Defined in NIP, not yet implemented)
|
||||
- Challenge-response verification
|
||||
- Threshold witnessing (3+ signatures)
|
||||
- TLS replacement capabilities
|
||||
|
||||
2. **Economic Incentives** (Designed but not implemented)
|
||||
- Optional registration fees via Lightning
|
||||
- Reputation scoring for registry services
|
||||
- Subscription models
|
||||
|
||||
3. **Advanced Features**
|
||||
- Noise protocol for secure transport
|
||||
- Browser integration
|
||||
- DNS gateway (traditional DNS → FIND)
|
||||
|
||||
## Testing
|
||||
|
||||
### Unit Tests
|
||||
|
||||
Run existing tests:
|
||||
```bash
|
||||
cd pkg/find
|
||||
go test -v ./...
|
||||
```
|
||||
|
||||
Tests cover:
|
||||
- Name validation (validation_test.go)
|
||||
- Parser functions (parser_test.go)
|
||||
- Builder functions (builder_test.go)
|
||||
|
||||
### Integration Tests (To Be Added)
|
||||
|
||||
Recommended test scenarios:
|
||||
1. **Single proposal registration**
|
||||
2. **Competing proposals with consensus**
|
||||
3. **Renewal window validation**
|
||||
4. **Subdomain authority checks**
|
||||
5. **Trust graph calculation**
|
||||
6. **Multi-hop trust inheritance**
|
||||
|
||||
## Documentation
|
||||
|
||||
- **[Implementation Plan](FIND_IMPLEMENTATION_PLAN.md)** - Detailed architecture and phases
|
||||
- **[NIP Specification](names.md)** - Complete protocol specification
|
||||
- **[Usage Guide](FIND_USER_GUIDE.md)** - End-user documentation (to be created)
|
||||
- **[Operator Guide](FIND_OPERATOR_GUIDE.md)** - Registry operator documentation (to be created)
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Attack Mitigations
|
||||
|
||||
1. **Sybil Attacks**: Trust-weighted consensus prevents new services from dominating
|
||||
2. **Censorship**: Diverse trust graphs make network-wide censorship difficult
|
||||
3. **Name Squatting**: Mandatory 1-year expiration with preferential renewal window
|
||||
4. **Renewal DoS**: 30-day window, multiple retry opportunities
|
||||
5. **Transfer Fraud**: Cryptographic signature from previous owner required
|
||||
|
||||
### Privacy Considerations
|
||||
|
||||
- Registration proposals are public (necessary for consensus)
|
||||
- Ownership history is permanently visible on relays
|
||||
- Clients can use Tor or private relays for sensitive queries
|
||||
|
||||
## Performance Characteristics
|
||||
|
||||
- **Registration Finality**: 1-2 minutes (60-120s attestation window)
|
||||
- **Name Resolution**: < 100ms (database query)
|
||||
- **Trust Calculation**: O(n) where n = number of services (with 3-hop limit)
|
||||
- **Consensus Computation**: O(p×a) where p = proposals, a = attestations
|
||||
|
||||
## Support & Feedback
|
||||
|
||||
- **Issues**: https://github.com/orly-dev/orly/issues
|
||||
- **Discussions**: https://github.com/orly-dev/orly/discussions
|
||||
- **Nostr**: nostr:npub1... (relay operator npub)
|
||||
|
||||
## Next Steps
|
||||
|
||||
To complete the integration:
|
||||
|
||||
1. ✅ Review this summary
|
||||
2. 🔨 Add configuration fields to config.C
|
||||
3. 🔨 Implement database query helpers
|
||||
4. 🔨 Integrate registry service in app/main.go
|
||||
5. 🔨 Add HTTP API endpoints (optional)
|
||||
6. 🔨 Write integration tests
|
||||
7. 🔨 Create operator documentation
|
||||
8. 🔨 Create user guide with examples
|
||||
|
||||
The core FIND protocol logic is complete and ready for integration!
|
||||
Reference in New Issue
Block a user