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 := &ethpb.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  }