github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/merkletree2/storage_engine_for_test.go (about) 1 package merkletree2 2 3 import ( 4 "errors" 5 "fmt" 6 "math/bits" 7 "math/rand" 8 "sort" 9 10 "github.com/keybase/client/go/logger" 11 ) 12 13 // In memory StorageEngine implementation, used for tests. It ignores 14 // Transaction arguments, so it can't be used for concurrency tests. 15 type InMemoryStorageEngine struct { 16 Roots map[Seqno]RootMetadata 17 SortedKVPRs []*KVPRecord 18 Nodes map[string]*NodeRecord 19 MasterSecretsMap map[Seqno]MasterSecret 20 ReverseRootMap map[string]Seqno 21 22 // used to make prefix queries efficient. Not otherwise necessary 23 // PositionToKeys map[string](map[string]bool) 24 cfg Config 25 } 26 27 var _ StorageEngine = &InMemoryStorageEngine{} 28 var _ StorageEngineWithBlinding = &InMemoryStorageEngine{} 29 30 type SortedKVPR []*KVPRecord 31 32 func (s SortedKVPR) Len() int { 33 return len(s) 34 } 35 36 func (s SortedKVPR) Less(i, j int) bool { 37 return s[i].kevp.Key.Cmp(s[j].kevp.Key) < 0 38 } 39 40 func (s SortedKVPR) Swap(i, j int) { 41 s[i], s[j] = s[j], s[i] 42 } 43 44 var _ sort.Interface = SortedKVPR{} 45 46 type NodeRecord struct { 47 p Position 48 s Seqno 49 h Hash 50 next *NodeRecord 51 } 52 53 type KVPRecord struct { 54 kevp KeyEncodedValuePair 55 s Seqno 56 next *KVPRecord 57 } 58 59 func NewInMemoryStorageEngine(cfg Config) *InMemoryStorageEngine { 60 i := InMemoryStorageEngine{} 61 i.MasterSecretsMap = make(map[Seqno]MasterSecret) 62 i.Roots = make(map[Seqno]RootMetadata) 63 i.Nodes = make(map[string]*NodeRecord) 64 i.ReverseRootMap = make(map[string]Seqno) 65 i.cfg = cfg 66 return &i 67 } 68 69 func (i *InMemoryStorageEngine) ExecTransaction(ctx logger.ContextInterface, txFn func(logger.ContextInterface, Transaction) error) error { 70 return fmt.Errorf("Transactions are not supported by this engine!") 71 } 72 73 func (i *InMemoryStorageEngine) findKVPR(k Key) *KVPRecord { 74 j := sort.Search(len(i.SortedKVPRs), func(n int) bool { 75 return i.SortedKVPRs[n].kevp.Key.Cmp(k) >= 0 76 }) 77 if j < len(i.SortedKVPRs) && i.SortedKVPRs[j].kevp.Key.Cmp(k) == 0 { 78 return i.SortedKVPRs[j] 79 } 80 return nil 81 } 82 83 func (i *InMemoryStorageEngine) StoreKEVPairs(c logger.ContextInterface, t Transaction, s Seqno, kevps []KeyEncodedValuePair) error { 84 newSKVPR := make([]*KVPRecord, len(kevps)) 85 86 for j, kevp := range kevps { 87 oldKvp := i.findKVPR(kevp.Key) 88 newSKVPR[j] = &KVPRecord{kevp: kevp, s: s, next: oldKvp} 89 if oldKvp != nil && oldKvp.s >= s { 90 return errors.New("Engine does not support out of order insertions") 91 } 92 } 93 94 sort.Sort(SortedKVPR(newSKVPR)) 95 i.SortedKVPRs = newSKVPR 96 return nil 97 } 98 99 func (i *InMemoryStorageEngine) StoreNodes(c logger.ContextInterface, t Transaction, s Seqno, phps []PositionHashPair) error { 100 for _, php := range phps { 101 err := i.StoreNode(c, t, s, &php.Position, php.Hash) 102 if err != nil { 103 return err 104 } 105 } 106 return nil 107 } 108 109 func (i *InMemoryStorageEngine) StoreNode(c logger.ContextInterface, t Transaction, s Seqno, p *Position, h Hash) error { 110 strKey := p.AsString() 111 oldNodeRec := i.Nodes[strKey] 112 i.Nodes[strKey] = &NodeRecord{s: s, p: *p, h: h, next: oldNodeRec} 113 if oldNodeRec != nil && oldNodeRec.s >= s { 114 return errors.New("Engine does not support out of order insertions") 115 } 116 return nil 117 } 118 119 func (i *InMemoryStorageEngine) StoreRootMetadata(c logger.ContextInterface, t Transaction, r RootMetadata, h Hash) error { 120 i.Roots[r.Seqno] = r 121 i.ReverseRootMap[string(h)] = r.Seqno 122 return nil 123 } 124 125 func (i *InMemoryStorageEngine) LookupLatestRoot(c logger.ContextInterface, t Transaction) (Seqno, RootMetadata, error) { 126 if len(i.Roots) == 0 { 127 return 0, RootMetadata{}, NewNoLatestRootFoundError() 128 } 129 max := Seqno(0) 130 for k := range i.Roots { 131 if k > max { 132 max = k 133 } 134 } 135 return max, i.Roots[max], nil 136 } 137 138 func (i *InMemoryStorageEngine) LookupRoot(c logger.ContextInterface, t Transaction, s Seqno) (RootMetadata, error) { 139 r, found := i.Roots[s] 140 if found { 141 return r, nil 142 } 143 return RootMetadata{}, NewInvalidSeqnoError(s, fmt.Errorf("No root at seqno %v", s)) 144 } 145 146 func (i *InMemoryStorageEngine) LookupRootFromHash(c logger.ContextInterface, t Transaction, h Hash) (RootMetadata, error) { 147 s, found := i.ReverseRootMap[string(h)] 148 if found { 149 return i.Roots[s], nil 150 } 151 return RootMetadata{}, NewInvalidSeqnoError(s, fmt.Errorf("No root at seqno %v", s)) 152 } 153 154 func (i *InMemoryStorageEngine) LookupRoots(c logger.ContextInterface, t Transaction, seqnos []Seqno) (roots []RootMetadata, err error) { 155 seqnosSorted := make([]Seqno, len(seqnos)) 156 copy(seqnosSorted, seqnos) 157 sort.Sort(SeqnoSortedAsInt(seqnosSorted)) 158 159 roots = make([]RootMetadata, len(seqnosSorted)) 160 161 for j, s := range seqnosSorted { 162 root, found := i.Roots[s] 163 if !found { 164 return nil, NewInvalidSeqnoError(s, fmt.Errorf("No root at seqno %v", s)) 165 } 166 roots[j] = root 167 } 168 169 return roots, nil 170 } 171 172 func (i *InMemoryStorageEngine) LookupRootHashes(c logger.ContextInterface, t Transaction, seqnos []Seqno) (hashes []Hash, err error) { 173 if len(seqnos) == 0 { 174 return nil, fmt.Errorf("No seqnos requested") 175 } 176 seqnosSorted := make([]Seqno, len(seqnos)) 177 copy(seqnosSorted, seqnos) 178 sort.Sort(SeqnoSortedAsInt(seqnosSorted)) 179 180 hashes = make([]Hash, len(seqnosSorted)) 181 182 for j, s := range seqnosSorted { 183 r, found := i.Roots[s] 184 if !found { 185 return nil, NewInvalidSeqnoError(s, fmt.Errorf("No root at seqno %v", s)) 186 } 187 _, hashes[j], err = i.cfg.Encoder.EncodeAndHashGeneric(r) 188 if err != nil { 189 panic(fmt.Sprintf("Error encoding %+v", r)) 190 } 191 } 192 193 return hashes, nil 194 } 195 196 func (i *InMemoryStorageEngine) LookupNode(c logger.ContextInterface, t Transaction, s Seqno, p *Position) (Hash, error) { 197 node, found := i.Nodes[string(p.GetBytes())] 198 if !found { 199 return nil, NewNodeNotFoundError() 200 } 201 for ; node != nil; node = node.next { 202 if node.s <= s { 203 return node.h, nil 204 } 205 } 206 return nil, NewNodeNotFoundError() 207 } 208 209 func (i *InMemoryStorageEngine) LookupNodes(c logger.ContextInterface, t Transaction, s Seqno, positions []Position) (res []PositionHashPair, err error) { 210 for _, p := range positions { 211 h, err := i.LookupNode(c, t, s, &p) 212 if err == nil { 213 res = append(res, PositionHashPair{Position: p, Hash: h}) 214 } 215 } 216 217 // Shuffle the result to catch bugs that happen when ordering is different. 218 rand.Shuffle(len(res), func(i, j int) { res[i], res[j] = res[j], res[i] }) 219 220 return res, nil 221 } 222 223 func (i *InMemoryStorageEngine) LookupKEVPair(c logger.ContextInterface, t Transaction, s Seqno, k Key) (EncodedValue, Seqno, error) { 224 kvpr := i.findKVPR(k) 225 if kvpr == nil { 226 return nil, 0, NewKeyNotFoundError() 227 } 228 for ; kvpr != nil; kvpr = kvpr.next { 229 if kvpr.s <= s { 230 return kvpr.kevp.Value, kvpr.s, nil 231 } 232 } 233 return nil, 0, NewKeyNotFoundError() 234 } 235 236 func (i *InMemoryStorageEngine) LookupKEVPairsUnderPosition(ctx logger.ContextInterface, t Transaction, s Seqno, p *Position) (kvps []KeyEncodedValuePair, seqnos []Seqno, err error) { 237 pBytes := p.GetBytes() 238 239 minIndex := sort.Search(len(i.SortedKVPRs), func(n int) bool { 240 k := i.SortedKVPRs[n].kevp.Key 241 pLeadingZeros := bits.LeadingZeros8(pBytes[0]) 242 for j := 1; j < 8*len(pBytes)-pLeadingZeros; j++ { 243 jthBitP := (pBytes[(pLeadingZeros+j)/8] & byte(1<<uint(7-((pLeadingZeros+j)%8)))) != 0 244 jthBitK := (k[(j-1)/8] & byte(1<<uint(7-((j-1)%8)))) != 0 245 if !jthBitK && jthBitP { 246 return false 247 } else if jthBitK == jthBitP { 248 continue 249 } else if jthBitK && !jthBitP { 250 return true 251 } 252 } 253 return true 254 }) 255 256 maxIndex := sort.Search(len(i.SortedKVPRs), func(n int) bool { 257 k := i.SortedKVPRs[n].kevp.Key 258 pLeadingZeros := bits.LeadingZeros8(pBytes[0]) 259 for j := 1; j < 8*len(pBytes)-pLeadingZeros; j++ { 260 jthBitP := (pBytes[(pLeadingZeros+j)/8] & byte(1<<uint(7-((pLeadingZeros+j)%8)))) != 0 261 jthBitK := (k[(j-1)/8] & byte(1<<uint(7-((j-1)%8)))) != 0 262 if !jthBitK && jthBitP { 263 return false 264 } else if jthBitK == jthBitP { 265 continue 266 } else if jthBitK && !jthBitP { 267 return true 268 } 269 } 270 return false 271 }) 272 273 kvps = make([]KeyEncodedValuePair, 0, maxIndex-minIndex) 274 seqnos = make([]Seqno, 0, maxIndex-minIndex) 275 for j := minIndex; j < maxIndex; j++ { 276 kvpr := i.SortedKVPRs[j] 277 for ; kvpr != nil; kvpr = kvpr.next { 278 if kvpr.s <= s { 279 kvps = append(kvps, kvpr.kevp) 280 seqnos = append(seqnos, kvpr.s) 281 break 282 } 283 } 284 } 285 if len(kvps) == 0 { 286 return nil, nil, NewKeyNotFoundError() 287 } 288 return kvps, seqnos, nil 289 } 290 291 // LookupAllKEVPairs returns all the keys and encoded values at the specified Seqno. 292 func (i *InMemoryStorageEngine) LookupAllKEVPairs(ctx logger.ContextInterface, t Transaction, s Seqno) (kevps []KeyEncodedValuePair, err error) { 293 kevps = make([]KeyEncodedValuePair, 0, len(i.SortedKVPRs)) 294 for _, kvpr := range i.SortedKVPRs { 295 for ; kvpr != nil; kvpr = kvpr.next { 296 if kvpr.s <= s { 297 kevps = append(kevps, kvpr.kevp) 298 break 299 } 300 } 301 } 302 return kevps, nil 303 } 304 305 func (i *InMemoryStorageEngine) StoreMasterSecret(ctx logger.ContextInterface, t Transaction, s Seqno, ms MasterSecret) (err error) { 306 i.MasterSecretsMap[s] = MasterSecret(append([]byte{}, []byte(ms)...)) 307 return nil 308 } 309 310 func (i *InMemoryStorageEngine) LookupMasterSecrets(ctx logger.ContextInterface, t Transaction, seqnos []Seqno) (msMap map[Seqno]MasterSecret, err error) { 311 if i.MasterSecretsMap == nil { 312 i.MasterSecretsMap = make(map[Seqno]MasterSecret) 313 } 314 msMap = make(map[Seqno]MasterSecret) 315 for _, s := range seqnos { 316 ms, found := i.MasterSecretsMap[s] 317 if found { 318 msMap[s] = ms 319 } else { 320 return nil, fmt.Errorf("MasterSecret for Seqno %v not found", s) 321 } 322 } 323 return msMap, nil 324 }