Browse Source

Changed config to confer, TOML format.

pull/39/head
Jae Kwon 10 years ago
parent
commit
05c642a84c
14 changed files with 149 additions and 216 deletions
  1. +25
    -31
      README.md
  2. +8
    -8
      alert/alert.go
  3. +6
    -6
      alert/email.go
  4. +2
    -2
      block/block.go
  5. +8
    -8
      cmd/daemon.go
  6. +1
    -1
      cmd/gen_validator.go
  7. +78
    -146
      config/config.go
  8. +7
    -0
      config/log.go
  9. +2
    -2
      consensus/state.go
  10. +4
    -4
      db/db.go
  11. +1
    -1
      p2p/README.md
  12. +3
    -3
      rpc/http_server.go
  13. +2
    -2
      state/priv_validator.go
  14. +2
    -2
      state/state_test.go

+ 25
- 31
README.md View File

@ -52,44 +52,38 @@ make
`./tendermint daemon --help`
### Editing your config file
When `./tendermint daemon` is first run, a file will be create in ~/.tendermint/config.toml
### Editing your config.json
There is not official or testnet SeedNode yet. Will updated with an official list of seed nodes.
The file will be create in ~/.tendermint/config.json
//TODO Explanation of other config.toml fields
There is not official or testnet SeedNode yet. Will updated with an official list of seed nodes.
```toml
# This is a TOML config file.
# For more information, see https://github.com/toml-lang/toml
//TODO Explanation of other config.json fields
Network = "tendermint_testnet0"
ListenAddr = "0.0.0.0:0"
# First node to connect to. Command-line overridable.
# Seed = "a.b.c.d:pppp"
```
{
"Network": "tendermint_testnet0",
"LAddr": "0.0.0.0:0",
"SeedNode": "",
"DB": {
"Backend": "leveldb",
"Dir": "/home/zaki/.tendermint/data"
},
"Alert": {
"MinInterval": 0,
"TwilioSid": "",
"TwilioToken": "",
"TwilioFrom": "",
"TwilioTo": "",
"EmailRecipients": null
},
"SMTP": {
"User": "",
"Password": "",
"Host": "",
"Port": 0
},
"RPC": {
"HTTPLAddr": "0.0.0.0:0"
}
}
[DB]
# The only other available backend is "memdb"
Backend = "leveldb"
# The leveldb data directory.
# Dir = "<YOUR_HOME_DIRECTORY>/.tendermint/data"
[RPC]
# For the RPC API HTTP server. Port required.
HTTP.ListenAddr = "0.0.0.0:8080"
[Alert]
# TODO: Document options
[SMTP]
# TODO: Document options
```
You will also to need to have a genesis.json in ~/.tendermint/. This must be the common genesis.json as the network you are joining from the Seed Node


+ 8
- 8
alert/alert.go View File

@ -5,7 +5,7 @@ import (
"time"
"github.com/sfreiberg/gotwilio"
. "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/config"
)
var lastAlertUnix int64 = 0
@ -15,16 +15,16 @@ var alertCountSince int = 0
func Alert(message string) {
log.Error("<!> ALERT <!>\n" + message)
now := time.Now().Unix()
if now-lastAlertUnix > int64(Config.Alert.MinInterval) {
message = fmt.Sprintf("%v:%v", Config.Network, message)
if now-lastAlertUnix > int64(config.App.GetInt("Alert.MinInterval")) {
message = fmt.Sprintf("%v:%v", config.App.GetString("Network"), message)
if alertCountSince > 0 {
message = fmt.Sprintf("%v (+%v more since)", message, alertCountSince)
alertCountSince = 0
}
if len(Config.Alert.TwilioSid) > 0 {
if len(config.App.GetString("Alert.TwilioSid")) > 0 {
go sendTwilio(message)
}
if len(Config.Alert.EmailRecipients) > 0 {
if len(config.App.GetString("Alert.EmailRecipients")) > 0 {
go sendEmail(message)
}
} else {
@ -41,8 +41,8 @@ func sendTwilio(message string) {
if len(message) > 50 {
message = message[:50]
}
twilio := gotwilio.NewTwilioClient(Config.Alert.TwilioSid, Config.Alert.TwilioToken)
res, exp, err := twilio.SendSMS(Config.Alert.TwilioFrom, Config.Alert.TwilioTo, message, "", "")
twilio := gotwilio.NewTwilioClient(config.App.GetString("Alert.TwilioSid"), config.App.GetString("Alert.TwilioToken"))
res, exp, err := twilio.SendSMS(config.App.GetString("Alert.TwilioFrom"), config.App.GetString("Alert.TwilioTo"), message, "", "")
if exp != nil || err != nil {
log.Error("sendTwilio error", "res", res, "exp", exp, "error", err)
}
@ -58,7 +58,7 @@ func sendEmail(message string) {
if len(subject) > 80 {
subject = subject[:80]
}
err := SendEmail(subject, message, Config.Alert.EmailRecipients)
err := SendEmail(subject, message, config.App.GetStringSlice("Alert.EmailRecipients"))
if err != nil {
log.Error("sendEmail error", "error", err, "message", message)
}


+ 6
- 6
alert/email.go View File

@ -13,13 +13,13 @@ import (
"regexp"
"strings"
. "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/config"
)
// Convenience function
func SendEmail(subject, body string, tos []string) error {
email := Compose(subject, body)
email.From = Config.SMTP.User
email.From = config.App.GetString("SMTP.User")
email.ContentType = "text/html; charset=utf-8"
email.AddRecipients(tos...)
err := email.Send()
@ -86,12 +86,12 @@ func (e *Email) Send() error {
auth := smtp.PlainAuth(
"",
Config.SMTP.User,
Config.SMTP.Password,
Config.SMTP.Host,
config.App.GetString("SMTP.User"),
config.App.GetString("SMTP.Password"),
config.App.GetString("SMTP.Host"),
)
conn, err := smtp.Dial(fmt.Sprintf("%v:%v", Config.SMTP.Host, Config.SMTP.Port))
conn, err := smtp.Dial(fmt.Sprintf("%v:%v", config.App.GetString("SMTP.Host"), config.App.GetString("SMTP.Port")))
if err != nil {
return err
}


+ 2
- 2
block/block.go View File

@ -11,7 +11,7 @@ import (
. "github.com/tendermint/tendermint/account"
. "github.com/tendermint/tendermint/binary"
. "github.com/tendermint/tendermint/common"
. "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/merkle"
)
@ -27,7 +27,7 @@ type Block struct {
// Basic validation that doesn't involve state data.
func (b *Block) ValidateBasic(lastBlockHeight uint, lastBlockHash []byte,
lastBlockParts PartSetHeader, lastBlockTime time.Time) error {
if b.Network != Config.Network {
if b.Network != config.App.GetString("Network") {
return errors.New("Wrong Block.Header.Network")
}
if b.Height != lastBlockHeight+1 {


+ 8
- 8
cmd/daemon.go View File

@ -36,18 +36,18 @@ func NewNode() *Node {
stateDB := db_.GetDB("state")
state := state_.LoadState(stateDB)
if state == nil {
state = state_.MakeGenesisStateFromFile(stateDB, config.GenesisFile())
state = state_.MakeGenesisStateFromFile(stateDB, config.App.GetString("GenesisFile"))
state.Save()
}
// Get PrivValidator
var privValidator *state_.PrivValidator
if _, err := os.Stat(config.PrivValidatorFile()); err == nil {
privValidator = state_.LoadPrivValidator(config.PrivValidatorFile())
if _, err := os.Stat(config.App.GetString("PrivValidatorFile")); err == nil {
privValidator = state_.LoadPrivValidator(config.App.GetString("PrivValidatorFile"))
}
// Get PEXReactor
book := p2p.NewAddrBook(config.AddrBookFile())
book := p2p.NewAddrBook(config.App.GetString("AddrBookFile"))
pexReactor := p2p.NewPEXReactor(book)
// Get MempoolReactor
@ -122,13 +122,13 @@ func daemon() {
// Create & start node
n := NewNode()
l := p2p.NewDefaultListener("tcp", config.Config.LAddr, false)
l := p2p.NewDefaultListener("tcp", config.App.GetString("ListenAddr"), false)
n.AddListener(l)
n.Start()
// If seedNode is provided by config, dial out.
if config.Config.SeedNode != "" {
peer, err := n.sw.DialPeerWithAddress(p2p.NewNetAddressString(config.Config.SeedNode))
if config.App.GetString("SeedNode") != "" {
peer, err := n.sw.DialPeerWithAddress(p2p.NewNetAddressString(config.App.GetString("SeedNode")))
if err != nil {
log.Error("Error dialing seed", "error", err)
//n.book.MarkAttempt(addr)
@ -139,7 +139,7 @@ func daemon() {
}
// Run the RPC server.
if config.Config.RPC.HTTPLAddr != "" {
if config.App.GetString("RPC.HTTP.ListenAddr") != "" {
rpc.SetRPCBlockStore(n.blockStore)
rpc.SetRPCState(n.state)
rpc.SetRPCMempoolReactor(n.mempoolReactor)


+ 1
- 1
cmd/gen_validator.go View File

@ -17,7 +17,7 @@ Paste the following JSON into your %v file
%v
`,
config.PrivValidatorFile(),
config.App.GetString("PrivValidatorFile"),
string(privValidatorJSONBytes),
)
}

