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 }