github.com/prysmaticlabs/prysm@v1.4.4/slasher/detection/proposals/detector.go (about)

     1  // Package proposals defines an implementation of a double-propose
     2  // detector in the slasher runtime.
     3  package proposals
     4  
     5  import (
     6  	"bytes"
     7  	"context"
     8  
     9  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    10  	"github.com/prysmaticlabs/prysm/slasher/db"
    11  	status "github.com/prysmaticlabs/prysm/slasher/db/types"
    12  	"go.opencensus.io/trace"
    13  )
    14  
    15  // ProposeDetector defines a struct which can detect slashable
    16  // block proposals.
    17  type ProposeDetector struct {
    18  	slasherDB db.Database
    19  }
    20  
    21  // NewProposeDetector creates a new instance of a struct.
    22  func NewProposeDetector(db db.Database) *ProposeDetector {
    23  	return &ProposeDetector{
    24  		slasherDB: db,
    25  	}
    26  }
    27  
    28  // DetectDoublePropose detects double proposals given a block by looking in the db.
    29  func (d *ProposeDetector) DetectDoublePropose(
    30  	ctx context.Context,
    31  	incomingBlk *ethpb.SignedBeaconBlockHeader,
    32  ) (*ethpb.ProposerSlashing, error) {
    33  	ctx, span := trace.StartSpan(ctx, "detector.DetectDoublePropose")
    34  	defer span.End()
    35  	headersFromIdx, err := d.slasherDB.BlockHeaders(ctx, incomingBlk.Header.Slot, incomingBlk.Header.ProposerIndex)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	for _, blockHeader := range headersFromIdx {
    40  		if bytes.Equal(blockHeader.Signature, incomingBlk.Signature) {
    41  			continue
    42  		}
    43  		ps := &ethpb.ProposerSlashing{Header_1: incomingBlk, Header_2: blockHeader}
    44  		if err := d.slasherDB.SaveProposerSlashing(ctx, status.Active, ps); err != nil {
    45  			return nil, err
    46  		}
    47  		return ps, nil
    48  	}
    49  	if err := d.slasherDB.SaveBlockHeader(ctx, incomingBlk); err != nil {
    50  		return nil, err
    51  	}
    52  	return nil, nil
    53  }
    54  
    55  // DetectDoubleProposeNoUpdate detects double proposals for a given block header by db search
    56  // without storing the incoming block to db.
    57  func (d *ProposeDetector) DetectDoubleProposeNoUpdate(
    58  	ctx context.Context,
    59  	incomingBlk *ethpb.BeaconBlockHeader,
    60  ) (bool, error) {
    61  	ctx, span := trace.StartSpan(ctx, "detector.DetectDoubleProposeNoUpdate")
    62  	defer span.End()
    63  	headersFromIdx, err := d.slasherDB.BlockHeaders(ctx, incomingBlk.Slot, incomingBlk.ProposerIndex)
    64  	if err != nil {
    65  		return false, err
    66  	}
    67  	for _, blockHeader := range headersFromIdx {
    68  		sameBodyRoot := bytes.Equal(blockHeader.Header.BodyRoot, incomingBlk.BodyRoot)
    69  		sameStateRoot := bytes.Equal(blockHeader.Header.StateRoot, incomingBlk.StateRoot)
    70  		sameParentRoot := bytes.Equal(blockHeader.Header.ParentRoot, incomingBlk.ParentRoot)
    71  		if sameBodyRoot && sameStateRoot && sameParentRoot {
    72  			continue
    73  		}
    74  		return true, nil
    75  	}
    76  	return false, nil
    77  }