Example #1
1
func run(ctx *cli.Context) {
	utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
	if ctx.GlobalBool(utils.OlympicFlag.Name) {
		utils.InitOlympic()
	}

	cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
	cfg.ExtraData = makeDefaultExtra()

	expanse, err := exp.New(cfg)
	if err != nil {
		utils.Fatalf("%v", err)
	}

	startEth(ctx, expanse)
	// this blocks the thread
	expanse.WaitForShutdown()
}
Example #2
0
func startEth(ctx *cli.Context, exp *exp.Expanse) {
	// Start Expanse itself
	utils.StartExpanse(exp)

	am := exp.AccountManager()
	account := ctx.GlobalString(utils.UnlockedAccountFlag.Name)
	accounts := strings.Split(account, " ")
	for i, account := range accounts {
		if len(account) > 0 {
			if account == "primary" {
				utils.Fatalf("the 'primary' keyword is deprecated. You can use integer indexes, but the indexes are not permanent, they can change if you add external keys, export your keys or copy your keystore to another node.")
			}
			unlockAccount(ctx, am, account, i)
		}
	}
	// Start auxiliary services if enabled.
	if !ctx.GlobalBool(utils.IPCDisabledFlag.Name) {
		if err := utils.StartIPC(exp, ctx); err != nil {
			utils.Fatalf("Error string IPC: %v", err)
		}
	}
	if ctx.GlobalBool(utils.RPCEnabledFlag.Name) {
		if err := utils.StartRPC(exp, ctx); err != nil {
			utils.Fatalf("Error starting RPC: %v", err)
		}
	}
	if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
		if err := exp.StartMining(ctx.GlobalInt(utils.MinerThreadsFlag.Name)); err != nil {
			utils.Fatalf("%v", err)
		}
	}
}
Example #3
0
func upgradeDB(ctx *cli.Context) {
	glog.Infoln("Upgrading blockchain database")

	chain, chainDb := utils.MakeChain(ctx)
	v, _ := chainDb.Get([]byte("BlockchainVersion"))
	bcVersion := int(common.NewValue(v).Uint())
	if bcVersion == 0 {
		bcVersion = core.BlockChainVersion
	}

	// Export the current chain.
	filename := fmt.Sprintf("blockchain_%d_%s.chain", bcVersion, time.Now().Format("20060102_150405"))
	exportFile := filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), filename)
	if err := utils.ExportChain(chain, exportFile); err != nil {
		utils.Fatalf("Unable to export chain for reimport %s", err)
	}
	chainDb.Close()
	os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "chaindata"))

	// Import the chain file.
	chain, chainDb = utils.MakeChain(ctx)
	chainDb.Put([]byte("BlockchainVersion"), common.NewValue(core.BlockChainVersion).Bytes())
	err := utils.ImportChain(chain, exportFile)
	chainDb.Close()
	if err != nil {
		utils.Fatalf("Import error %v (a backup is made in %s, use the import command to import it)", err, exportFile)
	} else {
		os.Remove(exportFile)
		glog.Infoln("Import finished")
	}
}
Example #4
0
func exportChain(ctx *cli.Context) {
	if len(ctx.Args()) < 1 {
		utils.Fatalf("This command requires an argument.")
	}
	chain, _ := utils.MakeChain(ctx)
	start := time.Now()

	var err error
	fp := ctx.Args().First()
	if len(ctx.Args()) < 3 {
		err = utils.ExportChain(chain, fp)
	} else {
		// This can be improved to allow for numbers larger than 9223372036854775807
		first, ferr := strconv.ParseInt(ctx.Args().Get(1), 10, 64)
		last, lerr := strconv.ParseInt(ctx.Args().Get(2), 10, 64)
		if ferr != nil || lerr != nil {
			utils.Fatalf("Export error in parsing parameters: block number not an integer\n")
		}
		if first < 0 || last < 0 {
			utils.Fatalf("Export error: block number must be greater than 0\n")
		}
		err = utils.ExportAppendChain(chain, fp, uint64(first), uint64(last))
	}

	if err != nil {
		utils.Fatalf("Export error: %v\n", err)
	}
	fmt.Printf("Export done in %v", time.Since(start))
}
Example #5
0
// startNode boots up the system node and all registered protocols, after which
// it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
// miner.
func startNode(ctx *cli.Context, stack *node.Node) {
	// Start up the node itself
	utils.StartNode(stack)

	// Unlock any account specifically requested
	var expanse *exp.Expanse
	if err := stack.Service(&expanse); err != nil {
		utils.Fatalf("ethereum service not running: %v", err)
	}
	accman := expanse.AccountManager()
	passwords := utils.MakePasswordList(ctx)

	accounts := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
	for i, account := range accounts {
		if trimmed := strings.TrimSpace(account); trimmed != "" {
			unlockAccount(ctx, accman, trimmed, i, passwords)
		}
	}
	// Start auxiliary services if enabled
	if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
		if err := expanse.StartMining(ctx.GlobalInt(utils.MinerThreadsFlag.Name), ctx.GlobalString(utils.MiningGPUFlag.Name)); err != nil {
			utils.Fatalf("Failed to start mining: %v", err)
		}
	}
}
Example #6
0
func makedag(ctx *cli.Context) {
	args := ctx.Args()
	wrongArgs := func() {
		utils.Fatalf(`Usage: gexp makedag <block number> <outputdir>`)
	}
	switch {
	case len(args) == 2:
		blockNum, err := strconv.ParseUint(args[0], 0, 64)
		dir := args[1]
		if err != nil {
			wrongArgs()
		} else {
			dir = filepath.Clean(dir)
			// seems to require a trailing slash
			if !strings.HasSuffix(dir, "/") {
				dir = dir + "/"
			}
			_, err = ioutil.ReadDir(dir)
			if err != nil {
				utils.Fatalf("Can't find dir")
			}
			fmt.Println("making DAG, this could take awhile...")
			ethash.MakeDAG(blockNum, dir)
		}
	default:
		wrongArgs()
	}
}
Example #7
0
// resolveMetrics takes a single of input metric pattern, and resolves it to one
// or more canonical metric names.
func resolveMetric(metrics map[string]interface{}, pattern string, path string) []string {
	results := []string{}

	// If a nested metric was requested, recurse optionally branching (via comma)
	parts := strings.SplitN(pattern, "/", 2)
	if len(parts) > 1 {
		for _, variation := range strings.Split(parts[0], ",") {
			if submetrics, ok := metrics[variation].(map[string]interface{}); !ok {
				utils.Fatalf("Failed to retrieve system metrics: %s", path+variation)
				return nil
			} else {
				results = append(results, resolveMetric(submetrics, parts[1], path+variation+"/")...)
			}
		}
		return results
	}
	// Depending what the last link is, return or expand
	for _, variation := range strings.Split(pattern, ",") {
		switch metric := metrics[variation].(type) {
		case float64:
			// Final metric value found, return as singleton
			results = append(results, path+variation)

		case map[string]interface{}:
			results = append(results, expandMetrics(metric, path+variation+"/")...)

		default:
			utils.Fatalf("Metric pattern resolved to unexpected type: %v", reflect.TypeOf(metric))
			return nil
		}
	}
	return results
}
Example #8
0
func runBlockTest(ctx *cli.Context) {
	var (
		file, testname string
		rpc            bool
	)
	args := ctx.Args()
	switch {
	case len(args) == 1:
		file = args[0]
	case len(args) == 2:
		file, testname = args[0], args[1]
	case len(args) == 3:
		file, testname = args[0], args[1]
		rpc = true
	default:
		utils.Fatalf(`Usage: expanse blocktest <path-to-test-file> [ <test-name> [ "rpc" ] ]`)
	}
	bt, err := tests.LoadBlockTests(file)
	if err != nil {
		utils.Fatalf("%v", err)
	}

	// run all tests if no test name is specified
	if testname == "" {
		ecode := 0
		for name, test := range bt {
			fmt.Printf("----------------- Running Block Test %q\n", name)
			expanse, err := runOneBlockTest(ctx, test)
			if err != nil {
				fmt.Println(err)
				fmt.Println("FAIL")
				ecode = 1
			}
			if expanse != nil {
				expanse.Stop()
				expanse.WaitForShutdown()
			}
		}
		os.Exit(ecode)
		return
	}
	// otherwise, run the given test
	test, ok := bt[testname]
	if !ok {
		utils.Fatalf("Test file does not contain test named %q", testname)
	}
	expanse, err := runOneBlockTest(ctx, test)
	if err != nil {
		utils.Fatalf("%v", err)
	}

	if rpc {
		fmt.Println("Block Test post state validated, starting RPC interface.")
		startEth(ctx, expanse)
		utils.StartRPC(expanse, ctx)
		expanse.WaitForShutdown()
	}
}
Example #9
0
func importChain(ctx *cli.Context) {
	if len(ctx.Args()) != 1 {
		utils.Fatalf("This command requires an argument.")
	}
	chain, chainDb := utils.MakeChain(ctx)
	start := time.Now()
	err := utils.ImportChain(chain, ctx.Args().First())
	chainDb.Close()
	if err != nil {
		utils.Fatalf("Import error: %v", err)
	}
	fmt.Printf("Import done in %v", time.Since(start))
}
Example #10
0
func accountImport(ctx *cli.Context) {
	keyfile := ctx.Args().First()
	if len(keyfile) == 0 {
		utils.Fatalf("keyfile must be given as argument")
	}
	am := utils.MakeAccountManager(ctx)
	passphrase, _ := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, nil)
	acct, err := am.Import(keyfile, passphrase)
	if err != nil {
		utils.Fatalf("Could not create the account: %v", err)
	}
	fmt.Printf("Address: %x\n", acct)
}
Example #11
0
func accountUpdate(ctx *cli.Context) {
	am := utils.MakeAccountManager(ctx)
	arg := ctx.Args().First()
	if len(arg) == 0 {
		utils.Fatalf("account address or index must be given as argument")
	}

	addr, authFrom, passphrases := unlockAccount(ctx, am, arg, 0, nil)
	authTo, _ := getPassPhrase(ctx, "Please give a new password. Do not forget this password.", true, 0, passphrases)
	err := am.Update(common.HexToAddress(addr), authFrom, authTo)
	if err != nil {
		utils.Fatalf("Could not update the account: %v", err)
	}
}
Example #12
0
func execJSFiles(ctx *cli.Context) {
	utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))

	cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
	expanse, err := exp.New(cfg)
	if err != nil {
		utils.Fatalf("%v", err)
	}

	client := comms.NewInProcClient(codec.JSON)
	startEth(ctx, expanse)
	repl := newJSRE(
		expanse,
		ctx.GlobalString(utils.JSpathFlag.Name),
		ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
		client,
		false,
		nil,
	)
	for _, file := range ctx.Args() {
		repl.exec(file)
	}

	expanse.Stop()
	expanse.WaitForShutdown()
}
Example #13
0
func accountUpdate(ctx *cli.Context) {
	utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))

	am := utils.MakeAccountManager(ctx)
	arg := ctx.Args().First()
	if len(arg) == 0 {
		utils.Fatalf("account address or index must be given as argument")
	}

	addr, authFrom := unlockAccount(ctx, am, arg, 0)
	authTo := getPassPhrase(ctx, "Please give a new password. Do not forget this password.", true, 0)
	err := am.Update(common.HexToAddress(addr), authFrom, authTo)
	if err != nil {
		utils.Fatalf("Could not update the account: %v", err)
	}
}
Example #14
0
func newLightweightJSRE(docRoot string, client comms.ExpanseClient, datadir string, interactive bool) *jsre {

	js := &jsre{ps1: "> "}
	js.wait = make(chan *big.Int)
	js.client = client

	// update state in separare forever blocks
	js.re = re.New(docRoot)
	if err := js.apiBindings(js); err != nil {
		utils.Fatalf("Unable to initialize console - %v", err)
	}

	if !liner.TerminalSupported() || !interactive {
		js.prompter = dumbterm{bufio.NewReader(os.Stdin)}
	} else {
		lr := liner.NewLiner()
		js.withHistory(datadir, func(hist *os.File) { lr.ReadHistory(hist) })
		lr.SetCtrlCAborts(true)
		js.loadAutoCompletion()
		lr.SetWordCompleter(apiWordCompleter)
		lr.SetTabCompletionStyle(liner.TabPrints)
		js.prompter = lr
		js.atexit = func() {
			js.withHistory(datadir, func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) })
			lr.Close()
			close(js.wait)
		}
	}
	return js
}
Example #15
0
func console(ctx *cli.Context) {
	cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)

	cfg.ExtraData = makeExtra(ctx)

	expanse, err := exp.New(cfg)
	if err != nil {
		utils.Fatalf("%v", err)
	}

	client := comms.NewInProcClient(codec.JSON)

	startEth(ctx, expanse)
	repl := newJSRE(
		expanse,
		ctx.GlobalString(utils.JSpathFlag.Name),
		ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
		client,
		true,
		nil,
	)

	if ctx.GlobalString(utils.ExecFlag.Name) != "" {
		repl.batch(ctx.GlobalString(utils.ExecFlag.Name))
	} else {
		repl.welcome()
		repl.interactive()
	}

	expanse.Stop()
	expanse.WaitForShutdown()
}
Example #16
0
func attach(ctx *cli.Context) {
	var client comms.ExpanseClient
	var err error
	if ctx.Args().Present() {
		client, err = comms.ClientFromEndpoint(ctx.Args().First(), codec.JSON)
	} else {
		cfg := comms.IpcConfig{
			Endpoint: utils.IpcSocketPath(ctx),
		}
		client, err = comms.NewIpcClient(cfg, codec.JSON)
	}

	if err != nil {
		utils.Fatalf("Unable to attach to gexp node - %v", err)
	}

	repl := newLightweightJSRE(
		ctx.GlobalString(utils.JSpathFlag.Name),
		client,
		ctx.GlobalString(utils.DataDirFlag.Name),
		true,
	)

	if ctx.GlobalString(utils.ExecFlag.Name) != "" {
		repl.batch(ctx.GlobalString(utils.ExecFlag.Name))
	} else {
		repl.welcome()
		repl.interactive()
	}
}
Example #17
0
func accountCreate(ctx *cli.Context) {
	am := utils.MakeAccountManager(ctx)
	passphrase, _ := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, nil)
	acct, err := am.NewAccount(passphrase)
	if err != nil {
		utils.Fatalf("Could not create the account: %v", err)
	}
	fmt.Printf("Address: %x\n", acct)
}
Example #18
0
func importWallet(ctx *cli.Context) {
	keyfile := ctx.Args().First()
	if len(keyfile) == 0 {
		utils.Fatalf("keyfile must be given as argument")
	}
	keyJson, err := ioutil.ReadFile(keyfile)
	if err != nil {
		utils.Fatalf("Could not read wallet file: %v", err)
	}

	am := utils.MakeAccountManager(ctx)
	passphrase, _ := getPassPhrase(ctx, "", false, 0, nil)

	acct, err := am.ImportPreSaleKey(keyJson, passphrase)
	if err != nil {
		utils.Fatalf("Could not create the account: %v", err)
	}
	fmt.Printf("Address: %x\n", acct)
}
Example #19
0
func accountList(ctx *cli.Context) {
	am := utils.MakeAccountManager(ctx)
	accts, err := am.Accounts()
	if err != nil {
		utils.Fatalf("Could not list accounts: %v", err)
	}
	for i, acct := range accts {
		fmt.Printf("Account #%d: %x\n", i, acct)
	}
}
Example #20
0
func accountCreate(ctx *cli.Context) {
	utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))

	am := utils.MakeAccountManager(ctx)
	passphrase := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0)
	acct, err := am.NewAccount(passphrase)
	if err != nil {
		utils.Fatalf("Could not create the account: %v", err)
	}
	fmt.Printf("Address: %x\n", acct)
}
Example #21
0
func main() {
	var (
		listenAddr  = flag.String("addr", ":42787", "listen address")
		genKey      = flag.String("genkey", "", "generate a node key and quit")
		nodeKeyFile = flag.String("nodekey", "", "private key filename")
		nodeKeyHex  = flag.String("nodekeyhex", "", "private key as hex (for testing)")
		natdesc     = flag.String("nat", "none", "port mapping mechanism (any|none|upnp|pmp|extip:<IP>)")

		nodeKey *ecdsa.PrivateKey
		err     error
	)
	flag.Var(glog.GetVerbosity(), "verbosity", "log verbosity (0-9)")
	flag.Var(glog.GetVModule(), "vmodule", "log verbosity pattern")
	glog.SetToStderr(true)
	flag.Parse()

	if *genKey != "" {
		key, err := crypto.GenerateKey()
		if err != nil {
			utils.Fatalf("could not generate key: %v", err)
		}
		if err := crypto.SaveECDSA(*genKey, key); err != nil {
			utils.Fatalf("%v", err)
		}
		os.Exit(0)
	}

	natm, err := nat.Parse(*natdesc)
	if err != nil {
		utils.Fatalf("-nat: %v", err)
	}
	switch {
	case *nodeKeyFile == "" && *nodeKeyHex == "":
		utils.Fatalf("Use -nodekey or -nodekeyhex to specify a private key")
	case *nodeKeyFile != "" && *nodeKeyHex != "":
		utils.Fatalf("Options -nodekey and -nodekeyhex are mutually exclusive")
	case *nodeKeyFile != "":
		if nodeKey, err = crypto.LoadECDSA(*nodeKeyFile); err != nil {
			utils.Fatalf("-nodekey: %v", err)
		}
	case *nodeKeyHex != "":
		if nodeKey, err = crypto.HexToECDSA(*nodeKeyHex); err != nil {
			utils.Fatalf("-nodekeyhex: %v", err)
		}
	}

	if _, err := discover.ListenUDP(nodeKey, *listenAddr, natm, ""); err != nil {
		utils.Fatalf("%v", err)
	}
	select {}
}
Example #22
0
func accountList(ctx *cli.Context) {
	utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))

	am := utils.MakeAccountManager(ctx)
	accts, err := am.Accounts()
	if err != nil {
		utils.Fatalf("Could not list accounts: %v", err)
	}
	for i, acct := range accts {
		fmt.Printf("Account #%d: %x\n", i, acct)
	}
}
Example #23
0
func getPassPhrase(ctx *cli.Context, desc string, confirmation bool, i int, inputpassphrases []string) (passphrase string, passphrases []string) {
	passfile := ctx.GlobalString(utils.PasswordFileFlag.Name)
	if len(passfile) == 0 {
		fmt.Println(desc)
		auth, err := utils.PromptPassword("Passphrase: ", true)
		if err != nil {
			utils.Fatalf("%v", err)
		}
		if confirmation {
			confirm, err := utils.PromptPassword("Repeat Passphrase: ", false)
			if err != nil {
				utils.Fatalf("%v", err)
			}
			if auth != confirm {
				utils.Fatalf("Passphrases did not match.")
			}
		}
		passphrase = auth

	} else {
		passphrases = inputpassphrases
		if passphrases == nil {
			passbytes, err := ioutil.ReadFile(passfile)
			if err != nil {
				utils.Fatalf("Unable to read password file '%s': %v", passfile, err)
			}
			// this is backwards compatible if the same password unlocks several accounts
			// it also has the consequence that trailing newlines will not count as part
			// of the password, so --password <(echo -n 'pass') will now work without -n
			passphrases = strings.Split(string(passbytes), "\n")
		}
		if i >= len(passphrases) {
			passphrase = passphrases[len(passphrases)-1]
		} else {
			passphrase = passphrases[i]
		}
	}
	return
}
Example #24
0
// initGenesis will initialise the given JSON format genesis file and writes it as
// the zero'd block (i.e. genesis) or will fail hard if it can't succeed.
func initGenesis(ctx *cli.Context) error {
	genesisPath := ctx.Args().First()
	if len(genesisPath) == 0 {
		utils.Fatalf("must supply path to genesis JSON file")
	}

	chainDb, err := ethdb.NewLDBDatabase(filepath.Join(utils.MustMakeDataDir(ctx), "chaindata"), 0, 0)
	if err != nil {
		utils.Fatalf("could not open database: %v", err)
	}

	genesisFile, err := os.Open(genesisPath)
	if err != nil {
		utils.Fatalf("failed to read genesis file: %v", err)
	}

	block, err := core.WriteGenesisBlock(chainDb, genesisFile)
	if err != nil {
		utils.Fatalf("failed to write genesis block: %v", err)
	}
	glog.V(logger.Info).Infof("successfully wrote genesis block and/or chain rule set: %x", block.Hash())
	return nil
}
Example #25
0
func dump(ctx *cli.Context) {
	chain, chainDb := utils.MakeChain(ctx)
	for _, arg := range ctx.Args() {
		var block *types.Block
		if hashish(arg) {
			block = chain.GetBlock(common.HexToHash(arg))
		} else {
			num, _ := strconv.Atoi(arg)
			block = chain.GetBlockByNumber(uint64(num))
		}
		if block == nil {
			fmt.Println("{}")
			utils.Fatalf("block not found")
		} else {
			state, err := state.New(block.Root(), chainDb)
			if err != nil {
				utils.Fatalf("could not create new state: %v", err)
				return
			}
			fmt.Printf("%s\n", state.Dump())
		}
	}
	chainDb.Close()
}
Example #26
0
func removeDB(ctx *cli.Context) {
	confirm, err := utils.PromptConfirm("Remove local database?")
	if err != nil {
		utils.Fatalf("%v", err)
	}

	if confirm {
		fmt.Println("Removing chaindata...")
		start := time.Now()

		os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "chaindata"))

		fmt.Printf("Removed in %v\n", time.Since(start))
	} else {
		fmt.Println("Operation aborted")
	}
}
Example #27
0
func gpubench(ctx *cli.Context) {
	args := ctx.Args()
	wrongArgs := func() {
		utils.Fatalf(`Usage: geth gpubench <gpu number>`)
	}
	switch {
	case len(args) == 1:
		n, err := strconv.ParseUint(args[0], 0, 64)
		if err != nil {
			wrongArgs()
		}
		exp.GPUBench(n)
	case len(args) == 0:
		exp.GPUBench(0)
	default:
		wrongArgs()
	}
}
Example #28
0
func newJSRE(expanse *exp.Expanse, docRoot, corsDomain string, client comms.ExpanseClient, interactive bool, f xeth.Frontend) *jsre {
	js := &jsre{expanse: expanse, ps1: "> "}

	// set default cors domain used by startRpc from CLI flag
	js.corsDomain = corsDomain
	if f == nil {
		f = js
	}

	js.xeth = xeth.New(expanse, f)

	js.wait = js.xeth.UpdateState()
	js.client = client
	if clt, ok := js.client.(*comms.InProcClient); ok {
		if offeredApis, err := api.ParseApiString(shared.AllApis, codec.JSON, js.xeth, expanse); err == nil {
			clt.Initialize(api.Merge(offeredApis...))
		}
	}

	// update state in separare forever blocks
	js.re = re.New(docRoot)
	if err := js.apiBindings(f); err != nil {
		utils.Fatalf("Unable to connect - %v", err)
	}

	if !liner.TerminalSupported() || !interactive {
		js.prompter = dumbterm{bufio.NewReader(os.Stdin)}
	} else {
		lr := liner.NewLiner()
		js.withHistory(expanse.DataDir, func(hist *os.File) { lr.ReadHistory(hist) })
		lr.SetCtrlCAborts(true)
		js.loadAutoCompletion()
		lr.SetWordCompleter(apiWordCompleter)
		lr.SetTabCompletionStyle(liner.TabPrints)
		js.prompter = lr
		js.atexit = func() {
			js.withHistory(expanse.DataDir, func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) })
			lr.Close()
			close(js.wait)
		}
	}
	return js
}
Example #29
0
// expandMetrics expands the entire tree of metrics into a flat list of paths.
func expandMetrics(metrics map[string]interface{}, path string) []string {
	// Iterate over all fields and expand individually
	list := []string{}
	for name, metric := range metrics {
		switch metric := metric.(type) {
		case float64:
			// Final metric value found, append to list
			list = append(list, path+name)

		case map[string]interface{}:
			// Tree of metrics found, expand recursively
			list = append(list, expandMetrics(metric, path+name+"/")...)

		default:
			utils.Fatalf("Metric pattern %s resolved to unexpected type: %v", path+name, reflect.TypeOf(metric))
			return nil
		}
	}
	return list
}
Example #30
-1
func run(ctx *cli.Context) {
	cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
	cfg.ExtraData = makeExtra(ctx)

	expanse, err := exp.New(cfg)
	if err != nil {
		utils.Fatalf("%v", err)
	}

	startEth(ctx, expanse)
	// this blocks the thread
	expanse.WaitForShutdown()
}