github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/mobile/geth.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 // Contains all the wrappers from the node package to support client side node 13 // management on mobile platforms. 14 15 package geth 16 17 import ( 18 "encoding/json" 19 "fmt" 20 "path/filepath" 21 22 "github.com/Sberex/go-sberex/core" 23 "github.com/Sberex/go-sberex/eth" 24 "github.com/Sberex/go-sberex/eth/downloader" 25 "github.com/Sberex/go-sberex/ethclient" 26 "github.com/Sberex/go-sberex/ethstats" 27 "github.com/Sberex/go-sberex/les" 28 "github.com/Sberex/go-sberex/node" 29 "github.com/Sberex/go-sberex/p2p" 30 "github.com/Sberex/go-sberex/p2p/nat" 31 "github.com/Sberex/go-sberex/params" 32 whisper "github.com/Sberex/go-sberex/whisper/whisperv5" 33 ) 34 35 // NodeConfig represents the collection of configuration values to fine tune the Geth 36 // node embedded into a mobile process. The available values are a subset of the 37 // entire API provided by go-sberex to reduce the maintenance surface and dev 38 // complexity. 39 type NodeConfig struct { 40 // Bootstrap nodes used to establish connectivity with the rest of the network. 41 BootstrapNodes *Enodes 42 43 // MaxPeers is the maximum number of peers that can be connected. If this is 44 // set to zero, then only the configured static and trusted peers can connect. 45 MaxPeers int 46 47 // SberexEnabled specifies whether the node should run the Sberex protocol. 48 SberexEnabled bool 49 50 // SberexNetworkID is the network identifier used by the Sberex protocol to 51 // decide if remote peers should be accepted or not. 52 SberexNetworkID int64 // uint64 in truth, but Java can't handle that... 53 54 // SberexGenesis is the genesis JSON to use to seed the blockchain with. An 55 // empty genesis state is equivalent to using the mainnet's state. 56 SberexGenesis string 57 58 // SberexDatabaseCache is the system memory in MB to allocate for database caching. 59 // A minimum of 16MB is always reserved. 60 SberexDatabaseCache int 61 62 // SberexNetStats is a netstats connection string to use to report various 63 // chain, transaction and node stats to a monitoring server. 64 // 65 // It has the form "nodename:secret@host:port" 66 SberexNetStats string 67 68 // WhisperEnabled specifies whether the node should run the Whisper protocol. 69 WhisperEnabled bool 70 } 71 72 // defaultNodeConfig contains the default node configuration values to use if all 73 // or some fields are missing from the user's specified list. 74 var defaultNodeConfig = &NodeConfig{ 75 BootstrapNodes: FoundationBootnodes(), 76 MaxPeers: 25, 77 SberexEnabled: true, 78 SberexNetworkID: 1, 79 SberexDatabaseCache: 16, 80 } 81 82 // NewNodeConfig creates a new node option set, initialized to the default values. 83 func NewNodeConfig() *NodeConfig { 84 config := *defaultNodeConfig 85 return &config 86 } 87 88 // Node represents a Geth Sberex node instance. 89 type Node struct { 90 node *node.Node 91 } 92 93 // NewNode creates and configures a new Geth node. 94 func NewNode(datadir string, config *NodeConfig) (stack *Node, _ error) { 95 // If no or partial configurations were specified, use defaults 96 if config == nil { 97 config = NewNodeConfig() 98 } 99 if config.MaxPeers == 0 { 100 config.MaxPeers = defaultNodeConfig.MaxPeers 101 } 102 if config.BootstrapNodes == nil || config.BootstrapNodes.Size() == 0 { 103 config.BootstrapNodes = defaultNodeConfig.BootstrapNodes 104 } 105 // Create the empty networking stack 106 nodeConf := &node.Config{ 107 Name: clientIdentifier, 108 Version: params.Version, 109 DataDir: datadir, 110 KeyStoreDir: filepath.Join(datadir, "keystore"), // Mobile should never use internal keystores! 111 P2P: p2p.Config{ 112 NoDiscovery: true, 113 DiscoveryV5: true, 114 BootstrapNodesV5: config.BootstrapNodes.nodes, 115 ListenAddr: ":0", 116 NAT: nat.Any(), 117 MaxPeers: config.MaxPeers, 118 }, 119 } 120 rawStack, err := node.New(nodeConf) 121 if err != nil { 122 return nil, err 123 } 124 125 var genesis *core.Genesis 126 if config.SberexGenesis != "" { 127 // Parse the user supplied genesis spec if not mainnet 128 genesis = new(core.Genesis) 129 if err := json.Unmarshal([]byte(config.SberexGenesis), genesis); err != nil { 130 return nil, fmt.Errorf("invalid genesis spec: %v", err) 131 } 132 // If we have the testnet, hard code the chain configs too 133 if config.SberexGenesis == TestnetGenesis() { 134 genesis.Config = params.TestnetChainConfig 135 if config.SberexNetworkID == 1 { 136 config.SberexNetworkID = 3 137 } 138 } 139 } 140 // Register the Sberex protocol if requested 141 if config.SberexEnabled { 142 ethConf := eth.DefaultConfig 143 ethConf.Genesis = genesis 144 ethConf.SyncMode = downloader.LightSync 145 ethConf.NetworkId = uint64(config.SberexNetworkID) 146 ethConf.DatabaseCache = config.SberexDatabaseCache 147 if err := rawStack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 148 return les.New(ctx, ðConf) 149 }); err != nil { 150 return nil, fmt.Errorf("sberex init: %v", err) 151 } 152 // If netstats reporting is requested, do it 153 if config.SberexNetStats != "" { 154 if err := rawStack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 155 var lesServ *les.LightSberex 156 ctx.Service(&lesServ) 157 158 return ethstats.New(config.SberexNetStats, nil, lesServ) 159 }); err != nil { 160 return nil, fmt.Errorf("netstats init: %v", err) 161 } 162 } 163 } 164 // Register the Whisper protocol if requested 165 if config.WhisperEnabled { 166 if err := rawStack.Register(func(*node.ServiceContext) (node.Service, error) { 167 return whisper.New(&whisper.DefaultConfig), nil 168 }); err != nil { 169 return nil, fmt.Errorf("whisper init: %v", err) 170 } 171 } 172 return &Node{rawStack}, nil 173 } 174 175 // Start creates a live P2P node and starts running it. 176 func (n *Node) Start() error { 177 return n.node.Start() 178 } 179 180 // Stop terminates a running node along with all it's services. In the node was 181 // not started, an error is returned. 182 func (n *Node) Stop() error { 183 return n.node.Stop() 184 } 185 186 // GetSberexClient retrieves a client to access the Sberex subsystem. 187 func (n *Node) GetSberexClient() (client *SberexClient, _ error) { 188 rpc, err := n.node.Attach() 189 if err != nil { 190 return nil, err 191 } 192 return &SberexClient{ethclient.NewClient(rpc)}, nil 193 } 194 195 // GetNodeInfo gathers and returns a collection of metadata known about the host. 196 func (n *Node) GetNodeInfo() *NodeInfo { 197 return &NodeInfo{n.node.Server().NodeInfo()} 198 } 199 200 // GetPeersInfo returns an array of metadata objects describing connected peers. 201 func (n *Node) GetPeersInfo() *PeerInfos { 202 return &PeerInfos{n.node.Server().PeersInfo()} 203 }