github.com/prysmaticlabs/prysm@v1.4.4/slasher/db/kv/attester_slashings.go (about) 1 package kv 2 3 import ( 4 "bytes" 5 "context" 6 7 "github.com/pkg/errors" 8 types "github.com/prysmaticlabs/eth2-types" 9 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 10 "github.com/prysmaticlabs/prysm/shared/bytesutil" 11 "github.com/prysmaticlabs/prysm/shared/hashutil" 12 slashertypes "github.com/prysmaticlabs/prysm/slasher/db/types" 13 bolt "go.etcd.io/bbolt" 14 "go.opencensus.io/trace" 15 "google.golang.org/protobuf/proto" 16 ) 17 18 func unmarshalAttSlashing(enc []byte) (*ethpb.AttesterSlashing, error) { 19 protoSlashing := ðpb.AttesterSlashing{} 20 err := proto.Unmarshal(enc, protoSlashing) 21 if err != nil { 22 return nil, errors.Wrap(err, "failed to unmarshal encoding") 23 } 24 return protoSlashing, nil 25 } 26 27 func unmarshalAttSlashings(encoded [][]byte) ([]*ethpb.AttesterSlashing, error) { 28 attesterSlashings := make([]*ethpb.AttesterSlashing, len(encoded)) 29 for i, enc := range encoded { 30 ps, err := unmarshalAttSlashing(enc) 31 if err != nil { 32 return nil, err 33 } 34 attesterSlashings[i] = ps 35 } 36 return attesterSlashings, nil 37 } 38 39 // AttesterSlashings accepts a status and returns all slashings with this status. 40 // returns empty []*ethpb.AttesterSlashing if no slashing has been found with this status. 41 func (s *Store) AttesterSlashings(ctx context.Context, status slashertypes.SlashingStatus) ([]*ethpb.AttesterSlashing, error) { 42 ctx, span := trace.StartSpan(ctx, "slasherDB.AttesterSlashings") 43 defer span.End() 44 encoded := make([][]byte, 0) 45 err := s.view(func(tx *bolt.Tx) error { 46 c := tx.Bucket(slashingBucket).Cursor() 47 prefix := encodeType(slashertypes.SlashingType(slashertypes.Attestation)) 48 for k, v := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix); k, v = c.Next() { 49 if v[0] == byte(status) { 50 encoded = append(encoded, v[1:]) 51 } 52 } 53 return nil 54 }) 55 if err != nil { 56 return nil, err 57 } 58 return unmarshalAttSlashings(encoded) 59 } 60 61 // DeleteAttesterSlashing deletes an attester slashing proof from db. 62 func (s *Store) DeleteAttesterSlashing(ctx context.Context, attesterSlashing *ethpb.AttesterSlashing) error { 63 ctx, span := trace.StartSpan(ctx, "slasherDB.deleteAttesterSlashing") 64 defer span.End() 65 root, err := hashutil.HashProto(attesterSlashing) 66 if err != nil { 67 return errors.Wrap(err, "failed to get hash root of attesterSlashing") 68 } 69 return s.update(func(tx *bolt.Tx) error { 70 bucket := tx.Bucket(slashingBucket) 71 k := encodeTypeRoot(slashertypes.SlashingType(slashertypes.Attestation), root) 72 if err != nil { 73 return errors.Wrap(err, "failed to get key for for attester slashing.") 74 } 75 if err := bucket.Delete(k); err != nil { 76 return errors.Wrap(err, "failed to delete the slashing proof from slashing bucket") 77 } 78 return nil 79 }) 80 } 81 82 // HasAttesterSlashing returns true and slashing status if a slashing is found in the db. 83 func (s *Store) HasAttesterSlashing(ctx context.Context, slashing *ethpb.AttesterSlashing) (bool, slashertypes.SlashingStatus, error) { 84 ctx, span := trace.StartSpan(ctx, "slasherDB.HasAttesterSlashing") 85 defer span.End() 86 var status slashertypes.SlashingStatus 87 var found bool 88 root, err := hashutil.HashProto(slashing) 89 if err != nil { 90 return found, status, errors.Wrap(err, "failed to get hash root of attesterSlashing") 91 } 92 key := encodeTypeRoot(slashertypes.SlashingType(slashertypes.Attestation), root) 93 err = s.view(func(tx *bolt.Tx) error { 94 b := tx.Bucket(slashingBucket) 95 enc := b.Get(key) 96 if enc != nil { 97 found = true 98 status = slashertypes.SlashingStatus(enc[0]) 99 } 100 return nil 101 }) 102 return found, status, err 103 } 104 105 // SaveAttesterSlashing accepts a slashing proof and its status and writes it to disk. 106 func (s *Store) SaveAttesterSlashing(ctx context.Context, status slashertypes.SlashingStatus, slashing *ethpb.AttesterSlashing) error { 107 ctx, span := trace.StartSpan(ctx, "slasherDB.SaveAttesterSlashing") 108 defer span.End() 109 enc, err := proto.Marshal(slashing) 110 if err != nil { 111 return errors.Wrap(err, "failed to marshal") 112 } 113 root, err := hashutil.HashProto(slashing) 114 if err != nil { 115 return err 116 } 117 key := encodeTypeRoot(slashertypes.SlashingType(slashertypes.Attestation), root) 118 return s.update(func(tx *bolt.Tx) error { 119 b := tx.Bucket(slashingBucket) 120 e := b.Put(key, append([]byte{byte(status)}, enc...)) 121 return e 122 }) 123 } 124 125 // SaveAttesterSlashings accepts a slice of slashing proof and its status and writes it to disk. 126 func (s *Store) SaveAttesterSlashings(ctx context.Context, status slashertypes.SlashingStatus, slashings []*ethpb.AttesterSlashing) error { 127 ctx, span := trace.StartSpan(ctx, "slasherDB.SaveAttesterSlashings") 128 defer span.End() 129 enc := make([][]byte, len(slashings)) 130 key := make([][]byte, len(slashings)) 131 var err error 132 for i, slashing := range slashings { 133 enc[i], err = proto.Marshal(slashing) 134 if err != nil { 135 return errors.Wrap(err, "failed to marshal") 136 } 137 root, err := hashutil.HashProto(slashing) 138 if err != nil { 139 return err 140 } 141 key[i] = encodeTypeRoot(slashertypes.SlashingType(slashertypes.Attestation), root) 142 } 143 144 return s.update(func(tx *bolt.Tx) error { 145 b := tx.Bucket(slashingBucket) 146 for i := 0; i < len(enc); i++ { 147 e := b.Put(key[i], append([]byte{byte(status)}, enc[i]...)) 148 if e != nil { 149 return e 150 } 151 } 152 return nil 153 }) 154 } 155 156 // GetLatestEpochDetected returns the latest detected epoch from db. 157 func (s *Store) GetLatestEpochDetected(ctx context.Context) (types.Epoch, error) { 158 ctx, span := trace.StartSpan(ctx, "slasherDB.GetLatestEpochDetected") 159 defer span.End() 160 var epoch types.Epoch 161 err := s.view(func(tx *bolt.Tx) error { 162 b := tx.Bucket(slashingBucket) 163 enc := b.Get([]byte(latestEpochKey)) 164 if enc == nil { 165 epoch = 0 166 return nil 167 } 168 epoch = types.Epoch(bytesutil.FromBytes8(enc)) 169 return nil 170 }) 171 return epoch, err 172 } 173 174 // SetLatestEpochDetected sets the latest slashing detected epoch in db. 175 func (s *Store) SetLatestEpochDetected(ctx context.Context, epoch types.Epoch) error { 176 ctx, span := trace.StartSpan(ctx, "slasherDB.SetLatestEpochDetected") 177 defer span.End() 178 return s.update(func(tx *bolt.Tx) error { 179 b := tx.Bucket(slashingBucket) 180 err := b.Put([]byte(latestEpochKey), bytesutil.Bytes8(uint64(epoch))) 181 return err 182 }) 183 }