mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-03 16:37:39 +00:00
06a5548424
* `Test_processAttestations`: Remove duplicated tests. * Sort indexed attestations by data root. * `processAttestations`: Don't return duplicate slashings anymore. Fix https://github.com/prysmaticlabs/prysm/issues/13592. * `AttesterDoubleVote`: Rename fields. * Detect double votes in different batches. In order to do that: 1. Each attestation of the batch is tested against the other attestations of the batch. 2. Each attestation of the batch is tested against the content of the database. 2. Attestations are saved into the database. Fixes https://github.com/prysmaticlabs/prysm/issues/13590.
120 lines
3.9 KiB
Go
120 lines
3.9 KiB
Go
package slasher
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/blocks"
|
|
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
|
"github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
|
|
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
|
)
|
|
|
|
// Verifies attester slashings, logs them, and submits them to the slashing operations pool
|
|
// in the beacon node if they pass validation.
|
|
func (s *Service) processAttesterSlashings(
|
|
ctx context.Context, slashings map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing,
|
|
) (map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing, error) {
|
|
processedSlashings := map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing{}
|
|
|
|
// If no slashings, return early.
|
|
if len(slashings) == 0 {
|
|
return processedSlashings, nil
|
|
}
|
|
|
|
// Get the head state.
|
|
beaconState, err := s.serviceCfg.HeadStateFetcher.HeadState(ctx)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not get head state")
|
|
}
|
|
|
|
for root, slashing := range slashings {
|
|
// Verify the signature of the first attestation.
|
|
if err := s.verifyAttSignature(ctx, slashing.Attestation_1); err != nil {
|
|
log.WithError(err).WithField("a", slashing.Attestation_1).Warn(
|
|
"Invalid signature for attestation in detected slashing offense",
|
|
)
|
|
|
|
continue
|
|
}
|
|
|
|
// Verify the signature of the second attestation.
|
|
if err := s.verifyAttSignature(ctx, slashing.Attestation_2); err != nil {
|
|
log.WithError(err).WithField("b", slashing.Attestation_2).Warn(
|
|
"Invalid signature for attestation in detected slashing offense",
|
|
)
|
|
|
|
continue
|
|
}
|
|
|
|
// Log the slashing event and insert into the beacon node's operations pool.
|
|
logAttesterSlashing(slashing)
|
|
if err := s.serviceCfg.SlashingPoolInserter.InsertAttesterSlashing(ctx, beaconState, slashing); err != nil {
|
|
log.WithError(err).Error("Could not insert attester slashing into operations pool")
|
|
}
|
|
|
|
processedSlashings[root] = slashing
|
|
}
|
|
|
|
return processedSlashings, nil
|
|
}
|
|
|
|
// Verifies proposer slashings, logs them, and submits them to the slashing operations pool
|
|
// in the beacon node if they pass validation.
|
|
func (s *Service) processProposerSlashings(ctx context.Context, slashings []*ethpb.ProposerSlashing) error {
|
|
// If no slashings, return early.
|
|
if len(slashings) == 0 {
|
|
return nil
|
|
}
|
|
|
|
// Get the head state.
|
|
beaconState, err := s.serviceCfg.HeadStateFetcher.HeadState(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, slashing := range slashings {
|
|
// Verify the signature of the first block.
|
|
if err := s.verifyBlockSignature(ctx, slashing.Header_1); err != nil {
|
|
log.WithError(err).WithField("a", slashing.Header_1).Warn(
|
|
"Invalid signature for block header in detected slashing offense",
|
|
)
|
|
|
|
continue
|
|
}
|
|
|
|
// Verify the signature of the second block.
|
|
if err := s.verifyBlockSignature(ctx, slashing.Header_2); err != nil {
|
|
log.WithError(err).WithField("b", slashing.Header_2).Warn(
|
|
"Invalid signature for block header in detected slashing offense",
|
|
)
|
|
|
|
continue
|
|
}
|
|
|
|
// Log the slashing event and insert into the beacon node's operations pool.
|
|
logProposerSlashing(slashing)
|
|
if err := s.serviceCfg.SlashingPoolInserter.InsertProposerSlashing(ctx, beaconState, slashing); err != nil {
|
|
log.WithError(err).Error("Could not insert proposer slashing into operations pool")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) verifyBlockSignature(ctx context.Context, header *ethpb.SignedBeaconBlockHeader) error {
|
|
parentState, err := s.serviceCfg.StateGen.StateByRoot(ctx, bytesutil.ToBytes32(header.Header.ParentRoot))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return blocks.VerifyBlockHeaderSignature(parentState, header)
|
|
}
|
|
|
|
func (s *Service) verifyAttSignature(ctx context.Context, att *ethpb.IndexedAttestation) error {
|
|
preState, err := s.serviceCfg.AttestationStateFetcher.AttestationTargetState(ctx, att.Data.Target)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return blocks.VerifyIndexedAttestation(ctx, preState, att)
|
|
}
|