Slasher Simulator

Background

Over the course of this quarter, we have redesigned our slasher to perform efficient slashing detection of blocks, double votes, and surround votes. Instead of having the slasher as a separate process from the beacon node, we now make it a service of the beacon node which can be toggled with a feature flag.

This new slasher has a really simple entrypoint: all it needs is a beaconDB and a feed of indexed attestations and beacon block headers. Anyone can send these items over their corresponding feed and slasher will be able to perform its job accordingly. That is:

package slasher

import (
	"time"

	"github.com/prysmaticlabs/prysm/beacon-chain/db"
	"github.com/prysmaticlabs/prysm/shared/event"
)

type SlasherConfig struct {
	IndexedAttsFeed        *event.Feed
	BeaconBlockHeadersFeed *event.Feed
	Database               db.Database
	GenesisTime            time.Time
}

func New(cfg *SlasherConfig) *Slasher {
    ...
}

Given this simple API, we can design a simulator which generates indexed attestations and beacon block headers of different kinds to profile and ensure that slasher works as expected. This document defines the requirements for such a simulator.

Goal

Our goal is to create a standalone binary which runs a slasher simulator and can allow us to profile the behavior of slasher as it would perform in a real node, helping us analyze disk i/o, CPU, and RAM usage in isolation. Additionally, we can also use a simulator to ensure that slasher can indeed detect slashable events. Eventually, we want the code for this simulator to make it into our end to end tests as a component.

Data Requirements

Double Block Proposals

In order to simulate block proposals, the only pieces of information slasher needs are:

  • The block signing root
  • The block slot
  • The block proposer index

When performing double block checking, we simply check the DB if we have an existing proposal for a slot:proposer_index combination, and check if the signing roots are mismatched.

As such, the simulator need not be concerned about the details of blocks. If we can simply simulate the 3 pieces of information, that's enough for the slasher to detect.

Double Votes and Surround Votes

The only pieces of information slasher needs for attester slashing checks are:

  • The att signing root
  • The att attesting indices
  • The att target epoch
  • The att source epoch

Every other part of an attestation is unnecessary. To detect double votes, the slasher algorithm when receiving a package containing the 4 fields above, simply:

  1. Loops over the attesting indices, for each:
    2. Check if we have an attestation at the target_epoch:validator_index combination
    3. If we do, we check if the signing roots are different, then return a slashable event. Otherwise, continue

As such, the generator need not be concerned with other fields of attestations, such as roots, slot, etc.

Surround votes are more complicated, but once again, slasher only needs the 4 fields above from an attestation in order to perform its duty.

Functional Requirements

  • We want the ability to configure:

    • Genesis time
    • Num validators
    • Probabilities of creating double votes, surround votes, and double proposals
    • Percent aggregated attestations per slot (100% means we pack as many attesting indices as possible into a single slot, 0% means there is a single attestation per validator index throughout an epoch)
  • We want the ability to profile this with pprof. The simulator branch already has this ability