diff --git a/cmd/tendermint/commands/init.go b/cmd/tendermint/commands/init.go index bb8aa45dc..5c3fbb52a 100644 --- a/cmd/tendermint/commands/init.go +++ b/cmd/tendermint/commands/init.go @@ -20,13 +20,13 @@ func init() { } func initFiles(cmd *cobra.Command, args []string) { - privValFile := config.PrivValidatorFile + privValFile := config.PrivValidatorFile() if _, err := os.Stat(privValFile); os.IsNotExist(err) { privValidator := types.GenPrivValidator() privValidator.SetFile(privValFile) privValidator.Save() - genFile := config.GenesisFile + genFile := config.GenesisFile() if _, err := os.Stat(genFile); os.IsNotExist(err) { genDoc := types.GenesisDoc{ diff --git a/cmd/tendermint/commands/reset_priv_validator.go b/cmd/tendermint/commands/reset_priv_validator.go index c84ebcf8b..c10f9c56a 100644 --- a/cmd/tendermint/commands/reset_priv_validator.go +++ b/cmd/tendermint/commands/reset_priv_validator.go @@ -29,13 +29,13 @@ func init() { // XXX: this is totally unsafe. // it's only suitable for testnets. func resetAll(cmd *cobra.Command, args []string) { - ResetAll(config.DBDir, config.PrivValidatorFile, log) + ResetAll(config.DBDir(), config.PrivValidatorFile(), log) } // XXX: this is totally unsafe. // it's only suitable for testnets. func resetPrivValidator(cmd *cobra.Command, args []string) { - resetPrivValidatorLocal(config.PrivValidatorFile, log) + resetPrivValidatorLocal(config.PrivValidatorFile(), log) } // Exported so other CLI tools can use it diff --git a/cmd/tendermint/commands/root.go b/cmd/tendermint/commands/root.go index 63ee0db5c..28527b7f1 100644 --- a/cmd/tendermint/commands/root.go +++ b/cmd/tendermint/commands/root.go @@ -14,7 +14,7 @@ var ( ) func init() { - config = cfg.DefaultConfig("REMOVE-ROOT") + config = cfg.DefaultConfig() RootCmd.PersistentFlags().String("log_level", config.LogLevel, "Log level") } diff --git a/cmd/tendermint/commands/run_node.go b/cmd/tendermint/commands/run_node.go index d8c268c26..a2c363dc9 100644 --- a/cmd/tendermint/commands/run_node.go +++ b/cmd/tendermint/commands/run_node.go @@ -56,7 +56,7 @@ func runNode(cmd *cobra.Command, args []string) error { // This is for Mintnet compatibility. // TODO: If Mintnet gets deprecated or genesis_file is // always available, remove. - genDocFile := config.GenesisFile + genDocFile := config.GenesisFile() if !cmn.FileExists(genDocFile) { log.Notice(cmn.Fmt("Waiting for genesis file %v...", genDocFile)) for { diff --git a/cmd/tendermint/commands/show_validator.go b/cmd/tendermint/commands/show_validator.go index b741ba8c0..6f2e2a07e 100644 --- a/cmd/tendermint/commands/show_validator.go +++ b/cmd/tendermint/commands/show_validator.go @@ -20,7 +20,7 @@ func init() { } func showValidator(cmd *cobra.Command, args []string) { - privValidator := types.LoadOrGenPrivValidator(config.PrivValidatorFile) + privValidator := types.LoadOrGenPrivValidator(config.PrivValidatorFile()) pubKeyJSONBytes, _ := data.ToJSON(privValidator.PubKey) fmt.Println(string(pubKeyJSONBytes)) } diff --git a/config/config.go b/config/config.go index 531ef9a50..7490f8037 100644 --- a/config/config.go +++ b/config/config.go @@ -1,6 +1,7 @@ package config import ( + "path/filepath" "time" "github.com/tendermint/tendermint/types" @@ -16,34 +17,45 @@ type Config struct { Consensus *ConsensusConfig `mapstructure:"consensus"` } -func DefaultConfig(rootDir string) *Config { +func DefaultConfig() *Config { return &Config{ - BaseConfig: DefaultBaseConfig(rootDir), - P2P: DefaultP2PConfig(rootDir), - Mempool: DefaultMempoolConfig(rootDir), - Consensus: DefaultConsensusConfig(rootDir), + BaseConfig: DefaultBaseConfig(), + P2P: DefaultP2PConfig(), + Mempool: DefaultMempoolConfig(), + Consensus: DefaultConsensusConfig(), } } -func TestConfig(rootDir string) *Config { +func TestConfig() *Config { return &Config{ - BaseConfig: DefaultBaseConfig(rootDir), - P2P: DefaultP2PConfig(rootDir), - Mempool: DefaultMempoolConfig(rootDir), - Consensus: TestConsensusConfig(rootDir), + BaseConfig: DefaultBaseConfig(), + P2P: DefaultP2PConfig(), + Mempool: DefaultMempoolConfig(), + Consensus: TestConsensusConfig(), } } +// TODO: set this from root or home.... or default.... +func SetRoot(cfg *Config, root string) { + cfg.BaseConfig.RootDir = root + cfg.P2P.RootDir = root + cfg.Mempool.RootDir = root + cfg.Consensus.RootDir = root +} + // BaseConfig struct for a Tendermint node type BaseConfig struct { + // TODO: set this from root or home.... or default.... + RootDir string `mapstructure:"home"` + // The ID of the chain to join (should be signed with every transaction and vote) ChainID string `mapstructure:"chain_id"` // A JSON file containing the initial validator set and other meta data - GenesisFile string `mapstructure:"genesis_file"` + Genesis string `mapstructure:"genesis_file"` // A JSON file containing the private key to use as a validator in the consensus protocol - PrivValidatorFile string `mapstructure:"priv_validator_file"` + PrivValidator string `mapstructure:"priv_validator_file"` // A custom human readable name for this node Moniker string `mapstructure:"moniker"` @@ -77,7 +89,7 @@ type BaseConfig struct { DBBackend string `mapstructure:"db_backend"` // Database directory - DBDir string `mapstructure:"db_dir"` + DBPath string `mapstructure:"db_dir"` // TCP or UNIX socket address for the RPC server to listen on RPCListenAddress string `mapstructure:"rpc_laddr"` @@ -87,10 +99,10 @@ type BaseConfig struct { GRPCListenAddress string `mapstructure:"grpc_laddr"` } -func DefaultBaseConfig(rootDir string) *BaseConfig { +func DefaultBaseConfig() *BaseConfig { return &BaseConfig{ - GenesisFile: rootDir + "/genesis.json", - PrivValidatorFile: rootDir + "/priv_validator.json", + Genesis: "genesis.json", + PrivValidator: "priv_validator.json", Moniker: "anonymous", ProxyApp: "tcp://127.0.0.1:46658", ABCI: "socket", @@ -100,51 +112,74 @@ func DefaultBaseConfig(rootDir string) *BaseConfig { FilterPeers: false, TxIndex: "kv", DBBackend: "leveldb", - DBDir: rootDir + "/data", + DBPath: "data", RPCListenAddress: "tcp://0.0.0.0:46657", GRPCListenAddress: "", } } +func (b *BaseConfig) GenesisFile() string { + return rootify(b.Genesis, b.RootDir) +} + +func (b *BaseConfig) PrivValidatorFile() string { + return rootify(b.PrivValidator, b.RootDir) +} + +func (b *BaseConfig) DBDir() string { + return rootify(b.DBPath, b.RootDir) +} + type P2PConfig struct { + RootDir string `mapstructure:"home"` ListenAddress string `mapstructure:"laddr"` Seeds string `mapstructure:"seeds"` SkipUPNP bool `mapstructure:"skip_upnp"` - AddrBookFile string `mapstructure:"addr_book_file"` + AddrBook string `mapstructure:"addr_book_file"` AddrBookStrict bool `mapstructure:"addr_book_strict"` PexReactor bool `mapstructure:"pex_reactor"` MaxNumPeers int `mapstructure:"max_num_peers"` } -func DefaultP2PConfig(rootDir string) *P2PConfig { +func DefaultP2PConfig() *P2PConfig { return &P2PConfig{ ListenAddress: "tcp://0.0.0.0:46656", - AddrBookFile: rootDir + "/addrbook.json", + AddrBook: "addrbook.json", AddrBookStrict: true, MaxNumPeers: 50, } } +func (p *P2PConfig) AddrBookFile() string { + return rootify(p.AddrBook, p.RootDir) +} + type MempoolConfig struct { + RootDir string `mapstructure:"home"` Recheck bool `mapstructure:"recheck"` // true RecheckEmpty bool `mapstructure:"recheck_empty"` // true Broadcast bool `mapstructure:"broadcast"` // true - WalDir string `mapstructure:"wal_dir"` // + WalPath string `mapstructure:"wal_dir"` // } -func DefaultMempoolConfig(rootDir string) *MempoolConfig { +func DefaultMempoolConfig() *MempoolConfig { return &MempoolConfig{ Recheck: true, RecheckEmpty: true, Broadcast: true, - WalDir: rootDir + "/data/mempool.wal", + WalPath: "data/mempool.wal", } } +func (m *MempoolConfig) WalDir() string { + return rootify(m.WalPath, m.RootDir) +} + // ConsensusConfig holds timeouts and details about the WAL, the block structure, // and timeouts in the consensus protocol. type ConsensusConfig struct { - WalFile string `mapstructure:"wal_file"` + RootDir string `mapstructure:"home"` + WalPath string `mapstructure:"wal_file"` WalLight bool `mapstructure:"wal_light"` // All timeouts are in ms @@ -188,9 +223,9 @@ func (cfg *ConsensusConfig) Commit(t time.Time) time.Time { return t.Add(time.Duration(cfg.TimeoutCommit) * time.Millisecond) } -func DefaultConsensusConfig(rootDir string) *ConsensusConfig { +func DefaultConsensusConfig() *ConsensusConfig { return &ConsensusConfig{ - WalFile: rootDir + "/data/cs.wal/wal", + WalPath: "data/cs.wal/wal", WalLight: false, TimeoutPropose: 3000, TimeoutProposeDelta: 500, @@ -206,8 +241,8 @@ func DefaultConsensusConfig(rootDir string) *ConsensusConfig { } } -func TestConsensusConfig(rootDir string) *ConsensusConfig { - config := DefaultConsensusConfig(rootDir) +func TestConsensusConfig() *ConsensusConfig { + config := DefaultConsensusConfig() config.TimeoutPropose = 2000 config.TimeoutProposeDelta = 1 config.TimeoutPrevote = 10 @@ -218,3 +253,15 @@ func TestConsensusConfig(rootDir string) *ConsensusConfig { config.SkipTimeoutCommit = true return config } + +func (c *ConsensusConfig) WalFile() string { + return rootify(c.WalPath, c.RootDir) +} + +// helper function to make config creation independent of root dir +func rootify(path, root string) string { + if filepath.IsAbs(path) { + return path + } + return filepath.Join(root, path) +} diff --git a/consensus/replay_file.go b/consensus/replay_file.go index e7d904bff..3735f8942 100644 --- a/consensus/replay_file.go +++ b/consensus/replay_file.go @@ -23,7 +23,7 @@ import ( func RunReplayFile(config *cfg.BaseConfig, csConfig *cfg.ConsensusConfig, console bool) { consensusState := newConsensusStateForReplay(config, csConfig) - if err := consensusState.ReplayFile(csConfig.WalFile, console); err != nil { + if err := consensusState.ReplayFile(csConfig.WalFile(), console); err != nil { cmn.Exit(cmn.Fmt("Error during consensus replay: %v", err)) } } @@ -237,15 +237,15 @@ func (pb *playback) replayConsoleLoop() int { // convenience for replay mode func newConsensusStateForReplay(config *cfg.BaseConfig, csConfig *cfg.ConsensusConfig) *ConsensusState { // Get BlockStore - blockStoreDB := dbm.NewDB("blockstore", config.DBBackend, config.DBDir) + blockStoreDB := dbm.NewDB("blockstore", config.DBBackend, config.DBDir()) blockStore := bc.NewBlockStore(blockStoreDB) // Get State - stateDB := dbm.NewDB("state", config.DBBackend, config.DBDir) - state := sm.MakeGenesisStateFromFile(stateDB, config.GenesisFile) + stateDB := dbm.NewDB("state", config.DBBackend, config.DBDir()) + state := sm.MakeGenesisStateFromFile(stateDB, config.GenesisFile()) // Create proxyAppConn connection (consensus, mempool, query) - clientCreator := proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir) + clientCreator := proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()) proxyApp := proxy.NewAppConns(clientCreator, NewHandshaker(state, blockStore)) _, err := proxyApp.Start() if err != nil { diff --git a/consensus/state.go b/consensus/state.go index a565dfdce..579f22ce5 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -302,7 +302,7 @@ func (cs *ConsensusState) LoadCommit(height int) *types.Commit { func (cs *ConsensusState) OnStart() error { - walFile := cs.config.WalFile + walFile := cs.config.WalFile() if err := cs.OpenWAL(walFile); err != nil { log.Error("Error loading ConsensusState wal", "error", err.Error()) return err diff --git a/mempool/mempool.go b/mempool/mempool.go index 6b168897c..44a20e6f5 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -86,7 +86,7 @@ func NewMempool(config *cfg.MempoolConfig, proxyAppConn proxy.AppConnMempool) *M } func (mem *Mempool) initWAL() { - walDir := mem.config.WalDir + walDir := mem.config.WalDir() if walDir != "" { err := cmn.EnsureDir(walDir, 0700) if err != nil { diff --git a/node/node.go b/node/node.go index b206c2ad9..6896bc4f1 100644 --- a/node/node.go +++ b/node/node.go @@ -59,20 +59,20 @@ type Node struct { func NewNodeDefault(config *cfg.Config) *Node { // Get PrivValidator - privValidator := types.LoadOrGenPrivValidator(config.PrivValidatorFile) + privValidator := types.LoadOrGenPrivValidator(config.PrivValidatorFile()) return NewNode(config, privValidator, - proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir)) + proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir())) } func NewNode(config *cfg.Config, privValidator *types.PrivValidator, clientCreator proxy.ClientCreator) *Node { // Get BlockStore - blockStoreDB := dbm.NewDB("blockstore", config.DBBackend, config.DBDir) + blockStoreDB := dbm.NewDB("blockstore", config.DBBackend, config.DBDir()) blockStore := bc.NewBlockStore(blockStoreDB) // Get State - stateDB := dbm.NewDB("state", config.DBBackend, config.DBDir) - state := sm.GetState(stateDB, config.GenesisFile) + stateDB := dbm.NewDB("state", config.DBBackend, config.DBDir()) + state := sm.GetState(stateDB, config.GenesisFile()) // add the chainid and number of validators to the global config // TODO: Set ChainID. eg: @@ -93,7 +93,7 @@ func NewNode(config *cfg.Config, privValidator *types.PrivValidator, clientCreat var txIndexer txindex.TxIndexer switch config.TxIndex { case "kv": - store := dbm.NewDB("tx_index", config.DBBackend, config.DBDir) + store := dbm.NewDB("tx_index", config.DBBackend, config.DBDir()) txIndexer = kv.NewTxIndex(store) default: txIndexer = &null.TxIndex{} @@ -142,7 +142,7 @@ func NewNode(config *cfg.Config, privValidator *types.PrivValidator, clientCreat // Optionally, start the pex reactor var addrBook *p2p.AddrBook if config.P2P.PexReactor { - addrBook = p2p.NewAddrBook(config.P2P.AddrBookFile, config.P2P.AddrBookStrict) + addrBook = p2p.NewAddrBook(config.P2P.AddrBookFile(), config.P2P.AddrBookStrict) pexReactor := p2p.NewPEXReactor(addrBook) sw.AddReactor("PEX", pexReactor) }