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