github.com/klaytn/klaytn@v1.10.2/cmd/utils/nodecmd/consolecmd.go (about)

     1  // Modifications Copyright 2018 The klaytn Authors
     2  // Copyright 2016 The go-ethereum Authors
     3  // This file is part of go-ethereum.
     4  //
     5  // go-ethereum is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // go-ethereum is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU General Public License
    16  // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from cmd/geth/consolecmd.go (2018/06/04).
    19  // Modified and improved for the klaytn development.
    20  
    21  package nodecmd
    22  
    23  import (
    24  	"fmt"
    25  	"path/filepath"
    26  	"strings"
    27  
    28  	"github.com/klaytn/klaytn/cmd/utils"
    29  	"github.com/klaytn/klaytn/console"
    30  	"github.com/klaytn/klaytn/log"
    31  	"github.com/klaytn/klaytn/networks/rpc"
    32  	"github.com/klaytn/klaytn/node"
    33  	"gopkg.in/urfave/cli.v1"
    34  	"gopkg.in/urfave/cli.v1/altsrc"
    35  )
    36  
    37  var (
    38  	ConsoleFlags = []cli.Flag{
    39  		altsrc.NewStringFlag(utils.JSpathFlag),
    40  		altsrc.NewStringFlag(utils.ExecFlag),
    41  		altsrc.NewStringFlag(utils.PreloadJSFlag),
    42  	}
    43  
    44  	AttachCommand = cli.Command{
    45  		Action:    utils.MigrateFlags(remoteConsole),
    46  		Name:      "attach",
    47  		Usage:     "Start an interactive JavaScript environment (connect to node)",
    48  		ArgsUsage: "[endpoint]",
    49  		Flags:     append(ConsoleFlags, utils.DataDirFlag),
    50  		Category:  "CONSOLE COMMANDS",
    51  		Description: `
    52  The Klaytn console is an interactive shell for the JavaScript runtime environment
    53  which exposes a node admin interface as well as the Ðapp JavaScript API.
    54  See https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console.
    55  This command allows to open a console on a running Klaytn node.`,
    56  	}
    57  )
    58  
    59  // GetConsoleCommand returns cli.Command `console` whose flags are initialized with nodeFlags, rpcFlags, and ConsoleFlags.
    60  func GetConsoleCommand(nodeFlags, rpcFlags []cli.Flag) cli.Command {
    61  	return cli.Command{
    62  		Action:   utils.MigrateFlags(localConsole),
    63  		Name:     "console",
    64  		Usage:    "Start an interactive JavaScript environment",
    65  		Flags:    append(append(nodeFlags, rpcFlags...), ConsoleFlags...),
    66  		Category: "CONSOLE COMMANDS",
    67  		Description: `
    68  The Klaytn console is an interactive shell for the JavaScript runtime environment
    69  which exposes a node admin interface as well as the Ðapp JavaScript API.
    70  See https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console.`,
    71  	}
    72  }
    73  
    74  // localConsole starts a new Klaytn node, attaching a JavaScript console to it at the
    75  // same time.
    76  func localConsole(ctx *cli.Context) error {
    77  	// Create and start the node based on the CLI flags
    78  	node := MakeFullNode(ctx)
    79  	startNode(ctx, node)
    80  	defer node.Stop()
    81  
    82  	// Attach to the newly started node and start the JavaScript console
    83  	client, err := node.Attach()
    84  	if err != nil {
    85  		log.Fatalf("Failed to attach to the inproc node: %v", err)
    86  	}
    87  	config := console.Config{
    88  		DataDir: utils.MakeDataDir(ctx),
    89  		DocRoot: ctx.GlobalString(utils.JSpathFlag.Name),
    90  		Client:  client,
    91  		Preload: utils.MakeConsolePreloads(ctx),
    92  	}
    93  
    94  	console, err := console.New(config)
    95  	if err != nil {
    96  		log.Fatalf("Failed to start the JavaScript console: %v", err)
    97  	}
    98  	defer console.Stop(false)
    99  
   100  	// If only a short execution was requested, evaluate and return
   101  	if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" {
   102  		console.Evaluate(script)
   103  		return nil
   104  	}
   105  	// Otherwise print the welcome screen and enter interactive mode
   106  	console.Welcome()
   107  	console.Interactive()
   108  
   109  	return nil
   110  }
   111  
   112  // remoteConsole will connect to a remote node instance, attaching a JavaScript
   113  // console to it.
   114  func remoteConsole(ctx *cli.Context) error {
   115  	// Attach to a remotely running node instance and start the JavaScript console
   116  	endpoint := ctx.Args().First()
   117  	if endpoint == "" {
   118  		path := node.DefaultDataDir()
   119  		if ctx.GlobalIsSet(utils.DataDirFlag.Name) {
   120  			path = ctx.GlobalString(utils.DataDirFlag.Name)
   121  		}
   122  		if path != "" {
   123  			if ctx.GlobalBool(utils.BaobabFlag.Name) {
   124  				path = filepath.Join(path, "baobab")
   125  			}
   126  		}
   127  		endpoint = fmt.Sprintf("%s/klay.ipc", path)
   128  	}
   129  	client, err := dialRPC(endpoint)
   130  	if err != nil {
   131  		log.Fatalf("Unable to attach to remote node: %v", err)
   132  	}
   133  	config := console.Config{
   134  		DataDir: utils.MakeDataDir(ctx),
   135  		DocRoot: ctx.GlobalString(utils.JSpathFlag.Name),
   136  		Client:  client,
   137  		Preload: utils.MakeConsolePreloads(ctx),
   138  	}
   139  
   140  	console, err := console.New(config)
   141  	if err != nil {
   142  		log.Fatalf("Failed to start the JavaScript console: %v", err)
   143  	}
   144  	defer console.Stop(false)
   145  
   146  	if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" {
   147  		console.Evaluate(script)
   148  		return nil
   149  	}
   150  
   151  	// Otherwise print the welcome screen and enter interactive mode
   152  	console.Welcome()
   153  	console.Interactive()
   154  
   155  	return nil
   156  }
   157  
   158  // dialRPC returns a RPC client which connects to the given endpoint.
   159  // The check for empty endpoint implements the defaulting logic
   160  // for "ken attach" and "ken monitor" with no argument.
   161  func dialRPC(endpoint string) (*rpc.Client, error) {
   162  	if endpoint == "" {
   163  		endpoint = node.DefaultIPCEndpoint(utils.ClientIdentifier)
   164  	} else if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") {
   165  		// TODO-Klaytn-RemoveLater: The below backward compatibility is not related to Klaytn.
   166  		// Backwards compatibility with klaytn < 1.5 which required
   167  		// these prefixes.
   168  		endpoint = endpoint[4:]
   169  	}
   170  	return rpc.Dial(endpoint)
   171  }