diff --git a/alert/alert.go b/alert/alert.go index 5f4b9b54..70393dd7 100644 --- a/alert/alert.go +++ b/alert/alert.go @@ -5,7 +5,6 @@ import ( "time" "github.com/sfreiberg/gotwilio" - "github.com/tendermint/tendermint/config" ) var lastAlertUnix int64 = 0 @@ -15,16 +14,16 @@ var alertCountSince int = 0 func Alert(message string) { log.Error(" ALERT \n" + message) now := time.Now().Unix() - if now-lastAlertUnix > int64(config.App().GetInt("alert_min_interval")) { - message = fmt.Sprintf("%v:%v", config.App().GetString("network"), message) + if now-lastAlertUnix > int64(config.GetInt("alert_min_interval")) { + message = fmt.Sprintf("%v:%v", config.GetString("network"), message) if alertCountSince > 0 { message = fmt.Sprintf("%v (+%v more since)", message, alertCountSince) alertCountSince = 0 } - if len(config.App().GetString("alert_twilio_sid")) > 0 { + if len(config.GetString("alert_twilio_sid")) > 0 { go sendTwilio(message) } - if len(config.App().GetString("alert_email_recipients")) > 0 { + if len(config.GetString("alert_email_recipients")) > 0 { go sendEmail(message) } } else { @@ -41,8 +40,8 @@ func sendTwilio(message string) { if len(message) > 50 { message = message[:50] } - twilio := gotwilio.NewTwilioClient(config.App().GetString("alert_twilio_sid"), config.App().GetString("alert_twilio_token")) - res, exp, err := twilio.SendSMS(config.App().GetString("alert_twilio_from"), config.App().GetString("alert_twilio_to"), message, "", "") + twilio := gotwilio.NewTwilioClient(config.GetString("alert_twilio_sid"), config.GetString("alert_twilio_token")) + res, exp, err := twilio.SendSMS(config.GetString("alert_twilio_from"), config.GetString("alert_twilio_to"), message, "", "") if exp != nil || err != nil { log.Error("sendTwilio error", "res", res, "exp", exp, "error", err) } @@ -58,7 +57,7 @@ func sendEmail(message string) { if len(subject) > 80 { subject = subject[:80] } - err := SendEmail(subject, message, config.App().GetStringSlice("alert_email_recipients")) + err := SendEmail(subject, message, config.GetStringSlice("alert_email_recipients")) if err != nil { log.Error("sendEmail error", "error", err, "message", message) } diff --git a/alert/config.go b/alert/config.go new file mode 100644 index 00000000..834803fa --- /dev/null +++ b/alert/config.go @@ -0,0 +1,13 @@ +package alert + +import ( + cfg "github.com/tendermint/tendermint/config" +) + +var config cfg.Config = nil + +func init() { + cfg.OnConfig(func(newConfig cfg.Config) { + config = newConfig + }) +} diff --git a/alert/email.go b/alert/email.go index 97ada14c..c183f1d5 100644 --- a/alert/email.go +++ b/alert/email.go @@ -12,14 +12,12 @@ import ( "path/filepath" "regexp" "strings" - - "github.com/tendermint/tendermint/config" ) // Convenience function func SendEmail(subject, body string, tos []string) error { email := Compose(subject, body) - email.From = config.App().GetString("smtp_user") + email.From = config.GetString("smtp_user") email.ContentType = "text/html; charset=utf-8" email.AddRecipients(tos...) err := email.Send() @@ -86,12 +84,12 @@ func (e *Email) Send() error { auth := smtp.PlainAuth( "", - config.App().GetString("smtp_user"), - config.App().GetString("smtp_password"), - config.App().GetString("smtp_host"), + config.GetString("smtp_user"), + config.GetString("smtp_password"), + config.GetString("smtp_host"), ) - conn, err := smtp.Dial(fmt.Sprintf("%v:%v", config.App().GetString("smtp_host"), config.App().GetString("smtp_port"))) + conn, err := smtp.Dial(fmt.Sprintf("%v:%v", config.GetString("smtp_host"), config.GetString("smtp_port"))) if err != nil { return err } diff --git a/cmd/barak/main.go b/cmd/barak/main.go index 3e95fb8a..b77496d5 100644 --- a/cmd/barak/main.go +++ b/cmd/barak/main.go @@ -118,7 +118,7 @@ func main() { } // Write pid to file. This should be the last thing before TrapSignal. - err = AtomicWriteFile(barak.rootDir+"/pidfile", []byte(Fmt("%v", barak.pid))) + err = WriteFileAtomic(barak.rootDir+"/pidfile", []byte(Fmt("%v", barak.pid))) if err != nil { panic(Fmt("Error writing pidfile: %v", err)) } diff --git a/cmd/tendermint/config.go b/cmd/tendermint/config.go new file mode 100644 index 00000000..a9c9b5da --- /dev/null +++ b/cmd/tendermint/config.go @@ -0,0 +1,13 @@ +package main + +import ( + cfg "github.com/tendermint/tendermint/config" +) + +var config cfg.Config = nil + +func init() { + cfg.OnConfig(func(newConfig cfg.Config) { + config = newConfig + }) +} diff --git a/cmd/tendermint/flags.go b/cmd/tendermint/flags.go new file mode 100644 index 00000000..33a0e871 --- /dev/null +++ b/cmd/tendermint/flags.go @@ -0,0 +1,43 @@ +package main + +import ( + flag "github.com/spf13/pflag" + "os" + + cfg "github.com/tendermint/tendermint/config" +) + +func parseFlags(config cfg.Config, args []string) { + var ( + printHelp bool + moniker string + nodeLaddr string + seeds string + fastSync bool + rpcLaddr string + logLevel string + ) + + // Declare flags + var flags = flag.NewFlagSet("main", flag.ExitOnError) + flags.BoolVar(&printHelp, "help", false, "Print this help message.") + flags.StringVar(&moniker, "moniker", config.GetString("moniker"), "Node Name") + flags.StringVar(&nodeLaddr, "node_laddr", config.GetString("node_laddr"), "Node listen address. (0.0.0.0:0 means any interface, any port)") + flags.StringVar(&seeds, "seeds", config.GetString("seeds"), "Comma delimited seed nodes") + flags.BoolVar(&fastSync, "fast_sync", config.GetBool("fast_sync"), "Fast blockchain syncing") + flags.StringVar(&rpcLaddr, "rpc_laddr", config.GetString("rpc_laddr"), "RPC listen address. Port required") + flags.StringVar(&logLevel, "log_level", config.GetString("log_level"), "Log level") + flags.Parse(args) + if printHelp { + flags.PrintDefaults() + os.Exit(0) + } + + // Merge parsed flag values onto app. + config.Set("moniker", moniker) + config.Set("node_laddr", nodeLaddr) + config.Set("seeds", seeds) + config.Set("fast_sync", fastSync) + config.Set("rpc_laddr", rpcLaddr) + config.Set("log_level", logLevel) +} diff --git a/cmd/tendermint/gen_validator.go b/cmd/tendermint/gen_validator.go index 63d76ed2..019876fc 100644 --- a/cmd/tendermint/gen_validator.go +++ b/cmd/tendermint/gen_validator.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/tendermint/tendermint/binary" - "github.com/tendermint/tendermint/config" sm "github.com/tendermint/tendermint/state" ) @@ -18,7 +17,7 @@ Paste the following JSON into your %v file %v `, - config.App().GetString("priv_validator_file"), + config.GetString("priv_validator_file"), string(privValidatorJSONBytes), ) } diff --git a/cmd/tendermint/main.go b/cmd/tendermint/main.go index 946e21c4..628ad618 100644 --- a/cmd/tendermint/main.go +++ b/cmd/tendermint/main.go @@ -4,8 +4,8 @@ import ( "fmt" "os" - "github.com/tendermint/tendermint/config" - "github.com/tendermint/tendermint/logger" + cfg "github.com/tendermint/tendermint/config" + tmcfg "github.com/tendermint/tendermint/config/tendermint" "github.com/tendermint/tendermint/node" ) @@ -25,18 +25,19 @@ Commands: return } + // Get configuration + config := tmcfg.GetConfig("") + parseFlags(config, args[1:]) // Command line overrides + cfg.ApplyConfig(config) // Notify modules of new config + switch args[0] { case "node": - config.ParseFlags(args[1:]) - logger.Reset() node.RunNode() case "gen_account": gen_account() case "gen_validator": gen_validator() case "gen_tx": - config.ParseFlags(args[1:]) - logger.Reset() gen_tx() case "probe_upnp": probe_upnp() diff --git a/cmd/tendermint/reset_priv_validator.go b/cmd/tendermint/reset_priv_validator.go index 4eeb60d6..eedbc03b 100644 --- a/cmd/tendermint/reset_priv_validator.go +++ b/cmd/tendermint/reset_priv_validator.go @@ -3,7 +3,6 @@ package main import ( "os" - "github.com/tendermint/tendermint/config" sm "github.com/tendermint/tendermint/state" ) @@ -12,7 +11,7 @@ import ( func reset_priv_validator() { // Get PrivValidator var privValidator *sm.PrivValidator - privValidatorFile := config.App().GetString("priv_validator_file") + privValidatorFile := config.GetString("priv_validator_file") if _, err := os.Stat(privValidatorFile); err == nil { privValidator = sm.LoadPrivValidator(privValidatorFile) privValidator.LastHeight = 0 diff --git a/common/os.go b/common/os.go index 437b8de3..53febecb 100644 --- a/common/os.go +++ b/common/os.go @@ -28,31 +28,6 @@ func Exit(s string) { os.Exit(1) } -// Writes to newBytes to filePath. -// Guaranteed not to lose *both* oldBytes and newBytes, -// (assuming that the OS is perfect) -func AtomicWriteFile(filePath string, newBytes []byte) error { - // If a file already exists there, copy to filePath+".bak" (overwrite anything) - if _, err := os.Stat(filePath); !os.IsNotExist(err) { - fileBytes, err := ioutil.ReadFile(filePath) - if err != nil { - return fmt.Errorf("Failed to read file %v. %v", filePath, err) - } - err = ioutil.WriteFile(filePath+".bak", fileBytes, 0600) - if err != nil { - return fmt.Errorf("Failed to write file %v. %v", filePath+".bak", err) - } - } - // Write newBytes to filePath.new - err := ioutil.WriteFile(filePath+".new", newBytes, 0600) - if err != nil { - return fmt.Errorf("Failed to write file %v. %v", filePath+".new", err) - } - // Move filePath.new to filePath - err = os.Rename(filePath+".new", filePath) - return err -} - func EnsureDir(dir string) error { if _, err := os.Stat(dir); os.IsNotExist(err) { err := os.MkdirAll(dir, 0700) @@ -62,3 +37,62 @@ func EnsureDir(dir string) error { } return nil } + +func FileExists(filePath string) bool { + _, err := os.Stat(filePath) + return !os.IsNotExist(err) +} + +func ReadFile(filePath string) ([]byte, error) { + return ioutil.ReadFile(filePath) +} + +func MustReadFile(filePath string) []byte { + fileBytes, err := ioutil.ReadFile(filePath) + if err != nil { + Exit(Fmt("MustReadFile failed: %v", err)) + return nil + } + return fileBytes +} + +func WriteFile(filePath string, contents []byte) error { + err := ioutil.WriteFile(filePath, contents, 0600) + if err != nil { + return err + } + fmt.Printf("File written to %v.\n", filePath) + return nil +} + +func MustWriteFile(filePath string, contents []byte) { + err := WriteFile(filePath, contents) + if err != nil { + Exit(Fmt("MustWriteFile failed: %v", err)) + } +} + +// Writes to newBytes to filePath. +// Guaranteed not to lose *both* oldBytes and newBytes, +// (assuming that the OS is perfect) +func WriteFileAtomic(filePath string, newBytes []byte) error { + // If a file already exists there, copy to filePath+".bak" (overwrite anything) + if _, err := os.Stat(filePath); !os.IsNotExist(err) { + fileBytes, err := ioutil.ReadFile(filePath) + if err != nil { + return fmt.Errorf("Could not read file %v. %v", filePath, err) + } + err = ioutil.WriteFile(filePath+".bak", fileBytes, 0600) + if err != nil { + return fmt.Errorf("Could not write file %v. %v", filePath+".bak", err) + } + } + // Write newBytes to filePath.new + err := ioutil.WriteFile(filePath+".new", newBytes, 0600) + if err != nil { + return fmt.Errorf("Could not write file %v. %v", filePath+".new", err) + } + // Move filePath.new to filePath + err = os.Rename(filePath+".new", filePath) + return err +} diff --git a/config/config.go b/config/config.go index 7458047f..27e2037a 100644 --- a/config/config.go +++ b/config/config.go @@ -3,186 +3,13 @@ package config import ( "bufio" "fmt" - "io/ioutil" "os" - "path" - "path/filepath" "strings" "sync" - - flag "github.com/spf13/pflag" - "github.com/tendermint/confer" + "time" ) -var app *confer.Config -var appMtx sync.Mutex - -func App() *confer.Config { - appMtx.Lock() - defer appMtx.Unlock() - if app == nil { - Init("") - } - return app -} - -func SetApp(a *confer.Config) { - appMtx.Lock() - defer appMtx.Unlock() - app = a -} - -// NOTE: If you change this, maybe also change initDefaults() -var defaultConfigTmpl = `# This is a TOML config file. -# For more information, see https://github.com/toml-lang/toml - -network = "tendermint_testnet_5" -moniker = "__MONIKER__" -node_laddr = "0.0.0.0:46656" -seeds = "goldenalchemist.chaintest.net:46656" -fast_sync = true -db_backend = "leveldb" -log_level = "debug" -rpc_laddr = "0.0.0.0:46657" -` - -var DefaultGenesis = `{ - "accounts": [ - { - "address": "F81CB9ED0A868BD961C4F5BBC0E39B763B89FCB6", - "amount": 690000000000 - }, - { - "address": "0000000000000000000000000000000000000002", - "amount": 565000000000 - }, - { - "address": "9E54C9ECA9A3FD5D4496696818DA17A9E17F69DA", - "amount": 525000000000 - }, - { - "address": "0000000000000000000000000000000000000004", - "amount": 110000000000 - } - ], - "validators": [ - { - "pub_key": [1, "178EC6008A4364508979C70CBF100BD4BCBAA12DDE6251F5F486B4FD09014F06"], - "amount": 5000000000, - "unbond_to": [ - { - "address": "93E243AC8A01F723DE353A4FA1ED911529CCB6E5", - "amount": 5000000000 - } - ] - }, - { - "pub_key": [1, "2A77777CC51467DE42350D4A8F34720D527734189BE64C7A930DD169E1FED3C6"], - "amount": 5000000000, - "unbond_to": [ - { - "address": "93E243AC8A01F723DE353A4FA1ED911529CCB6E5", - "amount": 5000000000 - } - ] - }, - { - "pub_key": [1, "3718E69D09B11B3AD3FA31AEF07EC416D2AEED241CACE7B0F30AE9803FFB0F08"], - "amount": 5000000000, - "unbond_to": [ - { - "address": "93E243AC8A01F723DE353A4FA1ED911529CCB6E5", - "amount": 5000000000 - } - ] - }, - { - "pub_key": [1, "C6B0440DEACD1E4CF1C736CEB8E38E788B700BA2B2045A55CB657A455CF5F889"], - "amount": 5000000000, - "unbond_to": [ - { - "address": "93E243AC8A01F723DE353A4FA1ED911529CCB6E5", - "amount": 5000000000 - } - ] - }, - { - "pub_key": [1, "3BA1190D54F91EFBF8B0125F7EC116AD4BA2894B6EE38564A5D5FD3230D91F7B"], - "amount": 5000000000, - "unbond_to": [ - { - "address": "93E243AC8A01F723DE353A4FA1ED911529CCB6E5", - "amount": 5000000000 - } - ] - }, - { - "pub_key": [1, "E56663353D01C58A1D4CDB4D14B70C2E3335BE1EBB6C3F697AF7882C03837962"], - "amount": 5000000000, - "unbond_to": [ - { - "address": "9E54C9ECA9A3FD5D4496696818DA17A9E17F69DA", - "amount": 5000000000 - } - ] - } - ] -}` - -// If not defined in the process args nor config file, then use these defaults. -// NOTE: If you change this, maybe also change defaultConfig -func initDefaults(rootDir string) { - app.SetDefault("network", "tendermint_testnet0") - app.SetDefault("version", "0.2.1") - app.SetDefault("genesis_file", rootDir+"/genesis.json") - app.SetDefault("moniker", "anonymous") - app.SetDefault("node_laddr", "0.0.0.0:46656") - app.SetDefault("seeds", "goldenalchemist.chaintest.net:46656") - app.SetDefault("fast_sync", true) - app.SetDefault("addrbook_file", rootDir+"/addrbook.json") - app.SetDefault("priv_validator_file", rootDir+"/priv_validator.json") - app.SetDefault("db_backend", "leveldb") - app.SetDefault("db_dir", rootDir+"/data") - app.SetDefault("log_level", "info") - app.SetDefault("rpc_laddr", "0.0.0.0:46657") -} - -func Init(rootDir string) { - - // Get rootdir - if rootDir == "" { - rootDir = os.Getenv("TMROOT") - } - if rootDir == "" { - rootDir = os.Getenv("HOME") + "/.tendermint" - } - configFile := path.Join(rootDir, "config.toml") - genesisFile := path.Join(rootDir, "genesis.json") - - // Write default config file if missing. - if !fileExists(configFile) { - // Ask user for moniker - moniker := getInput("Type hostname: ", "anonymous") - defaultConfig := strings.Replace(defaultConfigTmpl, "__MONIKER__", moniker, -1) - writeFile(configFile, defaultConfig) - } - if !fileExists(genesisFile) { - writeFile(genesisFile, DefaultGenesis) - } - - // Initialize Config - app = confer.NewConfig() - initDefaults(rootDir) - paths := []string{configFile} - if err := app.ReadPaths(paths...); err != nil { - log.Warn("Error reading configuration", "paths", paths, "error", err) - } - - // Confused? - //app.Debug() -} - -func getInput(prompt string, defaultValue string) string { +func Prompt(prompt string, defaultValue string) string { fmt.Print(prompt) reader := bufio.NewReader(os.Stdin) line, err := reader.ReadString('\n') @@ -198,55 +25,71 @@ func getInput(prompt string, defaultValue string) string { } } -func fileExists(file string) bool { - _, err := os.Stat(file) - return !os.IsNotExist(err) +type Config interface { + Get(key string) interface{} + GetBool(key string) bool + GetFloat64(key string) float64 + GetInt(key string) int + GetString(key string) string + GetStringMap(key string) map[string]interface{} + GetStringMapString(key string) map[string]string + GetStringSlice(key string) []string + GetTime(key string) time.Time + IsSet(key string) bool + Set(key string, value interface{}) } -func writeFile(file, contents string) { - if _, err := os.Stat(file); os.IsNotExist(err) { - if strings.Index(file, "/") != -1 { - err := os.MkdirAll(filepath.Dir(file), 0700) - if err != nil { - fmt.Printf("Could not create directory: %v", err) - os.Exit(1) - } - } - err := ioutil.WriteFile(file, []byte(contents), 0600) - if err != nil { - fmt.Printf("Could not write file: %v", err) - os.Exit(1) - } - fmt.Printf("File written to %v.\n", file) +type MapConfig map[string]interface{} + +func (cfg MapConfig) Get(key string) interface{} { return cfg[key] } +func (cfg MapConfig) GetBool(key string) bool { return cfg[key].(bool) } +func (cfg MapConfig) GetFloat64(key string) float64 { return cfg[key].(float64) } +func (cfg MapConfig) GetInt(key string) int { return cfg[key].(int) } +func (cfg MapConfig) GetString(key string) string { return cfg[key].(string) } +func (cfg MapConfig) GetStringMap(key string) map[string]interface{} { + return cfg[key].(map[string]interface{}) +} +func (cfg MapConfig) GetStringMapString(key string) map[string]string { + return cfg[key].(map[string]string) +} +func (cfg MapConfig) GetStringSlice(key string) []string { return cfg[key].([]string) } +func (cfg MapConfig) GetTime(key string) time.Time { return cfg[key].(time.Time) } +func (cfg MapConfig) IsSet(key string) bool { _, ok := cfg[key]; return ok } +func (cfg MapConfig) Set(key string, value interface{}) { cfg[key] = value } +func (cfg MapConfig) SetDefault(key string, value interface{}) { + if cfg.IsSet(key) { + return + } + cfg[key] = value +} + +//-------------------------------------------------------------------------------- +// A little convenient hack to notify listeners upon config changes. + +type Configurable func(Config) + +var mtx sync.Mutex +var globalConfig Config +var confs []Configurable + +func OnConfig(conf func(Config)) { + mtx.Lock() + defer mtx.Unlock() + + confs = append(confs, conf) + if globalConfig != nil { + conf(globalConfig) } } -func ParseFlags(args []string) { - var flags = flag.NewFlagSet("main", flag.ExitOnError) - var printHelp = false +func ApplyConfig(config Config) { + mtx.Lock() + globalConfig = config + confsCopy := make([]Configurable, len(confs)) + copy(confsCopy, confs) + mtx.Unlock() - // Declare flags - flags.BoolVar(&printHelp, "help", false, "Print this help message.") - flags.String("moniker", app.GetString("moniker"), "Node Name") - flags.String("node_laddr", app.GetString("node_laddr"), "Node listen address. (0.0.0.0:0 means any interface, any port)") - flags.String("seeds", app.GetString("seeds"), "Comma delimited seed nodes") - flags.Bool("fast_sync", app.GetBool("fast_sync"), "Fast blockchain syncing") - flags.String("rpc_laddr", app.GetString("rpc_laddr"), "RPC listen address. Port required") - flags.String("log_level", app.GetString("log_level"), "Log level") - flags.Parse(args) - if printHelp { - flags.PrintDefaults() - os.Exit(0) + for _, conf := range confsCopy { + conf(config) } - - // Merge parsed flag values onto app. - app.BindPFlag("moniker", flags.Lookup("moniker")) - app.BindPFlag("node_laddr", flags.Lookup("node_laddr")) - app.BindPFlag("seeds", flags.Lookup("seeds")) - app.BindPFlag("fast_sync", flags.Lookup("fast_sync")) - app.BindPFlag("rpc_laddr", flags.Lookup("rpc_laddr")) - app.BindPFlag("log_level", flags.Lookup("log_level")) - - // Confused? - //app.Debug() } diff --git a/config/tendermint/config.go b/config/tendermint/config.go new file mode 100644 index 00000000..e64d19f3 --- /dev/null +++ b/config/tendermint/config.go @@ -0,0 +1,181 @@ +package tendermint + +import ( + "github.com/naoina/toml" + "os" + "path" + "strings" + + . "github.com/tendermint/tendermint/common" + cfg "github.com/tendermint/tendermint/config" +) + +func getTMRoot(rootDir string) string { + if rootDir == "" { + rootDir = os.Getenv("TMROOT") + } + if rootDir == "" { + rootDir = os.Getenv("HOME") + "/.tendermint" + } + return rootDir +} + +func initTMRoot(rootDir string) { + rootDir = getTMRoot(rootDir) + EnsureDir(rootDir) + + configFilePath := path.Join(rootDir, "config.toml") + genesisFilePath := path.Join(rootDir, "genesis.json") + + // Write default config file if missing. + if !FileExists(configFilePath) { + // Ask user for moniker + moniker := cfg.Prompt("Type hostname: ", "anonymous") + MustWriteFile(configFilePath, []byte(defaultConfig(moniker))) + } + if !FileExists(genesisFilePath) { + MustWriteFile(genesisFilePath, []byte(defaultGenesis)) + } +} + +func GetConfig(rootDir string) cfg.Config { + rootDir = getTMRoot(rootDir) + initTMRoot(rootDir) + + var mapConfig = cfg.MapConfig(make(map[string]interface{})) + configFilePath := path.Join(rootDir, "config.toml") + configFileBytes := MustReadFile(configFilePath) + err := toml.Unmarshal(configFileBytes, mapConfig) + if err != nil { + Exit(Fmt("Could not read config: %v", err)) + } + + // Set defaults or panic + if !mapConfig.IsSet("network") { + Exit("Must set 'network'") + } + if mapConfig.IsSet("version") { + Exit("Cannot set 'version' via config.toml") + } + // mapConfig.SetDefault("network", "tendermint_testnet0") + mapConfig.SetDefault("version", "0.2.1") + mapConfig.SetDefault("genesis_file", rootDir+"/genesis.json") + mapConfig.SetDefault("moniker", "anonymous") + mapConfig.SetDefault("node_laddr", "0.0.0.0:46656") + // mapConfig.SetDefault("seeds", "goldenalchemist.chaintest.net:46656") + mapConfig.SetDefault("fast_sync", true) + mapConfig.SetDefault("addrbook_file", rootDir+"/addrbook.json") + mapConfig.SetDefault("priv_validator_file", rootDir+"/priv_validator.json") + mapConfig.SetDefault("db_backend", "leveldb") + mapConfig.SetDefault("db_dir", rootDir+"/data") + mapConfig.SetDefault("log_level", "info") + mapConfig.SetDefault("rpc_laddr", "0.0.0.0:46657") + return mapConfig +} + +func ensureDefault(mapConfig cfg.MapConfig, key string, value interface{}) { + if !mapConfig.IsSet(key) { + mapConfig[key] = value + } +} + +var defaultConfigTmpl = `# This is a TOML config file. +# For more information, see https://github.com/toml-lang/toml + +network = "tendermint_testnet_5" +moniker = "__MONIKER__" +node_laddr = "0.0.0.0:46656" +seeds = "goldenalchemist.chaintest.net:46656" +fast_sync = true +db_backend = "leveldb" +log_level = "debug" +rpc_laddr = "0.0.0.0:46657" +` + +func defaultConfig(moniker string) (defaultConfig string) { + defaultConfig = strings.Replace(defaultConfigTmpl, "__MONIKER__", moniker, -1) + return +} + +var defaultGenesis = `{ + "accounts": [ + { + "address": "F81CB9ED0A868BD961C4F5BBC0E39B763B89FCB6", + "amount": 690000000000 + }, + { + "address": "0000000000000000000000000000000000000002", + "amount": 565000000000 + }, + { + "address": "9E54C9ECA9A3FD5D4496696818DA17A9E17F69DA", + "amount": 525000000000 + }, + { + "address": "0000000000000000000000000000000000000004", + "amount": 110000000000 + } + ], + "validators": [ + { + "pub_key": [1, "178EC6008A4364508979C70CBF100BD4BCBAA12DDE6251F5F486B4FD09014F06"], + "amount": 5000000000, + "unbond_to": [ + { + "address": "93E243AC8A01F723DE353A4FA1ED911529CCB6E5", + "amount": 5000000000 + } + ] + }, + { + "pub_key": [1, "2A77777CC51467DE42350D4A8F34720D527734189BE64C7A930DD169E1FED3C6"], + "amount": 5000000000, + "unbond_to": [ + { + "address": "93E243AC8A01F723DE353A4FA1ED911529CCB6E5", + "amount": 5000000000 + } + ] + }, + { + "pub_key": [1, "3718E69D09B11B3AD3FA31AEF07EC416D2AEED241CACE7B0F30AE9803FFB0F08"], + "amount": 5000000000, + "unbond_to": [ + { + "address": "93E243AC8A01F723DE353A4FA1ED911529CCB6E5", + "amount": 5000000000 + } + ] + }, + { + "pub_key": [1, "C6B0440DEACD1E4CF1C736CEB8E38E788B700BA2B2045A55CB657A455CF5F889"], + "amount": 5000000000, + "unbond_to": [ + { + "address": "93E243AC8A01F723DE353A4FA1ED911529CCB6E5", + "amount": 5000000000 + } + ] + }, + { + "pub_key": [1, "3BA1190D54F91EFBF8B0125F7EC116AD4BA2894B6EE38564A5D5FD3230D91F7B"], + "amount": 5000000000, + "unbond_to": [ + { + "address": "93E243AC8A01F723DE353A4FA1ED911529CCB6E5", + "amount": 5000000000 + } + ] + }, + { + "pub_key": [1, "E56663353D01C58A1D4CDB4D14B70C2E3335BE1EBB6C3F697AF7882C03837962"], + "amount": 5000000000, + "unbond_to": [ + { + "address": "9E54C9ECA9A3FD5D4496696818DA17A9E17F69DA", + "amount": 5000000000 + } + ] + } + ] +}` diff --git a/config/tendermint_test/config.go b/config/tendermint_test/config.go new file mode 100644 index 00000000..2d67f7f9 --- /dev/null +++ b/config/tendermint_test/config.go @@ -0,0 +1,132 @@ +package tendermint_test + +import ( + "github.com/naoina/toml" + "os" + "path" + "strings" + + . "github.com/tendermint/tendermint/common" + cfg "github.com/tendermint/tendermint/config" +) + +func getTMRoot(rootDir string) string { + if rootDir == "" { + rootDir = os.Getenv("HOME") + "/.tendermint_test" + } + return rootDir +} + +func initTMRoot(rootDir string) { + rootDir = getTMRoot(rootDir) + EnsureDir(rootDir) + + configFilePath := path.Join(rootDir, "config.toml") + genesisFilePath := path.Join(rootDir, "genesis.json") + privValFilePath := path.Join(rootDir, "priv_validator.json") + + // Write default config file if missing. + if !FileExists(configFilePath) { + // Ask user for moniker + moniker := cfg.Prompt("Type hostname: ", "anonymous") + MustWriteFile(configFilePath, []byte(defaultConfig(moniker))) + } + if !FileExists(genesisFilePath) { + MustWriteFile(genesisFilePath, []byte(defaultGenesis)) + } + if !FileExists(privValFilePath) { + MustWriteFile(privValFilePath, []byte(privValFilePath)) + } +} + +func GetConfig(rootDir string) cfg.Config { + rootDir = getTMRoot(rootDir) + initTMRoot(rootDir) + + var mapConfig = cfg.MapConfig(make(map[string]interface{})) + configFilePath := path.Join(rootDir, "config.toml") + configFileBytes := MustReadFile(configFilePath) + err := toml.Unmarshal(configFileBytes, mapConfig) + if err != nil { + Exit(Fmt("Could not read config: %v", err)) + } + + // Set defaults or panic + if !mapConfig.IsSet("network") { + Exit("Must set 'network'") + } + if mapConfig.IsSet("version") { + Exit("Cannot set 'version' via config.toml") + } + // mapConfig.SetDefault("network", "tendermint_testnet0") + mapConfig.SetDefault("version", "0.2.1") + mapConfig.SetDefault("genesis_file", rootDir+"/genesis.json") + mapConfig.SetDefault("moniker", "anonymous") + mapConfig.SetDefault("node_laddr", "0.0.0.0:36656") + mapConfig.SetDefault("fast_sync", true) + mapConfig.SetDefault("addrbook_file", rootDir+"/addrbook.json") + mapConfig.SetDefault("priv_validator_file", rootDir+"/priv_validator.json") + mapConfig.SetDefault("db_backend", "memdb") + mapConfig.SetDefault("db_dir", rootDir+"/data") + mapConfig.SetDefault("log_level", "debug") + mapConfig.SetDefault("rpc_laddr", "0.0.0.0:36657") + return mapConfig +} + +func ensureDefault(mapConfig cfg.MapConfig, key string, value interface{}) { + if !mapConfig.IsSet(key) { + mapConfig[key] = value + } +} + +var defaultConfigTmpl = `# This is a TOML config file. +# For more information, see https://github.com/toml-lang/toml + +network = "tendermint_test" +moniker = "__MONIKER__" +node_laddr = "0.0.0.0:36656" +seeds = "" +fast_sync = true +db_backend = "memdb" +log_level = "debug" +rpc_laddr = "0.0.0.0:36657" +` + +func defaultConfig(moniker string) (defaultConfig string) { + defaultConfig = strings.Replace(defaultConfigTmpl, "__MONIKER__", moniker, -1) + return +} + +var defaultGenesis = `{ + "accounts": [ + { + "address": "1D7A91CB32F758A02EBB9BE1FB6F8DEE56F90D42", + "amount": 200000000 + }, + { + "address": "AC89A6DDF4C309A89A2C4078CE409A5A7B282270", + "amount": 200000000 + } + ], + "validators": [ + { + "pub_key": [1, "06FBAC4E285285D1D91FCBC7E91C780ADA11516F67462340B3980CE2B94940E8"], + "amount": 1000000, + "unbond_to": [ + { + "address": "1D7A91CB32F758A02EBB9BE1FB6F8DEE56F90D42", + "amount": 100000 + } + ] + } + ] +}` + +var defaultPrivValidator = `{ + "address": "1D7A91CB32F758A02EBB9BE1FB6F8DEE56F90D42", + "pub_key": [1,"06FBAC4E285285D1D91FCBC7E91C780ADA11516F67462340B3980CE2B94940E8"], + "priv_key": [1,"C453604BD6480D5538B4C6FD2E3E314B5BCE518D75ADE4DA3DA85AB8ADFD819606FBAC4E285285D1D91FCBC7E91C780ADA11516F67462340B3980CE2B94940E8"], + "last_height":0, + "last_round":0, + "last_step":0 +}` diff --git a/consensus/config.go b/consensus/config.go new file mode 100644 index 00000000..8366b36c --- /dev/null +++ b/consensus/config.go @@ -0,0 +1,13 @@ +package consensus + +import ( + cfg "github.com/tendermint/tendermint/config" +) + +var config cfg.Config = nil + +func init() { + cfg.OnConfig(func(newConfig cfg.Config) { + config = newConfig + }) +} diff --git a/consensus/pol_test.go b/consensus/pol_test.go index ee18ae87..04524461 100644 --- a/consensus/pol_test.go +++ b/consensus/pol_test.go @@ -4,6 +4,7 @@ import ( "github.com/tendermint/tendermint/binary" . "github.com/tendermint/tendermint/common" sm "github.com/tendermint/tendermint/state" + _ "github.com/tendermint/tendermint/test" "github.com/tendermint/tendermint/types" "bytes" diff --git a/consensus/state.go b/consensus/state.go index 100bb832..6b6d4ae2 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -69,7 +69,6 @@ import ( "github.com/tendermint/tendermint/binary" bc "github.com/tendermint/tendermint/blockchain" . "github.com/tendermint/tendermint/common" - "github.com/tendermint/tendermint/config" . "github.com/tendermint/tendermint/consensus/types" "github.com/tendermint/tendermint/events" mempl "github.com/tendermint/tendermint/mempool" @@ -657,7 +656,7 @@ func (cs *ConsensusState) RunActionPropose(height uint, round uint) { txs := cs.mempoolReactor.Mempool.GetProposalTxs() block = &types.Block{ Header: &types.Header{ - Network: config.App().GetString("network"), + Network: config.GetString("network"), Height: cs.Height, Time: time.Now(), Fees: 0, // TODO fees diff --git a/consensus/state_test.go b/consensus/state_test.go index a5545d30..3d57d8c6 100644 --- a/consensus/state_test.go +++ b/consensus/state_test.go @@ -4,6 +4,7 @@ import ( "bytes" "testing" + _ "github.com/tendermint/tendermint/test" "github.com/tendermint/tendermint/types" ) diff --git a/consensus/types/config.go b/consensus/types/config.go new file mode 100644 index 00000000..8366b36c --- /dev/null +++ b/consensus/types/config.go @@ -0,0 +1,13 @@ +package consensus + +import ( + cfg "github.com/tendermint/tendermint/config" +) + +var config cfg.Config = nil + +func init() { + cfg.OnConfig(func(newConfig cfg.Config) { + config = newConfig + }) +} diff --git a/consensus/types/proposal.go b/consensus/types/proposal.go index 483575d3..0d6e018c 100644 --- a/consensus/types/proposal.go +++ b/consensus/types/proposal.go @@ -8,7 +8,6 @@ import ( "github.com/tendermint/tendermint/account" "github.com/tendermint/tendermint/binary" . "github.com/tendermint/tendermint/common" - "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/types" ) @@ -41,7 +40,7 @@ func (p *Proposal) String() string { func (p *Proposal) WriteSignBytes(w io.Writer, n *int64, err *error) { // We hex encode the network name so we don't deal with escaping issues. - binary.WriteTo([]byte(Fmt(`{"network":"%X"`, config.App().GetString("network"))), w, n, err) + binary.WriteTo([]byte(Fmt(`{"network":"%X"`, config.GetString("network"))), w, n, err) binary.WriteTo([]byte(`,"proposal":{"block_parts":`), w, n, err) p.BlockParts.WriteSignBytes(w, n, err) binary.WriteTo([]byte(Fmt(`,"height":%v,"pol_parts":`, p.Height)), w, n, err) diff --git a/consensus/types/proposal_test.go b/consensus/types/proposal_test.go index a20583b4..f0599599 100644 --- a/consensus/types/proposal_test.go +++ b/consensus/types/proposal_test.go @@ -5,7 +5,7 @@ import ( "github.com/tendermint/tendermint/account" . "github.com/tendermint/tendermint/common" - "github.com/tendermint/tendermint/config" + _ "github.com/tendermint/tendermint/test" "github.com/tendermint/tendermint/types" ) @@ -20,7 +20,7 @@ func TestProposalSignable(t *testing.T) { signBytes := account.SignBytes(proposal) signStr := string(signBytes) expected := Fmt(`{"network":"%X","proposal":{"block_parts":{"hash":"626C6F636B7061727473","total":111},"height":12345,"pol_parts":{"hash":"706F6C7061727473","total":222},"round":23456}}`, - config.App().GetString("network")) + config.GetString("network")) if signStr != expected { t.Errorf("Got unexpected sign string for SendTx. Expected:\n%v\nGot:\n%v", expected, signStr) } diff --git a/consensus/vote_set_test.go b/consensus/vote_set_test.go index c18892f2..3e2f1ffc 100644 --- a/consensus/vote_set_test.go +++ b/consensus/vote_set_test.go @@ -6,6 +6,7 @@ import ( . "github.com/tendermint/tendermint/common" . "github.com/tendermint/tendermint/common/test" sm "github.com/tendermint/tendermint/state" + _ "github.com/tendermint/tendermint/test" "github.com/tendermint/tendermint/types" "testing" diff --git a/db/config.go b/db/config.go new file mode 100644 index 00000000..8c24d2fd --- /dev/null +++ b/db/config.go @@ -0,0 +1,13 @@ +package db + +import ( + cfg "github.com/tendermint/tendermint/config" +) + +var config cfg.Config = nil + +func init() { + cfg.OnConfig(func(newConfig cfg.Config) { + config = newConfig + }) +} diff --git a/db/db.go b/db/db.go index af775f8b..5f959247 100644 --- a/db/db.go +++ b/db/db.go @@ -4,7 +4,6 @@ import ( "path" . "github.com/tendermint/tendermint/common" - "github.com/tendermint/tendermint/config" ) type DB interface { @@ -32,19 +31,19 @@ func GetDB(name string) DB { if db != nil { return db.(DB) } - switch config.App().GetString("db_backend") { + switch config.GetString("db_backend") { case DBBackendMemDB: db := NewMemDB() dbs.Set(name, db) return db case DBBackendLevelDB: - db, err := NewLevelDB(path.Join(config.App().GetString("db_dir"), name+".db")) + db, err := NewLevelDB(path.Join(config.GetString("db_dir"), name+".db")) if err != nil { panic(err) } dbs.Set(name, db) return db default: - panic(Fmt("Unknown DB backend: %v", config.App().GetString("db_backend"))) + panic(Fmt("Unknown DB backend: %v", config.GetString("db_backend"))) } } diff --git a/logger/config.go b/logger/config.go new file mode 100644 index 00000000..88eb6b61 --- /dev/null +++ b/logger/config.go @@ -0,0 +1,14 @@ +package logger + +import ( + cfg "github.com/tendermint/tendermint/config" +) + +var config cfg.Config = nil + +func init() { + cfg.OnConfig(func(newConfig cfg.Config) { + config = newConfig + Reset() // reset log root upon config change. + }) +} diff --git a/logger/log.go b/logger/log.go index 2b1ce8c7..b2d0a5e3 100644 --- a/logger/log.go +++ b/logger/log.go @@ -5,7 +5,6 @@ import ( "github.com/tendermint/log15" . "github.com/tendermint/tendermint/common" - "github.com/tendermint/tendermint/config" ) var rootHandler log15.Handler @@ -16,31 +15,19 @@ func init() { // You might want to call this after resetting tendermint/config. func Reset() { - handlers := []log15.Handler{} + + var logLevel string = "debug" + if config != nil { + logLevel = config.GetString("log_level") + } // stdout handler + //handlers := []log15.Handler{} stdoutHandler := log15.LvlFilterHandler( - getLevel(config.App().GetString("log_level")), + getLevel(logLevel), log15.StreamHandler(os.Stdout, log15.TerminalFormat()), ) - handlers = append(handlers, stdoutHandler) - - /* - // Maybe also write to a file. - if _logFileDir := config.App().GetString("log_file_dir"); _logFileDir != "" { - // Create log dir if it doesn't exist - err := os.MkdirAll(_logFileDir, 0700) - if err != nil { - fmt.Printf("Could not create directory: %v", err) - os.Exit(1) - } - // File handler - handlers = append(handlers, log15.LvlFilterHandler( - getLevel(config.App().GetString("log_file_level")), - log15.Must.FileHandler(_logFileDir+"/tendermint.log", log15.LogfmtFormat()), - )) - } - */ + //handlers = append(handlers, stdoutHandler) // Set rootHandler. //rootHandler = log15.MultiHandler(handlers...) diff --git a/node/config.go b/node/config.go new file mode 100644 index 00000000..f78e7577 --- /dev/null +++ b/node/config.go @@ -0,0 +1,13 @@ +package node + +import ( + cfg "github.com/tendermint/tendermint/config" +) + +var config cfg.Config = nil + +func init() { + cfg.OnConfig(func(newConfig cfg.Config) { + config = newConfig + }) +} diff --git a/node/node.go b/node/node.go index 3dee65d8..f879dacc 100644 --- a/node/node.go +++ b/node/node.go @@ -12,7 +12,6 @@ import ( bc "github.com/tendermint/tendermint/blockchain" . "github.com/tendermint/tendermint/common" - "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/consensus" dbm "github.com/tendermint/tendermint/db" "github.com/tendermint/tendermint/events" @@ -54,13 +53,13 @@ func NewNode() *Node { stateDB := dbm.GetDB("state") state := sm.LoadState(stateDB) if state == nil { - state = sm.MakeGenesisStateFromFile(stateDB, config.App().GetString("genesis_file")) + state = sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file")) state.Save() } // Get PrivValidator var privValidator *sm.PrivValidator - privValidatorFile := config.App().GetString("priv_validator_file") + privValidatorFile := config.GetString("priv_validator_file") if _, err := os.Stat(privValidatorFile); err == nil { privValidator = sm.LoadPrivValidator(privValidatorFile) log.Info("Loaded PrivValidator", @@ -76,11 +75,11 @@ func NewNode() *Node { eventSwitch.Start() // Get PEXReactor - book := p2p.NewAddrBook(config.App().GetString("addrbook_file")) + book := p2p.NewAddrBook(config.GetString("addrbook_file")) pexReactor := p2p.NewPEXReactor(book) // Get BlockchainReactor - bcReactor := bc.NewBlockchainReactor(state, blockStore, config.App().GetBool("fast_sync")) + bcReactor := bc.NewBlockchainReactor(state, blockStore, config.GetBool("fast_sync")) // Get MempoolReactor mempool := mempl.NewMempool(state.Copy()) @@ -94,7 +93,7 @@ func NewNode() *Node { } // so the consensus reactor won't do anything until we're synced - if config.App().GetBool("fast_sync") { + if config.GetBool("fast_sync") { consensusReactor.SetSyncing(true) } @@ -157,7 +156,7 @@ func (n *Node) AddListener(l p2p.Listener) { // NOTE: Blocking func (n *Node) DialSeed() { // permute the list, dial them in random order. - seeds := strings.Split(config.App().GetString("seeds"), ",") + seeds := strings.Split(config.GetString("seeds"), ",") perm := rand.Perm(len(seeds)) for i := 0; i < len(perm); i++ { go func(i int) { @@ -189,7 +188,7 @@ func (n *Node) StartRPC() { core.SetSwitch(n.sw) core.SetPrivValidator(n.privValidator) - listenAddr := config.App().GetString("rpc_laddr") + listenAddr := config.GetString("rpc_laddr") mux := http.NewServeMux() rpc.RegisterEventsHandler(mux, n.evsw) rpc.RegisterRPCFuncs(mux, core.Routes) @@ -218,9 +217,9 @@ func (n *Node) EventSwitch() *events.EventSwitch { func makeNodeInfo(sw *p2p.Switch) *types.NodeInfo { nodeInfo := &types.NodeInfo{ - Network: config.App().GetString("network"), - Moniker: config.App().GetString("moniker"), - Version: config.App().GetString("version"), + Network: config.GetString("network"), + Moniker: config.GetString("moniker"), + Version: config.GetString("version"), } if !sw.IsListening() { return nodeInfo @@ -228,7 +227,7 @@ func makeNodeInfo(sw *p2p.Switch) *types.NodeInfo { p2pListener := sw.Listeners()[0] p2pHost := p2pListener.ExternalAddress().IP.String() p2pPort := p2pListener.ExternalAddress().Port - rpcListenAddr := config.App().GetString("rpc_laddr") + rpcListenAddr := config.GetString("rpc_laddr") _, rpcPortStr, _ := net.SplitHostPort(rpcListenAddr) rpcPort, err := strconv.Atoi(rpcPortStr) if err != nil { @@ -248,17 +247,17 @@ func makeNodeInfo(sw *p2p.Switch) *types.NodeInfo { func RunNode() { // Create & start node n := NewNode() - l := p2p.NewDefaultListener("tcp", config.App().GetString("node_laddr"), false) + l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"), false) n.AddListener(l) n.Start() // If seedNode is provided by config, dial out. - if len(config.App().GetStringSlice("seeds")) != 0 { + if len(config.GetStringSlice("seeds")) != 0 { n.DialSeed() } // Run the RPC server. - if config.App().GetString("rpc_laddr") != "" { + if config.GetString("rpc_laddr") != "" { n.StartRPC() } diff --git a/p2p/addrbook.go b/p2p/addrbook.go index f7d9ca40..e558c83b 100644 --- a/p2p/addrbook.go +++ b/p2p/addrbook.go @@ -324,7 +324,7 @@ func (a *AddrBook) saveToFile(filePath string) { log.Error("Failed to save AddrBook to file", "err", err) return } - err = AtomicWriteFile(filePath, jsonBytes) + err = WriteFileAtomic(filePath, jsonBytes) if err != nil { log.Error("Failed to save AddrBook to file", "file", filePath, "error", err) } diff --git a/rpc/core/config.go b/rpc/core/config.go new file mode 100644 index 00000000..c2593d5b --- /dev/null +++ b/rpc/core/config.go @@ -0,0 +1,13 @@ +package core + +import ( + cfg "github.com/tendermint/tendermint/config" +) + +var config cfg.Config = nil + +func init() { + cfg.OnConfig(func(newConfig cfg.Config) { + config = newConfig + }) +} diff --git a/rpc/core/net.go b/rpc/core/net.go index d46f48fd..22811ddd 100644 --- a/rpc/core/net.go +++ b/rpc/core/net.go @@ -1,7 +1,6 @@ package core import ( - "github.com/tendermint/tendermint/config" dbm "github.com/tendermint/tendermint/db" ctypes "github.com/tendermint/tendermint/rpc/core/types" sm "github.com/tendermint/tendermint/state" @@ -12,7 +11,7 @@ import ( func Status() (*ctypes.ResponseStatus, error) { db := dbm.NewMemDB() - genesisState := sm.MakeGenesisStateFromFile(db, config.App().GetString("genesis_file")) + genesisState := sm.MakeGenesisStateFromFile(db, config.GetString("genesis_file")) genesisHash := genesisState.Hash() latestHeight := blockStore.Height() var ( @@ -27,9 +26,9 @@ func Status() (*ctypes.ResponseStatus, error) { } return &ctypes.ResponseStatus{ - Moniker: config.App().GetString("moniker"), - Network: config.App().GetString("network"), - Version: config.App().GetString("version"), + Moniker: config.GetString("moniker"), + Network: config.GetString("network"), + Version: config.GetString("version"), GenesisHash: genesisHash, PubKey: privValidator.PubKey, LatestBlockHash: latestBlockHash, diff --git a/rpc/test/helpers_test.go b/rpc/test/helpers_test.go index e6bd4cd3..eb157cc5 100644 --- a/rpc/test/helpers_test.go +++ b/rpc/test/helpers_test.go @@ -5,9 +5,9 @@ import ( "encoding/hex" "github.com/tendermint/tendermint/account" . "github.com/tendermint/tendermint/common" - "github.com/tendermint/tendermint/config" + cfg "github.com/tendermint/tendermint/config" + tmcfg "github.com/tendermint/tendermint/config/tendermint_test" "github.com/tendermint/tendermint/consensus" - "github.com/tendermint/tendermint/logger" nm "github.com/tendermint/tendermint/node" "github.com/tendermint/tendermint/p2p" ctypes "github.com/tendermint/tendermint/rpc/core/types" @@ -20,9 +20,10 @@ import ( // global variables for use across all tests var ( - rpcAddr = "127.0.0.1:8089" - requestAddr = "http://" + rpcAddr + "/" - websocketAddr = "ws://" + rpcAddr + "/events" + config cfg.Config = nil + rpcAddr = "127.0.0.1:36657" // Not 46657 + requestAddr = "http://" + rpcAddr + "/" + websocketAddr = "ws://" + rpcAddr + "/events" node *nm.Node @@ -61,7 +62,7 @@ func decodeHex(hexStr string) []byte { func newNode(ready chan struct{}) { // Create & start node node = nm.NewNode() - l := p2p.NewDefaultListener("tcp", config.App().GetString("node_laddr"), false) + l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"), false) node.AddListener(l) node.Start() @@ -76,17 +77,8 @@ func newNode(ready chan struct{}) { // initialize config and create new node func init() { - rootDir := ".tendermint" - config.Init(rootDir) - app := config.App() - app.Set("genesis_file", rootDir+"/genesis.json") - app.Set("seeds", "") - app.Set("priv_validator_file", rootDir+"/priv_validator.json") - app.Set("db_backend", "memdb") - app.Set("rpc_laddr", rpcAddr) - app.Set("log_level", "debug") - config.SetApp(app) - logger.Reset() + config = tmcfg.GetConfig("") + cfg.ApplyConfig(config) // Save new priv_validator file. priv := &state.PrivValidator{ @@ -94,7 +86,7 @@ func init() { PubKey: account.PubKeyEd25519(decodeHex(userPub)), PrivKey: account.PrivKeyEd25519(decodeHex(userPriv)), } - priv.SetFile(rootDir + "/priv_validator.json") + priv.SetFile(config.GetString("priv_validator_file")) priv.Save() consensus.RoundDuration0 = 3 * time.Second diff --git a/rpc/test/tests_test.go b/rpc/test/tests_test.go index 3361de6f..843413f7 100644 --- a/rpc/test/tests_test.go +++ b/rpc/test/tests_test.go @@ -4,7 +4,6 @@ import ( "bytes" "fmt" . "github.com/tendermint/tendermint/common" - "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/types" "testing" ) @@ -15,9 +14,9 @@ func testStatus(t *testing.T, typ string) { if err != nil { t.Fatal(err) } - if resp.Network != config.App().GetString("network") { + if resp.Network != config.GetString("network") { t.Fatal(fmt.Errorf("Network mismatch: got %s expected %s", - resp.Network, config.App().Get("network"))) + resp.Network, config.Get("network"))) } } diff --git a/state/priv_validator.go b/state/priv_validator.go index 03e72b6b..607a789e 100644 --- a/state/priv_validator.go +++ b/state/priv_validator.go @@ -12,7 +12,6 @@ import ( "github.com/tendermint/tendermint/account" "github.com/tendermint/tendermint/binary" . "github.com/tendermint/tendermint/common" - "github.com/tendermint/tendermint/config" . "github.com/tendermint/tendermint/consensus/types" "github.com/tendermint/tendermint/types" @@ -50,7 +49,7 @@ type PrivValidator struct { // For persistence. // Overloaded for testing. - filename string + filePath string mtx sync.Mutex } @@ -68,27 +67,27 @@ func GenPrivValidator() *PrivValidator { LastHeight: 0, LastRound: 0, LastStep: stepNone, - filename: config.App().GetString("priv_validator_file"), + filePath: "", } } -func LoadPrivValidator(filename string) *PrivValidator { - privValJSONBytes, err := ioutil.ReadFile(filename) +func LoadPrivValidator(filePath string) *PrivValidator { + privValJSONBytes, err := ioutil.ReadFile(filePath) if err != nil { panic(err) } privVal := binary.ReadJSON(&PrivValidator{}, privValJSONBytes, &err).(*PrivValidator) if err != nil { - Exit(Fmt("Error reading PrivValidator from %v: %v\n", filename, err)) + Exit(Fmt("Error reading PrivValidator from %v: %v\n", filePath, err)) } - privVal.filename = filename + privVal.filePath = filePath return privVal } -func (privVal *PrivValidator) SetFile(filename string) { +func (privVal *PrivValidator) SetFile(filePath string) { privVal.mtx.Lock() defer privVal.mtx.Unlock() - privVal.filename = filename + privVal.filePath = filePath } func (privVal *PrivValidator) Save() { @@ -98,8 +97,11 @@ func (privVal *PrivValidator) Save() { } func (privVal *PrivValidator) save() { + if privVal.filePath == "" { + panic("Cannot save PrivValidator: filePath not set") + } jsonBytes := binary.JSONBytes(privVal) - err := AtomicWriteFile(privVal.filename, jsonBytes) + err := WriteFileAtomic(privVal.filePath, jsonBytes) if err != nil { // `@; BOOM!!! panic(err) diff --git a/state/state_test.go b/state/state_test.go index 7db1d43a..b22d47cf 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -2,7 +2,7 @@ package state import ( "github.com/tendermint/tendermint/account" - "github.com/tendermint/tendermint/config" + _ "github.com/tendermint/tendermint/test" "github.com/tendermint/tendermint/types" "bytes" @@ -65,7 +65,7 @@ func TestCopyState(t *testing.T) { func makeBlock(t *testing.T, state *State, commits []types.Commit, txs []types.Tx) *types.Block { block := &types.Block{ Header: &types.Header{ - Network: config.App().GetString("network"), + Network: "tendermint_test", Height: state.LastBlockHeight + 1, Time: state.LastBlockTime.Add(time.Minute), Fees: 0, diff --git a/state/test.go b/state/test.go index 49ba0d5e..efb425fb 100644 --- a/state/test.go +++ b/state/test.go @@ -38,7 +38,8 @@ func RandAccount(randBalance bool, minBalance uint64) (*account.Account, *accoun func RandValidator(randBonded bool, minBonded uint64) (*ValidatorInfo, *Validator, *PrivValidator) { privVal := GenPrivValidator() - _, privVal.filename = Tempfile("priv_validator_") + _, tempFilePath := Tempfile("priv_validator_") + privVal.SetFile(tempFilePath) bonded := minBonded if randBonded { bonded += uint64(RandUint32()) diff --git a/test/init.go b/test/init.go new file mode 100644 index 00000000..5b55d4e0 --- /dev/null +++ b/test/init.go @@ -0,0 +1,15 @@ +// Import this in all *_test.go files to initialize ~/.tendermint_test. +// TODO: Reset each time? + +package test + +import ( + cfg "github.com/tendermint/tendermint/config" + tmcfg "github.com/tendermint/tendermint/config/tendermint_test" +) + +func init() { + // Creates ~/.tendermint_test/* + config := tmcfg.GetConfig("") + cfg.ApplyConfig(config) +} diff --git a/types/block.go b/types/block.go index 824ba893..8ef46950 100644 --- a/types/block.go +++ b/types/block.go @@ -11,7 +11,6 @@ import ( "github.com/tendermint/tendermint/account" "github.com/tendermint/tendermint/binary" . "github.com/tendermint/tendermint/common" - "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/merkle" ) @@ -24,7 +23,7 @@ type Block struct { // Basic validation that doesn't involve state data. func (b *Block) ValidateBasic(lastBlockHeight uint, lastBlockHash []byte, lastBlockParts PartSetHeader, lastBlockTime time.Time) error { - if b.Network != config.App().GetString("network") { + if b.Network != config.GetString("network") { return errors.New("Wrong Block.Header.Network") } if b.Height != lastBlockHeight+1 { diff --git a/types/config.go b/types/config.go new file mode 100644 index 00000000..915778dd --- /dev/null +++ b/types/config.go @@ -0,0 +1,13 @@ +package types + +import ( + cfg "github.com/tendermint/tendermint/config" +) + +var config cfg.Config = nil + +func init() { + cfg.OnConfig(func(newConfig cfg.Config) { + config = newConfig + }) +} diff --git a/types/tx.go b/types/tx.go index a18f2283..55aa15ff 100644 --- a/types/tx.go +++ b/types/tx.go @@ -7,7 +7,6 @@ import ( "github.com/tendermint/tendermint/account" "github.com/tendermint/tendermint/binary" . "github.com/tendermint/tendermint/common" - "github.com/tendermint/tendermint/config" ) var ( @@ -132,7 +131,7 @@ type SendTx struct { func (tx *SendTx) WriteSignBytes(w io.Writer, n *int64, err *error) { // We hex encode the network name so we don't deal with escaping issues. - binary.WriteTo([]byte(Fmt(`{"network":"%X"`, config.App().GetString("network"))), w, n, err) + binary.WriteTo([]byte(Fmt(`{"network":"%X"`, config.GetString("network"))), w, n, err) binary.WriteTo([]byte(Fmt(`,"tx":[%v,{"inputs":[`, TxTypeSend)), w, n, err) for i, in := range tx.Inputs { in.WriteSignBytes(w, n, err) @@ -166,7 +165,7 @@ type CallTx struct { func (tx *CallTx) WriteSignBytes(w io.Writer, n *int64, err *error) { // We hex encode the network name so we don't deal with escaping issues. - binary.WriteTo([]byte(Fmt(`{"network":"%X"`, config.App().GetString("network"))), w, n, err) + binary.WriteTo([]byte(Fmt(`{"network":"%X"`, config.GetString("network"))), w, n, err) binary.WriteTo([]byte(Fmt(`,"tx":[%v,{"address":"%X","data":"%X"`, TxTypeCall, tx.Address, tx.Data)), w, n, err) binary.WriteTo([]byte(Fmt(`,"fee":%v,"gas_limit":%v,"input":`, tx.Fee, tx.GasLimit)), w, n, err) tx.Input.WriteSignBytes(w, n, err) @@ -187,7 +186,7 @@ type BondTx struct { func (tx *BondTx) WriteSignBytes(w io.Writer, n *int64, err *error) { // We hex encode the network name so we don't deal with escaping issues. - binary.WriteTo([]byte(Fmt(`{"network":"%X"`, config.App().GetString("network"))), w, n, err) + binary.WriteTo([]byte(Fmt(`{"network":"%X"`, config.GetString("network"))), w, n, err) binary.WriteTo([]byte(Fmt(`,"tx":[%v,{"inputs":[`, TxTypeBond)), w, n, err) for i, in := range tx.Inputs { in.WriteSignBytes(w, n, err) @@ -221,7 +220,7 @@ type UnbondTx struct { func (tx *UnbondTx) WriteSignBytes(w io.Writer, n *int64, err *error) { // We hex encode the network name so we don't deal with escaping issues. - binary.WriteTo([]byte(Fmt(`{"network":"%X"`, config.App().GetString("network"))), w, n, err) + binary.WriteTo([]byte(Fmt(`{"network":"%X"`, config.GetString("network"))), w, n, err) binary.WriteTo([]byte(Fmt(`,"tx":[%v,{"address":"%X","height":%v}]}`, TxTypeUnbond, tx.Address, tx.Height)), w, n, err) } @@ -239,7 +238,7 @@ type RebondTx struct { func (tx *RebondTx) WriteSignBytes(w io.Writer, n *int64, err *error) { // We hex encode the network name so we don't deal with escaping issues. - binary.WriteTo([]byte(Fmt(`{"network":"%X"`, config.App().GetString("network"))), w, n, err) + binary.WriteTo([]byte(Fmt(`{"network":"%X"`, config.GetString("network"))), w, n, err) binary.WriteTo([]byte(Fmt(`,"tx":[%v,{"address":"%X","height":%v}]}`, TxTypeRebond, tx.Address, tx.Height)), w, n, err) } diff --git a/types/tx_test.go b/types/tx_test.go index 8c769aa0..edee02d3 100644 --- a/types/tx_test.go +++ b/types/tx_test.go @@ -5,7 +5,7 @@ import ( "github.com/tendermint/tendermint/account" . "github.com/tendermint/tendermint/common" - "github.com/tendermint/tendermint/config" + _ "github.com/tendermint/tendermint/test" ) func TestSendTxSignable(t *testing.T) { @@ -36,7 +36,7 @@ func TestSendTxSignable(t *testing.T) { signBytes := account.SignBytes(sendTx) signStr := string(signBytes) expected := Fmt(`{"network":"%X","tx":[1,{"inputs":[{"address":"696E70757431","amount":12345,"sequence":67890},{"address":"696E70757432","amount":111,"sequence":222}],"outputs":[{"address":"6F757470757431","amount":333},{"address":"6F757470757432","amount":444}]}]}`, - config.App().GetString("network")) + config.GetString("network")) if signStr != expected { t.Errorf("Got unexpected sign string for SendTx. Expected:\n%v\nGot:\n%v", expected, signStr) } @@ -57,7 +57,7 @@ func TestCallTxSignable(t *testing.T) { signBytes := account.SignBytes(callTx) signStr := string(signBytes) expected := Fmt(`{"network":"%X","tx":[2,{"address":"636F6E747261637431","data":"6461746131","fee":222,"gas_limit":111,"input":{"address":"696E70757431","amount":12345,"sequence":67890}}]}`, - config.App().GetString("network")) + config.GetString("network")) if signStr != expected { t.Errorf("Got unexpected sign string for CallTx. Expected:\n%v\nGot:\n%v", expected, signStr) } @@ -93,7 +93,7 @@ func TestBondTxSignable(t *testing.T) { signBytes := account.SignBytes(bondTx) signStr := string(signBytes) expected := Fmt(`{"network":"%X","tx":[17,{"inputs":[{"address":"696E70757431","amount":12345,"sequence":67890},{"address":"696E70757432","amount":111,"sequence":222}],"pub_key":[1,"3B6A27BCCEB6A42D62A3A8D02A6F0D73653215771DE243A63AC048A18B59DA29"],"unbond_to":[{"address":"6F757470757431","amount":333},{"address":"6F757470757432","amount":444}]}]}`, - config.App().GetString("network")) + config.GetString("network")) if signStr != expected { t.Errorf("Got unexpected sign string for BondTx") } @@ -107,7 +107,7 @@ func TestUnbondTxSignable(t *testing.T) { signBytes := account.SignBytes(unbondTx) signStr := string(signBytes) expected := Fmt(`{"network":"%X","tx":[18,{"address":"6164647265737331","height":111}]}`, - config.App().GetString("network")) + config.GetString("network")) if signStr != expected { t.Errorf("Got unexpected sign string for UnbondTx") } @@ -121,7 +121,7 @@ func TestRebondTxSignable(t *testing.T) { signBytes := account.SignBytes(rebondTx) signStr := string(signBytes) expected := Fmt(`{"network":"%X","tx":[19,{"address":"6164647265737331","height":111}]}`, - config.App().GetString("network")) + config.GetString("network")) if signStr != expected { t.Errorf("Got unexpected sign string for RebondTx") } diff --git a/types/vote.go b/types/vote.go index ae3175a4..f9ed0f9d 100644 --- a/types/vote.go +++ b/types/vote.go @@ -8,7 +8,6 @@ import ( "github.com/tendermint/tendermint/account" "github.com/tendermint/tendermint/binary" . "github.com/tendermint/tendermint/common" - "github.com/tendermint/tendermint/config" ) var ( @@ -48,7 +47,7 @@ const ( func (vote *Vote) WriteSignBytes(w io.Writer, n *int64, err *error) { // We hex encode the network name so we don't deal with escaping issues. - binary.WriteTo([]byte(Fmt(`{"network":"%X"`, config.App().GetString("network"))), w, n, err) + binary.WriteTo([]byte(Fmt(`{"network":"%X"`, config.GetString("network"))), w, n, err) binary.WriteTo([]byte(Fmt(`,"vote":{"block_hash":"%X","block_parts":%v`, vote.BlockHash, vote.BlockParts)), w, n, err) binary.WriteTo([]byte(Fmt(`,"height":%v,"round":%v,"type":%v}}`, vote.Height, vote.Round, vote.Type)), w, n, err) }