Files
prysm/beacon-chain/slasher/detect_blocks.go
Bastin 92bd211e4d upgrade v6 to v7 (#15989)
* upgrade v6 to v7

* changelog

* update-go-ssz
2025-11-06 16:16:23 +00:00

82 lines
3.1 KiB
Go

package slasher
import (
"context"
slashertypes "github.com/OffchainLabs/prysm/v7/beacon-chain/slasher/types"
"github.com/OffchainLabs/prysm/v7/monitoring/tracing/trace"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
"github.com/pkg/errors"
)
// 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
}