github.com/prysmaticlabs/prysm@v1.4.4/slasher/db/kv/proposer_slashings.go (about) 1 package kv 2 3 import ( 4 "bytes" 5 "context" 6 7 "github.com/pkg/errors" 8 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 9 "github.com/prysmaticlabs/prysm/shared/hashutil" 10 "github.com/prysmaticlabs/prysm/slasher/db/types" 11 bolt "go.etcd.io/bbolt" 12 "go.opencensus.io/trace" 13 "google.golang.org/protobuf/proto" 14 ) 15 16 func unmarshalProposerSlashing(ctx context.Context, enc []byte) (*ethpb.ProposerSlashing, error) { 17 ctx, span := trace.StartSpan(ctx, "slasherDB.unmarshalProposerSlashing") 18 defer span.End() 19 protoSlashing := ðpb.ProposerSlashing{} 20 if err := proto.Unmarshal(enc, protoSlashing); err != nil { 21 return nil, errors.Wrap(err, "failed to unmarshal encoded proposer slashing") 22 } 23 return protoSlashing, nil 24 } 25 26 func unmarshalProposerSlashingArray(ctx context.Context, encoded [][]byte) ([]*ethpb.ProposerSlashing, error) { 27 ctx, span := trace.StartSpan(ctx, "slasherDB.unmarshalProposerSlashingArray") 28 defer span.End() 29 proposerSlashings := make([]*ethpb.ProposerSlashing, len(encoded)) 30 for i, enc := range encoded { 31 ps, err := unmarshalProposerSlashing(ctx, enc) 32 if err != nil { 33 return nil, err 34 } 35 proposerSlashings[i] = ps 36 } 37 return proposerSlashings, nil 38 } 39 40 // ProposalSlashingsByStatus returns all the proposal slashing proofs with a certain status. 41 func (s *Store) ProposalSlashingsByStatus(ctx context.Context, status types.SlashingStatus) ([]*ethpb.ProposerSlashing, error) { 42 ctx, span := trace.StartSpan(ctx, "slasherDB.ProposalSlashingsByStatus") 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(types.SlashingType(types.Proposal)) 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 unmarshalProposerSlashingArray(ctx, encoded) 59 } 60 61 // DeleteProposerSlashing deletes a proposer slashing proof. 62 func (s *Store) DeleteProposerSlashing(ctx context.Context, slashing *ethpb.ProposerSlashing) error { 63 ctx, span := trace.StartSpan(ctx, "slasherDB.deleteProposerSlashing") 64 defer span.End() 65 root, err := hashutil.HashProto(slashing) 66 if err != nil { 67 return errors.Wrap(err, "failed to get hash root of proposerSlashing") 68 } 69 err = s.update(func(tx *bolt.Tx) error { 70 bucket := tx.Bucket(slashingBucket) 71 k := encodeTypeRoot(types.SlashingType(types.Proposal), root) 72 if err := bucket.Delete(k); err != nil { 73 return errors.Wrap(err, "failed to delete the slashing proof from slashing bucket") 74 } 75 return nil 76 }) 77 return err 78 } 79 80 // HasProposerSlashing returns the slashing key if it is found in db. 81 func (s *Store) HasProposerSlashing(ctx context.Context, slashing *ethpb.ProposerSlashing) (bool, types.SlashingStatus, error) { 82 ctx, span := trace.StartSpan(ctx, "slasherDB.HasProposerSlashing") 83 defer span.End() 84 var status types.SlashingStatus 85 var found bool 86 root, err := hashutil.HashProto(slashing) 87 if err != nil { 88 return found, status, errors.Wrap(err, "failed to get hash root of proposerSlashing") 89 } 90 key := encodeTypeRoot(types.SlashingType(types.Proposal), root) 91 92 err = s.view(func(tx *bolt.Tx) error { 93 b := tx.Bucket(slashingBucket) 94 enc := b.Get(key) 95 if enc != nil { 96 found = true 97 status = types.SlashingStatus(enc[0]) 98 } 99 return nil 100 }) 101 return found, status, err 102 } 103 104 // SaveProposerSlashing accepts a proposer slashing and its status header and writes it to disk. 105 func (s *Store) SaveProposerSlashing(ctx context.Context, status types.SlashingStatus, slashing *ethpb.ProposerSlashing) error { 106 ctx, span := trace.StartSpan(ctx, "slasherDB.SaveProposerSlashing") 107 defer span.End() 108 enc, err := proto.Marshal(slashing) 109 if err != nil { 110 return errors.Wrap(err, "failed to marshal") 111 } 112 root, err := hashutil.HashProto(slashing) 113 if err != nil { 114 return err 115 } 116 key := encodeTypeRoot(types.SlashingType(types.Proposal), root) 117 return s.update(func(tx *bolt.Tx) error { 118 b := tx.Bucket(slashingBucket) 119 e := b.Put(key, append([]byte{byte(status)}, enc...)) 120 return e 121 }) 122 } 123 124 // SaveProposerSlashings accepts a slice of slashing proof and its status and writes it to disk. 125 func (s *Store) SaveProposerSlashings(ctx context.Context, status types.SlashingStatus, slashings []*ethpb.ProposerSlashing) error { 126 ctx, span := trace.StartSpan(ctx, "slasherDB.SaveProposerSlashings") 127 defer span.End() 128 encSlashings := make([][]byte, len(slashings)) 129 keys := make([][]byte, len(slashings)) 130 var err error 131 for i, slashing := range slashings { 132 encSlashings[i], err = proto.Marshal(slashing) 133 if err != nil { 134 return errors.Wrap(err, "failed to marshal") 135 } 136 root, err := hashutil.HashProto(slashing) 137 if err != nil { 138 return err 139 } 140 keys[i] = encodeTypeRoot(types.SlashingType(types.Proposal), root) 141 } 142 143 return s.update(func(tx *bolt.Tx) error { 144 b := tx.Bucket(slashingBucket) 145 for i := 0; i < len(keys); i++ { 146 err := b.Put(keys[i], append([]byte{byte(status)}, encSlashings[i]...)) 147 if err != nil { 148 return err 149 } 150 } 151 return nil 152 }) 153 }