prysm-pulse/config/params/configset.go
kasey 588dea83b7
Config registry (#10683)
* test coverage and updates to config twiddlers

* LoadChainConfigFile error if SetActive conflicts

* lint

* wip working around test issues

* more fixes, mass test updates

* lint

* linting

* thanks deepsource!

* fix undeclared vars

* fixing more undefined

* fix a bug, make a bug, repeat

* gaz

* use stock mainnet in case fork schedule matters

* remove unused KnownConfigs

* post-merge cleanup

* eliminating OverrideBeaconConfig outside tests

* more cleanup of OverrideBeaconConfig outside tests

* config for interop w/ genesis gen support

* improve var name

* API on package instead of exported value

* cleanup remainders of "registry" naming

* Nishant feedback

* add ropstein to configset

* lint

* lint #2

* ✂️

* revert accidental commented line

* check if active is nil (replace called on empty)

* Nishant feedback

* replace OverrideBeaconConfig call

* update interop instructions w/ new flag

* don't let interop replace config set via cli flags

Co-authored-by: kasey <kasey@users.noreply.github.com>
2022-05-20 07:16:53 +00:00

172 lines
4.8 KiB
Go

package params
import (
"github.com/pkg/errors"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
)
var configs *configset
// All returns a slice of every BeaconChainConfig contained in the configset.
func All() []*BeaconChainConfig {
return configs.all()
}
// ByName returns the BeaconChainConfig with the matching `ConfigName` field.
// The runtime ensures that each config name uniquely refers to a single BeaconChainConfig.
func ByName(name string) (*BeaconChainConfig, error) {
return configs.byName(name)
}
// ByVersion returns the BeaconChainConfig that has the given version in its ForkVersionSchedule.
// The configset ensures that each fork version schedule entry uniquely points to a single BeaconChainConfig.
func ByVersion(version [fieldparams.VersionLength]byte) (*BeaconChainConfig, error) {
return configs.byVersion(version)
}
// SetActive sets the given config as active (the config that will be returned by GetActive).
// SetActive will always overwrite any config with the same ConfigName before setting the updated value to active.
func SetActive(c *BeaconChainConfig) error {
return configs.setActive(c)
}
// SetActiveWithUndo attempts to set the active config, and if successful,
// returns a callback function that can be used to revert the configset back to its previous state.
func SetActiveWithUndo(c *BeaconChainConfig) (func() error, error) {
return configs.setActiveWithUndo(c)
}
type configset struct {
active *BeaconChainConfig
versionToName map[[fieldparams.VersionLength]byte]string
nameToConfig map[string]*BeaconChainConfig
}
func newConfigset(configs ...*BeaconChainConfig) *configset {
r := &configset{
versionToName: make(map[[fieldparams.VersionLength]byte]string),
nameToConfig: make(map[string]*BeaconChainConfig),
}
for _, c := range configs {
if err := r.add(c); err != nil {
panic(err)
}
}
return r
}
var errCannotNullifyActive = errors.New("cannot set a config marked as active to nil")
var errCollisionFork = errors.New("configset cannot add config with conflicting fork version schedule")
var errCollisionName = errors.New("config with conflicting name already exists")
var errConfigNotFound = errors.New("unable to find requested BeaconChainConfig")
var errReplaceNilConfig = errors.New("replace called with a nil value")
func (r *configset) add(c *BeaconChainConfig) error {
name := c.ConfigName
if _, exists := r.nameToConfig[name]; exists {
return errors.Wrapf(errCollisionName, "ConfigName=%s", name)
}
c.InitializeForkSchedule()
for v := range c.ForkVersionSchedule {
if n, exists := r.versionToName[v]; exists {
return errors.Wrapf(errCollisionFork, "config name=%s conflicts with existing config named=%s", name, n)
}
r.versionToName[v] = name
}
r.nameToConfig[name] = c
return nil
}
func (r *configset) delete(name string) {
c, exists := r.nameToConfig[name]
if !exists {
return
}
for v := range c.ForkVersionSchedule {
delete(r.versionToName, v)
}
delete(r.nameToConfig, name)
}
func (r *configset) replace(cfg *BeaconChainConfig) error {
if cfg == nil {
return errReplaceNilConfig
}
name := cfg.ConfigName
r.delete(name)
if err := r.add(cfg); err != nil {
return err
}
if r.active != nil && r.active.ConfigName == name {
r.active = cfg
}
return nil
}
func (r *configset) replaceWithUndo(cfg *BeaconChainConfig) (func() error, error) {
name := cfg.ConfigName
prev := r.nameToConfig[name]
if err := r.replace(cfg); err != nil {
return nil, err
}
return func() error {
if prev == nil {
if r.active.ConfigName == name {
return errors.Wrapf(errCannotNullifyActive, "active config name=%s", name)
}
r.delete(name)
return nil
}
return r.replace(prev)
}, nil
}
func (r *configset) getActive() *BeaconChainConfig {
return r.active
}
func (r *configset) setActive(c *BeaconChainConfig) error {
if err := r.replace(c); err != nil {
return err
}
r.active = c
return nil
}
func (r *configset) setActiveWithUndo(c *BeaconChainConfig) (func() error, error) {
active := r.active
r.active = c
undo, err := r.replaceWithUndo(c)
if err != nil {
return nil, err
}
return func() error {
r.active = active
return undo()
}, nil
}
func (r *configset) byName(name string) (*BeaconChainConfig, error) {
c, ok := r.nameToConfig[name]
if !ok {
return nil, errors.Wrapf(errConfigNotFound, "name=%s is not a known BeaconChainConfig name", name)
}
return c, nil
}
func (r *configset) byVersion(version [fieldparams.VersionLength]byte) (*BeaconChainConfig, error) {
name, ok := r.versionToName[version]
if !ok {
return nil, errors.Wrapf(errConfigNotFound, "version=%#x not found in any known fork choice schedule", version)
}
return r.byName(name)
}
func (r *configset) all() []*BeaconChainConfig {
all := make([]*BeaconChainConfig, 0)
for _, c := range r.nameToConfig {
all = append(all, c)
}
return all
}