get-fullidpubkey-by-serials.go raw

   1  //go:build !(js && wasm)
   2  
   3  package database
   4  
   5  import (
   6  	"bytes"
   7  
   8  	"github.com/dgraph-io/badger/v4"
   9  	"next.orly.dev/pkg/lol/chk"
  10  	"next.orly.dev/pkg/database/indexes"
  11  	"next.orly.dev/pkg/database/indexes/types"
  12  	"next.orly.dev/pkg/interfaces/store"
  13  )
  14  
  15  // GetFullIdPubkeyBySerials seeks directly to each serial's prefix in the
  16  // FullIdPubkey index. The input sers slice is expected to be sorted in
  17  // ascending order, allowing efficient forward-only iteration via a single
  18  // Badger iterator.
  19  func (d *D) GetFullIdPubkeyBySerials(sers []*types.Uint40) (
  20  	fidpks []*store.IdPkTs, err error,
  21  ) {
  22  	// Pre-allocate slice with exact capacity to reduce reallocations
  23  	fidpks = make([]*store.IdPkTs, 0, len(sers))
  24  	if len(sers) == 0 {
  25  		return
  26  	}
  27  	if err = d.View(
  28  		func(txn *badger.Txn) (err error) {
  29  			// Scope the iterator to the FullIdPubkey table using its 3-byte prefix.
  30  			buf := new(bytes.Buffer)
  31  			if err = indexes.NewPrefix(indexes.FullIdPubkey).MarshalWrite(buf); chk.E(err) {
  32  				return
  33  			}
  34  			tablePrefix := buf.Bytes()
  35  			it := txn.NewIterator(badger.IteratorOptions{Prefix: tablePrefix})
  36  			defer it.Close()
  37  
  38  			for _, s := range sers {
  39  				if s == nil {
  40  					continue
  41  				}
  42  				// Build the serial-specific prefix: 3-byte table prefix + 5-byte serial.
  43  				sbuf := new(bytes.Buffer)
  44  				if err = indexes.FullIdPubkeyEnc(
  45  					s, nil, nil, nil,
  46  				).MarshalWrite(sbuf); chk.E(err) {
  47  					return
  48  				}
  49  				serialPrefix := sbuf.Bytes()
  50  
  51  				// Seek to the first key for this serial and verify it matches the prefix.
  52  				it.Seek(serialPrefix)
  53  				if it.ValidForPrefix(serialPrefix) {
  54  					item := it.Item()
  55  					key := item.Key()
  56  					ser, fid, p, ca := indexes.FullIdPubkeyVars()
  57  					if err = indexes.FullIdPubkeyDec(
  58  						ser, fid, p, ca,
  59  					).UnmarshalRead(bytes.NewBuffer(key)); chk.E(err) {
  60  						return
  61  					}
  62  					idpkts := store.NewIdPkTs(
  63  						fid.Bytes(),
  64  						p.Bytes(),
  65  						int64(ca.Get()),
  66  						ser.Get(),
  67  					)
  68  					fidpks = append(fidpks, &idpkts)
  69  				}
  70  			}
  71  			return
  72  		},
  73  	); chk.E(err) {
  74  		return
  75  	}
  76  	return
  77  }
  78