Пример #1
0
// Load the most recent state from "state" db,
// or create a new one (and save) from genesis.
func getState(config cfg.Config, stateDB dbm.DB) *sm.State {
	state := sm.LoadState(stateDB)
	if state == nil {
		state = sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file"))
		state.Save()
	}
	return state
}
Пример #2
0
// Convenience function
func SendEmail(config cfg.Config, subject, body string, tos []string) error {
	email := Compose(subject, body)
	email.From = config.GetString("smtp_user")
	email.ContentType = "text/html; charset=utf-8"
	email.AddRecipients(tos...)
	err := email.Send(config)
	return err
}
Пример #3
0
// Send sends the email, returning any error encountered.
func (e *Email) Send(config cfg.Config) error {
	if e.From == "" {
		return errors.New("Error: No sender specified. Please set the Email.From field.")
	}
	if e.To == nil || len(e.To) == 0 {
		return errors.New("Error: No recipient specified. Please set the Email.To field.")
	}

	auth := smtp.PlainAuth(
		"",
		config.GetString("smtp_user"),
		config.GetString("smtp_password"),
		config.GetString("smtp_host"),
	)

	conn, err := smtp.Dial(fmt.Sprintf("%v:%v", config.GetString("smtp_host"), config.GetString("smtp_port")))
	if err != nil {
		return err
	}

	err = conn.StartTLS(&tls.Config{})
	if err != nil {
		return err
	}

	err = conn.Auth(auth)
	if err != nil {
		return err
	}

	err = conn.Mail(e.From)
	if err != nil {
		if strings.Contains(err.Error(), "530 5.5.1") {
			return errors.New("Error: Authentication failure. Your username or password is incorrect.")
		}
		return err
	}

	for _, recipient := range e.To {
		err = conn.Rcpt(recipient)
		if err != nil {
			return err
		}
	}

	wc, err := conn.Data()
	if err != nil {
		return err
	}
	defer wc.Close()
	_, err = wc.Write(e.Bytes())
	if err != nil {
		return err
	}

	return nil
}
Пример #4
0
func RunReplayConsole(config cfg.Config) {
	walFile := config.GetString("cswal")
	if walFile == "" {
		Exit("cswal file name not set in tendermint config")
	}

	consensusState := newConsensusState(config)

	if err := consensusState.ReplayConsole(walFile); err != nil {
		Exit(Fmt("Error during consensus replay: %v", err))
	}
}
Пример #5
0
func RunReplay(config cfg.Config) {
	walFile := config.GetString("cswal")
	if walFile == "" {
		Exit("cswal file name not set in tendermint config")
	}

	consensusState := newConsensusState(config)

	if err := consensusState.ReplayMessages(walFile); err != nil {
		Exit(Fmt("Error during consensus replay: %v", err))
	}
	log.Notice("Replay run successfully")
}
Пример #6
0
func parseFlags(config cfg.Config, args []string) {
	var (
		printHelp bool
		moniker   string
		nodeLaddr string
		seeds     string
		fastSync  bool
		skipUPNP  bool
		rpcLaddr  string
		logLevel  string
		proxyApp  string
	)

	// Declare flags
	var flags = flag.NewFlagSet("main", flag.ExitOnError)
	flags.BoolVar(&printHelp, "help", false, "Print this help message.")
	flags.StringVar(&moniker, "moniker", config.GetString("moniker"), "Node Name")
	flags.StringVar(&nodeLaddr, "node_laddr", config.GetString("node_laddr"), "Node listen address. (0.0.0.0:0 means any interface, any port)")
	flags.StringVar(&seeds, "seeds", config.GetString("seeds"), "Comma delimited host:port seed nodes")
	flags.BoolVar(&fastSync, "fast_sync", config.GetBool("fast_sync"), "Fast blockchain syncing")
	flags.BoolVar(&skipUPNP, "skip_upnp", config.GetBool("skip_upnp"), "Skip UPNP configuration")
	flags.StringVar(&rpcLaddr, "rpc_laddr", config.GetString("rpc_laddr"), "RPC listen address. Port required")
	flags.StringVar(&logLevel, "log_level", config.GetString("log_level"), "Log level")
	flags.StringVar(&proxyApp, "proxy_app", config.GetString("proxy_app"),
		"Proxy app address, or 'nilapp' or 'dummy' for local testing.")
	flags.Parse(args)
	if printHelp {
		flags.PrintDefaults()
		os.Exit(0)
	}

	// Merge parsed flag values onto app.
	config.Set("moniker", moniker)
	config.Set("node_laddr", nodeLaddr)
	config.Set("seeds", seeds)
	config.Set("fast_sync", fastSync)
	config.Set("skip_upnp", skipUPNP)
	config.Set("rpc_laddr", rpcLaddr)
	config.Set("log_level", logLevel)
	config.Set("proxy_app", proxyApp)
}
Пример #7
0
func sendTwilio(config cfg.Config, message string) {
	defer func() {
		if err := recover(); err != nil {
			log.Error("sendTwilio error", "error", err)
		}
	}()
	if len(message) > 50 {
		message = message[:50]
	}
	twilio := gotwilio.NewTwilioClient(config.GetString("alert_twilio_sid"), config.GetString("alert_twilio_token"))
	res, exp, err := twilio.SendSMS(config.GetString("alert_twilio_from"), config.GetString("alert_twilio_to"), message, "", "")
	if exp != nil || err != nil {
		log.Error("sendTwilio error", "res", res, "exp", exp, "error", err)
	}
}
Пример #8
0
func makeNodeInfo(config cfg.Config, sw *p2p.Switch, privKey crypto.PrivKeyEd25519) *p2p.NodeInfo {

	nodeInfo := &p2p.NodeInfo{
		PubKey:  privKey.PubKey().(crypto.PubKeyEd25519),
		Moniker: config.GetString("moniker"),
		Network: config.GetString("chain_id"),
		Version: version.Version,
		Other: []string{
			Fmt("wire_version=%v", wire.Version),
			Fmt("p2p_version=%v", p2p.Version),
			Fmt("consensus_version=%v", consensus.Version),
			Fmt("rpc_version=%v/%v", rpc.Version, rpccore.Version),
		},
	}

	// include git hash in the nodeInfo if available
	if rev, err := ReadFile(config.GetString("revision_file")); err == nil {
		nodeInfo.Other = append(nodeInfo.Other, Fmt("revision=%v", string(rev)))
	}

	if !sw.IsListening() {
		return nodeInfo
	}

	p2pListener := sw.Listeners()[0]
	p2pHost := p2pListener.ExternalAddress().IP.String()
	p2pPort := p2pListener.ExternalAddress().Port
	rpcListenAddr := config.GetString("rpc_laddr")

	// We assume that the rpcListener has the same ExternalAddress.
	// This is probably true because both P2P and RPC listeners use UPnP,
	// except of course if the rpc is only bound to localhost
	nodeInfo.ListenAddr = Fmt("%v:%v", p2pHost, p2pPort)
	nodeInfo.Other = append(nodeInfo.Other, Fmt("rpc_addr=%v", rpcListenAddr))
	return nodeInfo
}
Пример #9
0
// Sends a critical alert message to administrators.
func Alert(config cfg.Config, message string) {
	log.Error("<!> ALERT <!>\n" + message)
	now := time.Now().Unix()
	if now-lastAlertUnix > int64(config.GetInt("alert_min_interval")) {
		message = fmt.Sprintf("%v:%v", config.GetString("chain_id"), message)
		if alertCountSince > 0 {
			message = fmt.Sprintf("%v (+%v more since)", message, alertCountSince)
			alertCountSince = 0
		}
		if len(config.GetString("alert_twilio_sid")) > 0 {
			go sendTwilio(config, message)
		}
		if len(config.GetString("alert_email_recipients")) > 0 {
			go sendEmail(config, message)
		}
	} else {
		alertCountSince++
	}
}
Пример #10
0
func NewNode(config cfg.Config, privValidator *types.PrivValidator, getProxyApp func(proxyAddr string, appHash []byte) proxy.AppConn) *Node {

	EnsureDir(config.GetString("db_dir"), 0700) // incase we use memdb, cswal still gets written here

	// Get BlockStore
	blockStoreDB := dbm.NewDB("blockstore", config.GetString("db_backend"), config.GetString("db_dir"))
	blockStore := bc.NewBlockStore(blockStoreDB)

	// Get State db
	stateDB := dbm.NewDB("state", config.GetString("db_backend"), config.GetString("db_dir"))

	// Get State
	state := getState(config, stateDB)

	// Create two proxyAppConn connections,
	// one for the consensus and one for the mempool.
	proxyAddr := config.GetString("proxy_app")
	proxyAppConnMempool := getProxyApp(proxyAddr, state.AppHash)
	proxyAppConnConsensus := getProxyApp(proxyAddr, state.AppHash)

	// add the chainid and number of validators to the global config
	config.Set("chain_id", state.ChainID)
	config.Set("num_vals", state.Validators.Size())

	// Generate node PrivKey
	privKey := crypto.GenPrivKeyEd25519()

	// Make event switch
	eventSwitch := events.NewEventSwitch()
	_, err := eventSwitch.Start()
	if err != nil {
		Exit(Fmt("Failed to start switch: %v", err))
	}

	// Decide whether to fast-sync or not
	// We don't fast-sync when the only validator is us.
	fastSync := config.GetBool("fast_sync")
	if state.Validators.Size() == 1 {
		addr, _ := state.Validators.GetByIndex(0)
		if bytes.Equal(privValidator.Address, addr) {
			fastSync = false
		}
	}

	// Make BlockchainReactor
	bcReactor := bc.NewBlockchainReactor(state.Copy(), proxyAppConnConsensus, blockStore, fastSync)

	// Make MempoolReactor
	mempool := mempl.NewMempool(config, proxyAppConnMempool)
	mempoolReactor := mempl.NewMempoolReactor(config, mempool)

	// Make ConsensusReactor
	consensusState := consensus.NewConsensusState(config, state.Copy(), proxyAppConnConsensus, blockStore, mempool)
	consensusReactor := consensus.NewConsensusReactor(consensusState, blockStore, fastSync)
	if privValidator != nil {
		consensusReactor.SetPrivValidator(privValidator)
	}

	// deterministic accountability
	err = consensusState.OpenWAL(config.GetString("cswal"))
	if err != nil {
		log.Error("Failed to open cswal", "error", err.Error())
	}

	// Make p2p network switch
	sw := p2p.NewSwitch(config)
	sw.AddReactor("MEMPOOL", mempoolReactor)
	sw.AddReactor("BLOCKCHAIN", bcReactor)
	sw.AddReactor("CONSENSUS", consensusReactor)

	// add the event switch to all services
	// they should all satisfy events.Eventable
	SetEventSwitch(eventSwitch, bcReactor, mempoolReactor, consensusReactor)

	// run the profile server
	profileHost := config.GetString("prof_laddr")
	if profileHost != "" {
		go func() {
			log.Warn("Profile server", "error", http.ListenAndServe(profileHost, nil))
		}()
	}

	return &Node{
		config:           config,
		sw:               sw,
		evsw:             eventSwitch,
		blockStore:       blockStore,
		bcReactor:        bcReactor,
		mempoolReactor:   mempoolReactor,
		consensusState:   consensusState,
		consensusReactor: consensusReactor,
		privValidator:    privValidator,
		genesisDoc:       state.GenesisDoc,
		privKey:          privKey,
	}
}
Пример #11
0
// convenience for replay mode
func newConsensusState(config cfg.Config) *consensus.ConsensusState {
	// Get BlockStore
	blockStoreDB := dbm.NewDB("blockstore", config.GetString("db_backend"), config.GetString("db_dir"))
	blockStore := bc.NewBlockStore(blockStoreDB)

	// Get State
	stateDB := dbm.NewDB("state", config.GetString("db_backend"), config.GetString("db_dir"))
	state := sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file"))

	// Create two proxyAppConn connections,
	// one for the consensus and one for the mempool.
	proxyAddr := config.GetString("proxy_app")
	proxyAppConnMempool := GetProxyApp(proxyAddr, state.AppHash)
	proxyAppConnConsensus := GetProxyApp(proxyAddr, state.AppHash)

	// add the chainid to the global config
	config.Set("chain_id", state.ChainID)

	// Make event switch
	eventSwitch := events.NewEventSwitch()
	_, err := eventSwitch.Start()
	if err != nil {
		Exit(Fmt("Failed to start event switch: %v", err))
	}

	mempool := mempl.NewMempool(config, proxyAppConnMempool)

	consensusState := consensus.NewConsensusState(config, state.Copy(), proxyAppConnConsensus, blockStore, mempool)
	consensusState.SetEventSwitch(eventSwitch)
	return consensusState
}
Пример #12
0
// Users wishing to use an external signer for their validators
// should fork tendermint/tendermint and implement RunNode to
// load their custom priv validator and call NewNode(privVal, getProxyFunc)
func RunNode(config cfg.Config) {
	// Wait until the genesis doc becomes available
	genDocFile := config.GetString("genesis_file")
	if !FileExists(genDocFile) {
		log.Notice(Fmt("Waiting for genesis file %v...", genDocFile))
		for {
			time.Sleep(time.Second)
			if !FileExists(genDocFile) {
				continue
			}
			jsonBlob, err := ioutil.ReadFile(genDocFile)
			if err != nil {
				Exit(Fmt("Couldn't read GenesisDoc file: %v", err))
			}
			genDoc := types.GenesisDocFromJSON(jsonBlob)
			if genDoc.ChainID == "" {
				PanicSanity(Fmt("Genesis doc %v must include non-empty chain_id", genDocFile))
			}
			config.Set("chain_id", genDoc.ChainID)
		}
	}

	// Get PrivValidator
	privValidatorFile := config.GetString("priv_validator_file")
	privValidator := types.LoadOrGenPrivValidator(privValidatorFile)

	// Create & start node
	n := NewNode(config, privValidator, GetProxyApp)
	l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"), config.GetBool("skip_upnp"))
	n.AddListener(l)
	err := n.Start()
	if err != nil {
		Exit(Fmt("Failed to start node: %v", err))
	}

	log.Notice("Started node", "nodeInfo", n.sw.NodeInfo())

	// If seedNode is provided by config, dial out.
	if config.GetString("seeds") != "" {
		seeds := strings.Split(config.GetString("seeds"), ",")
		n.sw.DialSeeds(seeds)
	}

	// Run the RPC server.
	if config.GetString("rpc_laddr") != "" {
		_, err := n.StartRPC()
		if err != nil {
			PanicCrisis(err)
		}
	}

	// Sleep forever and then...
	TrapSignal(func() {
		n.Stop()
	})
}