github.com/snowblossomcoin/go-ethereum@v1.9.25/cmd/geth/consolecmd.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 package main 18 19 import ( 20 "fmt" 21 "os" 22 "os/signal" 23 "path/filepath" 24 "strings" 25 "syscall" 26 27 "github.com/ethereum/go-ethereum/cmd/utils" 28 "github.com/ethereum/go-ethereum/console" 29 "github.com/ethereum/go-ethereum/node" 30 "github.com/ethereum/go-ethereum/rpc" 31 "gopkg.in/urfave/cli.v1" 32 ) 33 34 var ( 35 consoleFlags = []cli.Flag{utils.JSpathFlag, utils.ExecFlag, utils.PreloadJSFlag} 36 37 consoleCommand = cli.Command{ 38 Action: utils.MigrateFlags(localConsole), 39 Name: "console", 40 Usage: "Start an interactive JavaScript environment", 41 Flags: append(append(append(nodeFlags, rpcFlags...), consoleFlags...), whisperFlags...), 42 Category: "CONSOLE COMMANDS", 43 Description: ` 44 The Geth 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 } 48 49 attachCommand = cli.Command{ 50 Action: utils.MigrateFlags(remoteConsole), 51 Name: "attach", 52 Usage: "Start an interactive JavaScript environment (connect to node)", 53 ArgsUsage: "[endpoint]", 54 Flags: append(consoleFlags, utils.DataDirFlag), 55 Category: "CONSOLE COMMANDS", 56 Description: ` 57 The Geth console is an interactive shell for the JavaScript runtime environment 58 which exposes a node admin interface as well as the Ðapp JavaScript API. 59 See https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console. 60 This command allows to open a console on a running geth node.`, 61 } 62 63 javascriptCommand = cli.Command{ 64 Action: utils.MigrateFlags(ephemeralConsole), 65 Name: "js", 66 Usage: "Execute the specified JavaScript files", 67 ArgsUsage: "<jsfile> [jsfile...]", 68 Flags: append(nodeFlags, consoleFlags...), 69 Category: "CONSOLE COMMANDS", 70 Description: ` 71 The JavaScript VM exposes a node admin interface as well as the Ðapp 72 JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console`, 73 } 74 ) 75 76 // localConsole starts a new geth node, attaching a JavaScript console to it at the 77 // same time. 78 func localConsole(ctx *cli.Context) error { 79 // Create and start the node based on the CLI flags 80 prepare(ctx) 81 stack, backend := makeFullNode(ctx) 82 startNode(ctx, stack, backend) 83 defer stack.Close() 84 85 // Attach to the newly started node and start the JavaScript console 86 client, err := stack.Attach() 87 if err != nil { 88 utils.Fatalf("Failed to attach to the inproc geth: %v", err) 89 } 90 config := console.Config{ 91 DataDir: utils.MakeDataDir(ctx), 92 DocRoot: ctx.GlobalString(utils.JSpathFlag.Name), 93 Client: client, 94 Preload: utils.MakeConsolePreloads(ctx), 95 } 96 97 console, err := console.New(config) 98 if err != nil { 99 utils.Fatalf("Failed to start the JavaScript console: %v", err) 100 } 101 defer console.Stop(false) 102 103 // If only a short execution was requested, evaluate and return 104 if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" { 105 console.Evaluate(script) 106 return nil 107 } 108 // Otherwise print the welcome screen and enter interactive mode 109 console.Welcome() 110 console.Interactive() 111 112 return nil 113 } 114 115 // remoteConsole will connect to a remote geth instance, attaching a JavaScript 116 // console to it. 117 func remoteConsole(ctx *cli.Context) error { 118 // Attach to a remotely running geth instance and start the JavaScript console 119 endpoint := ctx.Args().First() 120 if endpoint == "" { 121 path := node.DefaultDataDir() 122 if ctx.GlobalIsSet(utils.DataDirFlag.Name) { 123 path = ctx.GlobalString(utils.DataDirFlag.Name) 124 } 125 if path != "" { 126 if ctx.GlobalBool(utils.LegacyTestnetFlag.Name) || ctx.GlobalBool(utils.RopstenFlag.Name) { 127 // Maintain compatibility with older Geth configurations storing the 128 // Ropsten database in `testnet` instead of `ropsten`. 129 legacyPath := filepath.Join(path, "testnet") 130 if _, err := os.Stat(legacyPath); !os.IsNotExist(err) { 131 path = legacyPath 132 } else { 133 path = filepath.Join(path, "ropsten") 134 } 135 } else if ctx.GlobalBool(utils.RinkebyFlag.Name) { 136 path = filepath.Join(path, "rinkeby") 137 } else if ctx.GlobalBool(utils.GoerliFlag.Name) { 138 path = filepath.Join(path, "goerli") 139 } else if ctx.GlobalBool(utils.YoloV2Flag.Name) { 140 path = filepath.Join(path, "yolo-v2") 141 } 142 } 143 endpoint = fmt.Sprintf("%s/geth.ipc", path) 144 } 145 client, err := dialRPC(endpoint) 146 if err != nil { 147 utils.Fatalf("Unable to attach to remote geth: %v", err) 148 } 149 config := console.Config{ 150 DataDir: utils.MakeDataDir(ctx), 151 DocRoot: ctx.GlobalString(utils.JSpathFlag.Name), 152 Client: client, 153 Preload: utils.MakeConsolePreloads(ctx), 154 } 155 156 console, err := console.New(config) 157 if err != nil { 158 utils.Fatalf("Failed to start the JavaScript console: %v", err) 159 } 160 defer console.Stop(false) 161 162 if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" { 163 console.Evaluate(script) 164 return nil 165 } 166 167 // Otherwise print the welcome screen and enter interactive mode 168 console.Welcome() 169 console.Interactive() 170 171 return nil 172 } 173 174 // dialRPC returns a RPC client which connects to the given endpoint. 175 // The check for empty endpoint implements the defaulting logic 176 // for "geth attach" and "geth monitor" with no argument. 177 func dialRPC(endpoint string) (*rpc.Client, error) { 178 if endpoint == "" { 179 endpoint = node.DefaultIPCEndpoint(clientIdentifier) 180 } else if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") { 181 // Backwards compatibility with geth < 1.5 which required 182 // these prefixes. 183 endpoint = endpoint[4:] 184 } 185 return rpc.Dial(endpoint) 186 } 187 188 // ephemeralConsole starts a new geth node, attaches an ephemeral JavaScript 189 // console to it, executes each of the files specified as arguments and tears 190 // everything down. 191 func ephemeralConsole(ctx *cli.Context) error { 192 // Create and start the node based on the CLI flags 193 stack, backend := makeFullNode(ctx) 194 startNode(ctx, stack, backend) 195 defer stack.Close() 196 197 // Attach to the newly started node and start the JavaScript console 198 client, err := stack.Attach() 199 if err != nil { 200 utils.Fatalf("Failed to attach to the inproc geth: %v", err) 201 } 202 config := console.Config{ 203 DataDir: utils.MakeDataDir(ctx), 204 DocRoot: ctx.GlobalString(utils.JSpathFlag.Name), 205 Client: client, 206 Preload: utils.MakeConsolePreloads(ctx), 207 } 208 209 console, err := console.New(config) 210 if err != nil { 211 utils.Fatalf("Failed to start the JavaScript console: %v", err) 212 } 213 defer console.Stop(false) 214 215 // Evaluate each of the specified JavaScript files 216 for _, file := range ctx.Args() { 217 if err = console.Execute(file); err != nil { 218 utils.Fatalf("Failed to execute %s: %v", file, err) 219 } 220 } 221 // Wait for pending callbacks, but stop for Ctrl-C. 222 abort := make(chan os.Signal, 1) 223 signal.Notify(abort, syscall.SIGINT, syscall.SIGTERM) 224 225 go func() { 226 <-abort 227 os.Exit(0) 228 }() 229 console.Stop(true) 230 231 return nil 232 }