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 := ðpb.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 }