From 0dd6b92a642b96cc07e37b49de262712a3c293ae Mon Sep 17 00:00:00 2001 From: Thane Thomson Date: Thu, 30 May 2019 18:40:17 -0400 Subject: [PATCH] Relocate GenesisDocProvider and DefaultGenesisDocProviderFunc (#3693) * Move GenesisDocProvider and DefaultGenesisDocProviderFunc GenesisDocProvider, being a provider of *types.GenesisDoc, makes sense to be part of the types package. DefaultGenesisDocProviderFunc, which relies on *config.Config to produce a types.GenesisDocProvider, makes sense being part of the config package. * Add aliases to avoid breaking node package API * Revert to original structure After discussion, it appears as though the best place for the relocated structures is still in the node package. This means that for the v0.31.6 release and into the future, there will be no changes two these two entities' APIs. --- node/node.go | 69 +++++++++++++++++++++++++++++++++++++++++++-- rpc/test/helpers.go | 6 ++-- state/store.go | 65 ------------------------------------------ 3 files changed, 68 insertions(+), 72 deletions(-) diff --git a/node/node.go b/node/node.go index 2d7b3b3bb..0d05deee1 100644 --- a/node/node.go +++ b/node/node.go @@ -65,6 +65,19 @@ func DefaultDBProvider(ctx *DBContext) (dbm.DB, error) { return dbm.NewDB(ctx.ID, dbType, ctx.Config.DBDir()), nil } +// GenesisDocProvider returns a GenesisDoc. +// It allows the GenesisDoc to be pulled from sources other than the +// filesystem, for instance from a distributed key-value store cluster. +type GenesisDocProvider func() (*types.GenesisDoc, error) + +// DefaultGenesisDocProviderFunc returns a GenesisDocProvider that loads +// the GenesisDoc from the config.GenesisFile() on the filesystem. +func DefaultGenesisDocProviderFunc(config *cfg.Config) GenesisDocProvider { + return func() (*types.GenesisDoc, error) { + return types.GenesisDocFromFile(config.GenesisFile()) + } +} + // NodeProvider takes a config and a logger and returns a ready to go Node. type NodeProvider func(*cfg.Config, log.Logger) (*Node, error) @@ -99,7 +112,7 @@ func DefaultNewNode(config *cfg.Config, logger log.Logger) (*Node, error) { privval.LoadOrGenFilePV(newPrivValKey, newPrivValState), nodeKey, proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()), - sm.DefaultGenesisDocProviderFunc(config), + DefaultGenesisDocProviderFunc(config), DefaultDBProvider, DefaultMetricsProvider(config.Instrumentation), logger, @@ -466,7 +479,7 @@ func NewNode(config *cfg.Config, privValidator types.PrivValidator, nodeKey *p2p.NodeKey, clientCreator proxy.ClientCreator, - genesisDocProvider sm.GenesisDocProvider, + genesisDocProvider GenesisDocProvider, dbProvider DBProvider, metricsProvider MetricsProvider, logger log.Logger) (*Node, error) { @@ -476,7 +489,7 @@ func NewNode(config *cfg.Config, return nil, err } - state, genDoc, err := sm.LoadStateFromDBOrGenesisDocProvider(stateDB, genesisDocProvider) + state, genDoc, err := LoadStateFromDBOrGenesisDocProvider(stateDB, genesisDocProvider) if err != nil { return nil, err } @@ -1002,6 +1015,56 @@ func makeNodeInfo( //------------------------------------------------------------------------------ +var ( + genesisDocKey = []byte("genesisDoc") +) + +// LoadStateFromDBOrGenesisDocProvider attempts to load the state from the +// database, or creates one using the given genesisDocProvider and persists the +// result to the database. On success this also returns the genesis doc loaded +// through the given provider. +func LoadStateFromDBOrGenesisDocProvider(stateDB dbm.DB, genesisDocProvider GenesisDocProvider) (sm.State, *types.GenesisDoc, error) { + // Get genesis doc + genDoc, err := loadGenesisDoc(stateDB) + if err != nil { + genDoc, err = genesisDocProvider() + if err != nil { + return sm.State{}, nil, err + } + // save genesis doc to prevent a certain class of user errors (e.g. when it + // was changed, accidentally or not). Also good for audit trail. + saveGenesisDoc(stateDB, genDoc) + } + state, err := sm.LoadStateFromDBOrGenesisDoc(stateDB, genDoc) + if err != nil { + return sm.State{}, nil, err + } + return state, genDoc, nil +} + +// panics if failed to unmarshal bytes +func loadGenesisDoc(db dbm.DB) (*types.GenesisDoc, error) { + b := db.Get(genesisDocKey) + if len(b) == 0 { + return nil, errors.New("Genesis doc not found") + } + var genDoc *types.GenesisDoc + err := cdc.UnmarshalJSON(b, &genDoc) + if err != nil { + panic(fmt.Sprintf("Failed to load genesis doc due to unmarshaling error: %v (bytes: %X)", err, b)) + } + return genDoc, nil +} + +// panics if failed to marshal the given genesis document +func saveGenesisDoc(db dbm.DB, genDoc *types.GenesisDoc) { + b, err := cdc.MarshalJSON(genDoc) + if err != nil { + panic(fmt.Sprintf("Failed to save genesis doc due to marshaling error: %v", err)) + } + db.SetSync(genesisDocKey, b) +} + func createAndStartPrivValidatorSocketClient( listenAddr string, logger log.Logger, diff --git a/rpc/test/helpers.go b/rpc/test/helpers.go index f5c923bf4..033015d11 100644 --- a/rpc/test/helpers.go +++ b/rpc/test/helpers.go @@ -8,10 +8,8 @@ import ( "strings" "time" - "github.com/tendermint/tendermint/libs/log" - "github.com/tendermint/tendermint/state" - abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/libs/log" cfg "github.com/tendermint/tendermint/config" cmn "github.com/tendermint/tendermint/libs/common" @@ -167,7 +165,7 @@ func NewTendermint(app abci.Application, opts *Options) *nm.Node { panic(err) } node, err := nm.NewNode(config, pv, nodeKey, papp, - state.DefaultGenesisDocProviderFunc(config), + nm.DefaultGenesisDocProviderFunc(config), nm.DefaultDBProvider, nm.DefaultMetricsProvider(config.Instrumentation), logger) diff --git a/state/store.go b/state/store.go index e1fb5ba60..0301bc7c3 100644 --- a/state/store.go +++ b/state/store.go @@ -1,11 +1,9 @@ package state import ( - "errors" "fmt" abci "github.com/tendermint/tendermint/abci/types" - cfg "github.com/tendermint/tendermint/config" cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/types" @@ -19,23 +17,6 @@ const ( valSetCheckpointInterval = 100000 ) -var ( - genesisDocKey = []byte("genesisDoc") -) - -// GenesisDocProvider returns a GenesisDoc. -// It allows the GenesisDoc to be pulled from sources other than the -// filesystem, for instance from a distributed key-value store cluster. -type GenesisDocProvider func() (*types.GenesisDoc, error) - -// DefaultGenesisDocProviderFunc returns a GenesisDocProvider that loads -// the GenesisDoc from the config.GenesisFile() on the filesystem. -func DefaultGenesisDocProviderFunc(config *cfg.Config) GenesisDocProvider { - return func() (*types.GenesisDoc, error) { - return types.GenesisDocFromFile(config.GenesisFile()) - } -} - //------------------------------------------------------------------------ func calcValidatorsKey(height int64) []byte { @@ -84,52 +65,6 @@ func LoadStateFromDBOrGenesisDoc(stateDB dbm.DB, genesisDoc *types.GenesisDoc) ( return state, nil } -// LoadStateFromDBOrGenesisDocProvider attempts to load the state from the -// database, or creates one using the given genesisDocProvider and persists the -// result to the database. On success this also returns the genesis doc loaded -// through the given provider. -func LoadStateFromDBOrGenesisDocProvider(stateDB dbm.DB, genesisDocProvider GenesisDocProvider) (State, *types.GenesisDoc, error) { - // Get genesis doc - genDoc, err := loadGenesisDoc(stateDB) - if err != nil { - genDoc, err = genesisDocProvider() - if err != nil { - return State{}, nil, err - } - // save genesis doc to prevent a certain class of user errors (e.g. when it - // was changed, accidentally or not). Also good for audit trail. - saveGenesisDoc(stateDB, genDoc) - } - state, err := LoadStateFromDBOrGenesisDoc(stateDB, genDoc) - if err != nil { - return State{}, nil, err - } - return state, genDoc, nil -} - -// panics if failed to unmarshal bytes -func loadGenesisDoc(db dbm.DB) (*types.GenesisDoc, error) { - bytes := db.Get(genesisDocKey) - if len(bytes) == 0 { - return nil, errors.New("Genesis doc not found") - } - var genDoc *types.GenesisDoc - err := cdc.UnmarshalJSON(bytes, &genDoc) - if err != nil { - panic(fmt.Sprintf("Failed to load genesis doc due to unmarshaling error: %v (bytes: %X)", err, bytes)) - } - return genDoc, nil -} - -// panics if failed to marshal the given genesis document -func saveGenesisDoc(db dbm.DB, genDoc *types.GenesisDoc) { - bytes, err := cdc.MarshalJSON(genDoc) - if err != nil { - panic(fmt.Sprintf("Failed to save genesis doc due to marshaling error: %v", err)) - } - db.SetSync(genesisDocKey, bytes) -} - // LoadState loads the State from the database. func LoadState(db dbm.DB) State { return loadState(db, stateKey)