From f40a7575debd266450dadb234c1df0f38f9234a1 Mon Sep 17 00:00:00 2001 From: Shay Zluf Date: Wed, 10 Jun 2020 20:24:05 +0300 Subject: [PATCH] Send blocks that fail p2p validation to slasher (#6164) * send blocks that fails validation to block feed for slasher. in order to enable slashing proposers * add sig validation * fix imports * Update shared/featureconfig/config.go Co-authored-by: Ivan Martinez * Update shared/featureconfig/config.go Co-authored-by: Ivan Martinez * Update shared/featureconfig/flags.go Co-authored-by: Ivan Martinez * remove extra validation path for slasher * ivan feedback * notify all blocks that pass minimal validation to block stream * notify all blocks that pass minimal validation to block stream * add to e2e flags Co-authored-by: Ivan Martinez Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> --- beacon-chain/sync/subscriber_beacon_blocks.go | 20 +++++++------ beacon-chain/sync/validate_beacon_blocks.go | 30 +++++++++++++++++-- shared/featureconfig/config.go | 6 ++++ shared/featureconfig/flags.go | 8 +++++ 4 files changed, 53 insertions(+), 11 deletions(-) diff --git a/beacon-chain/sync/subscriber_beacon_blocks.go b/beacon-chain/sync/subscriber_beacon_blocks.go index cf347898b..c2b8a9fb8 100644 --- a/beacon-chain/sync/subscriber_beacon_blocks.go +++ b/beacon-chain/sync/subscriber_beacon_blocks.go @@ -11,6 +11,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/core/state/interop" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/shared/featureconfig" ) func (r *Service) beaconBlockSubscriber(ctx context.Context, msg proto.Message) error { @@ -31,15 +32,16 @@ func (r *Service) beaconBlockSubscriber(ctx context.Context, msg proto.Message) if err != nil { return err } - - // Broadcast the block on a feed to notify other services in the beacon node - // of a received block (even if it does not process correctly through a state transition). - r.blockNotifier.BlockFeed().Send(&feed.Event{ - Type: blockfeed.ReceivedBlock, - Data: &blockfeed.ReceivedBlockData{ - SignedBlock: signed, - }, - }) + if !featureconfig.Get().SlasherP2P { + // Broadcast the block on a feed to notify other services in the beacon node + // of a received block (even if it does not process correctly through a state transition). + r.blockNotifier.BlockFeed().Send(&feed.Event{ + Type: blockfeed.ReceivedBlock, + Data: &blockfeed.ReceivedBlockData{ + SignedBlock: signed, + }, + }) + } if err := r.chain.ReceiveBlockNoPubsub(ctx, signed, root); err != nil { interop.WriteBlockToDisk(signed, true /*failed*/) diff --git a/beacon-chain/sync/validate_beacon_blocks.go b/beacon-chain/sync/validate_beacon_blocks.go index 0aad7bdd6..edaef8beb 100644 --- a/beacon-chain/sync/validate_beacon_blocks.go +++ b/beacon-chain/sync/validate_beacon_blocks.go @@ -8,6 +8,8 @@ import ( pubsub "github.com/libp2p/go-libp2p-pubsub" ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1" "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" + "github.com/prysmaticlabs/prysm/beacon-chain/core/feed" + blockfeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/block" "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/shared/bytesutil" @@ -54,10 +56,13 @@ func (r *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms if blk.Block == nil { return pubsub.ValidationReject } - + hasSeen := false // Verify the block is the first block received for the proposer for the slot. if r.hasSeenBlockIndexSlot(blk.Block.Slot, blk.Block.ProposerIndex) { - return pubsub.ValidationIgnore + if !featureconfig.Get().SlasherP2P { + return pubsub.ValidationIgnore + } + hasSeen = true } blockRoot, err := stateutil.BlockRoot(blk.Block) @@ -75,6 +80,27 @@ func (r *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms } r.pendingQueueLock.RUnlock() + // Send block to block stream for slasher detection after minimal validation. + if featureconfig.Get().SlasherP2P { + state, err := r.chain.HeadState(ctx) + if err != nil { + return pubsub.ValidationIgnore + } + if err := blocks.VerifyBlockSignature(state, blk); err != nil { + log.WithError(err).WithField("blockSlot", blk.Block.Slot).Warn("Could not verify block signature") + return pubsub.ValidationReject + } + r.blockNotifier.BlockFeed().Send(&feed.Event{ + Type: blockfeed.ReceivedBlock, + Data: &blockfeed.ReceivedBlockData{ + SignedBlock: blk, + }, + }) + } + if hasSeen { + return pubsub.ValidationReject + } + // Add metrics for block arrival time subtracts slot start time. if captureArrivalTimeMetric(uint64(r.chain.GenesisTime().Unix()), blk.Block.Slot) != nil { return pubsub.ValidationIgnore diff --git a/shared/featureconfig/config.go b/shared/featureconfig/config.go index 9dbb0a948..28b6774e2 100644 --- a/shared/featureconfig/config.go +++ b/shared/featureconfig/config.go @@ -45,6 +45,7 @@ type Flags struct { ProtectProposer bool // ProtectProposer prevents the validator client from signing any proposals that would be considered a slashable offense. ProtectAttester bool // ProtectAttester prevents the validator client from signing any attestations that would be considered a slashable offense. SlasherProtection bool // SlasherProtection protects validator fron sending over a slashable offense over the network using external slasher. + SlasherP2P bool // SlasherP2P use less restrictive p2p validation for beacon nodes that have a connected slasher. DisableStrictAttestationPubsubVerification bool // DisableStrictAttestationPubsubVerification will disabling strict signature verification in pubsub. DisableUpdateHeadPerAttestation bool // DisableUpdateHeadPerAttestation will disabling update head on per attestation basis. EnableDomainDataCache bool // EnableDomainDataCache caches validator calls to DomainData per epoch. @@ -223,6 +224,11 @@ func ConfigureBeaconChain(ctx *cli.Context) { log.Warn("Enabling libp2p's kademlia discovery") cfg.EnableKadDHT = true } + if ctx.Bool(slasherP2P.Name) { + log.Warn("Enabled slasher-friendly P2P validation. Please do not use this flag if you are not running a slasher " + + "that connects to this beacon node!") + cfg.SlasherP2P = true + } if ctx.IsSet(deprecatedP2PWhitelist.Name) { log.Warnf("--%s is deprecated, please use --%s", deprecatedP2PWhitelist.Name, cmd.P2PAllowList.Name) if err := ctx.Set(cmd.P2PAllowList.Name, ctx.String(deprecatedP2PWhitelist.Name)); err != nil { diff --git a/shared/featureconfig/flags.go b/shared/featureconfig/flags.go index 053deba9e..25869cac3 100644 --- a/shared/featureconfig/flags.go +++ b/shared/featureconfig/flags.go @@ -165,6 +165,12 @@ var ( Name: "disable-init-sync-wrr", Usage: "Disables weighted round robin fetching optimization", } + // SlasherRPCProviderFlag defines a slasher node RPC endpoint. + slasherP2P = &cli.BoolFlag{ + Name: "slasher-p2p", + Usage: "Use this flag to reduce block p2p validation in order for the slasher to receive any blocks" + + "the beacon node receives. Please only use if there is a slasher connected to this beacon node", + } ) // devModeFlags holds list of flags that are set when development mode is on. @@ -531,6 +537,7 @@ var BeaconChainFlags = append(deprecatedFlags, []cli.Flag{ disableNewStateMgmt, enableKadDht, disableReduceAttesterStateCopy, + slasherP2P, }...) // E2EBeaconChainFlags contains a list of the beacon chain feature flags to be tested in E2E. @@ -538,4 +545,5 @@ var E2EBeaconChainFlags = []string{ "--cache-filtered-block-tree", "--enable-state-gen-sig-verify", "--check-head-state", + "--slasher-p2p", }