github.com/palisadeinc/bor@v0.0.0-20230615125219-ab7196213d15/internal/cli/attach.go (about) 1 package cli 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "strings" 8 9 "github.com/ethereum/go-ethereum/cmd/utils" 10 "github.com/ethereum/go-ethereum/console" 11 "github.com/ethereum/go-ethereum/internal/cli/flagset" 12 "github.com/ethereum/go-ethereum/node" 13 "github.com/ethereum/go-ethereum/rpc" 14 15 "github.com/mitchellh/cli" 16 ) 17 18 // AttachCommand is the command to Connect to remote Bor IPC console 19 type AttachCommand struct { 20 UI cli.Ui 21 Meta *Meta 22 Meta2 *Meta2 23 ExecCMD string 24 Endpoint string 25 PreloadJSFlag string 26 JSpathFlag string 27 } 28 29 // MarkDown implements cli.MarkDown interface 30 func (c *AttachCommand) MarkDown() string { 31 items := []string{ 32 "# Attach", 33 "Connect to remote Bor IPC console.", 34 c.Flags().MarkDown(), 35 } 36 37 return strings.Join(items, "\n\n") 38 } 39 40 // Help implements the cli.Command interface 41 func (c *AttachCommand) Help() string { 42 return `Usage: bor attach <IPC FILE> 43 44 Connect to remote Bor IPC console.` 45 } 46 47 // Synopsis implements the cli.Command interface 48 func (c *AttachCommand) Synopsis() string { 49 return "Connect to Bor via IPC" 50 } 51 52 func (c *AttachCommand) Flags() *flagset.Flagset { 53 f := flagset.NewFlagSet("attach") 54 55 f.StringFlag(&flagset.StringFlag{ 56 Name: "exec", 57 Usage: "Command to run in remote console", 58 Value: &c.ExecCMD, 59 }) 60 61 f.StringFlag(&flagset.StringFlag{ 62 Name: "preload", 63 Usage: "Comma separated list of JavaScript files to preload into the console", 64 Value: &c.PreloadJSFlag, 65 }) 66 67 f.StringFlag(&flagset.StringFlag{ 68 Name: "jspath", 69 Usage: "JavaScript root path for `loadScript`", 70 Value: &c.JSpathFlag, 71 }) 72 73 return f 74 } 75 76 // Run implements the cli.Command interface 77 func (c *AttachCommand) Run(args []string) int { 78 flags := c.Flags() 79 80 //check if first arg is flag or IPC location 81 if len(args) == 0 { 82 args = append(args, "") 83 } 84 85 if args[0] != "" && strings.HasPrefix(args[0], "--") { 86 if err := flags.Parse(args); err != nil { 87 c.UI.Error(err.Error()) 88 return 1 89 } 90 } else { 91 c.Endpoint = args[0] 92 if err := flags.Parse(args[1:]); err != nil { 93 c.UI.Error(err.Error()) 94 return 1 95 } 96 } 97 98 if err := c.remoteConsole(); err != nil { 99 c.UI.Error(err.Error()) 100 return 1 101 } 102 103 return 0 104 } 105 106 // remoteConsole will connect to a remote bor instance, attaching a JavaScript 107 // console to it. 108 // nolint: unparam 109 func (c *AttachCommand) remoteConsole() error { 110 // Attach to a remotely running geth instance and start the JavaScript console 111 path := node.DefaultDataDir() 112 113 if c.Endpoint == "" { 114 if c.Meta.dataDir != "" { 115 path = c.Meta.dataDir 116 } 117 118 if path != "" { 119 homeDir, _ := os.UserHomeDir() 120 path = filepath.Join(homeDir, "/.bor/data") 121 } 122 123 c.Endpoint = fmt.Sprintf("%s/bor.ipc", path) 124 } 125 126 client, err := dialRPC(c.Endpoint) 127 128 if err != nil { 129 utils.Fatalf("Unable to attach to remote bor: %v", err) 130 } 131 132 config := console.Config{ 133 DataDir: path, 134 DocRoot: c.JSpathFlag, 135 Client: client, 136 Preload: c.makeConsolePreloads(), 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 144 defer func() { 145 if err := console.Stop(false); err != nil { 146 c.UI.Error(err.Error()) 147 } 148 }() 149 150 if c.ExecCMD != "" { 151 console.Evaluate(c.ExecCMD) 152 return nil 153 } 154 155 // Otherwise print the welcome screen and enter interactive mode 156 console.Welcome() 157 console.Interactive() 158 159 return nil 160 } 161 162 // dialRPC returns a RPC client which connects to the given endpoint. 163 // The check for empty endpoint implements the defaulting logic 164 // for "geth attach" with no argument. 165 func dialRPC(endpoint string) (*rpc.Client, error) { 166 if endpoint == "" { 167 endpoint = node.DefaultIPCEndpoint("bor") 168 } else if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") { 169 // Backwards compatibility with geth < 1.5 which required 170 // these prefixes. 171 endpoint = endpoint[4:] 172 } 173 174 return rpc.Dial(endpoint) 175 } 176 177 // MakeConsolePreloads retrieves the absolute paths for the console JavaScript 178 // scripts to preload before starting. 179 func (c *AttachCommand) makeConsolePreloads() []string { 180 // Skip preloading if there's nothing to preload 181 if c.PreloadJSFlag == "" { 182 return nil 183 } 184 // Otherwise resolve absolute paths and return them 185 splitFlags := strings.Split(c.PreloadJSFlag, ",") 186 preloads := make([]string, 0, len(splitFlags)) 187 188 for _, file := range splitFlags { 189 preloads = append(preloads, strings.TrimSpace(file)) 190 } 191 192 return preloads 193 }