Compare commits

...

1 Commits

Author SHA1 Message Date
Callum Waters
4e82c24eed first attempt 2021-06-07 10:27:46 +02:00
8 changed files with 386 additions and 171 deletions

View File

@@ -8,6 +8,10 @@ import (
"os"
"path/filepath"
"time"
"github.com/tendermint/tendermint/libs/log"
abci "github.com/tendermint/tendermint/abci/client"
"github.com/tendermint/tendermint/types"
)
const (
@@ -35,36 +39,6 @@ const (
MempoolV1 = "v1"
)
// NOTE: Most of the structs & relevant comments + the
// default configuration options were used to manually
// generate the config.toml. Please reflect any changes
// made here in the defaultConfigTemplate constant in
// config/toml.go
// NOTE: libs/cli must know to look in the config dir!
var (
DefaultTendermintDir = ".tendermint"
defaultConfigDir = "config"
defaultDataDir = "data"
defaultConfigFileName = "config.toml"
defaultGenesisJSONName = "genesis.json"
defaultMode = ModeFull
defaultPrivValKeyName = "priv_validator_key.json"
defaultPrivValStateName = "priv_validator_state.json"
defaultNodeKeyName = "node_key.json"
defaultAddrBookName = "addrbook.json"
defaultConfigFilePath = filepath.Join(defaultConfigDir, defaultConfigFileName)
defaultGenesisJSONPath = filepath.Join(defaultConfigDir, defaultGenesisJSONName)
defaultPrivValKeyPath = filepath.Join(defaultConfigDir, defaultPrivValKeyName)
defaultPrivValStatePath = filepath.Join(defaultDataDir, defaultPrivValStateName)
defaultNodeKeyPath = filepath.Join(defaultConfigDir, defaultNodeKeyName)
defaultAddrBookPath = filepath.Join(defaultConfigDir, defaultAddrBookName)
)
// Config defines the top level configuration for a Tendermint node
type Config struct {
// Top level options use an anonymous struct
@@ -196,14 +170,13 @@ type BaseConfig struct { //nolint: maligned
// The root directory for all data.
// This should be set in viper so it can unmarshal into this struct
RootDir string `mapstructure:"home"`
RootDir string
// TCP or UNIX socket address of the ABCI application,
// or the name of an ABCI application compiled in with the Tendermint binary
ProxyApp string `mapstructure:"proxy-app"`
// Client connection to the application. Can be local or via a socket/grpc
ABCI abci.Client
// A custom human readable name for this node
Moniker string `mapstructure:"moniker"`
Moniker string
// Mode of Node: full | validator | seed
// * validator
@@ -215,83 +188,39 @@ type BaseConfig struct { //nolint: maligned
// * seed
// - only P2P, PEX Reactor
// - No priv_validator_key.json, priv_validator_state.json
Mode string `mapstructure:"mode"`
Mode string
// If this node is many blocks behind the tip of the chain, FastSync
// allows them to catchup quickly by downloading blocks in parallel
// and verifying their commits
FastSyncMode bool `mapstructure:"fast-sync"`
FastSyncMode bool
// Database backend: goleveldb | cleveldb | boltdb | rocksdb
// * goleveldb (github.com/syndtr/goleveldb - most popular implementation)
// - pure go
// - stable
// * cleveldb (uses levigo wrapper)
// - fast
// - requires gcc
// - use cleveldb build tag (go build -tags cleveldb)
// * boltdb (uses etcd's fork of bolt - github.com/etcd-io/bbolt)
// - EXPERIMENTAL
// - may be faster is some use-cases (random reads - indexer)
// - use boltdb build tag (go build -tags boltdb)
// * rocksdb (uses github.com/tecbot/gorocksdb)
// - EXPERIMENTAL
// - requires gcc
// - use rocksdb build tag (go build -tags rocksdb)
// * badgerdb (uses github.com/dgraph-io/badger)
// - EXPERIMENTAL
// - use badgerdb build tag (go build -tags badgerdb)
DBBackend string `mapstructure:"db-backend"`
// Database directory
DBPath string `mapstructure:"db-dir"`
// Database provider to initialize the DB backend
DBProvider DBProvider
// Output level for logging
LogLevel string `mapstructure:"log-level"`
Logger log.Logger
// Output format: 'plain' (colored text) or 'json'
LogFormat string `mapstructure:"log-format"`
// Path to the JSON file containing the initial validator set and other meta data
Genesis string `mapstructure:"genesis-file"`
// Genesis of the chain
Genesis types.GenesisDoc
// A JSON file containing the private key to use for p2p authenticated encryption
NodeKey string `mapstructure:"node-key-file"`
// Mechanism to connect to the ABCI application: socket | grpc
ABCI string `mapstructure:"abci"`
NodeKey string
// If true, query the ABCI app on connecting to a new peer
// so the app can decide if we should keep the connection or not
FilterPeers bool `mapstructure:"filter-peers"` // false
FilterPeers bool
}
// DefaultBaseConfig returns a default base configuration for a Tendermint node
func DefaultBaseConfig() BaseConfig {
return BaseConfig{
Genesis: defaultGenesisJSONPath,
NodeKey: defaultNodeKeyPath,
Mode: defaultMode,
Moniker: defaultMoniker,
ProxyApp: "tcp://127.0.0.1:26658",
ABCI: "socket",
LogLevel: DefaultLogLevel,
LogFormat: LogFormatPlain,
FastSyncMode: true,
FilterPeers: false,
DBBackend: "goleveldb",
DBPath: "data",
}
cfg, _ := DefaultBaseFileConfig().Build()
return cfg
}
// TestBaseConfig returns a base configuration for testing a Tendermint node
func TestBaseConfig() BaseConfig {
cfg := DefaultBaseConfig()
cfg.chainID = "tendermint_test"
cfg.Mode = ModeValidator
cfg.ProxyApp = "kvstore"
cfg.FastSyncMode = false
cfg.DBBackend = "memdb"
cfg, _ := TestBaseFileConfig().Build()
return cfg
}
@@ -299,42 +228,14 @@ func (cfg BaseConfig) ChainID() string {
return cfg.chainID
}
// GenesisFile returns the full path to the genesis.json file
func (cfg BaseConfig) GenesisFile() string {
return rootify(cfg.Genesis, cfg.RootDir)
}
// NodeKeyFile returns the full path to the node_key.json file
func (cfg BaseConfig) NodeKeyFile() string {
return rootify(cfg.NodeKey, cfg.RootDir)
}
// DBDir returns the full path to the database directory
func (cfg BaseConfig) DBDir() string {
return rootify(cfg.DBPath, cfg.RootDir)
}
func (cfg Config) ArePrivValidatorClientSecurityOptionsPresent() bool {
switch {
case cfg.PrivValidator.RootCA == "":
return false
case cfg.PrivValidator.ClientKey == "":
return false
case cfg.PrivValidator.ClientCertificate == "":
return false
default:
return true
}
}
// ValidateBasic performs basic validation (checking param bounds, etc.) and
// returns an error if any check fails.
func (cfg BaseConfig) ValidateBasic() error {
switch cfg.LogFormat {
case LogFormatPlain, LogFormatJSON:
default:
return errors.New("unknown log format (must be 'plain' or 'json')")
}
switch cfg.Mode {
case ModeFull, ModeValidator, ModeSeed:
case "":
@@ -380,6 +281,19 @@ func DefaultPrivValidatorConfig() *PrivValidatorConfig {
}
}
func (cfg PrivValidatorConfig) AreSecurityOptionsPresent() bool {
switch {
case cfg.RootCA == "":
return false
case cfg.ClientKey == "":
return false
case cfg.ClientCertificate == "":
return false
default:
return true
}
}
//-----------------------------------------------------------------------------
// RPCConfig

View File

@@ -9,24 +9,6 @@ import (
"github.com/stretchr/testify/require"
)
func TestDefaultConfig(t *testing.T) {
assert := assert.New(t)
// set up some defaults
cfg := DefaultConfig()
assert.NotNil(cfg.P2P)
assert.NotNil(cfg.Mempool)
assert.NotNil(cfg.Consensus)
// check the root dir stuff...
cfg.SetRoot("/foo")
cfg.Genesis = "bar"
cfg.DBPath = "/opt/data"
assert.Equal("/foo/bar", cfg.GenesisFile())
assert.Equal("/opt/data", cfg.DBDir())
}
func TestConfigValidateBasic(t *testing.T) {
cfg := DefaultConfig()
assert.NoError(t, cfg.ValidateBasic())
@@ -52,15 +34,6 @@ func TestTLSConfiguration(t *testing.T) {
assert.Equal("/abs/path/to/file.key", cfg.RPC.KeyFile())
}
func TestBaseConfigValidateBasic(t *testing.T) {
cfg := TestBaseConfig()
assert.NoError(t, cfg.ValidateBasic())
// tamper with log format
cfg.LogFormat = "invalid"
assert.Error(t, cfg.ValidateBasic())
}
func TestRPCConfigValidateBasic(t *testing.T) {
cfg := TestRPCConfig()
assert.NoError(t, cfg.ValidateBasic())

View File

@@ -9,18 +9,21 @@ import (
// ServiceProvider takes a config and a logger and returns a ready to go Node.
type ServiceProvider func(*Config, log.Logger) (service.Service, error)
// DBContext specifies config information for loading a new DB.
type DBContext struct {
ID string
Config *Config
// DBProivder is an interface for initializing instances of DB
type DBProvider interface {
Initialize(ID string) (db.DB, error)
}
// DBProvider takes a DBContext and returns an instantiated DB.
type DBProvider func(*DBContext) (db.DB, error)
// DefaultDBProvider returns a database using the DBBackend and DBDir
// specified in the Config.
func DefaultDBProvider(ctx *DBContext) (db.DB, error) {
dbType := db.BackendType(ctx.Config.DBBackend)
return db.NewDB(ctx.ID, dbType, ctx.Config.DBDir())
// DefaultDBProvider is the default provider that is constructed from the FileConfig
type DefaultDBProvider struct {
backend string
dir string
}
func (dbp DefaultDBProvider) Initialize(ID string) (db.DB, error) {
dbType := db.BackendType(dbp.backend)
return db.NewDB(ID, dbType, dbp.dir)
}

295
config/file.go Normal file
View File

@@ -0,0 +1,295 @@
package config
import (
"errors"
"os"
"path/filepath"
"github.com/tendermint/tendermint/abci/client"
abci"github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/abci/example/counter"
"github.com/tendermint/tendermint/abci/example/kvstore"
tmsync "github.com/tendermint/tendermint/internal/libs/sync"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/types"
)
// NOTE: Most of the structs & relevant comments + the
// default configuration options were used to manually
// generate the config.toml. Please reflect any changes
// made here in the defaultConfigTemplate constant in
// config/toml.go
// NOTE: libs/cli must know to look in the config dir!
var (
DefaultTendermintDir = ".tendermint"
defaultConfigDir = "config"
defaultDataDir = "data"
defaultConfigFileName = "config.toml"
defaultGenesisJSONName = "genesis.json"
defaultMode = ModeFull
defaultPrivValKeyName = "priv_validator_key.json"
defaultPrivValStateName = "priv_validator_state.json"
defaultNodeKeyName = "node_key.json"
defaultAddrBookName = "addrbook.json"
defaultConfigFilePath = filepath.Join(defaultConfigDir, defaultConfigFileName)
defaultGenesisJSONPath = filepath.Join(defaultConfigDir, defaultGenesisJSONName)
defaultPrivValKeyPath = filepath.Join(defaultConfigDir, defaultPrivValKeyName)
defaultPrivValStatePath = filepath.Join(defaultDataDir, defaultPrivValStateName)
defaultNodeKeyPath = filepath.Join(defaultConfigDir, defaultNodeKeyName)
defaultAddrBookPath = filepath.Join(defaultConfigDir, defaultAddrBookName)
)
type FileConfig struct {
// Top level options use an anonymous struct
BaseFileConfig `mapstructure:",squash"`
// Options for services
RPC *RPCConfig `mapstructure:"rpc"`
P2P *P2PConfig `mapstructure:"p2p"`
Mempool *MempoolConfig `mapstructure:"mempool"`
StateSync *StateSyncConfig `mapstructure:"statesync"`
FastSync *FastSyncConfig `mapstructure:"fastsync"`
Consensus *ConsensusConfig `mapstructure:"consensus"`
TxIndex *TxIndexConfig `mapstructure:"tx-index"`
Instrumentation *InstrumentationConfig `mapstructure:"instrumentation"`
PrivValidator *PrivValidatorConfig `mapstructure:"priv-validator"`
}
// DefaultConfig returns a default configuration for a Tendermint node
func DefaultFileConfig() *FileConfig {
return &FileConfig{
BaseFileConfig: DefaultBaseFileConfig(),
RPC: DefaultRPCConfig(),
P2P: DefaultP2PConfig(),
Mempool: DefaultMempoolConfig(),
StateSync: DefaultStateSyncConfig(),
FastSync: DefaultFastSyncConfig(),
Consensus: DefaultConsensusConfig(),
TxIndex: DefaultTxIndexConfig(),
Instrumentation: DefaultInstrumentationConfig(),
PrivValidator: DefaultPrivValidatorConfig(),
}
}
// TestConfig returns a configuration that can be used for testing
func TestFileConfig() *FileConfig {
return &FileConfig{
BaseFileConfig: TestBaseFileConfig(),
RPC: TestRPCConfig(),
P2P: TestP2PConfig(),
Mempool: TestMempoolConfig(),
StateSync: TestStateSyncConfig(),
FastSync: TestFastSyncConfig(),
Consensus: TestConsensusConfig(),
TxIndex: TestTxIndexConfig(),
Instrumentation: TestInstrumentationConfig(),
PrivValidator: DefaultPrivValidatorConfig(),
}
}
func (cfg FileConfig) Build() (Config, error) {
baseConfig, err := cfg.BaseFileConfig.Build()
if err != nil {
return Config{}, err
}
return Config{
BaseConfig: baseConfig,
RPC: cfg.RPC,
P2P: cfg.P2P,
Mempool: cfg.Mempool,
StateSync: cfg.StateSync,
FastSync: cfg.FastSync,
Consensus: cfg.Consensus,
TxIndex: cfg.TxIndex,
Instrumentation: cfg.Instrumentation,
PrivValidator: cfg.PrivValidator,
}, nil
}
// SetRoot sets the RootDir for all Config structs
func (cfg *FileConfig) SetRoot(root string) *FileConfig {
cfg.BaseFileConfig.RootDir = root
cfg.RPC.RootDir = root
cfg.P2P.RootDir = root
cfg.Mempool.RootDir = root
cfg.Consensus.RootDir = root
return cfg
}
type BaseFileConfig struct { //nolint: maligned
// chainID is unexposed and immutable but here for convenience
chainID string
// The root directory for all data.
// This should be set in viper so it can unmarshal into this struct
RootDir string `mapstructure:"home"`
// TCP or UNIX socket address of the ABCI application,
// or the name of an ABCI application compiled in with the Tendermint binary
ProxyApp string `mapstructure:"proxy-app"`
// A custom human readable name for this node
Moniker string `mapstructure:"moniker"`
// Mode of Node: full | validator | seed
// * validator
// - all reactors
// - with priv_validator_key.json, priv_validator_state.json
// * full
// - all reactors
// - No priv_validator_key.json, priv_validator_state.json
// * seed
// - only P2P, PEX Reactor
// - No priv_validator_key.json, priv_validator_state.json
Mode string `mapstructure:"mode"`
// If this node is many blocks behind the tip of the chain, FastSync
// allows them to catchup quickly by downloading blocks in parallel
// and verifying their commits
FastSyncMode bool `mapstructure:"fast-sync"`
// Database backend: goleveldb | cleveldb | boltdb | rocksdb
// * goleveldb (github.com/syndtr/goleveldb - most popular implementation)
// - pure go
// - stable
// * cleveldb (uses levigo wrapper)
// - fast
// - requires gcc
// - use cleveldb build tag (go build -tags cleveldb)
// * boltdb (uses etcd's fork of bolt - github.com/etcd-io/bbolt)
// - EXPERIMENTAL
// - may be faster is some use-cases (random reads - indexer)
// - use boltdb build tag (go build -tags boltdb)
// * rocksdb (uses github.com/tecbot/gorocksdb)
// - EXPERIMENTAL
// - requires gcc
// - use rocksdb build tag (go build -tags rocksdb)
// * badgerdb (uses github.com/dgraph-io/badger)
// - EXPERIMENTAL
// - use badgerdb build tag (go build -tags badgerdb)
DBBackend string `mapstructure:"db-backend"`
// Database directory
DBPath string `mapstructure:"db-dir"`
// Output level for logging
LogLevel string `mapstructure:"log-level"`
// Output format: 'plain' (colored text) or 'json'
LogFormat string `mapstructure:"log-format"`
// Path to the JSON file containing the initial validator set and other meta data
Genesis string `mapstructure:"genesis-file"`
// A JSON file containing the private key to use for p2p authenticated encryption
NodeKey string `mapstructure:"node-key-file"`
// Mechanism to connect to the ABCI application: socket | grpc
ABCI string `mapstructure:"abci"`
// If true, query the ABCI app on connecting to a new peer
// so the app can decide if we should keep the connection or not
FilterPeers bool `mapstructure:"filter-peers"` // false
}
// DefaultBaseConfig returns a default base configuration for a Tendermint node
func DefaultBaseFileConfig() BaseFileConfig {
return BaseFileConfig{
Genesis: defaultGenesisJSONPath,
NodeKey: defaultNodeKeyPath,
Mode: defaultMode,
Moniker: defaultMoniker,
ProxyApp: "tcp://127.0.0.1:26658",
ABCI: "socket",
LogLevel: DefaultLogLevel,
LogFormat: LogFormatPlain,
FastSyncMode: true,
FilterPeers: false,
DBBackend: "goleveldb",
DBPath: "data",
}
}
// TestBaseConfig returns a base configuration for testing a Tendermint node
func TestBaseFileConfig() BaseFileConfig {
cfg := DefaultBaseFileConfig()
cfg.chainID = "tendermint_test"
cfg.Mode = ModeValidator
cfg.ProxyApp = "kvstore"
cfg.FastSyncMode = false
cfg.DBBackend = "memdb"
return cfg
}
func (cfg BaseFileConfig) Build() (BaseConfig, error) {
abciClient, err := createClient(cfg.ProxyApp, cfg.ABCI, cfg.DBDir())
if err != nil {
return BaseConfig{}, err
}
genDoc, err := types.GenesisDocFromFile(cfg.GenesisFile())
if err != nil {
return BaseConfig{}, err
}
return BaseConfig{
chainID: cfg.chainID,
RootDir: cfg.RootDir,
ABCI: abciClient,
Moniker: cfg.Moniker,
Mode: cfg.Mode,
FastSyncMode: cfg.FastSyncMode,
DBProvider: DefaultDBProvider{
backend: cfg.DBBackend,
dir: cfg.DBDir(),
},
Logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)),
Genesis: *genDoc,
NodeKey: cfg.NodeKey,
FilterPeers: cfg.FilterPeers,
}, nil
}
// GenesisFile returns the full path to the genesis.json file
func (cfg BaseFileConfig) GenesisFile() string {
return rootify(cfg.Genesis, cfg.RootDir)
}
// DBDir returns the full path to the database directory
func (cfg BaseFileConfig) DBDir() string {
return rootify(cfg.DBPath, cfg.RootDir)
}
func (cfg BaseFileConfig) ValidateBasic() error {
switch cfg.LogFormat {
case LogFormatPlain, LogFormatJSON:
default:
return errors.New("unknown log format (must be 'plain' or 'json')")
}
return nil
}
func createClient(addr, transport, dbDir string) (abcicli.Client, error) {
switch addr {
case "counter":
return abcicli.NewLocalClient(new(tmsync.RWMutex), counter.NewApplication(false)), nil
case "counter_serial":
return abcicli.NewLocalClient(new(tmsync.RWMutex), counter.NewApplication(true)), nil
case "kvstore":
return abcicli.NewLocalClient(new(tmsync.RWMutex), kvstore.NewApplication()), nil
case "persistent_kvstore":
app := kvstore.NewPersistentKVStoreApplication(dbDir)
return abcicli.NewLocalClient(new(tmsync.RWMutex), app), nil
case "noop":
return abcicli.NewLocalClient(new(tmsync.RWMutex), abci.NewBaseApplication()), nil
default:
mustConnect := false // loop retrying
return abcicli.NewClient(addr, transport, mustConnect)
}
}

34
config/file_test.go Normal file
View File

@@ -0,0 +1,34 @@
package config
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestDefaultConfig(t *testing.T) {
assert := assert.New(t)
// set up some defaults
cfg := DefaultFileConfig()
assert.NotNil(cfg.P2P)
assert.NotNil(cfg.Mempool)
assert.NotNil(cfg.Consensus)
// check the root dir stuff...
cfg.SetRoot("/foo")
cfg.Genesis = "bar"
cfg.DBPath = "/opt/data"
assert.Equal("/foo/bar", cfg.GenesisFile())
assert.Equal("/opt/data", cfg.DBDir())
}
func TestBaseConfigValidateBasic(t *testing.T) {
cfg := TestBaseFileConfig()
assert.NoError(t, cfg.ValidateBasic())
// tamper with log format
cfg.LogFormat = "invalid"
assert.Error(t, cfg.ValidateBasic())
}

View File

@@ -45,7 +45,7 @@ func EnsureRoot(rootDir string) {
// WriteConfigFile renders config using the template and writes it to configFilePath.
// This function is called by cmd/tendermint/commands/init.go
func WriteConfigFile(rootDir string, config *Config) {
func WriteConfigFile(rootDir string, config *FileConfig) {
var buffer bytes.Buffer
if err := configTemplate.Execute(&buffer, config); err != nil {
@@ -60,7 +60,7 @@ func WriteConfigFile(rootDir string, config *Config) {
func writeDefaultConfigFileIfNone(rootDir string) {
configFilePath := filepath.Join(rootDir, defaultConfigFilePath)
if !tmos.FileExists(configFilePath) {
WriteConfigFile(rootDir, DefaultConfig())
WriteConfigFile(rootDir, DefaultFileConfig())
}
}
@@ -523,11 +523,11 @@ namespace = "{{ .Instrumentation.Namespace }}"
/****** these are for test settings ***********/
func ResetTestRoot(testName string) *Config {
func ResetTestRoot(testName string) *FileConfig {
return ResetTestRootWithChainID(testName, "")
}
func ResetTestRootWithChainID(testName string, chainID string) *Config {
func ResetTestRootWithChainID(testName string, chainID string) *FileConfig {
// create a unique, concurrency-safe test directory under os.TempDir()
rootDir, err := ioutil.TempDir("", fmt.Sprintf("%s-%s_", chainID, testName))
if err != nil {
@@ -541,7 +541,7 @@ func ResetTestRootWithChainID(testName string, chainID string) *Config {
panic(err)
}
conf := DefaultConfig()
conf := DefaultFileConfig()
genesisFilePath := filepath.Join(rootDir, conf.Genesis)
privKeyFilePath := filepath.Join(rootDir, conf.PrivValidator.Key)
privStateFilePath := filepath.Join(rootDir, conf.PrivValidator.State)
@@ -559,7 +559,7 @@ func ResetTestRootWithChainID(testName string, chainID string) *Config {
mustWriteFile(privKeyFilePath, []byte(testPrivValidatorKey), 0644)
mustWriteFile(privStateFilePath, []byte(testPrivValidatorState), 0644)
config := TestConfig().SetRoot(rootDir)
config := TestFileConfig().SetRoot(rootDir)
return config
}

View File

@@ -30,7 +30,7 @@ func TestEnsureRoot(t *testing.T) {
// create root dir
EnsureRoot(tmpDir)
WriteConfigFile(tmpDir, DefaultConfig())
WriteConfigFile(tmpDir, DefaultFileConfig())
// make sure config is set properly
data, err := ioutil.ReadFile(filepath.Join(tmpDir, defaultConfigFilePath))
@@ -62,7 +62,7 @@ func TestEnsureTestRoot(t *testing.T) {
}
// TODO: make sure the cfg returned and testconfig are the same!
baseConfig := DefaultBaseConfig()
baseConfig := DefaultBaseFileConfig()
pvConfig := DefaultPrivValidatorConfig()
ensureFiles(t, rootDir, defaultDataDir, baseConfig.Genesis, pvConfig.Key, pvConfig.State)
}

View File

@@ -27,11 +27,7 @@ func NewDefault(conf *config.Config, logger log.Logger) (service.Service, error)
// Genesis document: if the value is nil, the genesis document is read
// from the file specified in the config, and otherwise the node uses
// value of the final argument.
func New(conf *config.Config,
logger log.Logger,
cf proxy.ClientCreator,
gen *types.GenesisDoc,
) (service.Service, error) {
func New(conf *config.Config) (service.Service, error) {
nodeKey, err := p2p.LoadOrGenNodeKey(conf.NodeKeyFile())
if err != nil {
return nil, fmt.Errorf("failed to load or gen node key %s: %w", conf.NodeKeyFile(), err)