| 
									
										
										
										
											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 ( | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"os/signal" | 
					
						
							| 
									
										
										
										
											2016-07-12 17:47:15 +02:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											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
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	consoleCommand = cli.Command{ | 
					
						
							| 
									
										
										
										
											2016-11-10 19:00:09 +08:00
										 |  |  | 		Action:    localConsole, | 
					
						
							|  |  |  | 		Name:      "console", | 
					
						
							|  |  |  | 		Usage:     "Start an interactive JavaScript environment", | 
					
						
							|  |  |  | 		ArgsUsage: "", // TODO: Write this! | 
					
						
							|  |  |  | 		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. | 
					
						
							|  |  |  | See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console | 
					
						
							|  |  |  | `, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	attachCommand = cli.Command{ | 
					
						
							| 
									
										
										
										
											2016-11-10 19:00:09 +08:00
										 |  |  | 		Action:    remoteConsole, | 
					
						
							|  |  |  | 		Name:      "attach", | 
					
						
							|  |  |  | 		Usage:     "Start an interactive JavaScript environment (connect to node)", | 
					
						
							|  |  |  | 		ArgsUsage: "", // TODO: Write this! | 
					
						
							|  |  |  | 		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. | 
					
						
							|  |  |  | See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console. | 
					
						
							|  |  |  | This command allows to open a console on a running geth node. | 
					
						
							| 
									
										
										
										
											2016-11-10 19:00:09 +08:00
										 |  |  | `, | 
					
						
							| 
									
										
										
										
											2016-05-06 12:40:23 +03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	javascriptCommand = cli.Command{ | 
					
						
							| 
									
										
										
										
											2016-11-10 19:00:09 +08:00
										 |  |  | 		Action:    ephemeralConsole, | 
					
						
							|  |  |  | 		Name:      "js", | 
					
						
							|  |  |  | 		Usage:     "Execute the specified JavaScript files", | 
					
						
							|  |  |  | 		ArgsUsage: "", // TODO: Write this! | 
					
						
							|  |  |  | 		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 | 
					
						
							|  |  |  | JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console | 
					
						
							|  |  |  | `, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 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{ | 
					
						
							|  |  |  | 		DataDir: node.DataDir(), | 
					
						
							|  |  |  | 		DocRoot: ctx.GlobalString(utils.JSpathFlag.Name), | 
					
						
							|  |  |  | 		Client:  client, | 
					
						
							|  |  |  | 		Preload: utils.MakeConsolePreloads(ctx), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	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 | 
					
						
							| 
									
										
										
										
											2016-07-12 17:47:15 +02:00
										 |  |  | 	client, err := dialRPC(ctx.Args().First()) | 
					
						
							| 
									
										
										
										
											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), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | // console to it, and each of the files specified as arguments and tears the | 
					
						
							|  |  |  | // 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{ | 
					
						
							|  |  |  | 		DataDir: node.DataDir(), | 
					
						
							|  |  |  | 		DocRoot: ctx.GlobalString(utils.JSpathFlag.Name), | 
					
						
							|  |  |  | 		Client:  client, | 
					
						
							|  |  |  | 		Preload: utils.MakeConsolePreloads(ctx), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | 	signal.Notify(abort, os.Interrupt) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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
										 |  |  | } |