github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/db/kv/state_summary.go (about) 1 package kv 2 3 import ( 4 "context" 5 6 pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" 7 "github.com/prysmaticlabs/prysm/shared/bytesutil" 8 bolt "go.etcd.io/bbolt" 9 "go.opencensus.io/trace" 10 ) 11 12 // SaveStateSummary saves a state summary object to the DB. 13 func (s *Store) SaveStateSummary(ctx context.Context, summary *pb.StateSummary) error { 14 ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveStateSummary") 15 defer span.End() 16 17 return s.SaveStateSummaries(ctx, []*pb.StateSummary{summary}) 18 } 19 20 // SaveStateSummaries saves state summary objects to the DB. 21 func (s *Store) SaveStateSummaries(ctx context.Context, summaries []*pb.StateSummary) error { 22 ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveStateSummaries") 23 defer span.End() 24 25 // When we reach the state summary cache prune count, 26 // dump the cached state summaries to the DB. 27 if s.stateSummaryCache.len() >= stateSummaryCachePruneCount { 28 if err := s.saveCachedStateSummariesDB(ctx); err != nil { 29 return err 30 } 31 } 32 33 for _, ss := range summaries { 34 s.stateSummaryCache.put(bytesutil.ToBytes32(ss.Root), ss) 35 } 36 37 return nil 38 } 39 40 // StateSummary returns the state summary object from the db using input block root. 41 func (s *Store) StateSummary(ctx context.Context, blockRoot [32]byte) (*pb.StateSummary, error) { 42 ctx, span := trace.StartSpan(ctx, "BeaconDB.StateSummary") 43 defer span.End() 44 45 if s.stateSummaryCache.has(blockRoot) { 46 return s.stateSummaryCache.get(blockRoot), nil 47 } 48 49 enc, err := s.stateSummaryBytes(ctx, blockRoot) 50 if err != nil { 51 return nil, err 52 } 53 if len(enc) == 0 { 54 return nil, nil 55 } 56 summary := &pb.StateSummary{} 57 if err := decode(ctx, enc, summary); err != nil { 58 return nil, err 59 } 60 return summary, nil 61 } 62 63 // HasStateSummary returns true if a state summary exists in DB. 64 func (s *Store) HasStateSummary(ctx context.Context, blockRoot [32]byte) bool { 65 ctx, span := trace.StartSpan(ctx, "BeaconDB.HasStateSummary") 66 defer span.End() 67 68 if s.stateSummaryCache.has(blockRoot) { 69 return true 70 } 71 72 enc, err := s.stateSummaryBytes(ctx, blockRoot) 73 if err != nil { 74 panic(err) 75 } 76 return len(enc) > 0 77 } 78 79 func (s *Store) stateSummaryBytes(ctx context.Context, blockRoot [32]byte) ([]byte, error) { 80 ctx, span := trace.StartSpan(ctx, "BeaconDB.stateSummaryBytes") 81 defer span.End() 82 83 var enc []byte 84 err := s.db.View(func(tx *bolt.Tx) error { 85 bucket := tx.Bucket(stateSummaryBucket) 86 enc = bucket.Get(blockRoot[:]) 87 return nil 88 }) 89 90 return enc, err 91 } 92 93 // This saves all cached state summary objects to DB, and clears up the cache. 94 func (s *Store) saveCachedStateSummariesDB(ctx context.Context) error { 95 summaries := s.stateSummaryCache.getAll() 96 encs := make([][]byte, len(summaries)) 97 for i, s := range summaries { 98 enc, err := encode(ctx, s) 99 if err != nil { 100 return err 101 } 102 encs[i] = enc 103 } 104 if err := s.db.Update(func(tx *bolt.Tx) error { 105 bucket := tx.Bucket(stateSummaryBucket) 106 for i, s := range summaries { 107 if err := bucket.Put(s.Root, encs[i]); err != nil { 108 return err 109 } 110 } 111 return nil 112 }); err != nil { 113 return err 114 } 115 s.stateSummaryCache.clear() 116 return nil 117 }