| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | // Copyright 2016 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of go-ethereum. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // go-ethereum is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // go-ethereum is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  | // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package main | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2017-11-28 14:00:00 +01:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	"os" | 
					
						
							|  |  |  | 	"os/signal" | 
					
						
							| 
									
										
										
										
											2017-12-05 02:17:38 -08:00
										 |  |  | 	"path/filepath" | 
					
						
							| 
									
										
										
										
											2016-07-12 17:47:15 +02:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2018-02-20 14:33:34 +02:00
										 |  |  | 	"syscall" | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/cmd/utils" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/console" | 
					
						
							| 
									
										
										
										
											2016-07-12 17:47:15 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/node" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/rpc" | 
					
						
							| 
									
										
										
										
											2016-06-09 11:44:42 +02:00
										 |  |  | 	"gopkg.in/urfave/cli.v1" | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-03 12:26:09 +02:00
										 |  |  | var ( | 
					
						
							|  |  |  | 	consoleFlags = []cli.Flag{utils.JSpathFlag, utils.ExecFlag, utils.PreloadJSFlag} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	consoleCommand = cli.Command{ | 
					
						
							| 
									
										
										
										
											2017-05-03 12:26:09 +02:00
										 |  |  | 		Action:   utils.MigrateFlags(localConsole), | 
					
						
							|  |  |  | 		Name:     "console", | 
					
						
							|  |  |  | 		Usage:    "Start an interactive JavaScript environment", | 
					
						
							| 
									
										
										
										
											2017-06-21 12:58:00 +02:00
										 |  |  | 		Flags:    append(append(append(nodeFlags, rpcFlags...), consoleFlags...), whisperFlags...), | 
					
						
							| 
									
										
										
										
											2017-05-03 12:26:09 +02:00
										 |  |  | 		Category: "CONSOLE COMMANDS", | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 		Description: ` | 
					
						
							|  |  |  | The Geth console is an interactive shell for the JavaScript runtime environment | 
					
						
							|  |  |  | which exposes a node admin interface as well as the Ðapp JavaScript API. | 
					
						
							| 
									
										
										
										
											2018-02-26 01:38:17 -08:00
										 |  |  | See https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console.`, | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-03 12:26:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	attachCommand = cli.Command{ | 
					
						
							| 
									
										
										
										
											2017-05-03 12:26:09 +02:00
										 |  |  | 		Action:    utils.MigrateFlags(remoteConsole), | 
					
						
							| 
									
										
										
										
											2016-11-10 19:00:09 +08:00
										 |  |  | 		Name:      "attach", | 
					
						
							|  |  |  | 		Usage:     "Start an interactive JavaScript environment (connect to node)", | 
					
						
							| 
									
										
										
										
											2017-05-03 12:26:09 +02:00
										 |  |  | 		ArgsUsage: "[endpoint]", | 
					
						
							|  |  |  | 		Flags:     append(consoleFlags, utils.DataDirFlag), | 
					
						
							| 
									
										
										
										
											2016-11-10 19:00:09 +08:00
										 |  |  | 		Category:  "CONSOLE COMMANDS", | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 		Description: ` | 
					
						
							|  |  |  | The Geth console is an interactive shell for the JavaScript runtime environment | 
					
						
							|  |  |  | which exposes a node admin interface as well as the Ðapp JavaScript API. | 
					
						
							| 
									
										
										
										
											2018-02-26 01:38:17 -08:00
										 |  |  | See https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console. | 
					
						
							| 
									
										
										
										
											2017-05-03 12:26:09 +02:00
										 |  |  | This command allows to open a console on a running geth node.`, | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-03 12:26:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	javascriptCommand = cli.Command{ | 
					
						
							| 
									
										
										
										
											2017-05-03 12:26:09 +02:00
										 |  |  | 		Action:    utils.MigrateFlags(ephemeralConsole), | 
					
						
							| 
									
										
										
										
											2016-11-10 19:00:09 +08:00
										 |  |  | 		Name:      "js", | 
					
						
							|  |  |  | 		Usage:     "Execute the specified JavaScript files", | 
					
						
							| 
									
										
										
										
											2017-05-03 12:26:09 +02:00
										 |  |  | 		ArgsUsage: "<jsfile> [jsfile...]", | 
					
						
							|  |  |  | 		Flags:     append(nodeFlags, consoleFlags...), | 
					
						
							| 
									
										
										
										
											2016-11-10 19:00:09 +08:00
										 |  |  | 		Category:  "CONSOLE COMMANDS", | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 		Description: ` | 
					
						
							|  |  |  | The JavaScript VM exposes a node admin interface as well as the Ðapp | 
					
						
							| 
									
										
										
										
											2018-02-26 01:38:17 -08:00
										 |  |  | JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console`, | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	} | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // localConsole starts a new geth node, attaching a JavaScript console to it at the | 
					
						
							|  |  |  | // same time. | 
					
						
							| 
									
										
										
										
											2016-06-10 11:23:00 +03:00
										 |  |  | func localConsole(ctx *cli.Context) error { | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	// Create and start the node based on the CLI flags | 
					
						
							| 
									
										
										
										
											2016-08-15 18:38:32 +02:00
										 |  |  | 	node := makeFullNode(ctx) | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	startNode(ctx, node) | 
					
						
							|  |  |  | 	defer node.Stop() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Attach to the newly started node and start the JavaScript console | 
					
						
							|  |  |  | 	client, err := node.Attach() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		utils.Fatalf("Failed to attach to the inproc geth: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	config := console.Config{ | 
					
						
							| 
									
										
										
										
											2017-05-03 12:26:09 +02:00
										 |  |  | 		DataDir: utils.MakeDataDir(ctx), | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 		DocRoot: ctx.GlobalString(utils.JSpathFlag.Name), | 
					
						
							|  |  |  | 		Client:  client, | 
					
						
							|  |  |  | 		Preload: utils.MakeConsolePreloads(ctx), | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-03 12:26:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	console, err := console.New(config) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		utils.Fatalf("Failed to start the JavaScript console: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer console.Stop(false) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// If only a short execution was requested, evaluate and return | 
					
						
							|  |  |  | 	if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" { | 
					
						
							|  |  |  | 		console.Evaluate(script) | 
					
						
							| 
									
										
										
										
											2016-06-10 11:23:00 +03:00
										 |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// Otherwise print the welcome screen and enter interactive mode | 
					
						
							|  |  |  | 	console.Welcome() | 
					
						
							|  |  |  | 	console.Interactive() | 
					
						
							| 
									
										
										
										
											2016-06-10 11:23:00 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // remoteConsole will connect to a remote geth instance, attaching a JavaScript | 
					
						
							|  |  |  | // console to it. | 
					
						
							| 
									
										
										
										
											2016-06-10 11:23:00 +03:00
										 |  |  | func remoteConsole(ctx *cli.Context) error { | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	// Attach to a remotely running geth instance and start the JavaScript console | 
					
						
							| 
									
										
										
										
											2017-11-28 14:00:00 +01:00
										 |  |  | 	endpoint := ctx.Args().First() | 
					
						
							| 
									
										
										
										
											2017-12-05 02:17:38 -08:00
										 |  |  | 	if endpoint == "" { | 
					
						
							|  |  |  | 		path := node.DefaultDataDir() | 
					
						
							|  |  |  | 		if ctx.GlobalIsSet(utils.DataDirFlag.Name) { | 
					
						
							|  |  |  | 			path = ctx.GlobalString(utils.DataDirFlag.Name) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-12-15 13:31:10 -08:00
										 |  |  | 		if path != "" { | 
					
						
							|  |  |  | 			if ctx.GlobalBool(utils.TestnetFlag.Name) { | 
					
						
							|  |  |  | 				path = filepath.Join(path, "testnet") | 
					
						
							|  |  |  | 			} else if ctx.GlobalBool(utils.RinkebyFlag.Name) { | 
					
						
							|  |  |  | 				path = filepath.Join(path, "rinkeby") | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-12-05 02:17:38 -08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		endpoint = fmt.Sprintf("%s/geth.ipc", path) | 
					
						
							| 
									
										
										
										
											2017-11-28 14:00:00 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	client, err := dialRPC(endpoint) | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		utils.Fatalf("Unable to attach to remote geth: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	config := console.Config{ | 
					
						
							| 
									
										
										
										
											2016-08-18 13:28:17 +02:00
										 |  |  | 		DataDir: utils.MakeDataDir(ctx), | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 		DocRoot: ctx.GlobalString(utils.JSpathFlag.Name), | 
					
						
							|  |  |  | 		Client:  client, | 
					
						
							|  |  |  | 		Preload: utils.MakeConsolePreloads(ctx), | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-03 12:26:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	console, err := console.New(config) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		utils.Fatalf("Failed to start the JavaScript console: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer console.Stop(false) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" { | 
					
						
							|  |  |  | 		console.Evaluate(script) | 
					
						
							| 
									
										
										
										
											2016-06-10 11:23:00 +03:00
										 |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-03 12:26:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	// Otherwise print the welcome screen and enter interactive mode | 
					
						
							|  |  |  | 	console.Welcome() | 
					
						
							|  |  |  | 	console.Interactive() | 
					
						
							| 
									
										
										
										
											2016-06-10 11:23:00 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-12 17:47:15 +02:00
										 |  |  | // dialRPC returns a RPC client which connects to the given endpoint. | 
					
						
							|  |  |  | // The check for empty endpoint implements the defaulting logic | 
					
						
							|  |  |  | // for "geth attach" and "geth monitor" with no argument. | 
					
						
							|  |  |  | func dialRPC(endpoint string) (*rpc.Client, error) { | 
					
						
							|  |  |  | 	if endpoint == "" { | 
					
						
							| 
									
										
										
										
											2016-08-18 13:28:17 +02:00
										 |  |  | 		endpoint = node.DefaultIPCEndpoint(clientIdentifier) | 
					
						
							| 
									
										
										
										
											2016-07-12 17:47:15 +02:00
										 |  |  | 	} else if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") { | 
					
						
							|  |  |  | 		// Backwards compatibility with geth < 1.5 which required | 
					
						
							|  |  |  | 		// these prefixes. | 
					
						
							|  |  |  | 		endpoint = endpoint[4:] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return rpc.Dial(endpoint) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | // ephemeralConsole starts a new geth node, attaches an ephemeral JavaScript | 
					
						
							| 
									
										
										
										
											2017-05-03 12:26:09 +02:00
										 |  |  | // console to it, executes each of the files specified as arguments and tears | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | // everything down. | 
					
						
							| 
									
										
										
										
											2016-06-10 11:23:00 +03:00
										 |  |  | func ephemeralConsole(ctx *cli.Context) error { | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	// Create and start the node based on the CLI flags | 
					
						
							| 
									
										
										
										
											2016-08-15 18:38:32 +02:00
										 |  |  | 	node := makeFullNode(ctx) | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	startNode(ctx, node) | 
					
						
							|  |  |  | 	defer node.Stop() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Attach to the newly started node and start the JavaScript console | 
					
						
							|  |  |  | 	client, err := node.Attach() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		utils.Fatalf("Failed to attach to the inproc geth: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	config := console.Config{ | 
					
						
							| 
									
										
										
										
											2017-05-03 12:26:09 +02:00
										 |  |  | 		DataDir: utils.MakeDataDir(ctx), | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 		DocRoot: ctx.GlobalString(utils.JSpathFlag.Name), | 
					
						
							|  |  |  | 		Client:  client, | 
					
						
							|  |  |  | 		Preload: utils.MakeConsolePreloads(ctx), | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-03 12:26:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	console, err := console.New(config) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		utils.Fatalf("Failed to start the JavaScript console: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer console.Stop(false) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Evaluate each of the specified JavaScript files | 
					
						
							|  |  |  | 	for _, file := range ctx.Args() { | 
					
						
							|  |  |  | 		if err = console.Execute(file); err != nil { | 
					
						
							|  |  |  | 			utils.Fatalf("Failed to execute %s: %v", file, err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Wait for pending callbacks, but stop for Ctrl-C. | 
					
						
							|  |  |  | 	abort := make(chan os.Signal, 1) | 
					
						
							| 
									
										
										
										
											2018-02-20 14:33:34 +02:00
										 |  |  | 	signal.Notify(abort, syscall.SIGINT, syscall.SIGTERM) | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	go func() { | 
					
						
							|  |  |  | 		<-abort | 
					
						
							|  |  |  | 		os.Exit(0) | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 	console.Stop(true) | 
					
						
							| 
									
										
										
										
											2016-06-10 11:23:00 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | } |