github.com/prysmaticlabs/prysm@v1.4.4/shared/featureconfig/config.go (about)

     1  /*
     2  Package featureconfig defines which features are enabled for runtime
     3  in order to selectively enable certain features to maintain a stable runtime.
     4  
     5  The process for implementing new features using this package is as follows:
     6  	1. Add a new CMD flag in flags.go, and place it in the proper list(s) var for its client.
     7  	2. Add a condition for the flag in the proper Configure function(s) below.
     8  	3. Place any "new" behavior in the `if flagEnabled` statement.
     9  	4. Place any "previous" behavior in the `else` statement.
    10  	5. Ensure any tests using the new feature fail if the flag isn't enabled.
    11  	5a. Use the following to enable your flag for tests:
    12  	cfg := &featureconfig.Flags{
    13  		VerifyAttestationSigs: true,
    14  	}
    15  	resetCfg := featureconfig.InitWithReset(cfg)
    16  	defer resetCfg()
    17  	6. Add the string for the flags that should be running within E2E to E2EValidatorFlags
    18  	and E2EBeaconChainFlags.
    19  */
    20  package featureconfig
    21  
    22  import (
    23  	"sync"
    24  	"time"
    25  
    26  	"github.com/prysmaticlabs/prysm/shared/params"
    27  	"github.com/sirupsen/logrus"
    28  	"github.com/urfave/cli/v2"
    29  )
    30  
    31  var log = logrus.WithField("prefix", "flags")
    32  
    33  const enabledFeatureFlag = "Enabled feature flag"
    34  
    35  // Flags is a struct to represent which features the client will perform on runtime.
    36  type Flags struct {
    37  	// Testnet Flags.
    38  	ToledoTestnet  bool // ToledoTestnet defines the flag through which we can enable the node to run on the Toledo testnet.
    39  	PyrmontTestnet bool // PyrmontTestnet defines the flag through which we can enable the node to run on the Pyrmont testnet.
    40  
    41  	// Feature related flags.
    42  	WriteSSZStateTransitions           bool // WriteSSZStateTransitions to tmp directory.
    43  	SkipBLSVerify                      bool // Skips BLS verification across the runtime.
    44  	SlasherProtection                  bool // SlasherProtection protects validator fron sending over a slashable offense over the network using external slasher.
    45  	EnablePeerScorer                   bool // EnablePeerScorer enables experimental peer scoring in p2p.
    46  	EnableLargerGossipHistory          bool // EnableLargerGossipHistory increases the gossip history we store in our caches.
    47  	WriteWalletPasswordOnWebOnboarding bool // WriteWalletPasswordOnWebOnboarding writes the password to disk after Prysm web signup.
    48  	DisableAttestingHistoryDBCache     bool // DisableAttestingHistoryDBCache for the validator client increases disk reads/writes.
    49  	UpdateHeadTimely                   bool // UpdateHeadTimely updates head right after state transition.
    50  	ProposerAttsSelectionUsingMaxCover bool // ProposerAttsSelectionUsingMaxCover enables max-cover algorithm when selecting attestations for proposing.
    51  	EnableOptimizedBalanceUpdate       bool // EnableOptimizedBalanceUpdate uses an updated method of performing balance updates.
    52  	EnableDoppelGanger                 bool // EnableDoppelGanger enables doppelganger protection on startup for the validator.
    53  	// Logging related toggles.
    54  	DisableGRPCConnectionLogs bool // Disables logging when a new grpc client has connected.
    55  
    56  	// Slasher toggles.
    57  	DisableLookback           bool // DisableLookback updates slasher to not use the lookback and update validator histories until epoch 0.
    58  	DisableBroadcastSlashings bool // DisableBroadcastSlashings disables p2p broadcasting of proposer and attester slashings.
    59  
    60  	// Cache toggles.
    61  	EnableSSZCache           bool // EnableSSZCache see https://github.com/prysmaticlabs/prysm/pull/4558.
    62  	EnableNextSlotStateCache bool // EnableNextSlotStateCache enables next slot state cache to improve validator performance.
    63  
    64  	// Bug fixes related flags.
    65  	AttestTimely bool // AttestTimely fixes #8185. It is gated behind a flag to ensure beacon node's fix can safely roll out first. We'll invert this in v1.1.0.
    66  
    67  	KafkaBootstrapServers          string // KafkaBootstrapServers to find kafka servers to stream blocks, attestations, etc.
    68  	AttestationAggregationStrategy string // AttestationAggregationStrategy defines aggregation strategy to be used when aggregating.
    69  
    70  	// KeystoreImportDebounceInterval specifies the time duration the validator waits to reload new keys if they have
    71  	// changed on disk. This feature is for advanced use cases only.
    72  	KeystoreImportDebounceInterval time.Duration
    73  
    74  	// EnableSlashingProtectionPruning for the validator client.
    75  	EnableSlashingProtectionPruning bool
    76  
    77  	// Bug fixes related flags.
    78  	CorrectlyInsertOrphanedAtts bool
    79  	CorrectlyPruneCanonicalAtts bool
    80  }
    81  
    82  var featureConfig *Flags
    83  var featureConfigLock sync.RWMutex
    84  
    85  // Get retrieves feature config.
    86  func Get() *Flags {
    87  	featureConfigLock.RLock()
    88  	defer featureConfigLock.RUnlock()
    89  
    90  	if featureConfig == nil {
    91  		return &Flags{}
    92  	}
    93  	return featureConfig
    94  }
    95  
    96  // Init sets the global config equal to the config that is passed in.
    97  func Init(c *Flags) {
    98  	featureConfigLock.Lock()
    99  	defer featureConfigLock.Unlock()
   100  
   101  	featureConfig = c
   102  }
   103  
   104  // InitWithReset sets the global config and returns function that is used to reset configuration.
   105  func InitWithReset(c *Flags) func() {
   106  	var prevConfig Flags
   107  	if featureConfig != nil {
   108  		prevConfig = *featureConfig
   109  	} else {
   110  		prevConfig = Flags{}
   111  	}
   112  	resetFunc := func() {
   113  		Init(&prevConfig)
   114  	}
   115  	Init(c)
   116  	return resetFunc
   117  }
   118  
   119  // configureTestnet sets the config according to specified testnet flag
   120  func configureTestnet(ctx *cli.Context, cfg *Flags) {
   121  	if ctx.Bool(ToledoTestnet.Name) {
   122  		log.Warn("Running on Toledo Testnet")
   123  		params.UseToledoConfig()
   124  		params.UseToledoNetworkConfig()
   125  		cfg.ToledoTestnet = true
   126  	} else if ctx.Bool(PyrmontTestnet.Name) {
   127  		log.Warn("Running on Pyrmont Testnet")
   128  		params.UsePyrmontConfig()
   129  		params.UsePyrmontNetworkConfig()
   130  		cfg.PyrmontTestnet = true
   131  	} else if ctx.Bool(PraterTestnet.Name) {
   132  		log.Warn("Running on the Prater Testnet")
   133  		params.UsePraterConfig()
   134  		params.UsePraterNetworkConfig()
   135  	} else {
   136  		log.Warn("Running on Ethereum Consensus Mainnet")
   137  		params.UseMainnetConfig()
   138  	}
   139  }
   140  
   141  // ConfigureBeaconChain sets the global config based
   142  // on what flags are enabled for the beacon-chain client.
   143  func ConfigureBeaconChain(ctx *cli.Context) {
   144  	complainOnDeprecatedFlags(ctx)
   145  	cfg := &Flags{}
   146  	if ctx.Bool(devModeFlag.Name) {
   147  		enableDevModeFlags(ctx)
   148  	}
   149  	configureTestnet(ctx, cfg)
   150  
   151  	if ctx.Bool(writeSSZStateTransitionsFlag.Name) {
   152  		log.WithField(writeSSZStateTransitionsFlag.Name, writeSSZStateTransitionsFlag.Usage).Warn(enabledFeatureFlag)
   153  		cfg.WriteSSZStateTransitions = true
   154  	}
   155  
   156  	cfg.EnableSSZCache = true
   157  
   158  	if ctx.String(kafkaBootstrapServersFlag.Name) != "" {
   159  		log.WithField(kafkaBootstrapServersFlag.Name, kafkaBootstrapServersFlag.Usage).Warn(enabledFeatureFlag)
   160  		cfg.KafkaBootstrapServers = ctx.String(kafkaBootstrapServersFlag.Name)
   161  	}
   162  	if ctx.IsSet(disableGRPCConnectionLogging.Name) {
   163  		log.WithField(disableGRPCConnectionLogging.Name, disableGRPCConnectionLogging.Usage).Warn(enabledFeatureFlag)
   164  		cfg.DisableGRPCConnectionLogs = true
   165  	}
   166  	cfg.AttestationAggregationStrategy = ctx.String(attestationAggregationStrategy.Name)
   167  	if ctx.Bool(forceOptMaxCoverAggregationStategy.Name) {
   168  		log.WithField(forceOptMaxCoverAggregationStategy.Name, forceOptMaxCoverAggregationStategy.Usage).Warn(enabledFeatureFlag)
   169  		cfg.AttestationAggregationStrategy = "opt_max_cover"
   170  	}
   171  	if ctx.Bool(enablePeerScorer.Name) {
   172  		log.WithField(enablePeerScorer.Name, enablePeerScorer.Usage).Warn(enabledFeatureFlag)
   173  		cfg.EnablePeerScorer = true
   174  	}
   175  	if ctx.Bool(checkPtInfoCache.Name) {
   176  		log.Warn("Advance check point info cache is no longer supported and will soon be deleted")
   177  	}
   178  	if ctx.Bool(enableLargerGossipHistory.Name) {
   179  		log.WithField(enableLargerGossipHistory.Name, enableLargerGossipHistory.Usage).Warn(enabledFeatureFlag)
   180  		cfg.EnableLargerGossipHistory = true
   181  	}
   182  	if ctx.Bool(disableBroadcastSlashingFlag.Name) {
   183  		log.WithField(disableBroadcastSlashingFlag.Name, disableBroadcastSlashingFlag.Usage).Warn(enabledFeatureFlag)
   184  		cfg.DisableBroadcastSlashings = true
   185  	}
   186  	if ctx.Bool(enableNextSlotStateCache.Name) {
   187  		log.WithField(enableNextSlotStateCache.Name, enableNextSlotStateCache.Usage).Warn(enabledFeatureFlag)
   188  		cfg.EnableNextSlotStateCache = true
   189  	}
   190  	cfg.UpdateHeadTimely = true
   191  	if ctx.Bool(disableUpdateHeadTimely.Name) {
   192  		log.WithField(disableUpdateHeadTimely.Name, disableUpdateHeadTimely.Usage).Warn(enabledFeatureFlag)
   193  		cfg.UpdateHeadTimely = false
   194  	}
   195  	cfg.ProposerAttsSelectionUsingMaxCover = true
   196  	if ctx.Bool(disableProposerAttsSelectionUsingMaxCover.Name) {
   197  		log.WithField(disableProposerAttsSelectionUsingMaxCover.Name, disableProposerAttsSelectionUsingMaxCover.Usage).Warn(enabledFeatureFlag)
   198  		cfg.ProposerAttsSelectionUsingMaxCover = false
   199  	}
   200  	cfg.EnableOptimizedBalanceUpdate = true
   201  	if ctx.Bool(disableOptimizedBalanceUpdate.Name) {
   202  		log.WithField(disableOptimizedBalanceUpdate.Name, disableOptimizedBalanceUpdate.Usage).Warn(enabledFeatureFlag)
   203  		cfg.EnableOptimizedBalanceUpdate = false
   204  	}
   205  	if ctx.Bool(correctlyInsertOrphanedAtts.Name) {
   206  		log.WithField(correctlyInsertOrphanedAtts.Name, correctlyInsertOrphanedAtts.Usage).Warn(enabledFeatureFlag)
   207  		cfg.CorrectlyInsertOrphanedAtts = true
   208  	}
   209  	if ctx.Bool(correctlyPruneCanonicalAtts.Name) {
   210  		log.WithField(correctlyPruneCanonicalAtts.Name, correctlyPruneCanonicalAtts.Usage).Warn(enabledFeatureFlag)
   211  		cfg.CorrectlyPruneCanonicalAtts = true
   212  	}
   213  	Init(cfg)
   214  }
   215  
   216  // ConfigureSlasher sets the global config based
   217  // on what flags are enabled for the slasher client.
   218  func ConfigureSlasher(ctx *cli.Context) {
   219  	complainOnDeprecatedFlags(ctx)
   220  	cfg := &Flags{}
   221  	configureTestnet(ctx, cfg)
   222  
   223  	if ctx.Bool(disableLookbackFlag.Name) {
   224  		log.WithField(disableLookbackFlag.Name, disableLookbackFlag.Usage).Warn(enabledFeatureFlag)
   225  		cfg.DisableLookback = true
   226  	}
   227  	Init(cfg)
   228  }
   229  
   230  // ConfigureValidator sets the global config based
   231  // on what flags are enabled for the validator client.
   232  func ConfigureValidator(ctx *cli.Context) {
   233  	complainOnDeprecatedFlags(ctx)
   234  	cfg := &Flags{}
   235  	configureTestnet(ctx, cfg)
   236  	if ctx.Bool(enableExternalSlasherProtectionFlag.Name) {
   237  		log.WithField(enableExternalSlasherProtectionFlag.Name, enableExternalSlasherProtectionFlag.Usage).Warn(enabledFeatureFlag)
   238  		cfg.SlasherProtection = true
   239  	}
   240  	if ctx.Bool(writeWalletPasswordOnWebOnboarding.Name) {
   241  		log.WithField(writeWalletPasswordOnWebOnboarding.Name, writeWalletPasswordOnWebOnboarding.Usage).Warn(enabledFeatureFlag)
   242  		cfg.WriteWalletPasswordOnWebOnboarding = true
   243  	}
   244  	if ctx.Bool(disableAttestingHistoryDBCache.Name) {
   245  		log.WithField(disableAttestingHistoryDBCache.Name, disableAttestingHistoryDBCache.Usage).Warn(enabledFeatureFlag)
   246  		cfg.DisableAttestingHistoryDBCache = true
   247  	}
   248  	if ctx.Bool(attestTimely.Name) {
   249  		log.WithField(attestTimely.Name, attestTimely.Usage).Warn(enabledFeatureFlag)
   250  		cfg.AttestTimely = true
   251  	}
   252  	if ctx.Bool(enableSlashingProtectionPruning.Name) {
   253  		log.WithField(enableSlashingProtectionPruning.Name, enableSlashingProtectionPruning.Usage).Warn(enabledFeatureFlag)
   254  		cfg.EnableSlashingProtectionPruning = true
   255  	}
   256  	if ctx.Bool(enableDoppelGangerProtection.Name) {
   257  		log.WithField(enableDoppelGangerProtection.Name, enableDoppelGangerProtection.Usage).Warn(enabledFeatureFlag)
   258  		cfg.EnableDoppelGanger = true
   259  	}
   260  	cfg.KeystoreImportDebounceInterval = ctx.Duration(dynamicKeyReloadDebounceInterval.Name)
   261  	Init(cfg)
   262  }
   263  
   264  // enableDevModeFlags switches development mode features on.
   265  func enableDevModeFlags(ctx *cli.Context) {
   266  	log.Warn("Enabling development mode flags")
   267  	for _, f := range devModeFlags {
   268  		log.WithField("flag", f.Names()[0]).Debug("Enabling development mode flag")
   269  		if !ctx.IsSet(f.Names()[0]) {
   270  			if err := ctx.Set(f.Names()[0], "true"); err != nil {
   271  				log.WithError(err).Debug("Error enabling development mode flag")
   272  			}
   273  		}
   274  	}
   275  }
   276  
   277  func complainOnDeprecatedFlags(ctx *cli.Context) {
   278  	for _, f := range deprecatedFlags {
   279  		if ctx.IsSet(f.Names()[0]) {
   280  			log.Errorf("%s is deprecated and has no effect. Do not use this flag, it will be deleted soon.", f.Names()[0])
   281  		}
   282  	}
   283  }