rest of slasher beacon changes

This commit is contained in:
rauljordan
2021-09-28 17:35:40 -04:00
parent 4e3a344948
commit 978a061635
28 changed files with 305 additions and 43 deletions

View File

@@ -26,6 +26,7 @@ go_library(
],
deps = [
"//async:go_default_library",
"//async/event:go_default_library",
"//beacon-chain/cache:go_default_library",
"//beacon-chain/cache/depositcache:go_default_library",
"//beacon-chain/core:go_default_library",

View File

@@ -16,6 +16,7 @@ import (
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/crypto/bls"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/monitoring/tracing"
ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation"
@@ -106,6 +107,32 @@ func (s *Service) onBlock(ctx context.Context, signed block.SignedBeaconBlock, b
return err
}
// If slasher is configured, forward the attestations in the block via
// an event feed for processing.
if features.Get().EnableSlasher {
// Feed the indexed attestation to slasher if enabled. This action
// is done in the background to avoid adding more load to this critical code path.
go func() {
for _, att := range signed.Block().Body().Attestations() {
committee, err := helpers.BeaconCommitteeFromState(ctx, preState, att.Data.Slot, att.Data.CommitteeIndex)
if err != nil {
log.WithError(err).Error("Could not get attestation committee")
tracing.AnnotateError(span, err)
return
}
// Using a different context to prevent timeouts as this operation can be expensive
// and we want to avoid affecting the critical code path.
indexedAtt, err := attestation.ConvertToIndexed(context.TODO(), att, committee)
if err != nil {
log.WithError(err).Error("Could not convert to indexed attestation")
tracing.AnnotateError(span, err)
return
}
s.cfg.SlasherAttestationsFeed.Send(indexedAtt)
}
}()
}
// Updating next slot state cache can happen in the background. It shouldn't block rest of the process.
if features.Get().EnableNextSlotStateCache {
go func() {

View File

@@ -11,6 +11,7 @@ import (
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/async/event"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
"github.com/prysmaticlabs/prysm/beacon-chain/core"
@@ -82,6 +83,7 @@ type Config struct {
ForkChoiceStore f.ForkChoicer
AttService *attestations.Service
StateGen *stategen.State
SlasherAttestationsFeed *event.Feed
WeakSubjectivityCheckpt *ethpb.Checkpoint
}

View File

@@ -2,11 +2,11 @@ load("@prysm//tools/go:def.bzl", "go_library")
go_library(
name = "go_default_library",
testonly = True,
srcs = ["mock.go"],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing",
visibility = [
"//beacon-chain:__subpackages__",
"//testing/endtoend:__subpackages__",
"//testing/fuzz:__pkg__",
],
deps = [

View File

@@ -10,6 +10,9 @@ import (
// a Committee struct.
var ErrNotCommittee = errors.New("object is not a committee struct")
// ErrNonCommitteeKey will be returned when the committee key does not exist in cache.
var ErrNonCommitteeKey = errors.New("committee key does not exist")
// Committees defines the shuffled committees seed.
type Committees struct {
CommitteeCount uint64

View File

@@ -72,7 +72,7 @@ func ProcessProposerSlashings(
// VerifyProposerSlashing verifies that the data provided from slashing is valid.
func VerifyProposerSlashing(
beaconState state.BeaconState,
beaconState state.ReadOnlyBeaconState,
slashing *ethpb.ProposerSlashing,
) error {
if slashing.Header_1 == nil || slashing.Header_1.Header == nil || slashing.Header_2 == nil || slashing.Header_2.Header == nil {

View File

@@ -95,6 +95,21 @@ func VerifyBlockHeaderSignature(beaconState state.BeaconState, header *ethpb.Sig
return signing.VerifyBlockHeaderSigningRoot(header.Header, proposerPubKey, header.Signature, domain)
}
// VerifyBlockHeaderSignature verifies the proposer signature of a beacon block header.
func VerifyBlockHeaderSignature(beaconState state.BeaconState, header *ethpb.SignedBeaconBlockHeader) error {
currentEpoch := core.SlotToEpoch(beaconState.Slot())
domain, err := helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot())
if err != nil {
return err
}
proposer, err := beaconState.ValidatorAtIndex(header.Header.ProposerIndex)
if err != nil {
return err
}
proposerPubKey := proposer.PublicKey
return helpers.VerifyBlockHeaderSigningRoot(header.Header, proposerPubKey, header.Signature, domain)
}
// VerifyBlockSignatureUsingCurrentFork verifies the proposer signature of a beacon block. This differs
// from the above method by not using fork data from the state and instead retrieving it
// via the respective epoch.

View File

@@ -64,7 +64,7 @@ func signingData(rootFunc func() ([32]byte, error), domain []byte) ([32]byte, er
}
// ComputeDomainVerifySigningRoot computes domain and verifies signing root of an object given the beacon state, validator index and signature.
func ComputeDomainVerifySigningRoot(st state.BeaconState, index types.ValidatorIndex, epoch types.Epoch, obj fssz.HashRoot, domain [4]byte, sig []byte) error {
func ComputeDomainVerifySigningRoot(st state.ReadOnlyBeaconState, index types.ValidatorIndex, epoch types.Epoch, obj fssz.HashRoot, domain [4]byte, sig []byte) error {
v, err := st.ValidatorAtIndex(index)
if err != nil {
return err

View File

@@ -24,7 +24,7 @@ import (
// GossipTypeMapping.
var ErrMessageNotMapped = errors.New("message type is not mapped to a PubSub topic")
// Broadcast a message to the p2p network, the message is assumed to be
// Broadcasts a message to the p2p network, the message is assumed to be
// broadcasted to the current fork.
func (s *Service) Broadcast(ctx context.Context, msg proto.Message) error {
ctx, span := trace.StartSpan(ctx, "p2p.Broadcast")

View File

@@ -1,7 +1,7 @@
package testing
import (
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/metadata"
metadata "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/metadata"
)
// MockMetadataProvider is a fake implementation of the MetadataProvider interface.

View File

@@ -30,8 +30,10 @@ go_library(
"//beacon-chain/rpc/prysm/v1alpha1/beacon:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/debug:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/node:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/slasher:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library",
"//beacon-chain/rpc/statefetcher:go_default_library",
"//beacon-chain/slasher:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/sync:go_default_library",
"//config/features:go_default_library",

View File

@@ -0,0 +1,29 @@
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"attestations.go",
"blocks.go",
"server.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/slasher",
visibility = ["//beacon-chain:__subpackages__"],
deps = [
"//beacon-chain/slasher:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"@org_golang_google_grpc//codes:go_default_library",
"@org_golang_google_grpc//status:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["server_test.go"],
embed = [":go_default_library"],
deps = [
"//beacon-chain/slasher:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"@com_github_prysmaticlabs_prysm//shared/testutil/require:go_default_library",
],
)

View File

@@ -0,0 +1,34 @@
package slasher
import (
"context"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// IsSlashableAttestation returns an attester slashing if an input
// attestation is found to be slashable.
func (s *Server) IsSlashableAttestation(
ctx context.Context, req *ethpb.IndexedAttestation,
) (*ethpb.AttesterSlashingResponse, error) {
attesterSlashings, err := s.SlashingChecker.IsSlashableAttestation(ctx, req)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not determine if attestation is slashable: %v", err)
}
if len(attesterSlashings) > 0 {
return &ethpb.AttesterSlashingResponse{
AttesterSlashings: attesterSlashings,
}, nil
}
return &ethpb.AttesterSlashingResponse{}, nil
}
// HighestAttestations returns the highest source and target epochs attested for
// validator indices that have been observed by slasher.
func (s *Server) HighestAttestations(
ctx context.Context, req *ethpb.HighestAttestationRequest,
) (*ethpb.HighestAttestationResponse, error) {
return nil, status.Error(codes.Unimplemented, "Unimplemented")
}

View File

@@ -0,0 +1,23 @@
package slasher
import (
"context"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// IsSlashableBlock returns a proposer slashing if an input
// signed beacon block header is found to be slashable.
func (s *Server) IsSlashableBlock(
ctx context.Context, req *ethpb.SignedBeaconBlockHeader,
) (*ethpb.ProposerSlashingResponse, error) {
proposerSlashing, err := s.SlashingChecker.IsSlashableBlock(ctx, req)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not determine if block is slashable: %v", err)
}
return &ethpb.ProposerSlashingResponse{
ProposerSlashings: []*ethpb.ProposerSlashing{proposerSlashing},
}, nil
}

View File

@@ -0,0 +1,12 @@
// Package slasher defines a gRPC server implementation of a slasher service
// which allows for checking if attestations or blocks are slashable.
package slasher
import (
slasherservice "github.com/prysmaticlabs/prysm/beacon-chain/slasher"
)
// Server defines a server implementation of the gRPC slasher service.
type Server struct {
SlashingChecker slasherservice.SlashingChecker
}

View File

@@ -0,0 +1,54 @@
package slasher
import (
"context"
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/slasher"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
)
func TestServer_IsSlashableAttestation_SlashingFound(t *testing.T) {
mockSlasher := &slasher.MockSlashingChecker{
AttesterSlashingFound: true,
}
s := Server{SlashingChecker: mockSlasher}
ctx := context.Background()
slashing, err := s.IsSlashableAttestation(ctx, &ethpb.IndexedAttestation{})
require.NoError(t, err)
require.Equal(t, true, len(slashing.AttesterSlashings) > 0)
}
func TestServer_IsSlashableAttestation_SlashingNotFound(t *testing.T) {
mockSlasher := &slasher.MockSlashingChecker{
AttesterSlashingFound: false,
}
s := Server{SlashingChecker: mockSlasher}
ctx := context.Background()
slashing, err := s.IsSlashableAttestation(ctx, &ethpb.IndexedAttestation{})
require.NoError(t, err)
require.Equal(t, true, len(slashing.AttesterSlashings) == 0)
}
func TestServer_IsSlashableBlock_SlashingFound(t *testing.T) {
mockSlasher := &slasher.MockSlashingChecker{
ProposerSlashingFound: true,
}
s := Server{SlashingChecker: mockSlasher}
ctx := context.Background()
slashing, err := s.IsSlashableBlock(ctx, &ethpb.SignedBeaconBlockHeader{})
require.NoError(t, err)
require.Equal(t, true, len(slashing.ProposerSlashings) > 0)
}
func TestServer_IsSlashableBlock_SlashingNotFound(t *testing.T) {
mockSlasher := &slasher.MockSlashingChecker{
ProposerSlashingFound: false,
}
s := Server{SlashingChecker: mockSlasher}
ctx := context.Background()
slashing, err := s.IsSlashableBlock(ctx, &ethpb.SignedBeaconBlockHeader{})
require.NoError(t, err)
require.Equal(t, true, len(slashing.ProposerSlashings) == 0)
}

View File

@@ -48,6 +48,11 @@ type eth1DataSingleVote struct {
blockHeight *big.Int
}
type eth1DataAggregatedVote struct {
data eth1DataSingleVote
votes int
}
// blockData required to create a beacon block.
type blockData struct {
ParentRoot []byte

View File

@@ -34,8 +34,10 @@ import (
beaconv1alpha1 "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/beacon"
debugv1alpha1 "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/debug"
nodev1alpha1 "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/node"
slasher2 "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/slasher"
validatorv1alpha1 "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/validator"
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/statefetcher"
slasherservice "github.com/prysmaticlabs/prysm/beacon-chain/slasher"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
chainSync "github.com/prysmaticlabs/prysm/beacon-chain/sync"
"github.com/prysmaticlabs/prysm/config/features"
@@ -93,6 +95,7 @@ type Config struct {
AttestationsPool attestations.Pool
ExitPool voluntaryexits.PoolManager
SlashingsPool slashings.PoolManager
SlashingChecker slasherservice.SlashingChecker
SyncCommitteeObjectPool synccommittee.Pool
SyncService chainSync.Checker
Broadcaster p2p.Broadcaster
@@ -234,6 +237,10 @@ func (s *Service) Start() {
HeadFetcher: s.cfg.HeadFetcher,
}
slasherServer := &slasher2.Server{
SlashingChecker: s.cfg.SlashingChecker,
}
beaconChainServer := &beaconv1alpha1.Server{
Ctx: s.ctx,
BeaconDB: s.cfg.BeaconDB,
@@ -280,6 +287,7 @@ func (s *Service) Start() {
ethpbv1alpha1.RegisterNodeServer(s.grpcServer, nodeServer)
ethpbservice.RegisterBeaconNodeServer(s.grpcServer, nodeServerV1)
ethpbv1alpha1.RegisterHealthServer(s.grpcServer, nodeServer)
ethpbv1alpha1.RegisterSlasherServer(s.grpcServer, slasherServer)
ethpbv1alpha1.RegisterBeaconChainServer(s.grpcServer, beaconChainServer)
ethpbservice.RegisterBeaconChainServer(s.grpcServer, beaconChainServerV1)
ethpbservice.RegisterEventsServer(s.grpcServer, &events.Server{

View File

@@ -18,6 +18,7 @@ go_library(
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen",
visibility = [
"//beacon-chain:__subpackages__",
"//testing/endtoend:__subpackages__",
"//testing/fuzz:__pkg__",
],
deps = [

View File

@@ -8,7 +8,7 @@ import (
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core"
"github.com/prysmaticlabs/prysm/beacon-chain/core/altair"
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
transition "github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"

View File

@@ -52,6 +52,7 @@ go_library(
deps = [
"//async:go_default_library",
"//async/abool:go_default_library",
"//async/event:go_default_library",
"//beacon-chain/blockchain:go_default_library",
"//beacon-chain/cache:go_default_library",
"//beacon-chain/core:go_default_library",
@@ -89,6 +90,7 @@ go_library(
"//monitoring/tracing:go_default_library",
"//network/forks:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/attestation:go_default_library",
"//proto/prysm/v1alpha1/block:go_default_library",
"//proto/prysm/v1alpha1/metadata:go_default_library",
"//proto/prysm/v1alpha1/wrapper:go_default_library",

View File

@@ -6,9 +6,6 @@ package sync
import (
"context"
"sync"
"time"
lru "github.com/hashicorp/golang-lru"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-core/protocol"
@@ -17,6 +14,7 @@ import (
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/async"
"github.com/prysmaticlabs/prysm/async/abool"
"github.com/prysmaticlabs/prysm/async/event"
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
"github.com/prysmaticlabs/prysm/beacon-chain/core"
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
@@ -37,6 +35,8 @@ import (
"github.com/prysmaticlabs/prysm/runtime"
prysmTime "github.com/prysmaticlabs/prysm/time"
"github.com/prysmaticlabs/prysm/time/slots"
"sync"
"time"
)
var _ runtime.Service = (*Service)(nil)
@@ -68,18 +68,21 @@ type validationFn func(ctx context.Context) (pubsub.ValidationResult, error)
// Config to set up the regular sync service.
type Config struct {
P2P p2p.P2P
DB db.NoHeadAccessDatabase
AttPool attestations.Pool
ExitPool voluntaryexits.PoolManager
SlashingPool slashings.PoolManager
SyncCommsPool synccommittee.Pool
Chain blockchainService
InitialSync Checker
StateNotifier statefeed.Notifier
BlockNotifier blockfeed.Notifier
OperationNotifier operation.Notifier
StateGen *stategen.State
AttestationNotifier operation.Notifier
P2P p2p.P2P
DB db.NoHeadAccessDatabase
AttPool attestations.Pool
ExitPool voluntaryexits.PoolManager
SlashingPool slashings.PoolManager
SyncCommsPool synccommittee.Pool
Chain blockchainService
InitialSync Checker
StateNotifier statefeed.Notifier
BlockNotifier blockfeed.Notifier
OperationNotifier operation.Notifier
StateGen *stategen.State
SlasherAttestationsFeed *event.Feed
SlasherBlockHeadersFeed *event.Feed
}
// This defines the interface for interacting with block chain service

View File

@@ -17,8 +17,8 @@ import (
func TestBeaconAggregateProofSubscriber_CanSaveAggregatedAttestation(t *testing.T) {
r := &Service{
cfg: &Config{
AttPool: attestations.NewPool(),
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
AttPool: attestations.NewPool(),
AttestationNotifier: (&mock.ChainService{}).OperationNotifier(),
},
seenUnAggregatedAttestationCache: lruwrpr.New(10),
}
@@ -39,8 +39,8 @@ func TestBeaconAggregateProofSubscriber_CanSaveAggregatedAttestation(t *testing.
func TestBeaconAggregateProofSubscriber_CanSaveUnaggregatedAttestation(t *testing.T) {
r := &Service{
cfg: &Config{
AttPool: attestations.NewPool(),
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
AttPool: attestations.NewPool(),
AttestationNotifier: (&mock.ChainService{}).OperationNotifier(),
},
seenUnAggregatedAttestationCache: lruwrpr.New(10),
}

View File

@@ -59,7 +59,7 @@ func (s *Service) validateAggregateAndProof(ctx context.Context, pid peer.ID, ms
// Broadcast the aggregated attestation on a feed to notify other services in the beacon node
// of a received aggregated attestation.
s.cfg.OperationNotifier.OperationFeed().Send(&feed.Event{
s.cfg.AttestationNotifier.OperationFeed().Send(&feed.Event{
Type: operation.AggregatedAttReceived,
Data: &operation.AggregatedAttReceivedData{
Attestation: m.Message,

View File

@@ -189,8 +189,8 @@ func TestValidateAggregateAndProof_NotWithinSlotRange(t *testing.T) {
Genesis: time.Now(),
State: beaconState,
},
AttPool: attestations.NewPool(),
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
AttPool: attestations.NewPool(),
AttestationNotifier: (&mock.ChainService{}).OperationNotifier(),
},
seenAggregatedAttestationCache: lruwrpr.New(10),
}
@@ -271,7 +271,7 @@ func TestValidateAggregateAndProof_ExistedInPool(t *testing.T) {
InitialSync: &mockSync.Sync{IsSyncing: false},
Chain: &mock.ChainService{Genesis: time.Now(),
State: beaconState},
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
AttestationNotifier: (&mock.ChainService{}).OperationNotifier(),
},
seenAggregatedAttestationCache: lruwrpr.New(10),
blkRootToPendingAtts: make(map[[32]byte][]*ethpb.SignedAggregateAttestationAndProof),
@@ -364,8 +364,8 @@ func TestValidateAggregateAndProof_CanValidate(t *testing.T) {
Epoch: 0,
Root: att.Data.BeaconBlockRoot,
}},
AttPool: attestations.NewPool(),
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
AttPool: attestations.NewPool(),
AttestationNotifier: (&mock.ChainService{}).OperationNotifier(),
},
seenAggregatedAttestationCache: lruwrpr.New(10),
}
@@ -459,8 +459,8 @@ func TestVerifyIndexInCommittee_SeenAggregatorEpoch(t *testing.T) {
Root: signedAggregateAndProof.Message.Aggregate.Data.BeaconBlockRoot,
}},
AttPool: attestations.NewPool(),
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
AttPool: attestations.NewPool(),
AttestationNotifier: (&mock.ChainService{}).OperationNotifier(),
},
seenAggregatedAttestationCache: lruwrpr.New(10),
}
@@ -570,8 +570,8 @@ func TestValidateAggregateAndProof_BadBlock(t *testing.T) {
FinalizedCheckPoint: &ethpb.Checkpoint{
Epoch: 0,
}},
AttPool: attestations.NewPool(),
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
AttPool: attestations.NewPool(),
AttestationNotifier: (&mock.ChainService{}).OperationNotifier(),
},
seenAggregatedAttestationCache: lruwrpr.New(10),
}
@@ -661,8 +661,8 @@ func TestValidateAggregateAndProof_RejectWhenAttEpochDoesntEqualTargetEpoch(t *t
Epoch: 0,
Root: att.Data.BeaconBlockRoot,
}},
AttPool: attestations.NewPool(),
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
AttPool: attestations.NewPool(),
AttestationNotifier: (&mock.ChainService{}).OperationNotifier(),
},
seenAggregatedAttestationCache: lruwrpr.New(10),
}

View File

@@ -21,6 +21,7 @@ import (
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/monitoring/tracing"
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation"
"go.opencensus.io/trace"
)
@@ -63,7 +64,7 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p
// Broadcast the unaggregated attestation on a feed to notify other services in the beacon node
// of a received unaggregated attestation.
s.cfg.OperationNotifier.OperationFeed().Send(&feed.Event{
s.cfg.AttestationNotifier.OperationFeed().Send(&feed.Event{
Type: operation.UnaggregatedAttReceived,
Data: &operation.UnAggregatedAttReceivedData{
Attestation: att,
@@ -81,6 +82,32 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p
return pubsub.ValidationReject, err
}
if features.Get().EnableSlasher {
// Feed the indexed attestation to slasher if enabled. This action
// is done in the background to avoid adding more load to this critical code path.
go func() {
preState, err := s.cfg.Chain.AttestationTargetState(ctx, att.Data.Target)
if err != nil {
log.WithError(err).Error("Could not retrieve pre state")
tracing.AnnotateError(span, err)
return
}
committee, err := helpers.BeaconCommitteeFromState(ctx, preState, att.Data.Slot, att.Data.CommitteeIndex)
if err != nil {
log.WithError(err).Error("Could not get attestation committee")
tracing.AnnotateError(span, err)
return
}
indexedAtt, err := attestation.ConvertToIndexed(ctx, att, committee)
if err != nil {
log.WithError(err).Error("Could not convert to indexed attestation")
traceutil.AnnotateError(span, err)
return
}
s.cfg.SlasherAttestationsFeed.Send(indexedAtt)
}()
}
// Verify this the first attestation received for the participating validator for the slot.
if s.hasSeenCommitteeIndicesSlot(att.Data.Slot, att.Data.CommitteeIndex, att.AggregationBits) {
return pubsub.ValidationIgnore, nil

View File

@@ -38,11 +38,11 @@ func TestService_validateCommitteeIndexBeaconAttestation(t *testing.T) {
s := &Service{
cfg: &Config{
InitialSync: &mockSync.Sync{IsSyncing: false},
P2P: p,
DB: db,
Chain: chain,
OperationNotifier: (&mockChain.ChainService{}).OperationNotifier(),
InitialSync: &mockSync.Sync{IsSyncing: false},
P2P: p,
DB: db,
Chain: chain,
AttestationNotifier: (&mockChain.ChainService{}).OperationNotifier(),
},
blkRootToPendingAtts: make(map[[32]byte][]*ethpb.SignedAggregateAttestationAndProof),
seenUnAggregatedAttestationCache: lruwrpr.New(10),

View File

@@ -15,6 +15,7 @@ import (
blockfeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/block"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
"github.com/prysmaticlabs/prysm/config/features"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/monitoring/tracing"
@@ -70,6 +71,18 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms
},
})
if features.Get().EnableSlasher {
// Feed the block header to slasher if enabled. This action
// is done in the background to avoid adding more load to this critical code path.
go func() {
blockHeader, err := block.SignedBeaconBlockHeaderFromBlockInterface(blk)
if err != nil {
log.WithError(err).WithField("blockSlot", blk.Block().Slot()).Warn("Could not extract block header")
}
s.cfg.SlasherBlockHeadersFeed.Send(blockHeader)
}()
}
// Verify the block is the first block received for the proposer for the slot.
if s.hasSeenBlockIndexSlot(blk.Block().Slot(), blk.Block().ProposerIndex()) {
return pubsub.ValidationIgnore, nil
@@ -149,6 +162,7 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms
if err := s.validateBeaconBlock(ctx, blk, blockRoot); err != nil {
return pubsub.ValidationReject, err
}
// Record attribute of valid block.
span.AddAttributes(trace.Int64Attribute("slotInEpoch", int64(blk.Block().Slot()%params.BeaconConfig().SlotsPerEpoch)))
msg.ValidatorData = blk.Proto() // Used in downstream subscriber