+ 78
- 146
config/config.go View File

@ -1,182 +1,114 @@
package config
import (
"encoding/json"
"errors"
"flag"
"fmt"
"io/ioutil"
"net"
"os"
"path/filepath"
"strings"
. "github.com/tendermint/tendermint/common"
"github.com/tendermint/confer"
flag "github.com/spf13/pflag"
)
//-----------------------------------------------------------------------------j
// Configuration types
type ConfigType struct {
Network string
LAddr string
SeedNode string
DB DBConfig
Alert AlertConfig
SMTP SMTPConfig
RPC RPCConfig
}
var rootDir string
var App *confer.Config
var defaultConfig = `
# This is a TOML config file.
# For more information, see https://github.com/toml-lang/toml
type DBConfig struct {
Backend string
Dir string
}
Network = "tendermint_testnet0"
ListenAddr = "0.0.0.0:0"
# First node to connect to. Command-line overridable.
# SeedNode = "a.b.c.d:pppp"
type AlertConfig struct {
MinInterval int
[DB]
# The only other available backend is "memdb"
Backend = "leveldb"
# The leveldb data directory.
# Dir = "<YOUR_HOME_DIRECTORY>/.tendermint/data"
TwilioSid string
TwilioToken string
TwilioFrom string
TwilioTo string
[RPC]
# For the RPC API HTTP server. Port required.
HTTP.ListenAddr = "0.0.0.0:8080"
EmailRecipients []string
}
[Alert]
# TODO: Document options
type SMTPConfig struct {
User string
Password string
Host string
Port uint
}
type RPCConfig struct {
HTTPLAddr string
}
func (cfg *ConfigType) validate() error {
if cfg.Network == "" {
cfg.Network = defaultConfig.Network
}
if cfg.LAddr == "" {
cfg.LAddr = defaultConfig.LAddr
}
if cfg.SeedNode == "" {
cfg.SeedNode = defaultConfig.SeedNode
}
if cfg.DB.Backend == "" {
return errors.New("DB.Backend must be set")
}
if cfg.RPC.HTTPLAddr == "" {
fmt.Println("Set RPC.HTTPLAddr to \"0.0.0.0:8888\" in your config.json to enable the RPC API server.")
} else {
_, port, err := net.SplitHostPort(cfg.RPC.HTTPLAddr)
if err != nil {
return errors.New(Fmt("RPC.HTTPLAddr is invalid. %v", err))
}
if port == "" || port == "0" {
return errors.New("RPC.HTTPLAddr is invalid. Port number must be defined")
}
}
return nil
}
func (cfg *ConfigType) bytes() []byte {
configBytes, err := json.MarshalIndent(cfg, "", "\t")
if err != nil {
panic(err)
}
return configBytes
}
func (cfg *ConfigType) write(configFile string) {
if strings.Index(configFile, "/") != -1 {
err := os.MkdirAll(filepath.Dir(configFile), 0700)
if err != nil {
panic(err)
}
}
err := ioutil.WriteFile(configFile, cfg.bytes(), 0600)
if err != nil {
panic(err)
}
}
//-----------------------------------------------------------------------------
var rootDir string
var defaultConfig ConfigType
[SMTP]
# TODO: Document options
`
func init() {
// Get RootDir
rootDir = os.Getenv("TMROOT")
if rootDir == "" {
rootDir = os.Getenv("HOME") + "/.tendermint"
}
configFile := rootDir + "/config.toml"
// Write default config file if missing.
if _, err := os.Stat(configFile); os.IsNotExist(err) {
if strings.Index(configFile, "/") != -1 {
err := os.MkdirAll(filepath.Dir(configFile), 0700)
if err != nil {
fmt.Printf("Could not create directory: %v", err)
os.Exit(1)
}
}
err := ioutil.WriteFile(configFile, []byte(defaultConfig), 0600)
if err != nil {
fmt.Printf("Could not write config file: %v", err)
os.Exit(1)
}
fmt.Printf("Config file written to %v. Please edit & run again\n", configFile)
os.Exit(1)
}
// Compute defaultConfig
defaultConfig = ConfigType{
Network: "tendermint_testnet0",
LAddr: "0.0.0.0:0",
SeedNode: "",
DB: DBConfig{
Backend: "leveldb",
Dir: DataDir(),
},
Alert: AlertConfig{},
SMTP: SMTPConfig{},
RPC: RPCConfig{
HTTPLAddr: "0.0.0.0:0",
},
// Initialize Config
App = confer.NewConfig()
initDefaults()
paths := []string{configFile}
if err := App.ReadPaths(paths...); err != nil {
log.Warn("Error reading configuration", "paths", paths, "error", err)
}
}
func ConfigFile() string { return rootDir + "/config.json" }
func GenesisFile() string { return rootDir + "/genesis.json" }
func AddrBookFile() string { return rootDir + "/addrbook.json" }
func PrivValidatorFile() string { return rootDir + "/priv_validator.json" }
func DataDir() string { return rootDir + "/data" }
// The actual global config singleton object.
var Config ConfigType
func parseFlags(flags *flag.FlagSet, args []string) (printHelp bool) {
flags.BoolVar(&printHelp, "help", false, "Print this help message.")
flags.StringVar(&Config.LAddr, "laddr", Config.LAddr, "Listen address. (0.0.0.0:0 means any interface, any port)")
flags.StringVar(&Config.SeedNode, "seed", Config.SeedNode, "Address of seed node")
flags.StringVar(&Config.RPC.HTTPLAddr, "rpc_http_laddr", Config.RPC.HTTPLAddr, "RPC listen address. (0.0.0.0:0 means any interface, any port)")
flags.Parse(args)
return
func initDefaults() {
App.SetDefault("Network", "tendermint_testnet0")
App.SetDefault("ListenAddr", "0.0.0.0:0")
App.SetDefault("DB.Backend", "leveldb")
App.SetDefault("DB.Dir", rootDir+"/data")
App.SetDefault("Log.Level", "debug")
App.SetDefault("Log.Dir", rootDir+"/log")
App.SetDefault("RPC.HTTP.ListenAddr", "0.0.0.0:8080")
App.SetDefault("GenesisFile", rootDir+"/genesis.json")
App.SetDefault("AddrbookFile", rootDir+"/addrbook.json")
App.SetDefault("PrivValidatorfile", rootDir+"/priv_valdiator.json")
}
func ParseFlags(args []string) {
configFile := ConfigFile()
// try to read configuration from file. if missing, write default
configBytes, err := ioutil.ReadFile(configFile)
if err != nil {
defaultConfig.write(configFile)
fmt.Println("Config file written to config.json. Please edit & run again")
os.Exit(1)
return
}
// try to parse configuration. on error, die
Config = ConfigType{}
err = json.Unmarshal(configBytes, &Config)
if err != nil {
Exit(Fmt("Invalid configuration file %s:\n%v\n", configFile, err))
}
err = Config.validate()
if err != nil {
Exit(Fmt("Invalid configuration file %s:\n%v\n", configFile, err))
}
var flags = flag.NewFlagSet("main", flag.ExitOnError)
var printHelp = false
// try to parse arg flags, which can override file configuration.
flags := flag.NewFlagSet("main", flag.ExitOnError)
printHelp := parseFlags(flags, args)
// Declare flags
flags.BoolVar(&printHelp, "help", false, "Print this help message.")
flags.String("listen_addr", App.GetString("ListenAddr"), "Listen address. (0.0.0.0:0 means any interface, any port)")
flags.String("seed_node", App.GetString("SeedNode"), "Address of seed node")
flags.String("rpc_http_listen_addr", App.GetString("RPC.HTTP.ListenAddr"), "RPC listen address. Port required")
flags.Parse(args)
if printHelp {
flags.PrintDefaults()
os.Exit(0)
}
// Merge parsed flag values onto App.
App.BindPFlag("ListenAddr", flags.Lookup("listen_addr"))
App.BindPFlag("SeedNode", flags.Lookup("seed_node"))
App.BindPFlag("RPC.HTTP.ListenAddr", flags.Lookup("rpc_http_listen_addr"))
// Confused?
//App.Debug()
}

+ 7
- 0
config/log.go View File

@ -0,0 +1,7 @@
package config
import (
"github.com/tendermint/log15"
)
var log = log15.New("module", "config")

+ 2
- 2
consensus/state.go View File

@ -64,7 +64,7 @@ import (
. "github.com/tendermint/tendermint/binary"
. "github.com/tendermint/tendermint/block"
. "github.com/tendermint/tendermint/common"
. "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/config"
. "github.com/tendermint/tendermint/consensus/types"
"github.com/tendermint/tendermint/mempool"
"github.com/tendermint/tendermint/state"
@ -598,7 +598,7 @@ func (cs *ConsensusState) RunActionPropose(height uint, round uint) {
txs := cs.mempoolReactor.Mempool.GetProposalTxs()
block = &Block{
Header: &Header{
Network: Config.Network,
Network: config.App.GetString("Network"),
Height: cs.Height,
Time: time.Now(),
Fees: 0, // TODO fees


+ 4
- 4
db/db.go View File

@ -4,7 +4,7 @@ import (
"path"
. "github.com/tendermint/tendermint/common"
. "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/config"
)
type DB interface {
@ -28,19 +28,19 @@ func GetDB(name string) DB {
if db != nil {
return db.(DB)
}
switch Config.DB.Backend {
switch config.App.GetString("DB.Backend") {
case DBBackendMemDB:
db := NewMemDB()
dbs.Set(name, db)
return db
case DBBackendLevelDB:
db, err := NewLevelDB(path.Join(Config.DB.Dir, name+".db"))
db, err := NewLevelDB(path.Join(config.App.GetString("DB.Dir"), name+".db"))
if err != nil {
panic(err)
}
dbs.Set(name, db)
return db
default:
panic(Fmt("Unknown DB backend: %v", Config.DB.Backend))
panic(Fmt("Unknown DB backend: %v", config.App.GetString("DB.Backend")))
}
}

+ 1
- 1
p2p/README.md View File

@ -70,7 +70,7 @@ for _, peer := range switch.Peers().List() {
A `PEXReactor` reactor implementation is provided to automate peer discovery.
```go
book := p2p.NewAddrBook(config.AddrBookFile())
book := p2p.NewAddrBook(config.App.GetString("AddrBookFile"))
pexReactor := p2p.NewPEXReactor(book)
...
switch := NewSwitch([]Reactor{pexReactor, myReactor, ...})


+ 3
- 3
rpc/http_server.go View File

@ -4,7 +4,7 @@ import (
"net/http"
. "github.com/tendermint/tendermint/common"
. "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/config"
)
func StartHTTPServer() {
@ -13,9 +13,9 @@ func StartHTTPServer() {
http.HandleFunc("/block", BlockHandler)
http.HandleFunc("/broadcast_tx", BroadcastTxHandler)
log.Info(Fmt("Starting RPC HTTP server on %s", Config.RPC.HTTPLAddr))
log.Info(Fmt("Starting RPC HTTP server on %s", config.App.GetString("RPC.HTTP.ListenAddr")))
go func() {
log.Crit("RPC HTTPServer stopped", "result", http.ListenAndServe(Config.RPC.HTTPLAddr, RecoverAndLogHandler(http.DefaultServeMux)))
log.Crit("RPC HTTPServer stopped", "result", http.ListenAndServe(config.App.GetString("RPC.HTTP.ListenAddr"), RecoverAndLogHandler(http.DefaultServeMux)))
}()
}

+ 2
- 2
state/priv_validator.go View File

@ -16,7 +16,7 @@ import (
. "github.com/tendermint/tendermint/binary"
. "github.com/tendermint/tendermint/block"
. "github.com/tendermint/tendermint/common"
. "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/config"
. "github.com/tendermint/tendermint/consensus/types"
"github.com/tendermint/go-ed25519"
@ -70,7 +70,7 @@ func GenPrivValidator() *PrivValidator {
LastHeight: 0,
LastRound: 0,
LastStep: stepNone,
filename: PrivValidatorFile(),
filename: config.App.GetString("PrivValidatorFile"),
}
}


+ 2
- 2
state/state_test.go View File

@ -4,7 +4,7 @@ import (
. "github.com/tendermint/tendermint/account"
. "github.com/tendermint/tendermint/binary"
. "github.com/tendermint/tendermint/block"
. "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/config"
"bytes"
"testing"
@ -60,7 +60,7 @@ func TestGenesisSaveLoad(t *testing.T) {
// Mutate the state to append one empty block.
block := &Block{
Header: &Header{
Network: Config.Network,
Network: config.App.GetString("Network"),
Height: 1,
Time: s0.LastBlockTime.Add(time.Minute),
Fees: 0,


Loading…
Cancel
Save