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