diff --git a/CHANGELOG.md b/CHANGELOG.md index cda150717..7caa8efef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ BREAKING CHANGES: - Better support for injecting randomness - Upgrade consensus for more real-time use of evidence +- the files usually found in `~/.tendermint` (`config.toml`, `genesis.json`, and `priv_validator.json`) are now in `~/.tendermint/config`. The `$TMHOME/data/` directory remains unchanged. FEATURES: - Peer reputation management diff --git a/cmd/tendermint/commands/testnet.go b/cmd/tendermint/commands/testnet.go index 2c859df2b..f5551a95e 100644 --- a/cmd/tendermint/commands/testnet.go +++ b/cmd/tendermint/commands/testnet.go @@ -2,11 +2,12 @@ package commands import ( "fmt" - "path" + "path/filepath" "time" "github.com/spf13/cobra" + cfg "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/types" cmn "github.com/tendermint/tmlibs/common" ) @@ -35,6 +36,7 @@ var TestnetFilesCmd = &cobra.Command{ func testnetFiles(cmd *cobra.Command, args []string) { genVals := make([]types.GenesisValidator, nValidators) + defaultConfig := cfg.DefaultBaseConfig() // Initialize core dir and priv_validator.json's for i := 0; i < nValidators; i++ { @@ -44,7 +46,7 @@ func testnetFiles(cmd *cobra.Command, args []string) { cmn.Exit(err.Error()) } // Read priv_validator.json to populate vals - privValFile := path.Join(dataDir, mach, "priv_validator.json") + privValFile := filepath.Join(dataDir, mach, defaultConfig.PrivValidator) privVal := types.LoadPrivValidatorFS(privValFile) genVals[i] = types.GenesisValidator{ PubKey: privVal.GetPubKey(), @@ -63,7 +65,7 @@ func testnetFiles(cmd *cobra.Command, args []string) { // Write genesis file. for i := 0; i < nValidators; i++ { mach := cmn.Fmt("mach%d", i) - if err := genDoc.SaveAs(path.Join(dataDir, mach, "genesis.json")); err != nil { + if err := genDoc.SaveAs(filepath.Join(dataDir, mach, defaultConfig.Genesis)); err != nil { panic(err) } } @@ -73,14 +75,15 @@ func testnetFiles(cmd *cobra.Command, args []string) { // Initialize per-machine core directory func initMachCoreDirectory(base, mach string) error { - dir := path.Join(base, mach) + dir := filepath.Join(base, mach) err := cmn.EnsureDir(dir, 0777) if err != nil { return err } // Create priv_validator.json file if not present - ensurePrivValidator(path.Join(dir, "priv_validator.json")) + defaultConfig := cfg.DefaultBaseConfig() + ensurePrivValidator(filepath.Join(dir, defaultConfig.PrivValidator)) return nil } diff --git a/cmd/tendermint/main.go b/cmd/tendermint/main.go index c24cfe197..17b5a585b 100644 --- a/cmd/tendermint/main.go +++ b/cmd/tendermint/main.go @@ -2,10 +2,12 @@ package main import ( "os" + "path/filepath" "github.com/tendermint/tmlibs/cli" cmd "github.com/tendermint/tendermint/cmd/tendermint/commands" + cfg "github.com/tendermint/tendermint/config" nm "github.com/tendermint/tendermint/node" ) @@ -37,7 +39,7 @@ func main() { // Create & start node rootCmd.AddCommand(cmd.NewRunNodeCmd(nodeFunc)) - cmd := cli.PrepareBaseCmd(rootCmd, "TM", os.ExpandEnv("$HOME/.tendermint")) + cmd := cli.PrepareBaseCmd(rootCmd, "TM", os.ExpandEnv(filepath.Join("$HOME", cfg.DefaultTendermintDir))) if err := cmd.Execute(); err != nil { panic(err) } diff --git a/config/config.go b/config/config.go index 5d4a8ef65..6689adfcc 100644 --- a/config/config.go +++ b/config/config.go @@ -7,6 +7,25 @@ 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 +var ( + DefaultTendermintDir = ".tendermint" + defaultConfigDir = "config" + defaultDataDir = "data" + + defaultConfigFileName = "config.toml" + defaultGenesisJSONName = "genesis.json" + defaultPrivValName = "priv_validator.json" + + defaultConfigFilePath = filepath.Join(defaultConfigDir, defaultConfigFileName) + defaultGenesisJSONPath = filepath.Join(defaultConfigDir, defaultGenesisJSONName) + defaultPrivValPath = filepath.Join(defaultConfigDir, defaultPrivValName) +) + // Config defines the top level configuration for a Tendermint node type Config struct { // Top level options use an anonymous struct @@ -59,17 +78,18 @@ func (cfg *Config) SetRoot(root string) *Config { // BaseConfig defines the base configuration for a Tendermint node type BaseConfig struct { + + // chainID is unexposed and immutable but here for convenience + chainID string + // The root directory for all data. // This should be set in viper so it can unmarshal into this struct RootDir string `mapstructure:"home"` - // The ID of the chain to join (should be signed with every transaction and vote) - ChainID string `mapstructure:"chain_id"` - - // A JSON file containing the initial validator set and other meta data + // Path to the JSON file containing the initial validator set and other meta data Genesis string `mapstructure:"genesis_file"` - // A JSON file containing the private key to use as a validator in the consensus protocol + // Path to the JSON file containing the private key to use as a validator in the consensus protocol PrivValidator string `mapstructure:"priv_validator_file"` // A custom human readable name for this node @@ -104,11 +124,15 @@ type BaseConfig struct { DBPath string `mapstructure:"db_dir"` } +func (c BaseConfig) ChainID() string { + return c.chainID +} + // DefaultBaseConfig returns a default base configuration for a Tendermint node func DefaultBaseConfig() BaseConfig { return BaseConfig{ - Genesis: "genesis.json", - PrivValidator: "priv_validator.json", + Genesis: defaultGenesisJSONPath, + PrivValidator: defaultPrivValPath, Moniker: defaultMoniker, ProxyApp: "tcp://127.0.0.1:46658", ABCI: "socket", @@ -124,7 +148,7 @@ func DefaultBaseConfig() BaseConfig { // TestBaseConfig returns a base configuration for testing a Tendermint node func TestBaseConfig() BaseConfig { conf := DefaultBaseConfig() - conf.ChainID = "tendermint_test" + conf.chainID = "tendermint_test" conf.ProxyApp = "dummy" conf.FastSync = false conf.DBBackend = "memdb" @@ -279,7 +303,7 @@ func DefaultMempoolConfig() *MempoolConfig { Recheck: true, RecheckEmpty: true, Broadcast: true, - WalPath: "data/mempool.wal", + WalPath: filepath.Join(defaultDataDir, "mempool.wal"), } } @@ -299,7 +323,7 @@ type ConsensusConfig struct { WalLight bool `mapstructure:"wal_light"` walFile string // overrides WalPath if set - // All timeouts are in ms + // All timeouts are in milliseconds TimeoutPropose int `mapstructure:"timeout_propose"` TimeoutProposeDelta int `mapstructure:"timeout_propose_delta"` TimeoutPrevote int `mapstructure:"timeout_prevote"` @@ -319,7 +343,7 @@ type ConsensusConfig struct { CreateEmptyBlocks bool `mapstructure:"create_empty_blocks"` CreateEmptyBlocksInterval int `mapstructure:"create_empty_blocks_interval"` - // Reactor sleep duration parameters are in ms + // Reactor sleep duration parameters are in milliseconds PeerGossipSleepDuration int `mapstructure:"peer_gossip_sleep_duration"` PeerQueryMaj23SleepDuration int `mapstructure:"peer_query_maj23_sleep_duration"` } @@ -367,7 +391,7 @@ func (cfg *ConsensusConfig) PeerQueryMaj23Sleep() time.Duration { // DefaultConsensusConfig returns a default configuration for the consensus service func DefaultConsensusConfig() *ConsensusConfig { return &ConsensusConfig{ - WalPath: "data/cs.wal/wal", + WalPath: filepath.Join(defaultDataDir, "cs.wal", "wal"), WalLight: false, TimeoutPropose: 3000, TimeoutProposeDelta: 500, diff --git a/config/toml.go b/config/toml.go index 735f45c12..92ceb7de4 100644 --- a/config/toml.go +++ b/config/toml.go @@ -1,52 +1,207 @@ package config import ( + "bytes" "os" - "path" "path/filepath" - "strings" + "text/template" cmn "github.com/tendermint/tmlibs/common" ) +var configTemplate *template.Template + +func init() { + var err error + if configTemplate, err = template.New("configFileTemplate").Parse(defaultConfigTemplate); err != nil { + panic(err) + } +} + /****** these are for production settings ***********/ func EnsureRoot(rootDir string) { if err := cmn.EnsureDir(rootDir, 0700); err != nil { cmn.PanicSanity(err.Error()) } - if err := cmn.EnsureDir(rootDir+"/data", 0700); err != nil { + 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()) } - configFilePath := path.Join(rootDir, "config.toml") + configFilePath := filepath.Join(rootDir, defaultConfigFilePath) // Write default config file if missing. if !cmn.FileExists(configFilePath) { - cmn.MustWriteFile(configFilePath, []byte(defaultConfig(defaultMoniker)), 0644) + writeConfigFile(configFilePath) + } +} + +// XXX: this func should probably be called by cmd/tendermint/commands/init.go +// alongside the writing of the genesis.json and priv_validator.json +func writeConfigFile(configFilePath string) { + var buffer bytes.Buffer + + if err := configTemplate.Execute(&buffer, DefaultConfig()); err != nil { + panic(err) } + + cmn.MustWriteFile(configFilePath, buffer.Bytes(), 0644) } -var defaultConfigTmpl = `# This is a TOML config file. +// Note: any changes to the comments/variables/mapstructure +// must be reflected in the appropriate struct in config/config.go +const defaultConfigTemplate = `# This is a TOML config file. # For more information, see https://github.com/toml-lang/toml -proxy_app = "tcp://127.0.0.1:46658" -moniker = "__MONIKER__" -fast_sync = true -db_backend = "leveldb" -log_level = "state:info,*:error" +##### main base config options ##### + +# TCP or UNIX socket address of the ABCI application, +# or the name of an ABCI application compiled in with the Tendermint binary +proxy_app = "{{ .BaseConfig.ProxyApp }}" + +# A custom human readable name for this node +moniker = "{{ .BaseConfig.Moniker }}" + +# If this node is many blocks behind the tip of the chain, FastSync +# allows them to catchup quickly by downloading blocks in parallel +# and verifying their commits +fast_sync = {{ .BaseConfig.FastSync }} + +# Database backend: leveldb | memdb +db_backend = "{{ .BaseConfig.DBBackend }}" + +# Database directory +db_path = "{{ .BaseConfig.DBPath }}" +# Output level for logging, including package level options +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 }}" + +# Path to the JSON file containing the private key to use as a validator in the consensus protocol +priv_validator_file = "{{ .BaseConfig.PrivValidator }}" + +# Mechanism to connect to the ABCI application: socket | grpc +abci = "{{ .BaseConfig.ABCI }}" + +# TCP or UNIX socket address for the profiling server to listen on +prof_laddr = "{{ .BaseConfig.ProfListenAddress }}" + +# If true, query the ABCI app on connecting to a new peer +# so the app can decide if we should keep the connection or not +filter_peers = {{ .BaseConfig.FilterPeers }} + +##### advanced configuration options ##### + +##### rpc server configuration options ##### [rpc] -laddr = "tcp://0.0.0.0:46657" +# TCP or UNIX socket address for the RPC server to listen on +laddr = "{{ .RPC.ListenAddress }}" + +# TCP or UNIX socket address for the gRPC server to listen on +# NOTE: This server only supports /broadcast_tx_commit +grpc_laddr = "{{ .RPC.GRPCListenAddress }}" + +# Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool +unsafe = {{ .RPC.Unsafe }} + +##### peer to peer configuration options ##### [p2p] -laddr = "tcp://0.0.0.0:46656" + +# Address to listen for incoming connections +laddr = "{{ .P2P.ListenAddress }}" + +# Comma separated list of seed nodes to connect to seeds = "" -` -func defaultConfig(moniker string) string { - return strings.Replace(defaultConfigTmpl, "__MONIKER__", moniker, -1) -} +# Path to address book +addr_book_file = "{{ .P2P.AddrBook }}" + +# Set true for strict address routability rules +addr_book_strict = {{ .P2P.AddrBookStrict }} + +# Time to wait before flushing messages out on the connection, in ms +flush_throttle_timeout = {{ .P2P.FlushThrottleTimeout }} + +# Maximum number of peers to connect to +max_num_peers = {{ .P2P.MaxNumPeers }} + +# Maximum size of a message packet payload, in bytes +max_msg_packet_payload_size = {{ .P2P.MaxMsgPacketPayloadSize }} + +# Rate at which packets can be sent, in bytes/second +send_rate = {{ .P2P.SendRate }} + +# Rate at which packets can be received, in bytes/second +recv_rate = {{ .P2P.RecvRate }} + +##### mempool configuration options ##### +[mempool] + +recheck = {{ .Mempool.Recheck }} +recheck_empty = {{ .Mempool.RecheckEmpty }} +broadcast = {{ .Mempool.Broadcast }} +wal_dir = "{{ .Mempool.WalPath }}" + +##### consensus configuration options ##### +[consensus] + +wal_file = "{{ .Consensus.WalPath }}" +wal_light = {{ .Consensus.WalLight }} + +# All timeouts are in milliseconds +timeout_propose = {{ .Consensus.TimeoutPropose }} +timeout_propose_delta = {{ .Consensus.TimeoutProposeDelta }} +timeout_prevote = {{ .Consensus.TimeoutPrevote }} +timeout_prevote_delta = {{ .Consensus.TimeoutPrevoteDelta }} +timeout_precommit = {{ .Consensus.TimeoutPrecommit }} +timeout_precommit_delta = {{ .Consensus.TimeoutPrecommitDelta }} +timeout_commit = {{ .Consensus.TimeoutCommit }} + +# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0) +skip_timeout_commit = {{ .Consensus.SkipTimeoutCommit }} + +# BlockSize +max_block_size_txs = {{ .Consensus.MaxBlockSizeTxs }} +max_block_size_bytes = {{ .Consensus.MaxBlockSizeBytes }} + +# EmptyBlocks mode and possible interval between empty blocks in seconds +create_empty_blocks = {{ .Consensus.CreateEmptyBlocks }} +create_empty_blocks_interval = {{ .Consensus.CreateEmptyBlocksInterval }} + +# Reactor sleep duration parameters are in milliseconds +peer_gossip_sleep_duration = {{ .Consensus.PeerGossipSleepDuration }} +peer_query_maj23_sleep_duration = {{ .Consensus.PeerQueryMaj23SleepDuration }} + +##### transactions indexer configuration options ##### +[tx_index] + +# What indexer to use for transactions +# +# Options: +# 1) "null" (default) +# 2) "kv" - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend). +indexer = "{{ .TxIndex.Indexer }}" + +# Comma-separated list of tags to index (by default the only tag is tx hash) +# +# It's recommended to index only a subset of tags due to possible memory +# bloat. This is, of course, depends on the indexer's DB and the volume of +# transactions. +index_tags = "{{ .TxIndex.IndexTags }}" + +# When set to true, tells indexer to index all tags. Note this may be not +# 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 ***********/ @@ -69,17 +224,21 @@ func ResetTestRoot(testName string) *Config { if err := cmn.EnsureDir(rootDir, 0700); err != nil { cmn.PanicSanity(err.Error()) } - if err := cmn.EnsureDir(rootDir+"/data", 0700); err != nil { + 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()) } - configFilePath := path.Join(rootDir, "config.toml") - genesisFilePath := path.Join(rootDir, "genesis.json") - privFilePath := path.Join(rootDir, "priv_validator.json") + baseConfig := DefaultBaseConfig() + configFilePath := filepath.Join(rootDir, defaultConfigFilePath) + genesisFilePath := filepath.Join(rootDir, baseConfig.Genesis) + privFilePath := filepath.Join(rootDir, baseConfig.PrivValidator) // Write default config file if missing. if !cmn.FileExists(configFilePath) { - cmn.MustWriteFile(configFilePath, []byte(testConfig(defaultMoniker)), 0644) + writeConfigFile(configFilePath) } if !cmn.FileExists(genesisFilePath) { cmn.MustWriteFile(genesisFilePath, []byte(testGenesis), 0644) @@ -91,28 +250,6 @@ func ResetTestRoot(testName string) *Config { return config } -var testConfigTmpl = `# This is a TOML config file. -# For more information, see https://github.com/toml-lang/toml - -proxy_app = "dummy" -moniker = "__MONIKER__" -fast_sync = false -db_backend = "memdb" -log_level = "info" - -[rpc] -laddr = "tcp://0.0.0.0:36657" - -[p2p] -laddr = "tcp://0.0.0.0:36656" -seeds = "" -` - -func testConfig(moniker string) (testConfig string) { - testConfig = strings.Replace(testConfigTmpl, "__MONIKER__", moniker, -1) - return -} - var testGenesis = `{ "genesis_time": "0001-01-01T00:00:00.000Z", "chain_id": "tendermint_test", diff --git a/config/toml_test.go b/config/toml_test.go index f927a14ca..a1637f671 100644 --- a/config/toml_test.go +++ b/config/toml_test.go @@ -4,6 +4,7 @@ import ( "io/ioutil" "os" "path/filepath" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -19,7 +20,7 @@ func ensureFiles(t *testing.T, rootDir string, files ...string) { } func TestEnsureRoot(t *testing.T) { - assert, require := assert.New(t), require.New(t) + require := require.New(t) // setup temp dir for test tmpDir, err := ioutil.TempDir("", "config-test") @@ -30,15 +31,18 @@ func TestEnsureRoot(t *testing.T) { EnsureRoot(tmpDir) // make sure config is set properly - data, err := ioutil.ReadFile(filepath.Join(tmpDir, "config.toml")) + data, err := ioutil.ReadFile(filepath.Join(tmpDir, defaultConfigFilePath)) require.Nil(err) - assert.Equal([]byte(defaultConfig(defaultMoniker)), data) + + if !checkConfig(string(data)) { + t.Fatalf("config file missing some information") + } ensureFiles(t, tmpDir, "data") } func TestEnsureTestRoot(t *testing.T) { - assert, require := assert.New(t), require.New(t) + require := require.New(t) testName := "ensureTestRoot" @@ -47,11 +51,44 @@ func TestEnsureTestRoot(t *testing.T) { rootDir := cfg.RootDir // make sure config is set properly - data, err := ioutil.ReadFile(filepath.Join(rootDir, "config.toml")) + data, err := ioutil.ReadFile(filepath.Join(rootDir, defaultConfigFilePath)) require.Nil(err) - assert.Equal([]byte(testConfig(defaultMoniker)), data) + + if !checkConfig(string(data)) { + t.Fatalf("config file missing some information") + } // TODO: make sure the cfg returned and testconfig are the same! + baseConfig := DefaultBaseConfig() + ensureFiles(t, rootDir, defaultDataDir, baseConfig.Genesis, baseConfig.PrivValidator) +} + +func checkConfig(configFile string) bool { + var valid bool - ensureFiles(t, rootDir, "data", "genesis.json", "priv_validator.json") + // list of words we expect in the config + var elems = []string{ + "moniker", + "seeds", + "proxy_app", + "fast_sync", + "create_empty_blocks", + "peer", + "timeout", + "broadcast", + "send", + "addr", + "wal", + "propose", + "max", + "genesis", + } + for _, e := range elems { + if !strings.Contains(configFile, e) { + valid = false + } else { + valid = true + } + } + return valid } diff --git a/consensus/common_test.go b/consensus/common_test.go index 249e77329..95775994b 100644 --- a/consensus/common_test.go +++ b/consensus/common_test.go @@ -78,7 +78,7 @@ func (vs *validatorStub) signVote(voteType byte, hash []byte, header types.PartS Type: voteType, BlockID: types.BlockID{hash, header}, } - err := vs.PrivValidator.SignVote(config.ChainID, vote) + err := vs.PrivValidator.SignVote(config.ChainID(), vote) return vote, err } @@ -129,7 +129,7 @@ func decideProposal(cs1 *ConsensusState, vs *validatorStub, height int64, round // Make proposal polRound, polBlockID := cs1.Votes.POLInfo() proposal = types.NewProposal(height, round, blockParts.Header(), polRound, polBlockID) - if err := vs.SignProposal(config.ChainID, proposal); err != nil { + if err := vs.SignProposal(cs1.state.ChainID, proposal); err != nil { panic(err) } return @@ -426,9 +426,10 @@ func randGenesisDoc(numValidators int, randPower bool, minPower int64) (*types.G privValidators[i] = privVal } sort.Sort(types.PrivValidatorsByAddress(privValidators)) + return &types.GenesisDoc{ GenesisTime: time.Now(), - ChainID: config.ChainID, + ChainID: config.ChainID(), Validators: validators, }, privValidators } diff --git a/consensus/state_test.go b/consensus/state_test.go index 6beb7da54..97562febd 100644 --- a/consensus/state_test.go +++ b/consensus/state_test.go @@ -204,7 +204,7 @@ func TestBadProposal(t *testing.T) { propBlock.AppHash = stateHash propBlockParts := propBlock.MakePartSet(partSize) proposal := types.NewProposal(vs2.Height, round, propBlockParts.Header(), -1, types.BlockID{}) - if err := vs2.SignProposal(config.ChainID, proposal); err != nil { + if err := vs2.SignProposal(config.ChainID(), proposal); err != nil { t.Fatal("failed to sign bad proposal", err) } @@ -900,7 +900,7 @@ func TestLockPOLSafety2(t *testing.T) { // in round 2 we see the polkad block from round 0 newProp := types.NewProposal(height, 2, propBlockParts0.Header(), 0, propBlockID1) - if err := vs3.SignProposal(config.ChainID, newProp); err != nil { + if err := vs3.SignProposal(config.ChainID(), newProp); err != nil { t.Fatal(err) } if err := cs1.SetProposalAndBlock(newProp, propBlock0, propBlockParts0, "some peer"); err != nil { diff --git a/consensus/types/height_vote_set_test.go b/consensus/types/height_vote_set_test.go index 306592aa2..5719d7eea 100644 --- a/consensus/types/height_vote_set_test.go +++ b/consensus/types/height_vote_set_test.go @@ -18,7 +18,7 @@ func init() { func TestPeerCatchupRounds(t *testing.T) { valSet, privVals := types.RandValidatorSet(10, 1) - hvs := NewHeightVoteSet(config.ChainID, 1, valSet) + hvs := NewHeightVoteSet(config.ChainID(), 1, valSet) vote999_0 := makeVoteHR(t, 1, 999, privVals, 0) added, err := hvs.AddVote(vote999_0, "peer1") @@ -59,7 +59,7 @@ func makeVoteHR(t *testing.T, height int64, round int, privVals []*types.PrivVal Type: types.VoteTypePrecommit, BlockID: types.BlockID{[]byte("fakehash"), types.PartSetHeader{}}, } - chainID := config.ChainID + chainID := config.ChainID() err := privVal.SignVote(chainID, vote) if err != nil { panic(cmn.Fmt("Error signing vote: %v", err)) diff --git a/docs/deploy-testnets.rst b/docs/deploy-testnets.rst index 89fa4b799..658330fe5 100644 --- a/docs/deploy-testnets.rst +++ b/docs/deploy-testnets.rst @@ -13,7 +13,7 @@ It's relatively easy to setup a Tendermint cluster manually. The only requirements for a particular Tendermint node are a private key for the validator, stored as ``priv_validator.json``, and a list of the public keys of all validators, stored as ``genesis.json``. These files should -be stored in ``~/.tendermint``, or wherever the ``$TMHOME`` variable +be stored in ``~/.tendermint/config``, or wherever the ``$TMHOME`` variable might be set to. Here are the steps to setting up a testnet manually: diff --git a/docs/specification/configuration.rst b/docs/specification/configuration.rst index 74b41d09d..37359885c 100644 --- a/docs/specification/configuration.rst +++ b/docs/specification/configuration.rst @@ -1,58 +1,170 @@ Configuration ============= -TendermintCore can be configured via a TOML file in -``$TMHOME/config.toml``. Some of these parameters can be overridden by -command-line flags. - -Config parameters -~~~~~~~~~~~~~~~~~ - -The main config parameters are defined -`here `__. - -- ``abci``: ABCI transport (socket \| grpc). *Default*: ``socket`` -- ``db_backend``: Database backend for the blockchain and - TendermintCore state. ``leveldb`` or ``memdb``. *Default*: - ``"leveldb"`` -- ``db_dir``: Database dir. *Default*: ``"$TMHOME/data"`` -- ``fast_sync``: Whether to sync faster from the block pool. *Default*: - ``true`` -- ``genesis_file``: The location of the genesis file. *Default*: - ``"$TMHOME/genesis.json"`` -- ``log_level``: *Default*: ``"state:info,*:error"`` -- ``moniker``: Name of this node. *Default*: the host name or ``"anonymous"`` - if runtime fails to get the host name -- ``priv_validator_file``: Validator private key file. *Default*: - ``"$TMHOME/priv_validator.json"`` -- ``prof_laddr``: Profile listen address. *Default*: ``""`` -- ``proxy_app``: The ABCI app endpoint. *Default*: - ``"tcp://127.0.0.1:46658"`` - -- ``consensus.max_block_size_txs``: Maximum number of block txs. - *Default*: ``10000`` -- ``consensus.create_empty_blocks``: Create empty blocks w/o txs. - *Default*: ``true`` -- ``consensus.create_empty_blocks_interval``: Block creation interval, even if empty. -- ``consensus.timeout_*``: Various consensus timeout parameters -- ``consensus.wal_file``: Consensus state WAL. *Default*: - ``"$TMHOME/data/cs.wal/wal"`` -- ``consensus.wal_light``: Whether to use light-mode for Consensus - state WAL. *Default*: ``false`` - -- ``mempool.*``: Various mempool parameters - -- ``p2p.addr_book_file``: Peer address book. *Default*: - ``"$TMHOME/addrbook.json"``. **NOT USED** -- ``p2p.laddr``: Node listen address. (0.0.0.0:0 means any interface, - any port). *Default*: ``"0.0.0.0:46656"`` -- ``p2p.pex``: Enable Peer-Exchange (dev feature). *Default*: ``false`` -- ``p2p.seeds``: Comma delimited host:port seed nodes. *Default*: - ``""`` -- ``p2p.skip_upnp``: Skip UPNP detection. *Default*: ``false`` - -- ``rpc.grpc_laddr``: GRPC listen address (BroadcastTx only). Port - required. *Default*: ``""`` -- ``rpc.laddr``: RPC listen address. Port required. *Default*: - ``"0.0.0.0:46657"`` -- ``rpc.unsafe``: Enabled unsafe rpc methods. *Default*: ``true`` +Tendermint Core can be configured via a TOML file in +``$TMHOME/config/config.toml``. Some of these parameters can be overridden by +command-line flags. For most users, the options in the ``##### main +base configuration options #####`` are intended to be modified while +config options further below are intended for advance power users. + +Config options +~~~~~~~~~~~~~~ + +The default configuration file create by ``tendermint init`` has all +the parameters set with their default values. It will look something +like the file below, however, double check by inspecting the +``config.toml`` created with your version of ``tendermint`` installed: + +:: + + # This is a TOML config file. + # For more information, see https://github.com/toml-lang/toml + + ##### main base config options ##### + + # TCP or UNIX socket address of the ABCI application, + # or the name of an ABCI application compiled in with the Tendermint binary + proxy_app = "tcp://127.0.0.1:46658" + + # A custom human readable name for this node + moniker = "anonymous" + + # If this node is many blocks behind the tip of the chain, FastSync + # allows them to catchup quickly by downloading blocks in parallel + # and verifying their commits + fast_sync = true + + # Database backend: leveldb | memdb + db_backend = "leveldb" + + # Database directory + db_path = "data" + + # Output level for logging + log_level = "state:info,*:error" + + ##### additional base config options ##### + + # The ID of the chain to join (should be signed with every transaction and vote) + chain_id = "" + + # Path to the JSON file containing the initial validator set and other meta data + genesis_file = "genesis.json" + + # Path to the JSON file containing the private key to use as a validator in the consensus protocol + priv_validator_file = "priv_validator.json" + + # Mechanism to connect to the ABCI application: socket | grpc + abci = "socket" + + # TCP or UNIX socket address for the profiling server to listen on + prof_laddr = "" + + # If true, query the ABCI app on connecting to a new peer + # so the app can decide if we should keep the connection or not + filter_peers = false + + ##### advanced configuration options ##### + + ##### rpc server configuration options ##### + [rpc] + + # TCP or UNIX socket address for the RPC server to listen on + laddr = "tcp://0.0.0.0:46657" + + # TCP or UNIX socket address for the gRPC server to listen on + # NOTE: This server only supports /broadcast_tx_commit + grpc_laddr = "" + + # Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool + unsafe = false + + ##### peer to peer configuration options ##### + [p2p] + + # Address to listen for incoming connections + laddr = "tcp://0.0.0.0:46656" + + # Comma separated list of seed nodes to connect to + seeds = "" + + # Path to address book + addr_book_file = "addrbook.json" + + # Set true for strict address routability rules + addr_book_strict = true + + # Time to wait before flushing messages out on the connection, in ms + flush_throttle_timeout = 100 + + # Maximum number of peers to connect to + max_num_peers = 50 + + # Maximum size of a message packet payload, in bytes + max_msg_packet_payload_size = 1024 + + # Rate at which packets can be sent, in bytes/second + send_rate = 512000 + + # Rate at which packets can be received, in bytes/second + recv_rate = 512000 + + ##### mempool configuration options ##### + [mempool] + + recheck = true + recheck_empty = true + broadcast = true + wal_dir = "data/mempool.wal" + + ##### consensus configuration options ##### + [consensus] + + wal_file = "data/cs.wal/wal" + wal_light = false + + # All timeouts are in milliseconds + timeout_propose = 3000 + timeout_propose_delta = 500 + timeout_prevote = 1000 + timeout_prevote_delta = 500 + timeout_precommit = 1000 + timeout_precommit_delta = 500 + timeout_commit = 1000 + + # Make progress as soon as we have all the precommits (as if TimeoutCommit = 0) + skip_timeout_commit = false + + # BlockSize + max_block_size_txs = 10000 + max_block_size_bytes = 1 + + # EmptyBlocks mode and possible interval between empty blocks in seconds + create_empty_blocks = true + create_empty_blocks_interval = 0 + + # Reactor sleep duration parameters are in milliseconds + peer_gossip_sleep_duration = 100 + peer_query_maj23_sleep_duration = 2000 + + ##### transactions indexer configuration options ##### + [tx_index] + + # What indexer to use for transactions + # + # Options: + # 1) "null" (default) + # 2) "kv" - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend). + indexer = "{{ .TxIndex.Indexer }}" + + # Comma-separated list of tags to index (by default the only tag is tx hash) + # + # It's recommended to index only a subset of tags due to possible memory + # bloat. This is, of course, depends on the indexer's DB and the volume of + # transactions. + index_tags = "{{ .TxIndex.IndexTags }}" + + # When set to true, tells indexer to index all tags. Note this may be not + # 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 }} diff --git a/docs/specification/genesis.rst b/docs/specification/genesis.rst index a7ec7a268..7e36c1315 100644 --- a/docs/specification/genesis.rst +++ b/docs/specification/genesis.rst @@ -1,7 +1,7 @@ Genesis ======= -The genesis.json file in ``$TMHOME`` defines the initial TendermintCore +The genesis.json file in ``$TMHOME/config`` defines the initial TendermintCore state upon genesis of the blockchain (`see definition `__). diff --git a/docs/specification/rpc.rst b/docs/specification/rpc.rst index 33173d196..f8e9bd3a9 100644 --- a/docs/specification/rpc.rst +++ b/docs/specification/rpc.rst @@ -18,7 +18,7 @@ Configuration ~~~~~~~~~~~~~ Set the ``laddr`` config parameter under ``[rpc]`` table in the -$TMHOME/config.toml file or the ``--rpc.laddr`` command-line flag to the +$TMHOME/config/config.toml file or the ``--rpc.laddr`` command-line flag to the desired protocol://host:port setting. Default: ``tcp://0.0.0.0:46657``. Arguments diff --git a/docs/using-tendermint.rst b/docs/using-tendermint.rst index 086a2570b..a7749d47b 100644 --- a/docs/using-tendermint.rst +++ b/docs/using-tendermint.rst @@ -24,7 +24,8 @@ Initialize the root directory by running: tendermint init This will create a new private key (``priv_validator.json``), and a -genesis file (``genesis.json``) containing the associated public key. +genesis file (``genesis.json``) containing the associated public key, +in ``$TMHOME/config``. This is all that's necessary to run a local testnet with one validator. For more elaborate initialization, see our `testnet deployment @@ -157,8 +158,7 @@ The block interval setting allows for a delay (in seconds) between the creation create_empty_blocks_interval = 5 With this setting, empty blocks will be produced every 5s if no block has been produced otherwise, -regardless of the value of `create_empty_blocks`. - +regardless of the value of ``create_empty_blocks``. Broadcast API ------------- @@ -200,7 +200,7 @@ Tendermint Networks ------------------- When ``tendermint init`` is run, both a ``genesis.json`` and -``priv_validator.json`` are created in ``~/.tendermint``. The +``priv_validator.json`` are created in ``~/.tendermint/config``. The ``genesis.json`` might look like: :: @@ -271,7 +271,7 @@ with the consensus protocol. Peers ~~~~~ -To connect to peers on start-up, specify them in the ``config.toml`` or +To connect to peers on start-up, specify them in the ``$TMHOME/config/config.toml`` or on the command line. For instance, @@ -297,7 +297,7 @@ Adding a Non-Validator ~~~~~~~~~~~~~~~~~~~~~~ Adding a non-validator is simple. Just copy the original -``genesis.json`` to ``~/.tendermint`` on the new machine and start the +``genesis.json`` to ``~/.tendermint/config`` on the new machine and start the node, specifying seeds as necessary. If no seeds are specified, the node won't make any blocks, because it's not a validator, and it won't hear about any blocks, because it's not connected to the other peer. @@ -366,8 +366,8 @@ then the new ``genesis.json`` will be: ] } -Update the ``genesis.json`` in ``~/.tendermint``. Copy the genesis file -and the new ``priv_validator.json`` to the ``~/.tendermint`` on a new +Update the ``genesis.json`` in ``~/.tendermint/config``. Copy the genesis file +and the new ``priv_validator.json`` to the ``~/.tendermint/config`` on a new machine. Now run ``tendermint node`` on both machines, and use either diff --git a/lite/client/provider_test.go b/lite/client/provider_test.go index 856769d9b..94d47da3f 100644 --- a/lite/client/provider_test.go +++ b/lite/client/provider_test.go @@ -10,6 +10,7 @@ import ( liteErr "github.com/tendermint/tendermint/lite/errors" rpcclient "github.com/tendermint/tendermint/rpc/client" rpctest "github.com/tendermint/tendermint/rpc/test" + "github.com/tendermint/tendermint/types" ) func TestProvider(t *testing.T) { @@ -17,7 +18,8 @@ func TestProvider(t *testing.T) { cfg := rpctest.GetConfig() rpcAddr := cfg.RPC.ListenAddress - chainID := cfg.ChainID + genDoc, _ := types.GenesisDocFromFile(cfg.GenesisFile()) + chainID := genDoc.ChainID p := NewHTTPProvider(rpcAddr) require.NotNil(t, p) diff --git a/rpc/core/doc.go b/rpc/core/doc.go index a72cec020..d3ec5d3b6 100644 --- a/rpc/core/doc.go +++ b/rpc/core/doc.go @@ -11,7 +11,7 @@ Tendermint RPC is built using [our own RPC library](https://github.com/tendermin ## Configuration -Set the `laddr` config parameter under `[rpc]` table in the `$TMHOME/config.toml` file or the `--rpc.laddr` command-line flag to the desired protocol://host:port setting. Default: `tcp://0.0.0.0:46657`. +Set the `laddr` config parameter under `[rpc]` table in the `$TMHOME/config/config.toml` file or the `--rpc.laddr` command-line flag to the desired protocol://host:port setting. Default: `tcp://0.0.0.0:46657`. ## Arguments diff --git a/scripts/debora/unsafe_reset_net.sh b/scripts/debora/unsafe_reset_net.sh index c6767427d..3698e5ace 100755 --- a/scripts/debora/unsafe_reset_net.sh +++ b/scripts/debora/unsafe_reset_net.sh @@ -3,7 +3,7 @@ set -euo pipefail IFS=$'\n\t' debora run -- bash -c "cd \$GOPATH/src/github.com/tendermint/tendermint; killall tendermint; killall logjack" -debora run -- bash -c "cd \$GOPATH/src/github.com/tendermint/tendermint; tendermint unsafe_reset_priv_validator; rm -rf ~/.tendermint/data; rm ~/.tendermint/genesis.json; rm ~/.tendermint/logs/*" +debora run -- bash -c "cd \$GOPATH/src/github.com/tendermint/tendermint; tendermint unsafe_reset_priv_validator; rm -rf ~/.tendermint/data; rm ~/.tendermint/config/genesis.json; rm ~/.tendermint/logs/*" debora run -- bash -c "cd \$GOPATH/src/github.com/tendermint/tendermint; git pull origin develop; make" debora run -- bash -c "cd \$GOPATH/src/github.com/tendermint/tendermint; mkdir -p ~/.tendermint/logs" debora run --bg --label tendermint -- bash -c "cd \$GOPATH/src/github.com/tendermint/tendermint; tendermint node 2>&1 | stdinwriter -outpath ~/.tendermint/logs/tendermint.log" diff --git a/test/p2p/data/mach1/core/genesis.json b/test/p2p/data/mach1/core/config/genesis.json similarity index 100% rename from test/p2p/data/mach1/core/genesis.json rename to test/p2p/data/mach1/core/config/genesis.json diff --git a/test/p2p/data/mach1/core/priv_validator.json b/test/p2p/data/mach1/core/config/priv_validator.json similarity index 100% rename from test/p2p/data/mach1/core/priv_validator.json rename to test/p2p/data/mach1/core/config/priv_validator.json diff --git a/test/p2p/data/mach2/core/genesis.json b/test/p2p/data/mach2/core/config/genesis.json similarity index 100% rename from test/p2p/data/mach2/core/genesis.json rename to test/p2p/data/mach2/core/config/genesis.json diff --git a/test/p2p/data/mach2/core/priv_validator.json b/test/p2p/data/mach2/core/config/priv_validator.json similarity index 100% rename from test/p2p/data/mach2/core/priv_validator.json rename to test/p2p/data/mach2/core/config/priv_validator.json diff --git a/test/p2p/data/mach3/core/genesis.json b/test/p2p/data/mach3/core/config/genesis.json similarity index 100% rename from test/p2p/data/mach3/core/genesis.json rename to test/p2p/data/mach3/core/config/genesis.json diff --git a/test/p2p/data/mach3/core/priv_validator.json b/test/p2p/data/mach3/core/config/priv_validator.json similarity index 100% rename from test/p2p/data/mach3/core/priv_validator.json rename to test/p2p/data/mach3/core/config/priv_validator.json diff --git a/test/p2p/data/mach4/core/genesis.json b/test/p2p/data/mach4/core/config/genesis.json similarity index 100% rename from test/p2p/data/mach4/core/genesis.json rename to test/p2p/data/mach4/core/config/genesis.json diff --git a/test/p2p/data/mach4/core/priv_validator.json b/test/p2p/data/mach4/core/config/priv_validator.json similarity index 100% rename from test/p2p/data/mach4/core/priv_validator.json rename to test/p2p/data/mach4/core/config/priv_validator.json