github.com/klaytn/klaytn@v1.12.1/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 "github.com/urfave/cli/v2" 34 ) 35 36 var AttachCommand = &cli.Command{ 37 Action: remoteConsole, 38 Name: "attach", 39 Usage: "Start an interactive JavaScript environment (connect to node)", 40 ArgsUsage: "[endpoint]", 41 Flags: append(utils.ConsoleFlags, utils.DataDirFlag), 42 Category: "CONSOLE COMMANDS", 43 Description: ` 44 The Klaytn console is an interactive shell for the JavaScript runtime environment 45 which exposes a node admin interface as well as the Ðapp JavaScript API. 46 See https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console. 47 This command allows to open a console on a running Klaytn node.`, 48 } 49 50 // GetConsoleCommand returns cli.Command `console` whose flags are initialized with nodeFlags, rpcFlags, and ConsoleFlags. 51 func GetConsoleCommand(nodeFlags, rpcFlags []cli.Flag) *cli.Command { 52 return &cli.Command{ 53 Action: localConsole, 54 Name: "console", 55 Usage: "Start an interactive JavaScript environment", 56 Flags: append(append(nodeFlags, rpcFlags...), utils.ConsoleFlags...), 57 Category: "CONSOLE COMMANDS", 58 Description: ` 59 The Klaytn console is an interactive shell for the JavaScript runtime environment 60 which exposes a node admin interface as well as the Ðapp JavaScript API. 61 See https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console.`, 62 } 63 } 64 65 // localConsole starts a new Klaytn node, attaching a JavaScript console to it at the 66 // same time. 67 func localConsole(ctx *cli.Context) error { 68 // Create and start the node based on the CLI flags 69 node := MakeFullNode(ctx) 70 startNode(ctx, node) 71 defer node.Stop() 72 73 // Attach to the newly started node and start the JavaScript console 74 client, err := node.Attach() 75 if err != nil { 76 log.Fatalf("Failed to attach to the inproc node: %v", err) 77 } 78 config := console.Config{ 79 DataDir: utils.MakeDataDir(ctx), 80 DocRoot: ctx.String(utils.JSpathFlag.Name), 81 Client: client, 82 Preload: utils.MakeConsolePreloads(ctx), 83 } 84 85 console, err := console.New(config) 86 if err != nil { 87 log.Fatalf("Failed to start the JavaScript console: %v", err) 88 } 89 defer console.Stop(false) 90 91 // If only a short execution was requested, evaluate and return 92 if script := ctx.String(utils.ExecFlag.Name); script != "" { 93 console.Evaluate(script) 94 return nil 95 } 96 // Otherwise print the welcome screen and enter interactive mode 97 console.Welcome() 98 console.Interactive() 99 100 return nil 101 } 102 103 // remoteConsole will connect to a remote node instance, attaching a JavaScript 104 // console to it. 105 func remoteConsole(ctx *cli.Context) error { 106 // Attach to a remotely running node instance and start the JavaScript console 107 endpoint := rpcEndpoint(ctx) 108 client, err := dialRPC(endpoint) 109 if err != nil { 110 log.Fatalf("Unable to attach to remote node: %v", err) 111 } 112 config := console.Config{ 113 DataDir: utils.MakeDataDir(ctx), 114 DocRoot: ctx.String(utils.JSpathFlag.Name), 115 Client: client, 116 Preload: utils.MakeConsolePreloads(ctx), 117 } 118 119 console, err := console.New(config) 120 if err != nil { 121 log.Fatalf("Failed to start the JavaScript console: %v", err) 122 } 123 defer console.Stop(false) 124 125 if script := ctx.String(utils.ExecFlag.Name); script != "" { 126 console.Evaluate(script) 127 return nil 128 } 129 130 // Otherwise print the welcome screen and enter interactive mode 131 console.Welcome() 132 console.Interactive() 133 134 return nil 135 } 136 137 func rpcEndpoint(ctx *cli.Context) string { 138 endpoint := ctx.Args().First() 139 if endpoint == "" { 140 path := node.DefaultDataDir() 141 if ctx.IsSet(utils.DataDirFlag.Name) { 142 path = ctx.String(utils.DataDirFlag.Name) 143 } 144 if path != "" { 145 if ctx.Bool(utils.BaobabFlag.Name) { 146 path = filepath.Join(path, "baobab") 147 } 148 } 149 endpoint = fmt.Sprintf("%s/klay.ipc", path) 150 } 151 return endpoint 152 } 153 154 // dialRPC returns a RPC client which connects to the given endpoint. 155 // The check for empty endpoint implements the defaulting logic 156 // for "ken attach" and "ken monitor" with no argument. 157 func dialRPC(endpoint string) (*rpc.Client, error) { 158 if endpoint == "" { 159 endpoint = node.DefaultIPCEndpoint(utils.ClientIdentifier) 160 } else if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") { 161 // TODO-Klaytn-RemoveLater: The below backward compatibility is not related to Klaytn. 162 // Backwards compatibility with klaytn < 1.5 which required 163 // these prefixes. 164 endpoint = endpoint[4:] 165 } 166 return rpc.Dial(endpoint) 167 }