github.com/phillinzzz/newBsc@v1.1.6/node/api.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser 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 // The go-ethereum library 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 Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package node 18 19 import ( 20 "context" 21 "fmt" 22 "strings" 23 24 "github.com/phillinzzz/newBsc/common/gopool" 25 "github.com/phillinzzz/newBsc/common/hexutil" 26 "github.com/phillinzzz/newBsc/crypto" 27 "github.com/phillinzzz/newBsc/internal/debug" 28 "github.com/phillinzzz/newBsc/log" 29 "github.com/phillinzzz/newBsc/p2p" 30 "github.com/phillinzzz/newBsc/p2p/enode" 31 "github.com/phillinzzz/newBsc/rpc" 32 ) 33 34 // apis returns the collection of built-in RPC APIs. 35 func (n *Node) apis() []rpc.API { 36 return []rpc.API{ 37 { 38 Namespace: "admin", 39 Version: "1.0", 40 Service: &privateAdminAPI{n}, 41 }, { 42 Namespace: "admin", 43 Version: "1.0", 44 Service: &publicAdminAPI{n}, 45 Public: true, 46 }, { 47 Namespace: "debug", 48 Version: "1.0", 49 Service: debug.Handler, 50 }, { 51 Namespace: "web3", 52 Version: "1.0", 53 Service: &publicWeb3API{n}, 54 Public: true, 55 }, 56 } 57 } 58 59 // privateAdminAPI is the collection of administrative API methods exposed only 60 // over a secure RPC channel. 61 type privateAdminAPI struct { 62 node *Node // Node interfaced by this API 63 } 64 65 // AddPeer requests connecting to a remote node, and also maintaining the new 66 // connection at all times, even reconnecting if it is lost. 67 func (api *privateAdminAPI) AddPeer(url string) (bool, error) { 68 // Make sure the server is running, fail otherwise 69 server := api.node.Server() 70 if server == nil { 71 return false, ErrNodeStopped 72 } 73 // Try to add the url as a static peer and return 74 node, err := enode.Parse(enode.ValidSchemes, url) 75 if err != nil { 76 return false, fmt.Errorf("invalid enode: %v", err) 77 } 78 server.AddPeer(node) 79 return true, nil 80 } 81 82 // RemovePeer disconnects from a remote node if the connection exists 83 func (api *privateAdminAPI) RemovePeer(url string) (bool, error) { 84 // Make sure the server is running, fail otherwise 85 server := api.node.Server() 86 if server == nil { 87 return false, ErrNodeStopped 88 } 89 // Try to remove the url as a static peer and return 90 node, err := enode.Parse(enode.ValidSchemes, url) 91 if err != nil { 92 return false, fmt.Errorf("invalid enode: %v", err) 93 } 94 server.RemovePeer(node) 95 return true, nil 96 } 97 98 // AddTrustedPeer allows a remote node to always connect, even if slots are full 99 func (api *privateAdminAPI) AddTrustedPeer(url string) (bool, error) { 100 // Make sure the server is running, fail otherwise 101 server := api.node.Server() 102 if server == nil { 103 return false, ErrNodeStopped 104 } 105 node, err := enode.Parse(enode.ValidSchemes, url) 106 if err != nil { 107 return false, fmt.Errorf("invalid enode: %v", err) 108 } 109 server.AddTrustedPeer(node) 110 return true, nil 111 } 112 113 // RemoveTrustedPeer removes a remote node from the trusted peer set, but it 114 // does not disconnect it automatically. 115 func (api *privateAdminAPI) RemoveTrustedPeer(url string) (bool, error) { 116 // Make sure the server is running, fail otherwise 117 server := api.node.Server() 118 if server == nil { 119 return false, ErrNodeStopped 120 } 121 node, err := enode.Parse(enode.ValidSchemes, url) 122 if err != nil { 123 return false, fmt.Errorf("invalid enode: %v", err) 124 } 125 server.RemoveTrustedPeer(node) 126 return true, nil 127 } 128 129 // PeerEvents creates an RPC subscription which receives peer events from the 130 // node's p2p.Server 131 func (api *privateAdminAPI) PeerEvents(ctx context.Context) (*rpc.Subscription, error) { 132 // Make sure the server is running, fail otherwise 133 server := api.node.Server() 134 if server == nil { 135 return nil, ErrNodeStopped 136 } 137 138 // Create the subscription 139 notifier, supported := rpc.NotifierFromContext(ctx) 140 if !supported { 141 return nil, rpc.ErrNotificationsUnsupported 142 } 143 rpcSub := notifier.CreateSubscription() 144 145 gopool.Submit(func() { 146 events := make(chan *p2p.PeerEvent) 147 sub := server.SubscribeEvents(events) 148 defer sub.Unsubscribe() 149 150 for { 151 select { 152 case event := <-events: 153 notifier.Notify(rpcSub.ID, event) 154 case <-sub.Err(): 155 return 156 case <-rpcSub.Err(): 157 return 158 case <-notifier.Closed(): 159 return 160 } 161 } 162 }) 163 164 return rpcSub, nil 165 } 166 167 // StartHTTP starts the HTTP RPC API server. 168 func (api *privateAdminAPI) StartHTTP(host *string, port *int, cors *string, apis *string, vhosts *string) (bool, error) { 169 api.node.lock.Lock() 170 defer api.node.lock.Unlock() 171 172 // Determine host and port. 173 if host == nil { 174 h := DefaultHTTPHost 175 if api.node.config.HTTPHost != "" { 176 h = api.node.config.HTTPHost 177 } 178 host = &h 179 } 180 if port == nil { 181 port = &api.node.config.HTTPPort 182 } 183 184 // Determine config. 185 config := httpConfig{ 186 CorsAllowedOrigins: api.node.config.HTTPCors, 187 Vhosts: api.node.config.HTTPVirtualHosts, 188 Modules: api.node.config.HTTPModules, 189 } 190 if cors != nil { 191 config.CorsAllowedOrigins = nil 192 for _, origin := range strings.Split(*cors, ",") { 193 config.CorsAllowedOrigins = append(config.CorsAllowedOrigins, strings.TrimSpace(origin)) 194 } 195 } 196 if vhosts != nil { 197 config.Vhosts = nil 198 for _, vhost := range strings.Split(*host, ",") { 199 config.Vhosts = append(config.Vhosts, strings.TrimSpace(vhost)) 200 } 201 } 202 if apis != nil { 203 config.Modules = nil 204 for _, m := range strings.Split(*apis, ",") { 205 config.Modules = append(config.Modules, strings.TrimSpace(m)) 206 } 207 } 208 209 if err := api.node.http.setListenAddr(*host, *port); err != nil { 210 return false, err 211 } 212 if err := api.node.http.enableRPC(api.node.rpcAPIs, config); err != nil { 213 return false, err 214 } 215 if err := api.node.http.start(); err != nil { 216 return false, err 217 } 218 return true, nil 219 } 220 221 // StartRPC starts the HTTP RPC API server. 222 // This method is deprecated. Use StartHTTP instead. 223 func (api *privateAdminAPI) StartRPC(host *string, port *int, cors *string, apis *string, vhosts *string) (bool, error) { 224 log.Warn("Deprecation warning", "method", "admin.StartRPC", "use-instead", "admin.StartHTTP") 225 return api.StartHTTP(host, port, cors, apis, vhosts) 226 } 227 228 // StopHTTP shuts down the HTTP server. 229 func (api *privateAdminAPI) StopHTTP() (bool, error) { 230 api.node.http.stop() 231 return true, nil 232 } 233 234 // StopRPC shuts down the HTTP server. 235 // This method is deprecated. Use StopHTTP instead. 236 func (api *privateAdminAPI) StopRPC() (bool, error) { 237 log.Warn("Deprecation warning", "method", "admin.StopRPC", "use-instead", "admin.StopHTTP") 238 return api.StopHTTP() 239 } 240 241 // StartWS starts the websocket RPC API server. 242 func (api *privateAdminAPI) StartWS(host *string, port *int, allowedOrigins *string, apis *string) (bool, error) { 243 api.node.lock.Lock() 244 defer api.node.lock.Unlock() 245 246 // Determine host and port. 247 if host == nil { 248 h := DefaultWSHost 249 if api.node.config.WSHost != "" { 250 h = api.node.config.WSHost 251 } 252 host = &h 253 } 254 if port == nil { 255 port = &api.node.config.WSPort 256 } 257 258 // Determine config. 259 config := wsConfig{ 260 Modules: api.node.config.WSModules, 261 Origins: api.node.config.WSOrigins, 262 // ExposeAll: api.node.config.WSExposeAll, 263 } 264 if apis != nil { 265 config.Modules = nil 266 for _, m := range strings.Split(*apis, ",") { 267 config.Modules = append(config.Modules, strings.TrimSpace(m)) 268 } 269 } 270 if allowedOrigins != nil { 271 config.Origins = nil 272 for _, origin := range strings.Split(*allowedOrigins, ",") { 273 config.Origins = append(config.Origins, strings.TrimSpace(origin)) 274 } 275 } 276 277 // Enable WebSocket on the server. 278 server := api.node.wsServerForPort(*port) 279 if err := server.setListenAddr(*host, *port); err != nil { 280 return false, err 281 } 282 if err := server.enableWS(api.node.rpcAPIs, config); err != nil { 283 return false, err 284 } 285 if err := server.start(); err != nil { 286 return false, err 287 } 288 api.node.http.log.Info("WebSocket endpoint opened", "url", api.node.WSEndpoint()) 289 return true, nil 290 } 291 292 // StopWS terminates all WebSocket servers. 293 func (api *privateAdminAPI) StopWS() (bool, error) { 294 api.node.http.stopWS() 295 api.node.ws.stop() 296 return true, nil 297 } 298 299 // publicAdminAPI is the collection of administrative API methods exposed over 300 // both secure and unsecure RPC channels. 301 type publicAdminAPI struct { 302 node *Node // Node interfaced by this API 303 } 304 305 // Peers retrieves all the information we know about each individual peer at the 306 // protocol granularity. 307 func (api *publicAdminAPI) Peers() ([]*p2p.PeerInfo, error) { 308 server := api.node.Server() 309 if server == nil { 310 return nil, ErrNodeStopped 311 } 312 return server.PeersInfo(), nil 313 } 314 315 // NodeInfo retrieves all the information we know about the host node at the 316 // protocol granularity. 317 func (api *publicAdminAPI) NodeInfo() (*p2p.NodeInfo, error) { 318 server := api.node.Server() 319 if server == nil { 320 return nil, ErrNodeStopped 321 } 322 return server.NodeInfo(), nil 323 } 324 325 // Datadir retrieves the current data directory the node is using. 326 func (api *publicAdminAPI) Datadir() string { 327 return api.node.DataDir() 328 } 329 330 // publicWeb3API offers helper utils 331 type publicWeb3API struct { 332 stack *Node 333 } 334 335 // ClientVersion returns the node name 336 func (s *publicWeb3API) ClientVersion() string { 337 return s.stack.Server().Name 338 } 339 340 // Sha3 applies the ethereum sha3 implementation on the input. 341 // It assumes the input is hex encoded. 342 func (s *publicWeb3API) Sha3(input hexutil.Bytes) hexutil.Bytes { 343 return crypto.Keccak256(input) 344 }