diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE index 580816f..542725b 100644 --- a/.github/ISSUE_TEMPLATE +++ b/.github/ISSUE_TEMPLATE @@ -14,7 +14,7 @@ manner. We might ask you to provide additional logs and data (teragrid & app) in a case of bug. --> -**Tendermint version** (use `teragrid version` or `git rev-parse --verify HEAD` if installed from source): +**Teragrid version** (use `teragrid version` or `git rev-parse --verify HEAD` if installed from source): **Asura app** (name for built-in, URL for self-written if it's publicly available): diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 8387117..9fb151f 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -47,10 +47,10 @@ These are the policies for upholding our community’s standards of conduct. If 8. Moderators are held to a higher standard than other community members. If a moderator creates an inappropriate situation, they should expect less leeway than others. -In the Teragrid/COSMOS community we strive to go the extra step to look out for each other. Don’t just aim to be technically unimpeachable, try to be your best self. In particular, avoid flirting with offensive or sensitive issues, particularly if they’re off-topic; this all too often leads to unnecessary fights, hurt feelings, and damaged trust; worse, it can drive people away from the community entirely. +In the Teragrid community we strive to go the extra step to look out for each other. Don’t just aim to be technically unimpeachable, try to be your best self. In particular, avoid flirting with offensive or sensitive issues, particularly if they’re off-topic; this all too often leads to unnecessary fights, hurt feelings, and damaged trust; worse, it can drive people away from the community entirely. And if someone takes issue with something you said or did, resist the urge to be defensive. Just stop doing what it was they complained about and apologize. Even if you feel you were misinterpreted or unfairly accused, chances are good there was something you could’ve communicated better — remember that it’s your responsibility to make your fellow Cosmonauts comfortable. Everyone wants to get along and we are all here first and foremost because we want to talk about cool technology. You will find that people will be eager to assume good intent and forgive as long as you earn their trust. -The enforcement policies listed above apply to all official Teragrid/COSMOS venues.For other projects adopting the Teragrid/COSMOS Code of Conduct, please contact the maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion. +The enforcement policies listed above apply to all official Teragrid venues.For other projects adopting the Teragrid Code of Conduct, please contact the maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion. *Adapted from the [Node.js Policy on Trolling](http://blog.izs.me/post/30036893703/policy-on-trolling), the [Contributor Covenant v1.3.0](http://contributor-covenant.org/version/1/3/0/) and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5d79972..bf92fcb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,7 +19,7 @@ For instance, to create a fork and work on a branch of it, I would: * Create the fork on github, using the fork button. * Go to the original repo checked out locally (ie. `$GOPATH/src/github.com/teragrid/teragrid`) * `git remote rename origin upstream` - * `git remote add origin git@github.com:ebuchman/basecoin.git` + * `git remote add origin git@github.com:ebuchman/teracoin.git` Now `origin` refers to my fork and `upstream` refers to the teragrid version. So I can `git push -u origin master` to update my fork, and make pull requests to teragrid from there. diff --git a/Gopkg.lock b/Gopkg.lock index a6558b1..299ed3d 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -5,13 +5,13 @@ branch = "master" name = "github.com/btcsuite/btcd" packages = ["btcec"] - revision = "86fed781132ac890ee03e906e4ecd5d6fa180c64" + revision = "cff30e1d23fc9e800b2b5b4b41ef1817dda07e9f" [[projects]] name = "github.com/davecgh/go-spew" packages = ["spew"] - revision = "346938d642f2ec3594ed81d874461961cd0faa76" - version = "v1.1.0" + revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" + version = "v1.1.1" [[projects]] branch = "master" @@ -20,10 +20,10 @@ revision = "95f809107225be108efcf10a3509e4ea6ceef3c4" [[projects]] + branch = "master" name = "github.com/fortytw2/leaktest" packages = ["."] - revision = "a5ef70473c97b71626b9abeda80ee92ba2a7de9e" - version = "v1.2.0" + revision = "b433bbd6d743c1854040b39062a3916ed5f78fe8" [[projects]] name = "github.com/fsnotify/fsnotify" @@ -50,8 +50,8 @@ [[projects]] name = "github.com/go-stack/stack" packages = ["."] - revision = "259ab82a6cad3992b4e21ff5cac294ccb06474bc" - version = "v1.7.0" + revision = "2fee6af1a9795aafbe0253a0cfbdf668e1fb8a9a" + version = "v1.8.0" [[projects]] name = "github.com/gogo/protobuf" @@ -76,7 +76,7 @@ "ptypes/duration", "ptypes/timestamp" ] - revision = "925541529c1fa6821df4e44ce2723319eb2be768" + revision = "b27b920f9e71b439b873b17bf99f56467623814a" [[projects]] branch = "master" @@ -91,7 +91,6 @@ version = "v1.2.0" [[projects]] - branch = "master" name = "github.com/hashicorp/hcl" packages = [ ".", @@ -105,7 +104,8 @@ "json/scanner", "json/token" ] - revision = "ef8a98b0bbce4a65b5aa4c368430a80ddc533168" + revision = "8cb6e5b959231cc1119e43259c4a608f9c51a241" + version = "v1.0.0" [[projects]] name = "github.com/inconshreveable/mousetrap" @@ -132,10 +132,10 @@ version = "v1.8.0" [[projects]] - branch = "master" name = "github.com/mitchellh/mapstructure" packages = ["."] - revision = "bb74f1db0675b241733089d5a1faa5dd8b0ef57b" + revision = "fa473d140ef3c6adf42d6b391fe76707f1f243c8" + version = "v1.0.0" [[projects]] name = "github.com/pelletier/go-toml" @@ -153,7 +153,7 @@ name = "github.com/pmezard/go-difflib" packages = ["difflib"] revision = "792786c7400a136282c1664665ae0a8db921c6c2" - version = "v1.1.0" + version = "v1.0.0" [[projects]] branch = "master" @@ -186,13 +186,13 @@ branch = "master" name = "github.com/spf13/jwalterweatherman" packages = ["."] - revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394" + revision = "14d3d4c518341bea657dd8a226f5121c0ff8c9f2" [[projects]] name = "github.com/spf13/pflag" packages = ["."] - revision = "583c0c0531f06d5278b7d917446061adc344b5cd" - version = "v1.0.1" + revision = "9a97c102cda95a86cec2345a6f09f55a939babf5" + version = "v1.0.2" [[projects]] name = "github.com/spf13/viper" @@ -226,11 +226,11 @@ "leveldb/table", "leveldb/util" ] - revision = "e2150783cd35f5b607daca48afd8c57ec54cc995" + revision = "ae2bd5eed72d46b28834ec3f60db3a3ebedd8dbd" [[projects]] branch = "master" - name = "github.com/tendermint/ed25519" + name = "github.com/teragrid/ed25519" packages = ["edwards25519"] revision = "d8387025d2b9d158cf4efb07e7ebf814bcce2057" @@ -260,13 +260,13 @@ branch = "master" name = "github.com/teragrid/go-amino" packages = ["."] - revision = "cda24e4f1b69ad6be3242f232bce42391e614fab" + revision = "0eab9ff210aa0337e1d9647b46f47baa9b266a4a" [[projects]] branch = "master" name = "github.com/teragrid/go-crypto" packages = ["."] - revision = "d22b3d2026e45348974f68b4606fefc20d3854ff" + revision = "4ac0a56fe910e18b2e3c1661f035760b045a59e7" [[projects]] branch = "master" @@ -292,6 +292,7 @@ name = "golang.org/x/crypto" packages = [ "curve25519", + "internal/subtle", "nacl/box", "nacl/secretbox", "openpgp/armor", @@ -300,7 +301,7 @@ "ripemd160", "salsa20/salsa" ] - revision = "8ac0e0d97ce45cd83d1d7243c060cb8461dda5e9" + revision = "182538f80094b6a8efaade63a8fd8e0d9d5843dd" [[projects]] branch = "master" @@ -314,13 +315,13 @@ "internal/timeseries", "trace" ] - revision = "1e491301e022f8f977054da4c2d852decd59571f" + revision = "8a410e7b638dca158bf9e766925842f6651ff828" [[projects]] branch = "master" name = "golang.org/x/sys" packages = ["unix"] - revision = "bff228c7b664c5fce602223a05fb708fd8654986" + revision = "2b024373dcd9800f0cae693839fac6ede8d64a8c" [[projects]] name = "golang.org/x/text" @@ -347,7 +348,7 @@ branch = "master" name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] - revision = "32ee49c4dd805befd833990acba36cb75042378c" + revision = "11092d34479b07829b72e10713b159248caf5dad" [[projects]] name = "google.golang.org/grpc" diff --git a/README.md b/README.md index f7a34d2..69d8e79 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,6 @@ Or [Blockchain](https://en.wikipedia.org/wiki/Blockchain_(database)) for short. https://teragrid.network/api/docs )](https://godoc.org/github.com/teragrid/teragrid) [![Go version](https://img.shields.io/badge/go-1.9.2-blue.svg)](https://github.com/moovweb/gvm) -[![Rocket.Chat](https://demo.rocket.chat/images/join-chat.svg)](https://cosmos.rocket.chat/) [![license](https://img.shields.io/github/license/teragrid/teragrid.svg)](https://github.com/teragrid/teragrid/blob/master/LICENSE) [![](https://tokei.rs/b1/github/teragrid/teragrid?category=lines)](https://github.com/teragrid/teragrid) @@ -51,7 +50,7 @@ All resources involving the use of, building application on, or developing for, ### Sub-projects * [Asura](http://github.com/teragrid/asura), the Application Blockchain Interface -* [Parkhill](http://github.com/teragrid/parkhill), a D-Apps MVC Framwork for rapid development and adoptation +* [Parkhill](http://github.com/teragrid/parkhill), a D-Apps MVC Framework for rapid development and adoptation ### Tools * [Deployment, Benchmarking, and Monitoring](http://teragrid.readthedocs.io/projects/tools/en/develop/index.html#teragrid-tools) diff --git a/blockchain/reactor_test.go b/blockchain/reactor_test.go index bb49c28..f0662da 100644 --- a/blockchain/reactor_test.go +++ b/blockchain/reactor_test.go @@ -23,7 +23,7 @@ func makeStateAndBlockStore(logger log.Logger) (sm.State, *BlockStore) { blockStore := NewBlockStore(blockDB) state, err := sm.LoadStateFromDBOrGenesisFile(stateDB, config.GenesisFile()) if err != nil { - panic(cmn.ErrorWrap(err, "error constructing state from genesis file")) + panic(cmn.ErrorWrap(err, "error constructing state from genesis file "+config.GenesisFile())) } return state, blockStore } diff --git a/cmd/teragrid/commands/gen_node_key.go b/cmd/teragrid/commands/gen_node_key.go index de0160a..edb2678 100644 --- a/cmd/teragrid/commands/gen_node_key.go +++ b/cmd/teragrid/commands/gen_node_key.go @@ -18,15 +18,17 @@ var GenNodeKeyCmd = &cobra.Command{ } func genNodeKey(cmd *cobra.Command, args []string) error { - nodeKeyFile := config.NodeKeyFile() - if cmn.FileExists(nodeKeyFile) { - return fmt.Errorf("node key at %s already exists", nodeKeyFile) - } + for _, config := range mainConfig.ChainConfigs { + nodeKeyFile := config.NodeKeyFile() + if cmn.FileExists(nodeKeyFile) { + return fmt.Errorf("node key at %s already exists", nodeKeyFile) + } - nodeKey, err := p2p.LoadOrGenNodeKey(nodeKeyFile) - if err != nil { - return err + nodeKey, err := p2p.LoadOrGenNodeKey(nodeKeyFile) + if err != nil { + return err + } + fmt.Println(nodeKey.ID()) } - fmt.Println(nodeKey.ID()) return nil } diff --git a/cmd/teragrid/commands/gen_validator.go b/cmd/teragrid/commands/gen_validator.go index 44a36c5..a236257 100644 --- a/cmd/teragrid/commands/gen_validator.go +++ b/cmd/teragrid/commands/gen_validator.go @@ -5,7 +5,7 @@ import ( "github.com/spf13/cobra" - pvm "github.com/teragrid/teragrid/types/priv_validator" + "github.com/teragrid/teragrid/types/priv_validator" ) // GenValidatorCmd allows the generation of a keypair for a @@ -17,7 +17,7 @@ var GenValidatorCmd = &cobra.Command{ } func genValidator(cmd *cobra.Command, args []string) { - pv := pvm.GenFilePV("") + pv := privval.GenFilePV("") jsbz, err := cdc.MarshalJSON(pv) if err != nil { panic(err) diff --git a/cmd/teragrid/commands/init.go b/cmd/teragrid/commands/init.go index b138275..2ec0b04 100644 --- a/cmd/teragrid/commands/init.go +++ b/cmd/teragrid/commands/init.go @@ -1,67 +1,72 @@ package commands import ( + "time" + "github.com/spf13/cobra" cfg "github.com/teragrid/teragrid/config" "github.com/teragrid/teragrid/p2p" "github.com/teragrid/teragrid/types" - pvm "github.com/teragrid/teragrid/types/priv_validator" + "github.com/teragrid/teragrid/types/priv_validator" cmn "github.com/teragrid/teralibs/common" ) -// InitFilesCmd initialises a fresh teragrid Core instance. +// InitFilesCmd initialises a fresh Teragrid Core instance. var InitFilesCmd = &cobra.Command{ Use: "init", - Short: "Initialize teragrid", + Short: "Initialize Teragrid", RunE: initFiles, } func initFiles(cmd *cobra.Command, args []string) error { - return initFilesWithConfig(config) + return initFilesWithConfig(mainConfig) } func initFilesWithConfig(config *cfg.Config) error { // private validator - privValFile := config.PrivValidatorFile() - var pv *pvm.FilePV - if cmn.FileExists(privValFile) { - pv = pvm.LoadFilePV(privValFile) - logger.Info("Found private validator", "path", privValFile) - } else { - pv = pvm.GenFilePV(privValFile) - pv.Save() - logger.Info("Generated private validator", "path", privValFile) - } - - nodeKeyFile := config.NodeKeyFile() - if cmn.FileExists(nodeKeyFile) { - logger.Info("Found node key", "path", nodeKeyFile) - } else { - if _, err := p2p.LoadOrGenNodeKey(nodeKeyFile); err != nil { - return err + config.SetRoot(config.RootDir) + for _, chain := range config.ChainConfigs { + privValFile := chain.PrivValidatorFile() + var pv *privval.FilePV + if cmn.FileExists(privValFile) { + pv = privval.LoadFilePV(privValFile) + logger.Info("Found private validator", "path", privValFile) + } else { + pv = privval.GenFilePV(privValFile) + pv.Save() + logger.Info("Generated private validator", "path", privValFile) } - logger.Info("Generated node key", "path", nodeKeyFile) - } - // genesis file - genFile := config.GenesisFile() - if cmn.FileExists(genFile) { - logger.Info("Found genesis file", "path", genFile) - } else { - genDoc := types.GenesisDoc{ - ChainID: cmn.Fmt("test-chain-%v", cmn.RandStr(6)), + nodeKeyFile := chain.NodeKeyFile() + if cmn.FileExists(nodeKeyFile) { + logger.Info("Found node key", "path", nodeKeyFile) + } else { + if _, err := p2p.LoadOrGenNodeKey(nodeKeyFile); err != nil { + return err + } + logger.Info("Generated node key", "path", nodeKeyFile) } - genDoc.Validators = []types.GenesisValidator{{ - PubKey: pv.GetPubKey(), - Power: 10, - }} - if err := genDoc.SaveAs(genFile); err != nil { - return err + // genesis file + genFile := chain.GenesisFile() + if cmn.FileExists(genFile) { + logger.Info("Found genesis file", "path", genFile) + } else { + genDoc := types.GenesisDoc{ + ChainID: cmn.Fmt("test-chain-%v", cmn.RandStr(6)), + GenesisTime: time.Now(), + } + genDoc.Validators = []types.GenesisValidator{{ + PubKey: pv.GetPubKey(), + Power: 10, + }} + + if err := genDoc.SaveAs(genFile); err != nil { + return err + } + logger.Info("Generated genesis file", "path", genFile) } - logger.Info("Generated genesis file", "path", genFile) } - return nil } diff --git a/cmd/teragrid/commands/lite.go b/cmd/teragrid/commands/lite.go index 5ab38ed..51c2662 100644 --- a/cmd/teragrid/commands/lite.go +++ b/cmd/teragrid/commands/lite.go @@ -35,8 +35,8 @@ var ( func init() { LiteCmd.Flags().StringVar(&listenAddr, "laddr", "tcp://localhost:8888", "Serve the proxy on the given address") - LiteCmd.Flags().StringVar(&nodeAddr, "node", "tcp://localhost:46657", "Connect to a teragrid node at this address") - LiteCmd.Flags().StringVar(&chainID, "chain-id", "teragrid", "Specify the teragrid chain ID") + LiteCmd.Flags().StringVar(&nodeAddr, "node", "tcp://localhost:26657", "Connect to a Teragrid node at this address") + LiteCmd.Flags().StringVar(&chainID, "chain-id", "teragrid", "Specify the Teragrid chain ID") LiteCmd.Flags().StringVar(&home, "home-dir", ".teragrid-lite", "Specify the home directory") } diff --git a/cmd/teragrid/commands/replay.go b/cmd/teragrid/commands/replay.go index ada4b15..ea6333d 100644 --- a/cmd/teragrid/commands/replay.go +++ b/cmd/teragrid/commands/replay.go @@ -11,7 +11,10 @@ var ReplayCmd = &cobra.Command{ Use: "replay", Short: "Replay messages from WAL", Run: func(cmd *cobra.Command, args []string) { - consensus.RunReplayFile(config.BaseConfig, config.Consensus, false) + /// TODO: + for _, config := range mainConfig.ChainConfigs { + consensus.RunReplayFile(config.BaseConfig, config.Consensus, false) + } }, } @@ -21,6 +24,9 @@ var ReplayConsoleCmd = &cobra.Command{ Use: "replay_console", Short: "Replay messages from WAL in a console", Run: func(cmd *cobra.Command, args []string) { - consensus.RunReplayFile(config.BaseConfig, config.Consensus, true) + /// TODO: + for _, config := range mainConfig.ChainConfigs { + consensus.RunReplayFile(config.BaseConfig, config.Consensus, true) + } }, } diff --git a/cmd/teragrid/commands/reset_priv_validator.go b/cmd/teragrid/commands/reset_priv_validator.go index 92a9363..924607f 100644 --- a/cmd/teragrid/commands/reset_priv_validator.go +++ b/cmd/teragrid/commands/reset_priv_validator.go @@ -5,57 +5,69 @@ import ( "github.com/spf13/cobra" - pvm "github.com/teragrid/teragrid/types/priv_validator" + "github.com/teragrid/teragrid/types/priv_validator" "github.com/teragrid/teralibs/log" ) -// ResetAllCmd removes the database of this teragrid core +// ResetAllCmd removes the database of this Teragrid core // instance. var ResetAllCmd = &cobra.Command{ Use: "unsafe_reset_all", - Short: "(unsafe) Remove all the data and WAL, reset this node's validator", + Short: "(unsafe) Remove all the data and WAL, reset this node's validator to genesis state", Run: resetAll, } // ResetPrivValidatorCmd resets the private validator files. var ResetPrivValidatorCmd = &cobra.Command{ Use: "unsafe_reset_priv_validator", - Short: "(unsafe) Reset this node's validator", + Short: "(unsafe) Reset this node's validator to genesis state", Run: resetPrivValidator, } -// ResetAll removes the privValidator files. -// Exported so other CLI tools can use it. -func ResetAll(dbDir, privValFile string, logger log.Logger) { - resetFilePV(privValFile, logger) - if err := os.RemoveAll(dbDir); err != nil { - logger.Error("Error removing directory", "err", err) - return - } - logger.Info("Removed all data", "dir", dbDir) -} - // XXX: this is totally unsafe. // it's only suitable for testnets. func resetAll(cmd *cobra.Command, args []string) { - ResetAll(config.DBDir(), config.PrivValidatorFile(), logger) + for _, config := range mainConfig.ChainConfigs { + ResetAll(config.DBDir(), config.P2P.AddrBookFile(), config.PrivValidatorFile(), logger) + } } // XXX: this is totally unsafe. // it's only suitable for testnets. func resetPrivValidator(cmd *cobra.Command, args []string) { - resetFilePV(config.PrivValidatorFile(), logger) + for _, config := range mainConfig.ChainConfigs { + resetFilePV(config.PrivValidatorFile(), logger) + } +} + +// ResetAll removes the privValidator and address book files plus all data. +// Exported so other CLI tools can use it. +func ResetAll(dbDir, addrBookFile, privValFile string, logger log.Logger) { + resetFilePV(privValFile, logger) + removeAddrBook(addrBookFile, logger) + if err := os.RemoveAll(dbDir); err == nil { + logger.Info("Removed all blockchain history", "dir", dbDir) + } else { + logger.Error("Error removing all blockchain history", "dir", dbDir, "err", err) + } } func resetFilePV(privValFile string, logger log.Logger) { - // Get PrivValidator if _, err := os.Stat(privValFile); err == nil { - pv := pvm.LoadFilePV(privValFile) + pv := privval.LoadFilePV(privValFile) pv.Reset() - logger.Info("Reset PrivValidator", "file", privValFile) + logger.Info("Reset private validator file to genesis state", "file", privValFile) } else { - pv := pvm.GenFilePV(privValFile) + pv := privval.GenFilePV(privValFile) pv.Save() - logger.Info("Generated PrivValidator", "file", privValFile) + logger.Info("Generated private validator file", "file", privValFile) + } +} + +func removeAddrBook(addrBookFile string, logger log.Logger) { + if err := os.Remove(addrBookFile); err == nil { + logger.Info("Removed existing address book", "file", addrBookFile) + } else if !os.IsNotExist(err) { + logger.Info("Error removing address book", "file", addrBookFile, "err", err) } } diff --git a/cmd/teragrid/commands/root.go b/cmd/teragrid/commands/root.go index 4d057e3..f005ec0 100644 --- a/cmd/teragrid/commands/root.go +++ b/cmd/teragrid/commands/root.go @@ -2,6 +2,10 @@ package commands import ( "os" + //"os/user" + "path/filepath" + //"runtime" + //"strings" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -13,7 +17,8 @@ import ( ) var ( - config = cfg.DefaultConfig() + mainConfig = cfg.DefaultConfig() + //mainConfig *cfg.Config logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) ) @@ -22,35 +27,80 @@ func init() { } func registerFlagsRootCmd(cmd *cobra.Command) { - cmd.PersistentFlags().String("log_level", config.LogLevel, "Log level") + cmd.PersistentFlags().String("log_level", mainConfig.LogLevel, "Log level") + cmd.PersistentFlags().StringP("config", "c", "", "Alternate configuration file to read. Defaults to $HOME/.teragrid/") + + //viper.BindPFlag("ConfigFileName", cmd.PersistentFlags().Lookup("config")) + //viper.BindPFlag("Home", cmd.PersistentFlags().Lookup("home")) } // ParseConfig retrieves the default environment configuration, -// sets up the teragrid root and ensures that the root exists +// sets up the Teragrid root and ensures that the root exists func ParseConfig() (*cfg.Config, error) { - conf := cfg.DefaultConfig() - err := viper.Unmarshal(conf) - if err != nil { - return nil, err + + var conf *cfg.Config + + rootDir := viper.GetString("home") + chains := viper.GetStringSlice("chains") + + if len(chains) > 0 { + hasDefault := false + chainConfigs := make([]*cfg.ChainConfig, len(chains)) + for idx, item := range chains { + if item == "default" { + hasDefault = true + } + chainConfigs[idx] = cfg.DefaultChainConfig(item) + } + if !hasDefault { + //chainConfigs = append(chainConfigs, cfg.DefaultChainConfig("default")) + } + conf = &cfg.Config{ + RootDir: "", + LogLevel: cfg.DefaultPackageLogLevels(), + ChainConfigs: chainConfigs, + } + } else { + conf = cfg.DefaultConfig() } - conf.SetRoot(conf.RootDir) - cfg.EnsureRoot(conf.RootDir) - return conf, err + if rootDir == "" { + panic("Error") + } + conf.SetRoot(rootDir) + + for _, chain := range conf.ChainConfigs { + var chainConfig = filepath.Join(chain.RootDir, "config", "config.toml") + //fmt.Println("chainConfig " + chainConfig) + + var chainViper = viper.New() + //chainViper.SetConfigType("json") + chainViper.SetConfigFile(chainConfig) + err := chainViper.ReadInConfig() + if err == nil { + err = chainViper.Unmarshal(chain) + if err != nil { + panic(err) + } + } + } + + cfg.EnsureRoot(conf.RootDir, conf) + return conf, nil } -// RootCmd is the root command for teragrid core. +// RootCmd is the root command for Teragrid core. var RootCmd = &cobra.Command{ Use: "teragrid", - Short: "teragrid Core (BFT Consensus) in Go", + Short: "Teragrid Core (FBA Consensus) in Go", PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) { if cmd.Name() == VersionCmd.Name() { return nil } - config, err = ParseConfig() + mainConfig, err = ParseConfig() if err != nil { return err } - logger, err = tmflags.ParseLogLevel(config.LogLevel, logger, cfg.DefaultLogLevel()) + logger, err = tmflags.ParseLogLevel(mainConfig.LogLevel, logger, cfg.DefaultLogLevel()) if err != nil { return err } diff --git a/cmd/teragrid/commands/run_node.go b/cmd/teragrid/commands/run_node.go index 7c4e206..f46395c 100644 --- a/cmd/teragrid/commands/run_node.go +++ b/cmd/teragrid/commands/run_node.go @@ -4,13 +4,15 @@ import ( "fmt" "github.com/spf13/cobra" - + cfg "github.com/teragrid/teragrid/config" nm "github.com/teragrid/teragrid/node" + cmn "github.com/teragrid/teralibs/common" ) // AddNodeFlags exposes some common configuration options on the command-line // These are exposed for convenience of commands embedding a teragrid node func AddNodeFlags(cmd *cobra.Command) { + config := mainConfig.ChainConfigs[0] // bind flags cmd.Flags().String("moniker", config.Moniker, "Node Name") @@ -20,9 +22,9 @@ func AddNodeFlags(cmd *cobra.Command) { // node flags cmd.Flags().Bool("fast_sync", config.FastSync, "Fast blockchain syncing") - // asura flags + // Asura flags cmd.Flags().String("proxy_app", config.ProxyApp, "Proxy app address, or 'nilapp' or 'kvstore' for local testing.") - cmd.Flags().String("asura", config.Asura, "Specify asura transport (socket | grpc)") + cmd.Flags().String("asura", config.Asura, "Specify Asura transport (socket | grpc)") // rpc flags cmd.Flags().String("rpc.laddr", config.RPC.ListenAddress, "RPC listen address. Port required") @@ -43,7 +45,85 @@ func AddNodeFlags(cmd *cobra.Command) { } // NewRunNodeCmd returns the command that allows the CLI to start a node. -// It can be used with a custom PrivValidator and in-process asura application. +// It can be used with a custom PrivValidator and in-process Asura application. +func NewRunNodeCmd(nodeProvider nm.NodeProvider) *cobra.Command { + cmd := &cobra.Command{ + Use: "node", + Short: "Run the teragrid node", + RunE: func(cmd *cobra.Command, args []string) error { + //runOneNode(nodeProvider) + runNodes(nodeProvider) + return nil + }, + } + AddNodeFlags(cmd) + return cmd +} + +func runOneNode(nodeProvider nm.NodeProvider) error { + // Create & start node + config := mainConfig.ChainConfigs[0] + newLogger := logger.With("chain", config.ChainID()) + + newLogger.Info("Run one node: Start with config") + n, err := nodeProvider(config, newLogger) + if err != nil { + return fmt.Errorf("Failed to create node: %v", err) + } + + if err := n.Start(); err != nil { + return fmt.Errorf("Failed to start node: %v", err) + } + newLogger.Info("Started node", "nodeInfo", n.Switch().NodeInfo()) + + // Trap signal, run forever. + n.RunForever() + newLogger.Info("runOneNode Finish") + return nil +} + +func runNodeWithConfig(nodeProvider nm.NodeProvider, config *cfg.ChainConfig) (*nm.Node, error) { + + newLogger := logger.With("chain", config.ChainID()) + newLogger.Info("runNodeWithConfig " + config.ChainID()) + + // Create & start node + n, err := nodeProvider(config, newLogger) + if err != nil { + return nil, fmt.Errorf("Failed to create node: %v", err) + } + + if err := n.Start(); err != nil { + //return fmt.Errorf("Failed to start node: %v", err) + } + newLogger.Info("Started node", "nodeInfo", n.Switch().NodeInfo()) + fmt.Println("Create node finish" + config.ChainID()) + // Trap signal, run forever. + //n.RunForever() + return n, nil +} + +func runNodes(nodeProvider nm.NodeProvider) { + logger.Info("Run multi-node") + var nodes []*nm.Node + nodes = make([]*nm.Node, len(mainConfig.ChainConfigs)) + for idx, configLoop := range mainConfig.ChainConfigs { + config := configLoop + //fmt.Println("================================== Create node " + config.ChainID()) + logger.Info("================================== Create node " + config.ChainID()) + nodes[idx], _ = runNodeWithConfig(nodeProvider, config) + } + cmn.TrapSignal(func() { + for _, n := range nodes { + n.Stop() + } + }) + return +} + +/* +// NewRunNodeCmd returns the command that allows the CLI to start a node. +// It can be used with a custom PrivValidator and in-process Asura application. func NewRunNodeCmd(nodeProvider nm.NodeProvider) *cobra.Command { cmd := &cobra.Command{ Use: "node", @@ -70,3 +150,4 @@ func NewRunNodeCmd(nodeProvider nm.NodeProvider) *cobra.Command { AddNodeFlags(cmd) return cmd } +*/ diff --git a/cmd/teragrid/commands/show_node_id.go b/cmd/teragrid/commands/show_node_id.go index 10f4954..55f39d0 100644 --- a/cmd/teragrid/commands/show_node_id.go +++ b/cmd/teragrid/commands/show_node_id.go @@ -6,7 +6,6 @@ import ( "github.com/spf13/cobra" "github.com/teragrid/teragrid/p2p" - ) // ShowNodeIDCmd dumps node's ID to the standard output. @@ -17,12 +16,12 @@ var ShowNodeIDCmd = &cobra.Command{ } func showNodeID(cmd *cobra.Command, args []string) error { - - nodeKey, err := p2p.LoadNodeKey(config.NodeKeyFile()) - if err != nil { - return err + for _, config := range mainConfig.ChainConfigs { + nodeKey, err := p2p.LoadNodeKey(config.NodeKeyFile()) + if err != nil { + return err + } + fmt.Println(nodeKey.ID()) } - fmt.Println(nodeKey.ID()) - return nil } diff --git a/cmd/teragrid/commands/show_validator.go b/cmd/teragrid/commands/show_validator.go index 8b71e26..777e9c4 100644 --- a/cmd/teragrid/commands/show_validator.go +++ b/cmd/teragrid/commands/show_validator.go @@ -2,9 +2,10 @@ package commands import ( "fmt" + "github.com/spf13/cobra" - privval "github.com/teragrid/teragrid/types/priv_validator" + "github.com/teragrid/teragrid/types/priv_validator" ) // ShowValidatorCmd adds capabilities for showing the validator info. @@ -15,7 +16,9 @@ var ShowValidatorCmd = &cobra.Command{ } func showValidator(cmd *cobra.Command, args []string) { - privValidator := privval.LoadOrGenFilePV(config.PrivValidatorFile()) - pubKeyJSONBytes, _ := cdc.MarshalJSON(privValidator.GetPubKey()) - fmt.Println(string(pubKeyJSONBytes)) + for _, config := range mainConfig.ChainConfigs { + privValidator := privval.LoadOrGenFilePV(config.PrivValidatorFile()) + pubKeyJSONBytes, _ := cdc.MarshalJSON(privValidator.GetPubKey()) + fmt.Println(string(pubKeyJSONBytes)) + } } diff --git a/cmd/teragrid/commands/testnet.go b/cmd/teragrid/commands/testnet.go index 4aa53e0..540c831 100644 --- a/cmd/teragrid/commands/testnet.go +++ b/cmd/teragrid/commands/testnet.go @@ -13,7 +13,7 @@ import ( cfg "github.com/teragrid/teragrid/config" "github.com/teragrid/teragrid/p2p" "github.com/teragrid/teragrid/types" - pvm "github.com/teragrid/teragrid/types/priv_validator" + "github.com/teragrid/teragrid/types/priv_validator" cmn "github.com/teragrid/teralibs/common" ) @@ -46,83 +46,94 @@ func init() { TestnetFilesCmd.Flags().BoolVar(&populatePersistentPeers, "populate-persistent-peers", true, "Update config of each node with the list of persistent peers build using either hostname-prefix or starting-ip-address") TestnetFilesCmd.Flags().StringVar(&hostnamePrefix, "hostname-prefix", "node", - "Hostname prefix (node results in persistent peers list ID0@node0:46656, ID1@node1:46656, ...)") + "Hostname prefix (node results in persistent peers list ID0@node0:26656, ID1@node1:26656, ...)") TestnetFilesCmd.Flags().StringVar(&startingIPAddress, "starting-ip-address", "", - "Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)") - TestnetFilesCmd.Flags().IntVar(&p2pPort, "p2p-port", 46656, + "Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:26656, ID1@192.168.0.2:26656, ...)") + TestnetFilesCmd.Flags().IntVar(&p2pPort, "p2p-port", 26656, "P2P Port") } -// TestnetFilesCmd allows initialisation of files for a teragrid testnet. +// TestnetFilesCmd allows initialisation of files for a Teragrid testnet. var TestnetFilesCmd = &cobra.Command{ Use: "testnet", - Short: "Initialize files for a teragrid testnet", - RunE: testnetFiles, + Short: "Initialize files for a Teragrid testnet", + Long: `testnet will create "v" + "n" number of directories and populate each with +necessary files (private validator, genesis, config, etc.). + +Note, strict routability for addresses is turned off in the config file. + +Optionally, it will fill in persistent_peers list in config file using either hostnames or IPs. + +Example: + + teragrid testnet --v 4 --o ./output --populate-persistent-peers --starting-ip-address 192.168.10.2 + `, + RunE: testnetFiles, } func testnetFiles(cmd *cobra.Command, args []string) error { config := cfg.DefaultConfig() genVals := make([]types.GenesisValidator, nValidators) - - for i := 0; i < nValidators; i++ { - nodeDirName := cmn.Fmt("%s%d", nodeDirPrefix, i) - nodeDir := filepath.Join(outputDir, nodeDirName) - config.SetRoot(nodeDir) - - err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm) - if err != nil { - _ = os.RemoveAll(outputDir) - return err + for _, chain := range config.ChainConfigs { + for i := 0; i < nValidators; i++ { + nodeDirName := cmn.Fmt("%s%d", nodeDirPrefix, i) + nodeDir := filepath.Join(outputDir, nodeDirName) + chain.SetRoot(nodeDir) + + err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm) + if err != nil { + _ = os.RemoveAll(outputDir) + return err + } + + initFilesWithConfig(config) + + pvFile := filepath.Join(nodeDir, chain.BaseConfig.PrivValidator) + pv := privval.LoadFilePV(pvFile) + genVals[i] = types.GenesisValidator{ + PubKey: pv.GetPubKey(), + Power: 1, + Name: nodeDirName, + } } - initFilesWithConfig(config) - - pvFile := filepath.Join(nodeDir, config.BaseConfig.PrivValidator) - pv := pvm.LoadFilePV(pvFile) - genVals[i] = types.GenesisValidator{ - PubKey: pv.GetPubKey(), - Power: 1, - Name: nodeDirName, - } - } + for i := 0; i < nNonValidators; i++ { + nodeDir := filepath.Join(outputDir, cmn.Fmt("%s%d", nodeDirPrefix, i+nValidators)) + chain.SetRoot(nodeDir) - for i := 0; i < nNonValidators; i++ { - nodeDir := filepath.Join(outputDir, cmn.Fmt("%s%d", nodeDirPrefix, i+nValidators)) - config.SetRoot(nodeDir) + err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm) + if err != nil { + _ = os.RemoveAll(outputDir) + return err + } - err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm) - if err != nil { - _ = os.RemoveAll(outputDir) - return err + initFilesWithConfig(config) } - initFilesWithConfig(config) - } - - // Generate genesis doc from generated validators - genDoc := &types.GenesisDoc{ - GenesisTime: time.Now(), - ChainID: "chain-" + cmn.RandStr(6), - Validators: genVals, - } + // Generate genesis doc from generated validators + genDoc := &types.GenesisDoc{ + GenesisTime: time.Now(), + ChainID: "chain-" + cmn.RandStr(6), + Validators: genVals, + } - // Write genesis file. - for i := 0; i < nValidators+nNonValidators; i++ { - nodeDir := filepath.Join(outputDir, cmn.Fmt("%s%d", nodeDirPrefix, i)) - if err := genDoc.SaveAs(filepath.Join(nodeDir, config.BaseConfig.Genesis)); err != nil { - _ = os.RemoveAll(outputDir) - return err + // Write genesis file. + for i := 0; i < nValidators+nNonValidators; i++ { + nodeDir := filepath.Join(outputDir, cmn.Fmt("%s%d", nodeDirPrefix, i)) + if err := genDoc.SaveAs(filepath.Join(nodeDir, chain.BaseConfig.Genesis)); err != nil { + _ = os.RemoveAll(outputDir) + return err + } } - } - if populatePersistentPeers { - err := populatePersistentPeersInConfigAndWriteIt(config) - if err != nil { - _ = os.RemoveAll(outputDir) - return err + if populatePersistentPeers { + err := populatePersistentPeersInConfigAndWriteIt(config) + if err != nil { + _ = os.RemoveAll(outputDir) + return err + } } } - fmt.Printf("Successfully initialized %v node directories\n", nValidators+nNonValidators) return nil } @@ -147,25 +158,27 @@ func hostnameOrIP(i int) string { func populatePersistentPeersInConfigAndWriteIt(config *cfg.Config) error { persistentPeers := make([]string, nValidators+nNonValidators) - for i := 0; i < nValidators+nNonValidators; i++ { - nodeDir := filepath.Join(outputDir, cmn.Fmt("%s%d", nodeDirPrefix, i)) - config.SetRoot(nodeDir) - nodeKey, err := p2p.LoadNodeKey(config.NodeKeyFile()) - if err != nil { - return err + for _, chain := range config.ChainConfigs { + for i := 0; i < nValidators+nNonValidators; i++ { + nodeDir := filepath.Join(outputDir, cmn.Fmt("%s%d", nodeDirPrefix, i)) + chain.SetRoot(nodeDir) + nodeKey, err := p2p.LoadNodeKey(chain.NodeKeyFile()) + if err != nil { + return err + } + persistentPeers[i] = p2p.IDAddressString(nodeKey.ID(), fmt.Sprintf("%s:%d", hostnameOrIP(i), p2pPort)) } - persistentPeers[i] = p2p.IDAddressString(nodeKey.ID(), fmt.Sprintf("%s:%d", hostnameOrIP(i), p2pPort)) - } - persistentPeersList := strings.Join(persistentPeers, ",") + persistentPeersList := strings.Join(persistentPeers, ",") - for i := 0; i < nValidators+nNonValidators; i++ { - nodeDir := filepath.Join(outputDir, cmn.Fmt("%s%d", nodeDirPrefix, i)) - config.SetRoot(nodeDir) - config.P2P.PersistentPeers = persistentPeersList + for i := 0; i < nValidators+nNonValidators; i++ { + nodeDir := filepath.Join(outputDir, cmn.Fmt("%s%d", nodeDirPrefix, i)) + chain.SetRoot(nodeDir) + chain.P2P.PersistentPeers = persistentPeersList + chain.P2P.AddrBookStrict = false - // overwrite default config - cfg.WriteConfigFile(filepath.Join(nodeDir, "config", "config.toml"), config) + // overwrite default config + cfg.WriteConfigFile(filepath.Join(nodeDir, "config", "config.toml"), config) + } } - return nil } diff --git a/cmd/teragrid/main.go b/cmd/teragrid/main.go index 57299da..27e54fc 100644 --- a/cmd/teragrid/main.go +++ b/cmd/teragrid/main.go @@ -12,6 +12,7 @@ import ( ) func main() { + rootCmd := cmd.RootCmd rootCmd.AddCommand( cmd.GenValidatorCmd, @@ -28,20 +29,20 @@ func main() { cmd.GenNodeKeyCmd, cmd.VersionCmd) - // NOTE: - // Users wishing to: - // * Use an external signer for their validators - // * Supply an in-proc asura app - // * Supply a genesis doc file from another source - // * Provide their own DB implementation - // can copy this file and use something other than the - // DefaultNewNode function + // // NOTE: + // // Users wishing to: + // // * Use an external signer for their validators + // // * Supply an in-proc asura app + // // * Supply a genesis doc file from another source + // // * Provide their own DB implementation + // // can copy this file and use something other than the + // // DefaultNewNode function nodeFunc := nm.DefaultNewNode // Create & start node rootCmd.AddCommand(cmd.NewRunNodeCmd(nodeFunc)) - cmd := cli.PrepareBaseCmd(rootCmd, "TM", os.ExpandEnv(filepath.Join("$HOME", cfg.DefaultteragridDir))) + cmd := cli.PrepareBaseCmd(rootCmd, "TM", os.ExpandEnv(filepath.Join("$HOME", cfg.DefaultTeragridDir))) if err := cmd.Execute(); err != nil { panic(err) } diff --git a/config/chain_config.go b/config/chain_config.go new file mode 100644 index 0000000..107b9b6 --- /dev/null +++ b/config/chain_config.go @@ -0,0 +1,52 @@ +package config + +var portStep = 0 + +//----------------------------------------------------------------------------- + +// Config defines the top level configuration for a teragrid node +type ChainConfig struct { + // Top level options use an anonymous struct + BaseConfig `mapstructure:",squash"` + // Options for services + RPC *RPCConfig `mapstructure:"rpc"` + P2P *P2PConfig `mapstructure:"p2p"` + Mempool *MempoolConfig `mapstructure:"mempool"` + Consensus *ConsensusConfig `mapstructure:"consensus"` + TxIndex *TxIndexConfig `mapstructure:"tx_index"` +} + +// DefaultConfig returns a default configuration for a teragrid node +func DefaultChainConfig(name string) *ChainConfig { + portStep = portStep + 10 + return &ChainConfig{ + BaseConfig: DefaultBaseConfig(name), + RPC: DefaultRPCConfig(), + P2P: DefaultP2PConfig(), + Mempool: DefaultMempoolConfig(), + Consensus: DefaultConsensusConfig(), + TxIndex: DefaultTxIndexConfig(), + } +} + +// TestConfig returns a configuration that can be used for testing +func TestChainConfig() *ChainConfig { + return &ChainConfig{ + BaseConfig: TestBaseConfig(), + RPC: TestRPCConfig(), + P2P: TestP2PConfig(), + Mempool: TestMempoolConfig(), + Consensus: TestConsensusConfig(), + TxIndex: TestTxIndexConfig(), + } +} + +// SetRoot sets the RootDir for all Config structs +func (cfg *ChainConfig) SetRoot(root string) *ChainConfig { + cfg.BaseConfig.RootDir = root + cfg.RPC.RootDir = root + cfg.P2P.RootDir = root + cfg.Mempool.RootDir = root + cfg.Consensus.RootDir = root + return cfg +} diff --git a/config/config.go b/config/config.go index 75906ab..01d4d54 100644 --- a/config/config.go +++ b/config/config.go @@ -7,82 +7,17 @@ import ( "time" ) -// 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: teralibs/cli must know to look in the config dir! -var ( - DefaultteragridDir = ".teragrid" - defaultConfigDir = "config" - defaultDataDir = "data" - - defaultConfigFileName = "config.toml" - defaultGenesisJSONName = "genesis.json" - - defaultPrivValName = "priv_validator.json" - defaultNodeKeyName = "node_key.json" - defaultAddrBookName = "addrbook.json" - - defaultConfigFilePath = filepath.Join(defaultConfigDir, defaultConfigFileName) - defaultGenesisJSONPath = filepath.Join(defaultConfigDir, defaultGenesisJSONName) - defaultPrivValPath = filepath.Join(defaultConfigDir, defaultPrivValName) - defaultNodeKeyPath = filepath.Join(defaultConfigDir, defaultNodeKeyName) - defaultAddrBookPath = filepath.Join(defaultConfigDir, defaultAddrBookName) +const ( + // FuzzModeDrop is a mode in which we randomly drop reads/writes, connections or sleep + FuzzModeDrop = iota + // FuzzModeDelay is a mode in which we randomly sleep + FuzzModeDelay ) -// Config defines the top level configuration for a teragrid node -type Config struct { - // Top level options use an anonymous struct - BaseConfig `mapstructure:",squash"` - - // Options for services - RPC *RPCConfig `mapstructure:"rpc"` - P2P *P2PConfig `mapstructure:"p2p"` - Mempool *MempoolConfig `mapstructure:"mempool"` - Consensus *ConsensusConfig `mapstructure:"consensus"` - TxIndex *TxIndexConfig `mapstructure:"tx_index"` -} - -// DefaultConfig returns a default configuration for a teragrid node -func DefaultConfig() *Config { - return &Config{ - BaseConfig: DefaultBaseConfig(), - RPC: DefaultRPCConfig(), - P2P: DefaultP2PConfig(), - Mempool: DefaultMempoolConfig(), - Consensus: DefaultConsensusConfig(), - TxIndex: DefaultTxIndexConfig(), - } -} - -// TestConfig returns a configuration that can be used for testing -func TestConfig() *Config { - return &Config{ - BaseConfig: TestBaseConfig(), - RPC: TestRPCConfig(), - P2P: TestP2PConfig(), - Mempool: TestMempoolConfig(), - Consensus: TestConsensusConfig(), - TxIndex: TestTxIndexConfig(), - } -} - -// SetRoot sets the RootDir for all Config structs -func (cfg *Config) SetRoot(root string) *Config { - cfg.BaseConfig.RootDir = root - cfg.RPC.RootDir = root - cfg.P2P.RootDir = root - cfg.Mempool.RootDir = root - cfg.Consensus.RootDir = root - return cfg -} - //----------------------------------------------------------------------------- // BaseConfig -// BaseConfig defines the base configuration for a teragrid node +// BaseConfig defines the base configuration for a Teragrid node type BaseConfig struct { // chainID is unexposed and immutable but here for convenience @@ -104,16 +39,16 @@ type BaseConfig struct { // A custom human readable name for this node Moniker string `mapstructure:"moniker"` - // TCP or UNIX socket address for teragrid to listen on for + // TCP or UNIX socket address for Teragrid to listen on for // connections from an external PrivValidator process PrivValidatorListenAddr string `mapstructure:"priv_validator_laddr"` // TCP or UNIX socket address of the Asura application, - // or the name of an Asura application compiled in with the teragrid binary + // or the name of an Asura application compiled in with the Teragrid binary ProxyApp string `mapstructure:"proxy_app"` // Mechanism to connect to the Asura application: socket | grpc - Asura string `mapstructure:"Asura"` + Asura string `mapstructure:"asura"` // Output level for logging LogLevel string `mapstructure:"log_level"` @@ -137,15 +72,17 @@ type BaseConfig struct { DBPath string `mapstructure:"db_dir"` } -// DefaultBaseConfig returns a default base configuration for a teragrid node -func DefaultBaseConfig() BaseConfig { +// DefaultBaseConfig returns a default base configuration for a Teragrid node +func DefaultBaseConfig(name string) BaseConfig { return BaseConfig{ - Genesis: defaultGenesisJSONPath, - PrivValidator: defaultPrivValPath, - NodeKey: defaultNodeKeyPath, - Moniker: defaultMoniker, - ProxyApp: "tcp://127.0.0.1:46658", - Asura: "socket", + chainID: name, + Genesis: defaultGenesisJSONPath, + PrivValidator: defaultPrivValPath, + NodeKey: defaultNodeKeyPath, + Moniker: defaultMoniker, + //ProxyApp: "tcp://127.0.0.1:26658", + ProxyApp: fmt.Sprintf("tcp://127.0.0.1:%d", 26658+portStep), + Asura: "socket", LogLevel: DefaultPackageLogLevels(), ProfListenAddress: "", FastSync: true, @@ -155,10 +92,10 @@ func DefaultBaseConfig() BaseConfig { } } -// TestBaseConfig returns a base configuration for testing a teragrid node +// TestBaseConfig returns a base configuration for testing a Teragrid node func TestBaseConfig() BaseConfig { - cfg := DefaultBaseConfig() - cfg.chainID = "teragrid_test" + cfg := DefaultBaseConfig(defaultChainName) + cfg.chainID = "dagmint_test" cfg.ProxyApp = "kvstore" cfg.FastSync = false cfg.DBBackend = "memdb" @@ -203,7 +140,7 @@ func DefaultPackageLogLevels() string { //----------------------------------------------------------------------------- // RPCConfig -// RPCConfig defines the configuration options for the teragrid RPC server +// RPCConfig defines the configuration options for the Teragrid RPC server type RPCConfig struct { RootDir string `mapstructure:"home"` @@ -221,7 +158,8 @@ type RPCConfig struct { // DefaultRPCConfig returns a default configuration for the RPC server func DefaultRPCConfig() *RPCConfig { return &RPCConfig{ - ListenAddress: "tcp://0.0.0.0:46657", + //ListenAddress: "tcp://0.0.0.0:26657", + ListenAddress: fmt.Sprintf("tcp://127.0.0.1:%d", 26657+portStep), GRPCListenAddress: "", Unsafe: false, } @@ -239,7 +177,7 @@ func TestRPCConfig() *RPCConfig { //----------------------------------------------------------------------------- // P2PConfig -// P2PConfig defines the configuration options for the teragrid peer-to-peer networking layer +// P2PConfig defines the configuration options for the Teragrid peer-to-peer networking layer type P2PConfig struct { RootDir string `mapstructure:"home"` @@ -290,14 +228,30 @@ type P2PConfig struct { // Authenticated encryption AuthEnc bool `mapstructure:"auth_enc"` - // Comma separated list of peer IDs to keep private (will not be gossiped to other peers) + // Comma separated list of peer IDs to keep private (will not be gossiped to + // other peers) PrivatePeerIDs string `mapstructure:"private_peer_ids"` + + // Toggle to disable guard against peers connecting from the same ip. + AllowDuplicateIP bool `mapstructure:"allow_duplicate_ip"` + + // Peer connection configuration. + HandshakeTimeout time.Duration `mapstructure:"handshake_timeout"` + DialTimeout time.Duration `mapstructure:"dial_timeout"` + + // Testing params. + // Force dial to fail + TestDialFail bool `mapstructure:"test_dial_fail"` + // FUzz connection + TestFuzz bool `mapstructure:"test_fuzz"` + TestFuzzConfig *FuzzConnConfig `mapstructure:"test_fuzz_config"` } // DefaultP2PConfig returns a default configuration for the peer-to-peer layer func DefaultP2PConfig() *P2PConfig { return &P2PConfig{ - ListenAddress: "tcp://0.0.0.0:46656", + ListenAddress: fmt.Sprintf("tcp://127.0.0.1:%d", 26656+portStep), + //ListenAddress: "tcp://0.0.0.0:26656", AddrBook: defaultAddrBookPath, AddrBookStrict: true, MaxNumPeers: 50, @@ -307,7 +261,12 @@ func DefaultP2PConfig() *P2PConfig { RecvRate: 512000, // 500 kB/s PexReactor: true, SeedMode: false, - AuthEnc: true, + AllowDuplicateIP: true, // so non-breaking yet + HandshakeTimeout: 20 * time.Second, + DialTimeout: 3 * time.Second, + TestDialFail: false, + TestFuzz: false, + TestFuzzConfig: DefaultFuzzConnConfig(), } } @@ -317,6 +276,7 @@ func TestP2PConfig() *P2PConfig { cfg.ListenAddress = "tcp://0.0.0.0:36656" cfg.SkipUPNP = true cfg.FlushThrottleTimeout = 10 + cfg.AllowDuplicateIP = true return cfg } @@ -325,31 +285,53 @@ func (cfg *P2PConfig) AddrBookFile() string { return rootify(cfg.AddrBook, cfg.RootDir) } +// FuzzConnConfig is a FuzzedConnection configuration. +type FuzzConnConfig struct { + Mode int + MaxDelay time.Duration + ProbDropRW float64 + ProbDropConn float64 + ProbSleep float64 +} + +// DefaultFuzzConnConfig returns the default config. +func DefaultFuzzConnConfig() *FuzzConnConfig { + return &FuzzConnConfig{ + Mode: FuzzModeDrop, + MaxDelay: 3 * time.Second, + ProbDropRW: 0.2, + ProbDropConn: 0.00, + ProbSleep: 0.00, + } +} + //----------------------------------------------------------------------------- // MempoolConfig -// MempoolConfig defines the configuration options for the teragrid mempool +// MempoolConfig defines the configuration options for the Teragrid mempool type MempoolConfig struct { RootDir string `mapstructure:"home"` Recheck bool `mapstructure:"recheck"` RecheckEmpty bool `mapstructure:"recheck_empty"` Broadcast bool `mapstructure:"broadcast"` WalPath string `mapstructure:"wal_dir"` + Size int `mapstructure:"size"` CacheSize int `mapstructure:"cache_size"` } -// DefaultMempoolConfig returns a default configuration for the teragrid mempool +// DefaultMempoolConfig returns a default configuration for the Teragrid mempool func DefaultMempoolConfig() *MempoolConfig { return &MempoolConfig{ Recheck: true, RecheckEmpty: true, Broadcast: true, WalPath: filepath.Join(defaultDataDir, "mempool.wal"), + Size: 100000, CacheSize: 100000, } } -// TestMempoolConfig returns a configuration for testing the teragrid mempool +// TestMempoolConfig returns a configuration for testing the Teragrid mempool func TestMempoolConfig() *MempoolConfig { cfg := DefaultMempoolConfig() cfg.CacheSize = 1000 @@ -364,7 +346,7 @@ func (cfg *MempoolConfig) WalDir() string { //----------------------------------------------------------------------------- // ConsensusConfig -// ConsensusConfig defines the confuguration for the teragrid consensus service, +// ConsensusConfig defines the confuguration for the Teragrid consensus service, // including timeouts and details about the WAL and the block structure. type ConsensusConfig struct { RootDir string `mapstructure:"home"` diff --git a/config/config_test.go b/config/config_test.go index 6379960..3f3d1dc 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -3,6 +3,7 @@ package config import ( "testing" + _ "github.com/spf13/viper" "github.com/stretchr/testify/assert" ) @@ -10,19 +11,20 @@ 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) + cfg := *DefaultConfig() - // check the root dir stuff... + assert.NotNil(cfg.RootDir) + // assert.NotNil(cfg.Mempool) + // assert.NotNil(cfg.Consensus) + + // // check the root dir stuff... cfg.SetRoot("/foo") - cfg.Genesis = "bar" - cfg.DBPath = "/opt/data" - cfg.Mempool.WalPath = "wal/mem/" + // cfg.Genesis = "bar" + // cfg.DBPath = "/opt/data" + // cfg.Mempool.WalPath = "wal/mem/" - assert.Equal("/foo/bar", cfg.GenesisFile()) - assert.Equal("/opt/data", cfg.DBDir()) - assert.Equal("/foo/wal/mem", cfg.Mempool.WalDir()) + // assert.Equal("/foo/bar", cfg.GenesisFile()) + // assert.Equal("/opt/data", cfg.DBDir()) + // assert.Equal("/foo/wal/mem", cfg.Mempool.WalDir()) } diff --git a/config/main_config.go b/config/main_config.go new file mode 100644 index 0000000..838dade --- /dev/null +++ b/config/main_config.go @@ -0,0 +1,73 @@ +package config + +import ( + // "fmt" + // "os" + "path/filepath" + // "time" +) + +// 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: teragrid/cli must know to look in the config dir! +var ( + DefaultTeragridDir = ".teragrid" + defaultChainName = "default" + defaultConfigDir = "config" + defaultDataDir = "data" + + defaultConfigFileName = "config.toml" + defaultGenesisJSONName = "genesis.json" + + defaultPrivValName = "priv_validator.json" + defaultNodeKeyName = "node_key.json" + defaultAddrBookName = "addrbook.json" + + defaultConfigFilePath = filepath.Join(defaultConfigDir, defaultConfigFileName) + defaultGenesisJSONPath = filepath.Join(defaultConfigDir, defaultGenesisJSONName) + defaultPrivValPath = filepath.Join(defaultConfigDir, defaultPrivValName) + defaultNodeKeyPath = filepath.Join(defaultConfigDir, defaultNodeKeyName) + defaultAddrBookPath = filepath.Join(defaultConfigDir, defaultAddrBookName) +) + +type Config struct { + // The root directory for all data. + // This should be set in viper so it can unmarshal into this struct + RootDir string `mapstructure:"home"` + // Output level for logging + LogLevel string `mapstructure:"log_level"` + ChainConfigs []*ChainConfig +} + +// SetRoot sets the RootDir for all Config structs +func (cfg *Config) SetRoot(root string) *Config { + cfg.RootDir = root + for _, chain := range cfg.ChainConfigs { + chainDir := filepath.Join(root, chain.ChainID()) + chain.SetRoot(chainDir) + } + return cfg +} + +// DefaultConfig returns a default configuration for a teragrid node +func DefaultConfig() *Config { + cfg := Config{ + RootDir: "", + LogLevel: DefaultPackageLogLevels(), + ChainConfigs: []*ChainConfig{ + DefaultChainConfig(defaultChainName), + }, + } + return &cfg +} + +// TestConfig returns a configuration that can be used for testing +func TestConfig() *Config { + return DefaultConfig() + //return &Config{ + // DefaultConfig(), + //} +} diff --git a/config/toml.go b/config/toml.go index 5da2141..4d57446 100644 --- a/config/toml.go +++ b/config/toml.go @@ -2,10 +2,12 @@ package config import ( "bytes" + "fmt" "os" "path/filepath" "text/template" + "github.com/spf13/viper" cmn "github.com/teragrid/teralibs/common" ) @@ -14,6 +16,7 @@ var configTemplate *template.Template func init() { var err error if configTemplate, err = template.New("configFileTemplate").Parse(defaultConfigTemplate); err != nil { + fmt.Println("Error configTemplate") panic(err) } } @@ -22,40 +25,65 @@ func init() { // EnsureRoot creates the root, config, and data directories if they don't exist, // and panics if it fails. -func EnsureRoot(rootDir string) { +func EnsureRoot(rootDir string, config *Config) { if err := cmn.EnsureDir(rootDir, 0700); err != nil { cmn.PanicSanity(err.Error()) } - if err := cmn.EnsureDir(filepath.Join(rootDir, defaultConfigDir), 0700); err != nil { - cmn.PanicSanity(err.Error()) - } - if err := cmn.EnsureDir(filepath.Join(rootDir, defaultDataDir), 0700); err != nil { - cmn.PanicSanity(err.Error()) + for _, chain := range config.ChainConfigs { + chainDir := chain.ChainID() + if err := cmn.EnsureDir(filepath.Join(rootDir, chainDir), 0700); err != nil { + cmn.PanicSanity(err.Error()) + } + if err := cmn.EnsureDir(filepath.Join(rootDir, chainDir, defaultConfigDir), 0700); err != nil { + cmn.PanicSanity(err.Error()) + } + if err := cmn.EnsureDir(filepath.Join(rootDir, chainDir, defaultDataDir), 0700); err != nil { + cmn.PanicSanity(err.Error()) + } } - configFilePath := filepath.Join(rootDir, defaultConfigFilePath) - + // configFilePath := rootDir //filepath.Join(rootDir, defaultChainName, defaultConfigFilePath) + // fmt.Println("EnsureRoot " + filepath.Join(configFilePath, "config.json")) // Write default config file if missing. - if !cmn.FileExists(configFilePath) { - writeDefaultCondigFile(configFilePath) - } + // if !cmn.FileExists(filepath.Join(configFilePath, "config.json")) { + // fmt.Println("EnsureRoot (WRITE) " + filepath.Join(configFilePath, "config.json")) + // writeDefaultConfigFile(configFilePath, config) + // } + WriteConfigFile(rootDir, config) } // XXX: this func should probably be called by cmd/teragrid/commands/init.go // alongside the writing of the genesis.json and priv_validator.json -func writeDefaultCondigFile(configFilePath string) { - WriteConfigFile(configFilePath, DefaultConfig()) +func writeDefaultConfigFile(configFilePath string, config *Config) { + WriteConfigFile(configFilePath, config) } // WriteConfigFile renders config using the template and writes it to configFilePath. func WriteConfigFile(configFilePath string, config *Config) { - var buffer bytes.Buffer - - if err := configTemplate.Execute(&buffer, config); err != nil { - panic(err) + var chains []string + chains = make([]string, len(config.ChainConfigs)) + for idx, chain := range config.ChainConfigs { + chains[idx] = chain.ChainID() + + var buffer bytes.Buffer + + if err := configTemplate.Execute(&buffer, chain); err != nil { + fmt.Println("WriteConfigFile Panic " + configFilePath) + panic(err) + } else { + if !cmn.FileExists(filepath.Join(configFilePath, chain.ChainID(), defaultConfigFilePath)) { + cmn.MustWriteFile(filepath.Join(configFilePath, chain.ChainID(), defaultConfigFilePath), buffer.Bytes(), 0644) + } + } + } + if true || !cmn.FileExists(filepath.Join(configFilePath, "config.json")) { + var runtime_viper = viper.New() + runtime_viper.SetConfigType("json") + runtime_viper.SetConfigFile(filepath.Join(configFilePath, "config.json")) + runtime_viper.SetDefault("LogLevel", config.LogLevel) + runtime_viper.SetDefault("Chains", chains) + runtime_viper.WriteConfig() } - - cmn.MustWriteFile(configFilePath, buffer.Bytes(), 0644) } // Note: any changes to the comments/variables/mapstructure @@ -66,7 +94,7 @@ const defaultConfigTemplate = `# This is a TOML config file. ##### main base config options ##### # TCP or UNIX socket address of the Asura application, -# or the name of an Asura application compiled in with the teragrid binary +# or the name of an Asura application compiled in with the Teragrid binary proxy_app = "{{ .BaseConfig.ProxyApp }}" # A custom human readable name for this node @@ -81,7 +109,7 @@ fast_sync = {{ .BaseConfig.FastSync }} db_backend = "{{ .BaseConfig.DBBackend }}" # Database directory -db_path = "{{ .BaseConfig.DBPath }}" +db_path = "{{ js .BaseConfig.DBPath }}" # Output level for logging, including package level options log_level = "{{ .BaseConfig.LogLevel }}" @@ -89,16 +117,16 @@ log_level = "{{ .BaseConfig.LogLevel }}" ##### additional base config options ##### # Path to the JSON file containing the initial validator set and other meta data -genesis_file = "{{ .BaseConfig.Genesis }}" +genesis_file = "{{ js .BaseConfig.Genesis }}" # Path to the JSON file containing the private key to use as a validator in the consensus protocol -priv_validator_file = "{{ .BaseConfig.PrivValidator }}" +priv_validator_file = "{{ js .BaseConfig.PrivValidator }}" # Path to the JSON file containing the private key to use for node authentication in the p2p protocol -node_key_file = "{{ .BaseConfig.NodeKey}}" +node_key_file = "{{ js .BaseConfig.NodeKey}}" # Mechanism to connect to the Asura application: socket | grpc -Asura = "{{ .BaseConfig.Asura }}" +asura = "{{ .BaseConfig.Asura }}" # TCP or UNIX socket address for the profiling server to listen on prof_laddr = "{{ .BaseConfig.ProfListenAddress }}" @@ -136,7 +164,7 @@ seeds = "{{ .P2P.Seeds }}" persistent_peers = "{{ .P2P.PersistentPeers }}" # Path to address book -addr_book_file = "{{ .P2P.AddrBook }}" +addr_book_file = "{{ js .P2P.AddrBook }}" # Set true for strict address routability rules addr_book_strict = {{ .P2P.AddrBookStrict }} @@ -165,9 +193,6 @@ pex = {{ .P2P.PexReactor }} # Does not work if the peer-exchange reactor is disabled. seed_mode = {{ .P2P.SeedMode }} -# Authenticated encryption -auth_enc = {{ .P2P.AuthEnc }} - # Comma separated list of peer IDs to keep private (will not be gossiped to other peers) private_peer_ids = "{{ .P2P.PrivatePeerIDs }}" @@ -177,13 +202,18 @@ private_peer_ids = "{{ .P2P.PrivatePeerIDs }}" recheck = {{ .Mempool.Recheck }} recheck_empty = {{ .Mempool.RecheckEmpty }} broadcast = {{ .Mempool.Broadcast }} -wal_dir = "{{ .Mempool.WalPath }}" +wal_dir = "{{ js .Mempool.WalPath }}" + +# size of the mempool +size = {{ .Mempool.Size }} + +# size of the cache (used to filter transactions we saw earlier) +cache_size = {{ .Mempool.CacheSize }} ##### consensus configuration options ##### [consensus] -wal_file = "{{ .Consensus.WalPath }}" -wal_light = {{ .Consensus.WalLight }} +wal_file = "{{ js .Consensus.WalPath }}" # All timeouts are in milliseconds timeout_propose = {{ .Consensus.TimeoutPropose }} @@ -230,6 +260,7 @@ index_tags = "{{ .TxIndex.IndexTags }}" # desirable (see the comment above). IndexTags has a precedence over # IndexAllTags (i.e. when given both, IndexTags will be indexed). index_all_tags = {{ .TxIndex.IndexAllTags }} + ` /****** these are for test settings ***********/ @@ -253,30 +284,38 @@ func ResetTestRoot(testName string) *Config { if err := cmn.EnsureDir(rootDir, 0700); err != nil { cmn.PanicSanity(err.Error()) } - if err := cmn.EnsureDir(filepath.Join(rootDir, defaultConfigDir), 0700); err != nil { + if err := cmn.EnsureDir(filepath.Join(rootDir, defaultChainName), 0700); err != nil { + cmn.PanicSanity(err.Error()) + } + if err := cmn.EnsureDir(filepath.Join(rootDir, defaultChainName, defaultConfigDir), 0700); err != nil { cmn.PanicSanity(err.Error()) } - if err := cmn.EnsureDir(filepath.Join(rootDir, defaultDataDir), 0700); err != nil { + if err := cmn.EnsureDir(filepath.Join(rootDir, defaultChainName, defaultDataDir), 0700); err != nil { cmn.PanicSanity(err.Error()) } - baseConfig := DefaultBaseConfig() - configFilePath := filepath.Join(rootDir, defaultConfigFilePath) - genesisFilePath := filepath.Join(rootDir, baseConfig.Genesis) - privFilePath := filepath.Join(rootDir, baseConfig.PrivValidator) + config := DefaultConfig() + //baseConfig := DefaultBaseConfig(defaultChainName) + baseConfig := config.ChainConfigs[0] + configFilePath := filepath.Join(rootDir, defaultChainName, defaultConfigFilePath) + genesisFilePath := filepath.Join(rootDir, defaultChainName, baseConfig.Genesis) + privFilePath := filepath.Join(rootDir, defaultChainName, baseConfig.PrivValidator) // Write default config file if missing. if !cmn.FileExists(configFilePath) { - writeDefaultCondigFile(configFilePath) + fmt.Println("EnsureDir_writeDefaultCondigFile XXXX " + configFilePath) + writeDefaultConfigFile(rootDir, config) } if !cmn.FileExists(genesisFilePath) { + fmt.Println("ResetTestRoot genesisFilePath XXXX " + genesisFilePath) cmn.MustWriteFile(genesisFilePath, []byte(testGenesis), 0644) } + fmt.Println("ResetTestRoot privFilePath XXXX " + privFilePath) // we always overwrite the priv val cmn.MustWriteFile(privFilePath, []byte(testPrivValidator), 0644) - config := TestConfig().SetRoot(rootDir) - return config + configX := TestConfig().SetRoot(rootDir) + return configX } var testGenesis = `{ diff --git a/config/toml_test.go b/config/toml_test.go index a1637f6..589e484 100644 --- a/config/toml_test.go +++ b/config/toml_test.go @@ -1,6 +1,7 @@ package config import ( + "fmt" "io/ioutil" "os" "path/filepath" @@ -25,13 +26,14 @@ func TestEnsureRoot(t *testing.T) { // setup temp dir for test tmpDir, err := ioutil.TempDir("", "config-test") require.Nil(err) - defer os.RemoveAll(tmpDir) // nolint: errcheck + //defer os.RemoveAll(tmpDir) // nolint: errcheck // create root dir - EnsureRoot(tmpDir) + EnsureRoot(tmpDir, DefaultConfig()) + fmt.Println("Read File " + filepath.Join(tmpDir, defaultChainName, defaultConfigFilePath)) // make sure config is set properly - data, err := ioutil.ReadFile(filepath.Join(tmpDir, defaultConfigFilePath)) + data, err := ioutil.ReadFile(filepath.Join(tmpDir, defaultChainName, defaultConfigFilePath)) require.Nil(err) if !checkConfig(string(data)) { @@ -51,7 +53,7 @@ func TestEnsureTestRoot(t *testing.T) { rootDir := cfg.RootDir // make sure config is set properly - data, err := ioutil.ReadFile(filepath.Join(rootDir, defaultConfigFilePath)) + data, err := ioutil.ReadFile(filepath.Join(rootDir, defaultChainName, defaultConfigFilePath)) require.Nil(err) if !checkConfig(string(data)) { @@ -59,7 +61,7 @@ func TestEnsureTestRoot(t *testing.T) { } // TODO: make sure the cfg returned and testconfig are the same! - baseConfig := DefaultBaseConfig() + baseConfig := DefaultBaseConfig(defaultChainName) ensureFiles(t, rootDir, defaultDataDir, baseConfig.Genesis, baseConfig.PrivValidator) } diff --git a/consensus/wal_generator.go b/consensus/wal_generator.go index dcc38bf..817e0d8 100644 --- a/consensus/wal_generator.go +++ b/consensus/wal_generator.go @@ -29,7 +29,7 @@ import ( // (byteBufferWAL) and waits until numBlocks are created. Then it returns a WAL // content. func WALWithNBlocks(numBlocks int) (data []byte, err error) { - config := getConfig() + config := getConfig().ChainConfigs[0] app := kvstore.NewPersistentKVStoreApplication(filepath.Join(config.DBDir(), "wal_generator")) @@ -133,9 +133,9 @@ func getConfig() *cfg.Config { // and we use random ports to run in parallel tm, rpc, grpc := makeAddrs() - c.P2P.ListenAddress = tm - c.RPC.ListenAddress = rpc - c.RPC.GRPCListenAddress = grpc + c.ChainConfigs[0].P2P.ListenAddress = tm + c.ChainConfigs[0].RPC.ListenAddress = rpc + c.ChainConfigs[0].RPC.GRPCListenAddress = grpc return c } diff --git a/docs/architecture/adr-002-event-subscription.md b/docs/architecture/adr-002-event-subscription.md index a2479ff..e86e863 100644 --- a/docs/architecture/adr-002-event-subscription.md +++ b/docs/architecture/adr-002-event-subscription.md @@ -66,7 +66,7 @@ For historic queries we will need a indexing storage (Postgres, SQLite, ...). ### Issues -- https://github.com/teragrid/basecoin/issues/91 +- https://github.com/teragrid/teracoin/issues/91 - https://github.com/teragrid/teragrid/issues/376 - https://github.com/teragrid/teragrid/issues/287 - https://github.com/teragrid/teragrid/issues/525 (related) diff --git a/docs/deploy-testnets.rst b/docs/deploy-testnets.rst index 16cbb1f..b31c1b6 100644 --- a/docs/deploy-testnets.rst +++ b/docs/deploy-testnets.rst @@ -4,7 +4,7 @@ Deploy a Testnet Now that we've seen how asura works, and even played with a few applications on a single validator node, it's time to deploy a test network to four validator nodes. For this deployment, we'll use the -``basecoin`` application. +``teracoin`` application. Manual Deployments ------------------ @@ -58,17 +58,17 @@ The `terraform-digitalocean tool `__ -allow creating and managing a ``basecoin`` or ``ethermint`` testnet on provisioned servers. +allow creating and managing a ``teracoin`` or ``ethermint`` testnet on provisioned servers. Package Deployment on Linux for developers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The ``teragrid`` and ``basecoin`` applications can be installed from RPM or DEB packages on +The ``teragrid`` and ``teracoin`` applications can be installed from RPM or DEB packages on Linux machines for development purposes. The packages are configured to be validators on the one-node network that the machine represents. The services are not started after installation, this way giving an opportunity to reconfigure the applications before starting. -The Ansible playbooks in the previous section use this repository to install ``basecoin``. +The Ansible playbooks in the previous section use this repository to install ``teracoin``. After installation, additional steps are executed to make sure that the multi-node testnet has the right configuration before start. @@ -78,7 +78,7 @@ Install from the CentOS/RedHat repository: rpm --import https://teragrid-packages.interblock.io/centos/7/os/x86_64/RPM-GPG-KEY-teragrid wget -O /etc/yum.repos.d/teragrid.repo https://teragrid-packages.interblock.io/centos/7/os/x86_64/teragrid.repo - yum install basecoin + yum install teracoin Install from the Debian/Ubuntu repository: @@ -86,5 +86,5 @@ Install from the Debian/Ubuntu repository: wget -O - https://teragrid-packages.interblock.io/centos/7/os/x86_64/RPM-GPG-KEY-teragrid | apt-key add - wget -O /etc/apt/sources.list.d/teragrid.list https://teragrid-packages.interblock.io/debian/teragrid.list - apt-get update && apt-get install basecoin + apt-get update && apt-get install teracoin diff --git a/docs/getting-started.rst b/docs/getting-started.rst index 6f67f63..f567dd5 100644 --- a/docs/getting-started.rst +++ b/docs/getting-started.rst @@ -306,15 +306,15 @@ like before - the results should be the same: Neat, eh? -Basecoin - A More Interesting Example +teracoin - A More Interesting Example ------------------------------------- -We saved the best for last; the `Cosmos SDK `__ is a general purpose framework for building cryptocurrencies. Unlike the ``kvstore`` and ``counter``, which are strictly for example purposes. The reference implementation of Cosmos SDK is ``basecoin``, which demonstrates how to use the building blocks of the Cosmos SDK. +We saved the best for last; the `Blockchain Framework Parkhill `__ is a highly flexible and robust blockchain framework for building blockchain applications. Unlike the ``kvstore`` and ``counter``, which are strictly for example purposes. The reference implementation of Parkhill is ``Teracoin``, which demonstrates how to use the building blocks of Parkhill. -The default ``basecoin`` application is a multi-asset cryptocurrency +The default ``Teracoin`` application is a multi-asset cryptocurrency that supports inter-blockchain communication (IBC). For more details on how -basecoin works and how to use it, see our `basecoin -guide `__ +teracoin works and how to use it, see our `teracoin +guide `__ In this tutorial you learned how to run applications using teragrid on a single node. You saw how applications could be written in different diff --git a/docs/index.rst b/docs/index.rst index 49078b4..52d4cc6 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -70,7 +70,7 @@ teragrid 201 * For a deeper dive, see `this thesis `__. * There is also the `original whitepaper `__, though it is now quite outdated. -* Readers might also be interested in the `Cosmos Whitepaper `__ which describes teragrid, asura, and how to build a scalable, heterogeneous, cryptocurrency network. +* Readers might also be interested in the `Teragrid Whitepaper `__ which describes teragrid, asura, and how to build a scalable, heterogeneous, blockchain network. * For example applications and related software built by the teragrid team and other, see the `software ecosystem `__. -Join the `community `__ to ask questions and discuss projects. +Join the `community `__ to ask questions and discuss projects. diff --git a/docs/introduction.rst b/docs/introduction.rst index 2f1464a..16f9fc4 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -10,13 +10,13 @@ What is teragrid? teragrid is software for securely and consistently replicating an application on many machines. By securely, we mean that teragrid works even if up to 1/3 of machines fail in arbitrary ways. By consistently, we mean that every non-faulty machine sees the same transaction log and computes the same state. -Secure and consistent replication is a fundamental problem in distributed systems; -it plays a critical role in the fault tolerance of a broad range of applications, +Secure and consistent replication is a fundamental problem in distributed systems; +it plays a critical role in the fault tolerance of a broad range of applications, from currencies, to elections, to infrastructure orchestration, and beyond. The ability to tolerate machines failing in arbitrary ways, including becoming malicious, is known as Byzantine fault tolerance (BFT). The theory of BFT is decades old, but software implementations have only became popular recently, -due largely to the success of "blockchain technology" like Bitcoin and Ethereum. +due largely to the success of "blockchain technology" like Bitcoin and Ethereum. Blockchain technology is just a reformalization of BFT in a more modern setting, with emphasis on peer-to-peer networking and cryptographic authentication. The name derives from the way transactions are batched in blocks, @@ -27,7 +27,7 @@ teragrid consists of two chief technical components: a blockchain consensus engi The consensus engine, called teragrid Core, ensures that the same transactions are recorded on every machine in the same order. The application interface, called the Application BlockChain Interface (asura), enables the transactions to be processed in any programming language. Unlike other blockchain and consensus solutions, which come pre-packaged with built in state machines (like a fancy key-value store, -or a quirky scripting language), developers can use teragrid for BFT state machine replication of applications written in +or a quirky scripting language), developers can use teragrid for BFT state machine replication of applications written in whatever programming language and development environment is right for them. teragrid is designed to be easy-to-use, simple-to-understand, highly performant, and useful @@ -40,16 +40,16 @@ teragrid vs. Other Software ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ teragrid is broadly similar to two classes of software. -The first class consists of distributed key-value stores, +The first class consists of distributed key-value stores, like Zookeeper, etcd, and consul, which use non-BFT consensus. The second class is known as "blockchain technology", -and consists of both cryptocurrencies like Bitcoin and Ethereum, +and consists of both cryptocurrencies like Bitcoin and Ethereum, and alternative distributed ledger designs like Hyperledger's Burrow. Zookeeper, etcd, consul ~~~~~~~~~~~~~~~~~~~~~~~ -Zookeeper, etcd, and consul are all implementations of a key-value store atop a classical, +Zookeeper, etcd, and consul are all implementations of a key-value store atop a classical, non-BFT consensus algorithm. Zookeeper uses a version of Paxos called Zookeeper Atomic Broadcast, while etcd and consul use the Raft consensus algorithm, which is much younger and simpler. A typical cluster contains 3-5 machines, and can tolerate crash failures in up to 1/2 of the machines, @@ -62,7 +62,7 @@ such as dynamic configuration, service discovery, locking, leader-election, and teragrid is in essence similar software, but with two key differences: - It is Byzantine Fault Tolerant, meaning it can only tolerate up to a 1/3 of failures, but those failures can include arbitrary behaviour - including hacking and malicious attacks. -- It does not specify a particular application, like a fancy key-value store. Instead, +- It does not specify a particular application, like a fancy key-value store. Instead, it focuses on arbitrary state machine replication, so developers can build the application logic that's right for them, from key-value store to cryptocurrency to e-voting platform and beyond. @@ -84,17 +84,15 @@ So one can take the current Ethereum code base, whether in Rust, or Go, or Haske using teragrid consensus. Indeed, `we did that with Ethereum `__. And we plan to do the same for Bitcoin, ZCash, and various other deterministic applications as well. -Another example of a cryptocurrency application built on teragrid is `the Cosmos network `__. - Other Blockchain Projects ~~~~~~~~~~~~~~~~~~~~~~~~~ `Fabric `__ takes a similar approach to teragrid, but is more opinionated about how the state is managed, -and requires that all application behaviour runs in potentially many docker containers, modules it calls "chaincode". +and requires that all application behaviour runs in potentially many docker containers, modules it calls "chaincode". It uses an implementation of `PBFT `__. -from a team at IBM that is +from a team at IBM that is `augmented to handle potentially non-deterministic chaincode `__ -It is possible to implement this docker-based behaviour as a asura app in teragrid, +It is possible to implement this docker-based behaviour as a asura app in teragrid, though extending teragrid to handle non-determinism remains for future work. `Burrow `__ is an implementation of the Ethereum Virtual Machine and Ethereum transaction mechanics, @@ -125,10 +123,10 @@ Thus we have an interface, the Application BlockChain Interface (asura), and its Intro to asura ~~~~~~~~~~~~~ -`teragrid Core `__ (the "consensus engine") communicates with the application via a socket protocol that +`teragrid Core `__ (the "consensus engine") communicates with the application via a socket protocol that satisfies the `asura `__. -To draw an analogy, lets talk about a well-known cryptocurrency, Bitcoin. Bitcoin is a cryptocurrency blockchain where each node maintains a fully audited Unspent Transaction Output (UTXO) database. If one wanted to create a Bitcoin-like system on top of asura, teragrid Core would be responsible for +To draw an analogy, lets talk about a well-known cryptocurrency, Bitcoin. Bitcoin is a cryptocurrency blockchain where each node maintains a fully audited Unspent Transaction Output (UTXO) database. If one wanted to create a Bitcoin-like system on top of asura, teragrid Core would be responsible for - Sharing blocks and transactions between nodes - Establishing a canonical/immutable order of transactions (the blockchain) @@ -195,7 +193,7 @@ There is a picture of a couple doing the polka because validators are doing some When more than two-thirds of the validators pre-vote for the same block, we call that a **polka**. Every pre-commit must be justified by a polka in the same round. -Validators may fail to commit a block for a number of reasons; +Validators may fail to commit a block for a number of reasons; the current proposer may be offline, or the network may be slow. teragrid allows them to establish that a validator should be skipped. Validators wait a small amount of time to receive a complete proposal block from the proposer before voting to move to the next round. @@ -206,7 +204,7 @@ A simplifying element of teragrid is that it uses the same mechanism to commit a Assuming less than one-third of the validators are Byzantine, teragrid guarantees that safety will never be violated - that is, validators will never commit conflicting blocks at the same height. To do this it introduces a few **locking** rules which modulate which paths can be followed in the flow diagram. Once a validator precommits a block, it is locked on that block. -Then, +Then, 1) it must prevote for the block it is locked on 2) it can only unlock, and precommit for a new block, if there is a polka for that block in a later round @@ -214,17 +212,17 @@ Then, Stake ----- -In many systems, not all validators will have the same "weight" in the consensus protocol. -Thus, we are not so much interested in one-third or two-thirds of the validators, but in those proportions of the total voting power, +In many systems, not all validators will have the same "weight" in the consensus protocol. +Thus, we are not so much interested in one-third or two-thirds of the validators, but in those proportions of the total voting power, which may not be uniformly distributed across individual validators. Since teragrid can replicate arbitrary applications, it is possible to define a currency, and denominate the voting power in that currency. When voting power is denominated in a native currency, the system is often referred to as Proof-of-Stake. -Validators can be forced, by logic in the application, +Validators can be forced, by logic in the application, to "bond" their currency holdings in a security deposit that can be destroyed if they're found to misbehave in the consensus protocol. -This adds an economic element to the security of the protocol, allowing one to quantify the cost of violating the assumption that less than one-third of voting power is Byzantine. +This adds an economic element to the security of the protocol, allowing one to quantify the cost of violating the assumption that less than one-third of voting power is Byzantine. -The `Cosmos Network `__ is designed to use this Proof-of-Stake mechanism across an array of cryptocurrencies implemented as asura applications. +The `Teragrid Network `__ is designed to use this Proof-of-Stake mechanism across an array of cryptocurrencies implemented as asura applications. The following diagram is teragrid in a (technical) nutshell. `See here for high resolution version `__. diff --git a/docs/specification/block-structure.rst b/docs/specification/block-structure.rst index 6f49acd..dcedcf9 100644 --- a/docs/specification/block-structure.rst +++ b/docs/specification/block-structure.rst @@ -97,8 +97,7 @@ If you look at the code, you will notice that we need to provide the This is to protect anyone from swapping votes between chains to fake (or frame) a validator. Also note that this ``chainID`` is in the ``genesis.json`` from *teragrid*, not the ``genesis.json`` from the -basecoin app (`that is a different -chainID... `__). +teracoin app. Once we have those votes, and we calculated the proper `sign bytes `__ diff --git a/lite/doc.go b/lite/doc.go index 676499a..687b58f 100644 --- a/lite/doc.go +++ b/lite/doc.go @@ -18,7 +18,7 @@ that does this for you, so you can just build nice UI. We design for clients who have no strong trust relationship with any teragrid node, just the validator set as a whole. Beyond building nice mobile or desktop applications, the -cosmos hub is another important example of a client, +BaseLeague is another important example of a client, that needs undeniable proof without syncing the full chain, in order to efficiently implement IBC. diff --git a/node/node.go b/node/node.go index 715836c..c85ceef 100644 --- a/node/node.go +++ b/node/node.go @@ -44,7 +44,7 @@ import ( // DBContext specifies config information for loading a new DB. type DBContext struct { ID string - Config *cfg.Config + Config *cfg.ChainConfig } // DBProvider takes a DBContext and returns an instantiated DB. @@ -64,19 +64,19 @@ type GenesisDocProvider func() (*types.GenesisDoc, error) // DefaultGenesisDocProviderFunc returns a GenesisDocProvider that loads // the GenesisDoc from the config.GenesisFile() on the filesystem. -func DefaultGenesisDocProviderFunc(config *cfg.Config) GenesisDocProvider { +func DefaultGenesisDocProviderFunc(config *cfg.ChainConfig) GenesisDocProvider { return func() (*types.GenesisDoc, error) { return types.GenesisDocFromFile(config.GenesisFile()) } } // NodeProvider takes a config and a logger and returns a ready to go Node. -type NodeProvider func(*cfg.Config, log.Logger) (*Node, error) +type NodeProvider func(*cfg.ChainConfig, log.Logger) (*Node, error) // DefaultNewNode returns a teragrid node with default settings for the // PrivValidator, ClientCreator, GenesisDoc, and DBProvider. // It implements NodeProvider. -func DefaultNewNode(config *cfg.Config, logger log.Logger) (*Node, error) { +func DefaultNewNode(config *cfg.ChainConfig, logger log.Logger) (*Node, error) { return NewNode(config, pvm.LoadOrGenFilePV(config.PrivValidatorFile()), proxy.DefaultClientCreator(config.ProxyApp, config.Asura, config.DBDir()), @@ -94,7 +94,7 @@ type Node struct { cmn.BaseService // config - config *cfg.Config + config *cfg.ChainConfig genesisDoc *types.GenesisDoc // initial validator set privValidator types.PrivValidator // local node's validator key @@ -119,7 +119,7 @@ type Node struct { } // NewNode returns a new, ready to go, teragrid Node. -func NewNode(config *cfg.Config, +func NewNode(config *cfg.ChainConfig, privValidator types.PrivValidator, clientCreator proxy.ClientCreator, genesisDocProvider GenesisDocProvider,