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