HighestSlotBlocksBelow, but in reverse (#10772)

Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
This commit is contained in:
kasey 2022-05-31 16:10:33 -05:00 committed by GitHub
parent 4353d39daa
commit 7563bc0444
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -403,33 +403,51 @@ func (s *Store) HighestSlotBlocksBelow(ctx context.Context, slot types.Slot) ([]
ctx, span := trace.StartSpan(ctx, "BeaconDB.HighestSlotBlocksBelow") ctx, span := trace.StartSpan(ctx, "BeaconDB.HighestSlotBlocksBelow")
defer span.End() defer span.End()
var best []byte var root [32]byte
if err := s.db.View(func(tx *bolt.Tx) error { sk := bytesutil.Uint64ToBytesBigEndian(uint64(slot))
err := s.db.View(func(tx *bolt.Tx) error {
bkt := tx.Bucket(blockSlotIndicesBucket) bkt := tx.Bucket(blockSlotIndicesBucket)
// Iterate through the index, which is in byte sorted order.
c := bkt.Cursor() c := bkt.Cursor()
for s, root := c.First(); s != nil; s, root = c.Next() { // The documentation for Seek says:
// "If the key does not exist then the next key is used. If no keys follow, a nil key is returned."
sl, r := c.Seek(sk)
// So if there are slots in the index higher than the requested slot, sl will be equal to the key that is
// one higher than the value we want. If the slot argument is higher than the highest value in the index,
// we'll get a nil value for `sl`. In that case we'll go backwards from Cursor.Last().
if sl == nil {
sl, r = c.Last()
}
for {
if ctx.Err() != nil { if ctx.Err() != nil {
return ctx.Err() return ctx.Err()
} }
key := bytesutil.BytesToSlotBigEndian(s) // termination condition: when .Prev() rewinds past the beginning off the collection, key will be nil.
if root == nil { // breaking without setting `root` means `root` will be the zero value, so this function will return
continue // the genesis block.
} if sl == nil {
if key >= slot {
break break
} }
best = root if r == nil {
continue
}
bs := bytesutil.BytesToSlotBigEndian(sl)
// Iterating through the index using .Prev will move from higher to lower, so the first key we find behind
// the requested slot must be the highest block below that slot.
if slot > bs {
root = bytesutil.ToBytes32(r)
break
}
sl, r = c.Prev()
} }
return nil return nil
}); err != nil { })
if err != nil {
return nil, err return nil, err
} }
var blk interfaces.SignedBeaconBlock var blk interfaces.SignedBeaconBlock
var err error if root != params.BeaconConfig().ZeroHash {
if best != nil { blk, err = s.Block(ctx, root)
blk, err = s.Block(ctx, bytesutil.ToBytes32(best))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -440,7 +458,6 @@ func (s *Store) HighestSlotBlocksBelow(ctx context.Context, slot types.Slot) ([]
return nil, err return nil, err
} }
} }
return []interfaces.SignedBeaconBlock{blk}, nil return []interfaces.SignedBeaconBlock{blk}, nil
} }