epistery 1.2.1 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/EpisteryRegistry.md +396 -0
- package/artifacts/build-info/9b85c8f19813050589c4ca647079da4e.json +1 -0
- package/artifacts/build-info/b0d21f00b5b6ae1bd915b0ac69b049ab.json +1 -0
- package/artifacts/contracts/IdentityContract.sol/IdentityContract.dbg.json +1 -1
- package/artifacts/contracts/IdentityContract.sol/IdentityContract.json +286 -3
- package/artifacts/contracts/agent.sol/Agent.dbg.json +1 -1
- package/artifacts/contracts/agent.sol/Agent.json +316 -2
- package/client/delegation.js +5 -2
- package/contracts/IdentityContract.sol +171 -3
- package/contracts/agent.sol +270 -46
- package/dist/utils/Utils.d.ts +4 -4
- package/dist/utils/Utils.d.ts.map +1 -1
- package/dist/utils/Utils.js +17 -17
- package/dist/utils/Utils.js.map +1 -1
- package/docs/DELEGATION.md +261 -0
- package/index.mjs +312 -19
- package/package.json +1 -1
- package/scripts/deploy-agent.js +96 -17
- package/src/utils/Utils.ts +19 -17
- package/artifacts/build-info/51c1b39609f492c0cce364e430e3fd10.json +0 -1
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
# Epistery Registry
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The Epistery Registry is a proposed centralized naming system for Epistery identities, analogous to DNS for domain names. It provides a canonical registry for human-readable identity names (e.g., "alice.epistery" or "bob.example.com") and maps them to their corresponding on-chain IdentityContract addresses.
|
|
6
|
+
|
|
7
|
+
## Problem Statement
|
|
8
|
+
|
|
9
|
+
Identity contracts need unique, human-readable names within their domain namespaces. While blockchain contracts can verify name uniqueness through on-chain registries, this approach faces several challenges:
|
|
10
|
+
|
|
11
|
+
1. **Gas Costs** - On-chain name lookups and registration are expensive, especially at scale
|
|
12
|
+
2. **Performance** - Querying availability requires blockchain RPC calls with latency
|
|
13
|
+
3. **User Experience** - Users expect instant feedback when checking name availability
|
|
14
|
+
4. **Scalability** - Large-scale name enumeration on-chain is prohibitively expensive
|
|
15
|
+
|
|
16
|
+
## Solution: Hybrid Registry Architecture
|
|
17
|
+
|
|
18
|
+
The Epistery Registry uses a **hybrid approach** combining centralized performance with decentralized verification:
|
|
19
|
+
|
|
20
|
+
- **Off-chain registry** provides fast lookups and availability checks
|
|
21
|
+
- **On-chain proof** ensures ownership and prevents disputes
|
|
22
|
+
- **Event-driven sync** keeps registry in sync with blockchain state
|
|
23
|
+
|
|
24
|
+
## Architecture
|
|
25
|
+
|
|
26
|
+
### Components
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
30
|
+
│ Epistery Registry Server │
|
|
31
|
+
│ │
|
|
32
|
+
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
|
|
33
|
+
│ │ Registry │ │ Indexer │ │ HTTP API │ │
|
|
34
|
+
│ │ Database │ │ Service │ │ Server │ │
|
|
35
|
+
│ └──────────────┘ └──────────────┘ │ │ │
|
|
36
|
+
│ │ │ │ /check │ │
|
|
37
|
+
│ │ │ │ /register │ │
|
|
38
|
+
│ └──────────────────┼─────────→│ /resolve │ │
|
|
39
|
+
│ │ │ /list │ │
|
|
40
|
+
│ ↓ └──────────────────┘ │
|
|
41
|
+
│ ┌──────────────┐ ↑ │
|
|
42
|
+
│ │ Event │ │ │
|
|
43
|
+
│ │ Listener │ │ │
|
|
44
|
+
│ └──────────────┘ │ │
|
|
45
|
+
└────────────────────────────┬───────────────────┼─────────────┘
|
|
46
|
+
│ │
|
|
47
|
+
↓ ↓
|
|
48
|
+
┌─────────────────┐ ┌──────────────┐
|
|
49
|
+
│ Blockchain │ │ Clients │
|
|
50
|
+
│ (Polygon) │ │ │
|
|
51
|
+
│ │ │ - Web Apps │
|
|
52
|
+
│ Agent Contract │ │ - CLI Tools │
|
|
53
|
+
│ Identity │ │ - Wallets │
|
|
54
|
+
│ Contracts │ │ │
|
|
55
|
+
└─────────────────┘ └──────────────┘
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Data Model
|
|
59
|
+
|
|
60
|
+
#### Registry Database Schema
|
|
61
|
+
|
|
62
|
+
```sql
|
|
63
|
+
-- Names table
|
|
64
|
+
CREATE TABLE names (
|
|
65
|
+
id SERIAL PRIMARY KEY,
|
|
66
|
+
name VARCHAR(255) NOT NULL,
|
|
67
|
+
domain VARCHAR(255) NOT NULL,
|
|
68
|
+
full_name VARCHAR(512) GENERATED ALWAYS AS (name || '.' || domain) STORED,
|
|
69
|
+
identity_contract_address VARCHAR(42) NOT NULL,
|
|
70
|
+
owner_address VARCHAR(42) NOT NULL,
|
|
71
|
+
registered_at TIMESTAMP NOT NULL,
|
|
72
|
+
tx_hash VARCHAR(66) NOT NULL,
|
|
73
|
+
block_number BIGINT NOT NULL,
|
|
74
|
+
UNIQUE(name, domain)
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
-- Create indexes for fast lookups
|
|
78
|
+
CREATE INDEX idx_full_name ON names(full_name);
|
|
79
|
+
CREATE INDEX idx_identity_contract ON names(identity_contract_address);
|
|
80
|
+
CREATE INDEX idx_owner ON names(owner_address);
|
|
81
|
+
CREATE INDEX idx_domain ON names(domain);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
#### Domain Hierarchy
|
|
85
|
+
|
|
86
|
+
Names follow a hierarchical structure:
|
|
87
|
+
- **TLD (epistery)**: `alice.epistery` - Global Epistery namespace
|
|
88
|
+
- **Domain-based**: `bob.example.com` - Attached to specific domains
|
|
89
|
+
- **Subdomains**: Reserved for future expansion
|
|
90
|
+
|
|
91
|
+
### Event Indexing
|
|
92
|
+
|
|
93
|
+
The registry stays synchronized with blockchain state by listening to contract events:
|
|
94
|
+
|
|
95
|
+
```javascript
|
|
96
|
+
// Listen to IdentityCreated events
|
|
97
|
+
agentContract.on('IdentityCreated', async (owner, firstRivet, name, domain, timestamp, event) => {
|
|
98
|
+
if (name && name.length > 0) {
|
|
99
|
+
await registry.registerName({
|
|
100
|
+
name: name,
|
|
101
|
+
domain: domain,
|
|
102
|
+
identityContract: event.address,
|
|
103
|
+
owner: owner,
|
|
104
|
+
txHash: event.transactionHash,
|
|
105
|
+
blockNumber: event.blockNumber,
|
|
106
|
+
timestamp: timestamp
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// Listen to IdentityNameUpdated events
|
|
112
|
+
identityContract.on('IdentityNameUpdated', async (oldName, newName, timestamp, event) => {
|
|
113
|
+
await registry.updateName({
|
|
114
|
+
identityContract: event.address,
|
|
115
|
+
oldName: oldName,
|
|
116
|
+
newName: newName,
|
|
117
|
+
txHash: event.transactionHash,
|
|
118
|
+
blockNumber: event.blockNumber
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## API Endpoints
|
|
124
|
+
|
|
125
|
+
### `GET /api/registry/check`
|
|
126
|
+
Check if a name is available in a domain.
|
|
127
|
+
|
|
128
|
+
**Query Parameters:**
|
|
129
|
+
- `name` - The identity name (required)
|
|
130
|
+
- `domain` - The domain (defaults to "epistery")
|
|
131
|
+
|
|
132
|
+
**Response:**
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"available": true,
|
|
136
|
+
"name": "alice",
|
|
137
|
+
"domain": "epistery",
|
|
138
|
+
"fullName": "alice.epistery"
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### `GET /api/registry/resolve`
|
|
143
|
+
Resolve a full name to an IdentityContract address.
|
|
144
|
+
|
|
145
|
+
**Query Parameters:**
|
|
146
|
+
- `name` - Full qualified name (e.g., "alice.epistery")
|
|
147
|
+
|
|
148
|
+
**Response:**
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"name": "alice.epistery",
|
|
152
|
+
"identityContract": "0x1234...",
|
|
153
|
+
"owner": "0x5678...",
|
|
154
|
+
"registeredAt": "2025-11-28T12:00:00Z",
|
|
155
|
+
"txHash": "0xabcd...",
|
|
156
|
+
"blockNumber": 12345678
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### `POST /api/registry/register`
|
|
161
|
+
Pre-register a name intent (off-chain reservation).
|
|
162
|
+
|
|
163
|
+
**Request Body:**
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"name": "alice",
|
|
167
|
+
"domain": "epistery",
|
|
168
|
+
"ownerAddress": "0x1234..."
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Response:**
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"success": true,
|
|
176
|
+
"reservation": {
|
|
177
|
+
"name": "alice.epistery",
|
|
178
|
+
"expiresAt": "2025-11-28T12:30:00Z",
|
|
179
|
+
"reservationId": "uuid-1234"
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Note:** Reservation is temporary (30 min) and must be confirmed by on-chain deployment.
|
|
185
|
+
|
|
186
|
+
### `GET /api/registry/list`
|
|
187
|
+
List all names in a domain.
|
|
188
|
+
|
|
189
|
+
**Query Parameters:**
|
|
190
|
+
- `domain` - Domain to list (required)
|
|
191
|
+
- `page` - Page number (default: 1)
|
|
192
|
+
- `limit` - Results per page (default: 50, max: 500)
|
|
193
|
+
|
|
194
|
+
**Response:**
|
|
195
|
+
```json
|
|
196
|
+
{
|
|
197
|
+
"domain": "epistery",
|
|
198
|
+
"total": 1523,
|
|
199
|
+
"page": 1,
|
|
200
|
+
"limit": 50,
|
|
201
|
+
"names": [
|
|
202
|
+
{
|
|
203
|
+
"name": "alice.epistery",
|
|
204
|
+
"identityContract": "0x1234...",
|
|
205
|
+
"registeredAt": "2025-11-20T10:00:00Z"
|
|
206
|
+
},
|
|
207
|
+
// ... more entries
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Registration Flow
|
|
213
|
+
|
|
214
|
+
### 1. Client-Side Registration
|
|
215
|
+
|
|
216
|
+
```javascript
|
|
217
|
+
// Check availability
|
|
218
|
+
const available = await fetch('/api/registry/check?name=alice&domain=epistery')
|
|
219
|
+
.then(r => r.json());
|
|
220
|
+
|
|
221
|
+
if (!available.available) {
|
|
222
|
+
throw new Error('Name already taken');
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Reserve name (optional, provides race condition protection)
|
|
226
|
+
const reservation = await fetch('/api/registry/register', {
|
|
227
|
+
method: 'POST',
|
|
228
|
+
body: JSON.stringify({
|
|
229
|
+
name: 'alice',
|
|
230
|
+
domain: 'epistery',
|
|
231
|
+
ownerAddress: rivetAddress
|
|
232
|
+
})
|
|
233
|
+
}).then(r => r.json());
|
|
234
|
+
|
|
235
|
+
// Deploy IdentityContract with name
|
|
236
|
+
const tx = await factory.deploy('alice', 'epistery');
|
|
237
|
+
await tx.wait();
|
|
238
|
+
|
|
239
|
+
// Registry automatically picks up IdentityCreated event
|
|
240
|
+
// Name is now confirmed and reservation is removed
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### 2. Event-Driven Confirmation
|
|
244
|
+
|
|
245
|
+
```javascript
|
|
246
|
+
// Registry event listener picks up deployment
|
|
247
|
+
agentContract.on('IdentityCreated', async (owner, rivet, name, domain) => {
|
|
248
|
+
// Find and confirm reservation
|
|
249
|
+
const reservation = await findReservation(name, domain);
|
|
250
|
+
if (reservation) {
|
|
251
|
+
await confirmReservation(reservation.id);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Or create new entry if no reservation exists
|
|
255
|
+
await createNameEntry({
|
|
256
|
+
name: name,
|
|
257
|
+
domain: domain,
|
|
258
|
+
identityContract: tx.contractAddress,
|
|
259
|
+
owner: owner
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Security Considerations
|
|
265
|
+
|
|
266
|
+
### Name Squatting Prevention
|
|
267
|
+
|
|
268
|
+
1. **Reservation System** - Temporary reservations (30 min) prevent front-running
|
|
269
|
+
2. **On-Chain Proof** - Only on-chain deployments are authoritative
|
|
270
|
+
3. **Event Verification** - All registrations verified against blockchain events
|
|
271
|
+
4. **Dispute Resolution** - Blockchain state is always the source of truth
|
|
272
|
+
|
|
273
|
+
### Race Conditions
|
|
274
|
+
|
|
275
|
+
**Scenario:** Two users try to register the same name simultaneously.
|
|
276
|
+
|
|
277
|
+
**Mitigation:**
|
|
278
|
+
1. Client checks availability via API (fast feedback)
|
|
279
|
+
2. Client creates reservation (locks name for 30 min)
|
|
280
|
+
3. Client deploys contract with name
|
|
281
|
+
4. First successful on-chain deployment wins
|
|
282
|
+
5. Second deployment fails (name already taken on-chain)
|
|
283
|
+
6. Failed reservation expires automatically
|
|
284
|
+
|
|
285
|
+
### Sync Reliability
|
|
286
|
+
|
|
287
|
+
**Problem:** Registry could get out of sync with blockchain.
|
|
288
|
+
|
|
289
|
+
**Solutions:**
|
|
290
|
+
1. **Event replay** - Periodic full re-sync from blockchain events
|
|
291
|
+
2. **Block confirmations** - Wait for N confirmations before considering final
|
|
292
|
+
3. **Health checks** - Monitor indexer lag and alert if behind
|
|
293
|
+
4. **Manual override** - Admin tools to fix inconsistencies
|
|
294
|
+
|
|
295
|
+
## Deployment Architecture
|
|
296
|
+
|
|
297
|
+
### Production Setup
|
|
298
|
+
|
|
299
|
+
```yaml
|
|
300
|
+
# docker-compose.yml
|
|
301
|
+
services:
|
|
302
|
+
registry-db:
|
|
303
|
+
image: postgres:15
|
|
304
|
+
volumes:
|
|
305
|
+
- registry-data:/var/lib/postgresql/data
|
|
306
|
+
environment:
|
|
307
|
+
POSTGRES_DB: epistery_registry
|
|
308
|
+
|
|
309
|
+
registry-api:
|
|
310
|
+
image: epistery/registry:latest
|
|
311
|
+
depends_on:
|
|
312
|
+
- registry-db
|
|
313
|
+
environment:
|
|
314
|
+
DATABASE_URL: postgres://registry-db/epistery_registry
|
|
315
|
+
BLOCKCHAIN_RPC: https://polygon-rpc.com
|
|
316
|
+
AGENT_CONTRACT_ADDRESS: 0x...
|
|
317
|
+
|
|
318
|
+
registry-indexer:
|
|
319
|
+
image: epistery/indexer:latest
|
|
320
|
+
depends_on:
|
|
321
|
+
- registry-db
|
|
322
|
+
environment:
|
|
323
|
+
DATABASE_URL: postgres://registry-db/epistery_registry
|
|
324
|
+
BLOCKCHAIN_RPC: https://polygon-rpc.com
|
|
325
|
+
START_BLOCK: 45000000 # Deploy block
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### High Availability
|
|
329
|
+
|
|
330
|
+
- **Multi-region deployment** - Reduce latency worldwide
|
|
331
|
+
- **Read replicas** - Scale read operations
|
|
332
|
+
- **CDN caching** - Cache frequently accessed names
|
|
333
|
+
- **Fallback to RPC** - Direct blockchain queries if registry unavailable
|
|
334
|
+
|
|
335
|
+
## Governance
|
|
336
|
+
|
|
337
|
+
### Name Policy
|
|
338
|
+
|
|
339
|
+
1. **Length** - Minimum 3 characters, maximum 32 characters
|
|
340
|
+
2. **Characters** - Alphanumeric and hyphens only (a-z, 0-9, -)
|
|
341
|
+
3. **Reserved names** - System reserves: admin, root, system, etc.
|
|
342
|
+
4. **Profanity filter** - Optional content moderation
|
|
343
|
+
|
|
344
|
+
### Domain Management
|
|
345
|
+
|
|
346
|
+
Each domain can set its own policies:
|
|
347
|
+
- **Public registration** - Anyone can register (e.g., "epistery")
|
|
348
|
+
- **Whitelist only** - Must be on domain whitelist
|
|
349
|
+
- **Invite only** - Requires invitation code
|
|
350
|
+
- **Custom validation** - Domain-specific name rules
|
|
351
|
+
|
|
352
|
+
## Future Enhancements
|
|
353
|
+
|
|
354
|
+
### Decentralization Path
|
|
355
|
+
|
|
356
|
+
While starting centralized for performance, the registry can evolve:
|
|
357
|
+
|
|
358
|
+
1. **Federated registries** - Multiple registry operators
|
|
359
|
+
2. **Blockchain checkpoints** - Periodic Merkle root commits on-chain
|
|
360
|
+
3. **IPFS backup** - Distribute registry snapshots via IPFS
|
|
361
|
+
4. **DAO governance** - Community control over policies
|
|
362
|
+
5. **ENS integration** - Bridge to Ethereum Name Service
|
|
363
|
+
|
|
364
|
+
### Advanced Features
|
|
365
|
+
|
|
366
|
+
- **Name transfers** - Transfer name to new IdentityContract
|
|
367
|
+
- **Aliases** - Multiple names pointing to same identity
|
|
368
|
+
- **Reverse lookup** - Contract address → names
|
|
369
|
+
- **Search** - Full-text search across names and metadata
|
|
370
|
+
- **Analytics** - Registration trends, popular names
|
|
371
|
+
- **Notifications** - Alert when watched names become available
|
|
372
|
+
|
|
373
|
+
## Implementation Priority
|
|
374
|
+
|
|
375
|
+
**Phase 1: MVP** (Immediate)
|
|
376
|
+
- Basic PostgreSQL database
|
|
377
|
+
- Event indexer for IdentityCreated
|
|
378
|
+
- Simple HTTP API (check, resolve, list)
|
|
379
|
+
|
|
380
|
+
**Phase 2: Production** (Next)
|
|
381
|
+
- Reservation system
|
|
382
|
+
- Multi-domain support
|
|
383
|
+
- Monitoring and alerts
|
|
384
|
+
- Performance optimization
|
|
385
|
+
|
|
386
|
+
**Phase 3: Scale** (Future)
|
|
387
|
+
- High availability setup
|
|
388
|
+
- CDN integration
|
|
389
|
+
- Advanced search
|
|
390
|
+
- Federation support
|
|
391
|
+
|
|
392
|
+
## Conclusion
|
|
393
|
+
|
|
394
|
+
The Epistery Registry provides a pragmatic solution to identity naming by combining the speed and convenience of centralized systems with the security and verifiability of blockchain. This hybrid approach delivers the best user experience while maintaining the trust properties of decentralized infrastructure.
|
|
395
|
+
|
|
396
|
+
The registry serves as a **discovery layer** rather than an authority—the blockchain remains the ultimate source of truth, and all registry data can be independently verified by querying contract events directly.
|