keys.mx raw
1 // Package index defines key prefix types and encoding for the store's index system.
2 // Each key type has a 3-byte prefix followed by fixed-width fields.
3 package index
4
5 import (
6 "git.smesh.lol/morly/pkg/store/serial"
7 )
8
9 // Prefix is a 3-byte index prefix.
10 type Prefix [3]byte
11
12 var (
13 Eid Prefix // event ID hash -> serial
14 Fpc Prefix // serial -> full ID + pubkey hash + timestamp
15 Sei Prefix // serial -> full 32-byte event ID
16 CA Prefix // created_at -> serial
17 Exp Prefix // expiration timestamp -> serial
18 KC Prefix // kind + created_at -> serial
19 PC Prefix // pubkey hash + created_at -> serial
20 KPC Prefix // kind + pubkey hash + created_at -> serial
21 TC Prefix // tag key + value hash + created_at -> serial
22 TKC Prefix // tag kind + key + value hash + created_at -> serial
23 TPC Prefix // tag pubkey + key + value hash + created_at -> serial
24 TKP Prefix // tag kind + pubkey + key + value hash + created_at -> serial
25 Wrd Prefix // word hash -> serial
26 Pks Prefix // pubkey hash -> pubkey serial
27 Spk Prefix // pubkey serial -> full pubkey (32 bytes in value)
28 Epg Prefix // event_serial|pubkey_serial|kind|direction
29 Peg Prefix // pubkey_serial|kind|direction|event_serial
30 Eeg Prefix // source_event_serial|target_event_serial|kind|direction
31 Gee Prefix // target_event_serial|kind|direction|source_event_serial
32 Ppg Prefix // source_pk_serial|target_pk_serial|kind|direction|event_serial
33 Gpp Prefix // target_pk_serial|kind|direction|source_pk_serial|event_serial
34 )
35
36 // Edge direction constants (match orly.dev exactly).
37 const (
38 // Event-pubkey edge directions (epg/peg).
39 DirAuthor byte = 0 // pubkey is the event author
40 DirPTagOut byte = 1 // event references pubkey via p-tag (outbound)
41 DirPTagIn byte = 2 // pubkey is referenced by event's p-tag (inbound)
42
43 // Event-event edge directions (eeg/gee).
44 DirETagOut byte = 0 // this event references target event via e-tag
45 DirETagIn byte = 1 // this event is referenced by source event via e-tag
46
47 // Pubkey-pubkey edge directions (ppg/gpp).
48 DirPKOut byte = 0 // source pubkey references target pubkey
49 DirPKIn byte = 1 // target pubkey is referenced by source pubkey
50 )
51
52 // Key sizes (prefix + fields). These are the total key lengths for each index type.
53 const (
54 EidKeyLen = 3 + serial.HashLen + serial.Len // 16
55 FpcKeyLen = 3 + serial.Len + 32 + serial.HashLen + 8 // 56
56 SeiKeyLen = 3 + serial.Len // 8 (value: 32 bytes)
57 CAKeyLen = 3 + 8 + serial.Len // 16
58 ExpKeyLen = 3 + 8 + serial.Len // 16
59 KCKeyLen = 3 + 2 + 8 + serial.Len // 18
60 PCKeyLen = 3 + serial.HashLen + 8 + serial.Len // 24
61 KPCKeyLen = 3 + 2 + serial.HashLen + 8 + serial.Len // 26
62 TCKeyLen = 3 + 1 + serial.HashLen + 8 + serial.Len // 25
63 TKCKeyLen = 3 + 2 + 1 + serial.HashLen + 8 + serial.Len // 27
64 TPCKeyLen = 3 + serial.HashLen + 1 + serial.HashLen + 8 + serial.Len // 33
65 TKPKeyLen = 3 + 2 + serial.HashLen + 1 + serial.HashLen + 8 + serial.Len // 35
66 WrdKeyLen = 3 + serial.HashLen + serial.Len // 16
67 PksKeyLen = 3 + serial.HashLen + serial.Len // 16
68 SpkKeyLen = 3 + serial.Len // 8 (value: 32 bytes)
69
70 // Graph index key lengths.
71 EpgKeyLen = 3 + serial.Len + serial.Len + 2 + 1 // 16: prefix|event_ser|pk_ser|kind|dir
72 PegKeyLen = 3 + serial.Len + 2 + 1 + serial.Len // 16: prefix|pk_ser|kind|dir|event_ser
73 EegKeyLen = 3 + serial.Len + serial.Len + 2 + 1 // 16: prefix|src_ser|tgt_ser|kind|dir
74 GeeKeyLen = 3 + serial.Len + 2 + 1 + serial.Len // 16: prefix|tgt_ser|kind|dir|src_ser
75 PpgKeyLen = 3 + serial.Len + serial.Len + 2 + 1 + serial.Len // 21: prefix|src_pk|tgt_pk|kind|dir|ev_ser
76 GppKeyLen = 3 + serial.Len + 2 + 1 + serial.Len + serial.Len // 21: prefix|tgt_pk|kind|dir|src_pk|ev_ser
77
78 // Record lengths for indexes that carry values after the key.
79 SeiRecLen = SeiKeyLen + 32 // 40 (key + 32-byte event ID)
80 SpkRecLen = SpkKeyLen + 32 // 40 (key + 32-byte pubkey)
81 FpcCmpLen = 3 + serial.Len // 8 (prefix + serial, for search)
82 // eid and pks are hashed-key indexes: the search key stops after the hash,
83 // so a point lookup (File.Get) matches the record by hash and the trailing
84 // serial stays a payload field. Comparing the full key made Get compare the
85 // caller's serial 0 against stored serials and never match, which turned
86 // every lookup into "not found" - a duplicate was accepted and every event
87 // registered a fresh pubkey serial.
88 EidCmpLen = 3 + serial.HashLen // 11 (prefix + id hash)
89 PksCmpLen = 3 + serial.HashLen // 11 (prefix + pubkey hash)
90 )
91
92 // MakeEid builds an eid key: prefix|id_hash(8)|serial(5).
93 func MakeEid(idHash []byte, ser uint64) (buf []byte) {
94 k := []byte{:EidKeyLen}
95 copy(k, Eid[:])
96 copy(k[3:], idHash[:serial.HashLen])
97 serial.Put(k[3+serial.HashLen:], ser)
98 return k
99 }
100
101 // MakeEidPrefix builds the id-hash part of an eid key: prefix|idHash(8). The
102 // key continues with the 5-byte serial, so a prefix lookup needs this much.
103 func MakeEidPrefix(idHash []byte) (buf []byte) {
104 k := []byte{:3 + serial.HashLen}
105 copy(k, Eid[:])
106 copy(k[3:], idHash[:serial.HashLen])
107 return k
108 }
109
110 // MakeSei builds a sei key: prefix|serial(5). Value is full 32-byte event ID.
111 func MakeSei(ser uint64) (buf []byte) {
112 k := []byte{:SeiKeyLen}
113 copy(k, Sei[:])
114 serial.Put(k[3:], ser)
115 return k
116 }
117
118 // MakeCA builds a created_at key: prefix|timestamp(8)|serial(5).
119 func MakeCA(ts int64, ser uint64) (buf []byte) {
120 k := []byte{:CAKeyLen}
121 copy(k, CA[:])
122 serial.PutTimestamp(k[3:], ts)
123 serial.Put(k[3+8:], ser)
124 return k
125 }
126
127 // MakeKC builds a kind+created_at key: prefix|kind(2)|timestamp(8)|serial(5).
128 func MakeKC(kind uint16, ts int64, ser uint64) (buf []byte) {
129 k := []byte{:KCKeyLen}
130 copy(k, KC[:])
131 serial.PutKind(k[3:], kind)
132 serial.PutTimestamp(k[5:], ts)
133 serial.Put(k[13:], ser)
134 return k
135 }
136
137 // MakePC builds a pubkey+created_at key: prefix|pubhash(8)|timestamp(8)|serial(5).
138 func MakePC(pubHash []byte, ts int64, ser uint64) (buf []byte) {
139 k := []byte{:PCKeyLen}
140 copy(k, PC[:])
141 copy(k[3:], pubHash[:serial.HashLen])
142 serial.PutTimestamp(k[3+serial.HashLen:], ts)
143 serial.Put(k[3+serial.HashLen+8:], ser)
144 return k
145 }
146
147 // MakeKPC builds a kind+pubkey+created_at key.
148 func MakeKPC(kind uint16, pubHash []byte, ts int64, ser uint64) (buf []byte) {
149 k := []byte{:KPCKeyLen}
150 copy(k, KPC[:])
151 serial.PutKind(k[3:], kind)
152 copy(k[5:], pubHash[:serial.HashLen])
153 serial.PutTimestamp(k[5+serial.HashLen:], ts)
154 serial.Put(k[5+serial.HashLen+8:], ser)
155 return k
156 }
157
158 // MakeTC builds a tag+created_at key: prefix|tagkey(1)|valuehash(8)|timestamp(8)|serial(5).
159 func MakeTC(tagKey byte, valHash []byte, ts int64, ser uint64) (buf []byte) {
160 k := []byte{:TCKeyLen}
161 copy(k, TC[:])
162 k[3] = tagKey
163 copy(k[4:], valHash[:serial.HashLen])
164 serial.PutTimestamp(k[4+serial.HashLen:], ts)
165 serial.Put(k[4+serial.HashLen+8:], ser)
166 return k
167 }
168
169 // MakeTKC builds a tag+kind+created_at key.
170 func MakeTKC(kind uint16, tagKey byte, valHash []byte, ts int64, ser uint64) (buf []byte) {
171 k := []byte{:TKCKeyLen}
172 copy(k, TKC[:])
173 serial.PutKind(k[3:], kind)
174 k[5] = tagKey
175 copy(k[6:], valHash[:serial.HashLen])
176 serial.PutTimestamp(k[6+serial.HashLen:], ts)
177 serial.Put(k[6+serial.HashLen+8:], ser)
178 return k
179 }
180
181 // MakeTPC builds a tag+pubkey+created_at key.
182 func MakeTPC(pubHash []byte, tagKey byte, valHash []byte, ts int64, ser uint64) (buf []byte) {
183 k := []byte{:TPCKeyLen}
184 copy(k, TPC[:])
185 copy(k[3:], pubHash[:serial.HashLen])
186 k[3+serial.HashLen] = tagKey
187 copy(k[3+serial.HashLen+1:], valHash[:serial.HashLen])
188 serial.PutTimestamp(k[3+serial.HashLen+1+serial.HashLen:], ts)
189 serial.Put(k[3+serial.HashLen+1+serial.HashLen+8:], ser)
190 return k
191 }
192
193 // MakeTKP builds a tag+kind+pubkey+created_at key.
194 func MakeTKP(kind uint16, pubHash []byte, tagKey byte, valHash []byte, ts int64, ser uint64) (buf []byte) {
195 k := []byte{:TKPKeyLen}
196 copy(k, TKP[:])
197 serial.PutKind(k[3:], kind)
198 copy(k[5:], pubHash[:serial.HashLen])
199 k[5+serial.HashLen] = tagKey
200 copy(k[5+serial.HashLen+1:], valHash[:serial.HashLen])
201 serial.PutTimestamp(k[5+serial.HashLen+1+serial.HashLen:], ts)
202 serial.Put(k[5+serial.HashLen+1+serial.HashLen+8:], ser)
203 return k
204 }
205
206 // MakeWrd builds a word key: prefix|wordhash(8)|serial(5).
207 func MakeWrd(wordHash []byte, ser uint64) (buf []byte) {
208 k := []byte{:WrdKeyLen}
209 copy(k, Wrd[:])
210 copy(k[3:], wordHash[:serial.HashLen])
211 serial.Put(k[3+serial.HashLen:], ser)
212 return k
213 }
214
215 // MakePks builds a pubkey serial key: prefix|pubhash(8)|serial(5).
216 func MakePks(pubHash []byte, ser uint64) (buf []byte) {
217 k := []byte{:PksKeyLen}
218 copy(k, Pks[:])
219 copy(k[3:], pubHash[:serial.HashLen])
220 serial.Put(k[3+serial.HashLen:], ser)
221 return k
222 }
223
224 // MakeSpk builds a serial->pubkey key: prefix|serial(5). Value: 32-byte pubkey.
225 func MakeSpk(ser uint64) (buf []byte) {
226 k := []byte{:SpkKeyLen}
227 copy(k, Spk[:])
228 serial.Put(k[3:], ser)
229 return k
230 }
231
232 // MakeExp builds an expiration key: prefix|timestamp(8)|serial(5).
233 func MakeExp(ts int64, ser uint64) (buf []byte) {
234 k := []byte{:ExpKeyLen}
235 copy(k, Exp[:])
236 serial.PutTimestamp(k[3:], ts)
237 serial.Put(k[3+8:], ser)
238 return k
239 }
240
241 // MakeFpc builds an fpc key: prefix|serial(5)|full_id(32)|pubhash(8)|timestamp(8).
242 func MakeFpc(ser uint64, fullID []byte, pubHash []byte, ts int64) (buf []byte) {
243 k := []byte{:FpcKeyLen}
244 copy(k, Fpc[:])
245 serial.Put(k[3:], ser)
246 copy(k[3+serial.Len:], fullID[:32])
247 copy(k[3+serial.Len+32:], pubHash[:serial.HashLen])
248 serial.PutTimestamp(k[3+serial.Len+32+serial.HashLen:], ts)
249 return k
250 }
251
252 // MakeSeiRec builds a sei record: prefix|serial(5)|event_id(32).
253 func MakeSeiRec(ser uint64, eventID []byte) (buf []byte) {
254 rec := []byte{:SeiRecLen}
255 copy(rec, Sei[:])
256 serial.Put(rec[3:], ser)
257 copy(rec[SeiKeyLen:], eventID[:32])
258 return rec
259 }
260
261 // MakeSpkRec builds a spk record: prefix|serial(5)|pubkey(32).
262 func MakeSpkRec(ser uint64, pubkey []byte) (buf []byte) {
263 rec := []byte{:SpkRecLen}
264 copy(rec, Spk[:])
265 serial.Put(rec[3:], ser)
266 copy(rec[SpkKeyLen:], pubkey[:32])
267 return rec
268 }
269
270 // --- Graph index key builders ---
271
272 // MakeEpg: prefix|event_serial(5)|pubkey_serial(5)|kind(2)|direction(1).
273 func MakeEpg(evSer, pkSer uint64, kind uint16, dir byte) (buf []byte) {
274 k := []byte{:EpgKeyLen}
275 copy(k, Epg[:])
276 serial.Put(k[3:], evSer)
277 serial.Put(k[8:], pkSer)
278 serial.PutKind(k[13:], kind)
279 k[15] = dir
280 return k
281 }
282
283 // MakePeg: prefix|pubkey_serial(5)|kind(2)|direction(1)|event_serial(5).
284 func MakePeg(pkSer uint64, kind uint16, dir byte, evSer uint64) (buf []byte) {
285 k := []byte{:PegKeyLen}
286 copy(k, Peg[:])
287 serial.Put(k[3:], pkSer)
288 serial.PutKind(k[8:], kind)
289 k[10] = dir
290 serial.Put(k[11:], evSer)
291 return k
292 }
293
294 // MakeEeg: prefix|source_serial(5)|target_serial(5)|kind(2)|direction(1).
295 func MakeEeg(srcSer, tgtSer uint64, kind uint16, dir byte) (buf []byte) {
296 k := []byte{:EegKeyLen}
297 copy(k, Eeg[:])
298 serial.Put(k[3:], srcSer)
299 serial.Put(k[8:], tgtSer)
300 serial.PutKind(k[13:], kind)
301 k[15] = dir
302 return k
303 }
304
305 // MakeGee: prefix|target_serial(5)|kind(2)|direction(1)|source_serial(5).
306 func MakeGee(tgtSer uint64, kind uint16, dir byte, srcSer uint64) (buf []byte) {
307 k := []byte{:GeeKeyLen}
308 copy(k, Gee[:])
309 serial.Put(k[3:], tgtSer)
310 serial.PutKind(k[8:], kind)
311 k[10] = dir
312 serial.Put(k[11:], srcSer)
313 return k
314 }
315
316 // MakePpg: prefix|src_pk(5)|tgt_pk(5)|kind(2)|direction(1)|event_serial(5).
317 func MakePpg(srcPK, tgtPK uint64, kind uint16, dir byte, evSer uint64) (buf []byte) {
318 k := []byte{:PpgKeyLen}
319 copy(k, Ppg[:])
320 serial.Put(k[3:], srcPK)
321 serial.Put(k[8:], tgtPK)
322 serial.PutKind(k[13:], kind)
323 k[15] = dir
324 serial.Put(k[16:], evSer)
325 return k
326 }
327
328 // MakeGpp: prefix|tgt_pk(5)|kind(2)|direction(1)|src_pk(5)|event_serial(5).
329 func MakeGpp(tgtPK uint64, kind uint16, dir byte, srcPK, evSer uint64) (buf []byte) {
330 k := []byte{:GppKeyLen}
331 copy(k, Gpp[:])
332 serial.Put(k[3:], tgtPK)
333 serial.PutKind(k[8:], kind)
334 k[10] = dir
335 serial.Put(k[11:], srcPK)
336 serial.Put(k[16:], evSer)
337 return k
338 }
339
340 func init() {
341 Eid = Prefix{'e', 'i', 'd'}
342 Fpc = Prefix{'f', 'p', 'c'}
343 Sei = Prefix{'s', 'e', 'i'}
344 CA = Prefix{'c', '-', '-'}
345 Exp = Prefix{'e', 'x', 'p'}
346 KC = Prefix{'k', 'c', '-'}
347 PC = Prefix{'p', 'c', '-'}
348 KPC = Prefix{'k', 'p', 'c'}
349 TC = Prefix{'t', 'c', '-'}
350 TKC = Prefix{'t', 'k', 'c'}
351 TPC = Prefix{'t', 'p', 'c'}
352 TKP = Prefix{'t', 'k', 'p'}
353 Wrd = Prefix{'w', 'r', 'd'}
354 Pks = Prefix{'p', 'k', 's'}
355 Spk = Prefix{'s', 'p', 'k'}
356 Epg = Prefix{'e', 'p', 'g'}
357 Peg = Prefix{'p', 'e', 'g'}
358 Eeg = Prefix{'e', 'e', 'g'}
359 Gee = Prefix{'g', 'e', 'e'}
360 Ppg = Prefix{'p', 'p', 'g'}
361 Gpp = Prefix{'g', 'p', 'p'}
362 }
363