prysm-pulse/beacon-chain/slasher/detect_blocks.go
terence 5a66807989
Update to V5 (#13622)
* First take at updating everything to v5

* Patch gRPC gateway to use prysm v5

Fix patch

* Update go ssz

---------

Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com>
2024-02-15 05:46:47 +00:00

82 lines
3.1 KiB
Go

package slasher
import (
"context"
"github.com/pkg/errors"
slashertypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/slasher/types"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"go.opencensus.io/trace"
)
// detectProposerSlashings takes in signed block header wrappers and returns a list of proposer slashings detected.
func (s *Service) detectProposerSlashings(
ctx context.Context,
incomingProposals []*slashertypes.SignedBlockHeaderWrapper,
) ([]*ethpb.ProposerSlashing, error) {
ctx, span := trace.StartSpan(ctx, "slasher.detectProposerSlashings")
defer span.End()
// internalSlashings will contain any slashable double proposals in the input list
// of proposals with respect to each other.
internalSlashings := []*ethpb.ProposerSlashing{}
existingProposals := make(map[string]*slashertypes.SignedBlockHeaderWrapper)
// We check if there are any slashable double proposals in the input list
// of proposals with respect to each other.
for _, incomingProposal := range incomingProposals {
key := proposalKey(incomingProposal)
existingProposal, ok := existingProposals[key]
// If we have not seen this proposal before, we add it to our map of existing proposals
// and we continue to the next proposal.
if !ok {
existingProposals[key] = incomingProposal
continue
}
// If we have seen this proposal before, we check if it is a double proposal.
if isDoubleProposal(incomingProposal.HeaderRoot, existingProposal.HeaderRoot) {
doubleProposalsTotal.Inc()
slashing := &ethpb.ProposerSlashing{
Header_1: existingProposal.SignedBeaconBlockHeader,
Header_2: incomingProposal.SignedBeaconBlockHeader,
}
internalSlashings = append(internalSlashings, slashing)
}
}
// We check if there are any slashable double proposals in the input list
// of proposals with respect to the slasher database.
databaseSlashings, err := s.serviceCfg.Database.CheckDoubleBlockProposals(ctx, incomingProposals)
if err != nil {
return nil, errors.Wrap(err, "could not check for double proposals on disk")
}
// We save the safe proposals (with respect to the database) to our database.
// If some proposals in incomingProposals are slashable with respect to each other,
// we (arbitrarily) save the last one to the database.
if err := s.serviceCfg.Database.SaveBlockProposals(ctx, incomingProposals); err != nil {
return nil, errors.Wrap(err, "could not save safe proposals")
}
// totalSlashings contain all slashings we have detected.
totalSlashings := append(internalSlashings, databaseSlashings...)
return totalSlashings, nil
}
// proposalKey build a key which is a combination of the slot and the proposer index.
// If a validator proposes several blocks for the same slot, then several (potentially slashable)
// proposals will correspond to the same key.
func proposalKey(proposal *slashertypes.SignedBlockHeaderWrapper) string {
header := proposal.SignedBeaconBlockHeader.Header
slotKey := uintToString(uint64(header.Slot))
proposerIndexKey := uintToString(uint64(header.ProposerIndex))
return slotKey + ":" + proposerIndexKey
}