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