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 "smesh.lol/pkg/store/serial"
7 )
8
9 // Prefix is a 3-byte index prefix.
10 type Prefix [3]byte
11
12 var (
13 Eid = Prefix{'e', 'i', 'd'} // event ID hash -> serial
14 Fpc = Prefix{'f', 'p', 'c'} // serial -> full ID + pubkey hash + timestamp
15 Sei = Prefix{'s', 'e', 'i'} // serial -> full 32-byte event ID
16 CA = Prefix{'c', '-', '-'} // created_at -> serial
17 Exp = Prefix{'e', 'x', 'p'} // expiration timestamp -> serial
18 KC = Prefix{'k', 'c', '-'} // kind + created_at -> serial
19 PC = Prefix{'p', 'c', '-'} // pubkey hash + created_at -> serial
20 KPC = Prefix{'k', 'p', 'c'} // kind + pubkey hash + created_at -> serial
21 TC = Prefix{'t', 'c', '-'} // tag key + value hash + created_at -> serial
22 TKC = Prefix{'t', 'k', 'c'} // tag kind + key + value hash + created_at -> serial
23 TPC = Prefix{'t', 'p', 'c'} // tag pubkey + key + value hash + created_at -> serial
24 TKP = Prefix{'t', 'k', 'p'} // tag kind + pubkey + key + value hash + created_at -> serial
25 Wrd = Prefix{'w', 'r', 'd'} // word hash -> serial
26 Pks = Prefix{'p', 'k', 's'} // pubkey hash -> pubkey serial
27 Spk = Prefix{'s', 'p', 'k'} // pubkey serial -> full pubkey (32 bytes in value)
28 Epg = Prefix{'e', 'p', 'g'} // event_serial|pubkey_serial|kind|direction
29 Peg = Prefix{'p', 'e', 'g'} // pubkey_serial|kind|direction|event_serial
30 Eeg = Prefix{'e', 'e', 'g'} // source_event_serial|target_event_serial|kind|direction
31 Gee = Prefix{'g', 'e', 'e'} // target_event_serial|kind|direction|source_event_serial
32 Ppg = Prefix{'p', 'p', 'g'} // source_pk_serial|target_pk_serial|kind|direction|event_serial
33 Gpp = Prefix{'g', 'p', 'p'} // 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 )
83
84 // MakeEid builds an eid key: prefix|id_hash(8)|serial(5).
85 func MakeEid(idHash []byte, ser uint64) []byte {
86 k := []byte{:EidKeyLen}
87 copy(k, Eid[:])
88 copy(k[3:], idHash[:serial.HashLen])
89 serial.Put(k[3+serial.HashLen:], ser)
90 return k
91 }
92
93 // MakeSei builds a sei key: prefix|serial(5). Value is full 32-byte event ID.
94 func MakeSei(ser uint64) []byte {
95 k := []byte{:SeiKeyLen}
96 copy(k, Sei[:])
97 serial.Put(k[3:], ser)
98 return k
99 }
100
101 // MakeCA builds a created_at key: prefix|timestamp(8)|serial(5).
102 func MakeCA(ts int64, ser uint64) []byte {
103 k := []byte{:CAKeyLen}
104 copy(k, CA[:])
105 serial.PutTimestamp(k[3:], ts)
106 serial.Put(k[3+8:], ser)
107 return k
108 }
109
110 // MakeKC builds a kind+created_at key: prefix|kind(2)|timestamp(8)|serial(5).
111 func MakeKC(kind uint16, ts int64, ser uint64) []byte {
112 k := []byte{:KCKeyLen}
113 copy(k, KC[:])
114 serial.PutKind(k[3:], kind)
115 serial.PutTimestamp(k[5:], ts)
116 serial.Put(k[13:], ser)
117 return k
118 }
119
120 // MakePC builds a pubkey+created_at key: prefix|pubhash(8)|timestamp(8)|serial(5).
121 func MakePC(pubHash []byte, ts int64, ser uint64) []byte {
122 k := []byte{:PCKeyLen}
123 copy(k, PC[:])
124 copy(k[3:], pubHash[:serial.HashLen])
125 serial.PutTimestamp(k[3+serial.HashLen:], ts)
126 serial.Put(k[3+serial.HashLen+8:], ser)
127 return k
128 }
129
130 // MakeKPC builds a kind+pubkey+created_at key.
131 func MakeKPC(kind uint16, pubHash []byte, ts int64, ser uint64) []byte {
132 k := []byte{:KPCKeyLen}
133 copy(k, KPC[:])
134 serial.PutKind(k[3:], kind)
135 copy(k[5:], pubHash[:serial.HashLen])
136 serial.PutTimestamp(k[5+serial.HashLen:], ts)
137 serial.Put(k[5+serial.HashLen+8:], ser)
138 return k
139 }
140
141 // MakeTC builds a tag+created_at key: prefix|tagkey(1)|valuehash(8)|timestamp(8)|serial(5).
142 func MakeTC(tagKey byte, valHash []byte, ts int64, ser uint64) []byte {
143 k := []byte{:TCKeyLen}
144 copy(k, TC[:])
145 k[3] = tagKey
146 copy(k[4:], valHash[:serial.HashLen])
147 serial.PutTimestamp(k[4+serial.HashLen:], ts)
148 serial.Put(k[4+serial.HashLen+8:], ser)
149 return k
150 }
151
152 // MakeTKC builds a tag+kind+created_at key.
153 func MakeTKC(kind uint16, tagKey byte, valHash []byte, ts int64, ser uint64) []byte {
154 k := []byte{:TKCKeyLen}
155 copy(k, TKC[:])
156 serial.PutKind(k[3:], kind)
157 k[5] = tagKey
158 copy(k[6:], valHash[:serial.HashLen])
159 serial.PutTimestamp(k[6+serial.HashLen:], ts)
160 serial.Put(k[6+serial.HashLen+8:], ser)
161 return k
162 }
163
164 // MakeTPC builds a tag+pubkey+created_at key.
165 func MakeTPC(pubHash []byte, tagKey byte, valHash []byte, ts int64, ser uint64) []byte {
166 k := []byte{:TPCKeyLen}
167 copy(k, TPC[:])
168 copy(k[3:], pubHash[:serial.HashLen])
169 k[3+serial.HashLen] = tagKey
170 copy(k[3+serial.HashLen+1:], valHash[:serial.HashLen])
171 serial.PutTimestamp(k[3+serial.HashLen+1+serial.HashLen:], ts)
172 serial.Put(k[3+serial.HashLen+1+serial.HashLen+8:], ser)
173 return k
174 }
175
176 // MakeTKP builds a tag+kind+pubkey+created_at key.
177 func MakeTKP(kind uint16, pubHash []byte, tagKey byte, valHash []byte, ts int64, ser uint64) []byte {
178 k := []byte{:TKPKeyLen}
179 copy(k, TKP[:])
180 serial.PutKind(k[3:], kind)
181 copy(k[5:], pubHash[:serial.HashLen])
182 k[5+serial.HashLen] = tagKey
183 copy(k[5+serial.HashLen+1:], valHash[:serial.HashLen])
184 serial.PutTimestamp(k[5+serial.HashLen+1+serial.HashLen:], ts)
185 serial.Put(k[5+serial.HashLen+1+serial.HashLen+8:], ser)
186 return k
187 }
188
189 // MakeWrd builds a word key: prefix|wordhash(8)|serial(5).
190 func MakeWrd(wordHash []byte, ser uint64) []byte {
191 k := []byte{:WrdKeyLen}
192 copy(k, Wrd[:])
193 copy(k[3:], wordHash[:serial.HashLen])
194 serial.Put(k[3+serial.HashLen:], ser)
195 return k
196 }
197
198 // MakePks builds a pubkey serial key: prefix|pubhash(8)|serial(5).
199 func MakePks(pubHash []byte, ser uint64) []byte {
200 k := []byte{:PksKeyLen}
201 copy(k, Pks[:])
202 copy(k[3:], pubHash[:serial.HashLen])
203 serial.Put(k[3+serial.HashLen:], ser)
204 return k
205 }
206
207 // MakeSpk builds a serial->pubkey key: prefix|serial(5). Value: 32-byte pubkey.
208 func MakeSpk(ser uint64) []byte {
209 k := []byte{:SpkKeyLen}
210 copy(k, Spk[:])
211 serial.Put(k[3:], ser)
212 return k
213 }
214
215 // MakeExp builds an expiration key: prefix|timestamp(8)|serial(5).
216 func MakeExp(ts int64, ser uint64) []byte {
217 k := []byte{:ExpKeyLen}
218 copy(k, Exp[:])
219 serial.PutTimestamp(k[3:], ts)
220 serial.Put(k[3+8:], ser)
221 return k
222 }
223
224 // MakeFpc builds an fpc key: prefix|serial(5)|full_id(32)|pubhash(8)|timestamp(8).
225 func MakeFpc(ser uint64, fullID []byte, pubHash []byte, ts int64) []byte {
226 k := []byte{:FpcKeyLen}
227 copy(k, Fpc[:])
228 serial.Put(k[3:], ser)
229 copy(k[3+serial.Len:], fullID[:32])
230 copy(k[3+serial.Len+32:], pubHash[:serial.HashLen])
231 serial.PutTimestamp(k[3+serial.Len+32+serial.HashLen:], ts)
232 return k
233 }
234
235 // MakeSeiRec builds a sei record: prefix|serial(5)|event_id(32).
236 func MakeSeiRec(ser uint64, eventID []byte) []byte {
237 rec := []byte{:SeiRecLen}
238 copy(rec, Sei[:])
239 serial.Put(rec[3:], ser)
240 copy(rec[SeiKeyLen:], eventID[:32])
241 return rec
242 }
243
244 // MakeSpkRec builds a spk record: prefix|serial(5)|pubkey(32).
245 func MakeSpkRec(ser uint64, pubkey []byte) []byte {
246 rec := []byte{:SpkRecLen}
247 copy(rec, Spk[:])
248 serial.Put(rec[3:], ser)
249 copy(rec[SpkKeyLen:], pubkey[:32])
250 return rec
251 }
252
253 // --- Graph index key builders ---
254
255 // MakeEpg: prefix|event_serial(5)|pubkey_serial(5)|kind(2)|direction(1).
256 func MakeEpg(evSer, pkSer uint64, kind uint16, dir byte) []byte {
257 k := []byte{:EpgKeyLen}
258 copy(k, Epg[:])
259 serial.Put(k[3:], evSer)
260 serial.Put(k[8:], pkSer)
261 serial.PutKind(k[13:], kind)
262 k[15] = dir
263 return k
264 }
265
266 // MakePeg: prefix|pubkey_serial(5)|kind(2)|direction(1)|event_serial(5).
267 func MakePeg(pkSer uint64, kind uint16, dir byte, evSer uint64) []byte {
268 k := []byte{:PegKeyLen}
269 copy(k, Peg[:])
270 serial.Put(k[3:], pkSer)
271 serial.PutKind(k[8:], kind)
272 k[10] = dir
273 serial.Put(k[11:], evSer)
274 return k
275 }
276
277 // MakeEeg: prefix|source_serial(5)|target_serial(5)|kind(2)|direction(1).
278 func MakeEeg(srcSer, tgtSer uint64, kind uint16, dir byte) []byte {
279 k := []byte{:EegKeyLen}
280 copy(k, Eeg[:])
281 serial.Put(k[3:], srcSer)
282 serial.Put(k[8:], tgtSer)
283 serial.PutKind(k[13:], kind)
284 k[15] = dir
285 return k
286 }
287
288 // MakeGee: prefix|target_serial(5)|kind(2)|direction(1)|source_serial(5).
289 func MakeGee(tgtSer uint64, kind uint16, dir byte, srcSer uint64) []byte {
290 k := []byte{:GeeKeyLen}
291 copy(k, Gee[:])
292 serial.Put(k[3:], tgtSer)
293 serial.PutKind(k[8:], kind)
294 k[10] = dir
295 serial.Put(k[11:], srcSer)
296 return k
297 }
298
299 // MakePpg: prefix|src_pk(5)|tgt_pk(5)|kind(2)|direction(1)|event_serial(5).
300 func MakePpg(srcPK, tgtPK uint64, kind uint16, dir byte, evSer uint64) []byte {
301 k := []byte{:PpgKeyLen}
302 copy(k, Ppg[:])
303 serial.Put(k[3:], srcPK)
304 serial.Put(k[8:], tgtPK)
305 serial.PutKind(k[13:], kind)
306 k[15] = dir
307 serial.Put(k[16:], evSer)
308 return k
309 }
310
311 // MakeGpp: prefix|tgt_pk(5)|kind(2)|direction(1)|src_pk(5)|event_serial(5).
312 func MakeGpp(tgtPK uint64, kind uint16, dir byte, srcPK, evSer uint64) []byte {
313 k := []byte{:GppKeyLen}
314 copy(k, Gpp[:])
315 serial.Put(k[3:], tgtPK)
316 serial.PutKind(k[8:], kind)
317 k[10] = dir
318 serial.Put(k[11:], srcPK)
319 serial.Put(k[16:], evSer)
320 return k
321 }
322