| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | // Copyright 2016 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of the go-ethereum library. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							|  |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Contains all the wrappers from the node package to support client side node | 
					
						
							|  |  |  | // management on mobile platforms. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package geth | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	"encoding/json" | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"path/filepath" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core" | 
					
						
							| 
									
										
										
										
											2017-04-12 16:27:23 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/eth/downloader" | 
					
						
							| 
									
										
										
										
											2021-02-05 20:51:15 +08:00
										 |  |  | 	"github.com/ethereum/go-ethereum/eth/ethconfig" | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/ethclient" | 
					
						
							| 
									
										
										
										
											2016-11-25 17:55:06 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/ethstats" | 
					
						
							| 
									
										
										
										
											2018-04-23 15:20:39 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/internal/debug" | 
					
						
							| 
									
										
										
										
											2016-11-09 16:19:19 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/les" | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/node" | 
					
						
							| 
									
										
										
										
											2017-04-12 16:27:23 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/p2p" | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/p2p/nat" | 
					
						
							| 
									
										
										
										
											2016-11-14 13:03:29 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/params" | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NodeConfig represents the collection of configuration values to fine tune the Geth | 
					
						
							|  |  |  | // node embedded into a mobile process. The available values are a subset of the | 
					
						
							|  |  |  | // entire API provided by go-ethereum to reduce the maintenance surface and dev | 
					
						
							|  |  |  | // complexity. | 
					
						
							|  |  |  | type NodeConfig struct { | 
					
						
							|  |  |  | 	// Bootstrap nodes used to establish connectivity with the rest of the network. | 
					
						
							|  |  |  | 	BootstrapNodes *Enodes | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// MaxPeers is the maximum number of peers that can be connected. If this is | 
					
						
							|  |  |  | 	// set to zero, then only the configured static and trusted peers can connect. | 
					
						
							|  |  |  | 	MaxPeers int | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// EthereumEnabled specifies whether the node should run the Ethereum protocol. | 
					
						
							|  |  |  | 	EthereumEnabled bool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// EthereumNetworkID is the network identifier used by the Ethereum protocol to | 
					
						
							|  |  |  | 	// decide if remote peers should be accepted or not. | 
					
						
							| 
									
										
										
										
											2017-04-25 14:31:15 +03:00
										 |  |  | 	EthereumNetworkID int64 // uint64 in truth, but Java can't handle that... | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// EthereumGenesis is the genesis JSON to use to seed the blockchain with. An | 
					
						
							|  |  |  | 	// empty genesis state is equivalent to using the mainnet's state. | 
					
						
							|  |  |  | 	EthereumGenesis string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// EthereumDatabaseCache is the system memory in MB to allocate for database caching. | 
					
						
							|  |  |  | 	// A minimum of 16MB is always reserved. | 
					
						
							|  |  |  | 	EthereumDatabaseCache int | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-25 17:55:06 +02:00
										 |  |  | 	// EthereumNetStats is a netstats connection string to use to report various | 
					
						
							|  |  |  | 	// chain, transaction and node stats to a monitoring server. | 
					
						
							|  |  |  | 	// | 
					
						
							|  |  |  | 	// It has the form "nodename:secret@host:port" | 
					
						
							|  |  |  | 	EthereumNetStats string | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-23 15:20:39 +02:00
										 |  |  | 	// Listening address of pprof server. | 
					
						
							|  |  |  | 	PprofAddress string | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // defaultNodeConfig contains the default node configuration values to use if all | 
					
						
							|  |  |  | // or some fields are missing from the user's specified list. | 
					
						
							|  |  |  | var defaultNodeConfig = &NodeConfig{ | 
					
						
							| 
									
										
										
										
											2016-11-09 16:35:04 +02:00
										 |  |  | 	BootstrapNodes:        FoundationBootnodes(), | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | 	MaxPeers:              25, | 
					
						
							|  |  |  | 	EthereumEnabled:       true, | 
					
						
							|  |  |  | 	EthereumNetworkID:     1, | 
					
						
							|  |  |  | 	EthereumDatabaseCache: 16, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewNodeConfig creates a new node option set, initialized to the default values. | 
					
						
							|  |  |  | func NewNodeConfig() *NodeConfig { | 
					
						
							|  |  |  | 	config := *defaultNodeConfig | 
					
						
							|  |  |  | 	return &config | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-21 16:33:35 +02:00
										 |  |  | // AddBootstrapNode adds an additional bootstrap node to the node config. | 
					
						
							|  |  |  | func (conf *NodeConfig) AddBootstrapNode(node *Enode) { | 
					
						
							|  |  |  | 	conf.BootstrapNodes.Append(node) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // EncodeJSON encodes a NodeConfig into a JSON data dump. | 
					
						
							|  |  |  | func (conf *NodeConfig) EncodeJSON() (string, error) { | 
					
						
							|  |  |  | 	data, err := json.Marshal(conf) | 
					
						
							|  |  |  | 	return string(data), err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // String returns a printable representation of the node config. | 
					
						
							|  |  |  | func (conf *NodeConfig) String() string { | 
					
						
							|  |  |  | 	return encodeOrError(conf) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | // Node represents a Geth Ethereum node instance. | 
					
						
							|  |  |  | type Node struct { | 
					
						
							|  |  |  | 	node *node.Node | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewNode creates and configures a new Geth node. | 
					
						
							| 
									
										
										
										
											2016-12-08 14:09:26 +02:00
										 |  |  | func NewNode(datadir string, config *NodeConfig) (stack *Node, _ error) { | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | 	// If no or partial configurations were specified, use defaults | 
					
						
							|  |  |  | 	if config == nil { | 
					
						
							|  |  |  | 		config = NewNodeConfig() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if config.MaxPeers == 0 { | 
					
						
							|  |  |  | 		config.MaxPeers = defaultNodeConfig.MaxPeers | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-11-09 16:35:04 +02:00
										 |  |  | 	if config.BootstrapNodes == nil || config.BootstrapNodes.Size() == 0 { | 
					
						
							|  |  |  | 		config.BootstrapNodes = defaultNodeConfig.BootstrapNodes | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-04-23 15:20:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if config.PprofAddress != "" { | 
					
						
							| 
									
										
										
										
											2020-07-03 12:12:22 -05:00
										 |  |  | 		debug.StartPProf(config.PprofAddress, true) | 
					
						
							| 
									
										
										
										
											2018-04-23 15:20:39 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | 	// Create the empty networking stack | 
					
						
							|  |  |  | 	nodeConf := &node.Config{ | 
					
						
							| 
									
										
										
										
											2017-04-12 16:27:23 +02:00
										 |  |  | 		Name:        clientIdentifier, | 
					
						
							| 
									
										
										
										
											2018-07-30 10:56:40 +02:00
										 |  |  | 		Version:     params.VersionWithMeta, | 
					
						
							| 
									
										
										
										
											2017-04-12 16:27:23 +02:00
										 |  |  | 		DataDir:     datadir, | 
					
						
							|  |  |  | 		KeyStoreDir: filepath.Join(datadir, "keystore"), // Mobile should never use internal keystores! | 
					
						
							|  |  |  | 		P2P: p2p.Config{ | 
					
						
							|  |  |  | 			NoDiscovery:      true, | 
					
						
							|  |  |  | 			DiscoveryV5:      true, | 
					
						
							|  |  |  | 			BootstrapNodesV5: config.BootstrapNodes.nodes, | 
					
						
							|  |  |  | 			ListenAddr:       ":0", | 
					
						
							|  |  |  | 			NAT:              nat.Any(), | 
					
						
							|  |  |  | 			MaxPeers:         config.MaxPeers, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-01-24 14:18:26 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-08 14:09:26 +02:00
										 |  |  | 	rawStack, err := node.New(nodeConf) | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-23 15:20:39 +02:00
										 |  |  | 	debug.Memsize.Add("node", rawStack) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	var genesis *core.Genesis | 
					
						
							|  |  |  | 	if config.EthereumGenesis != "" { | 
					
						
							| 
									
										
										
										
											2017-04-10 13:24:12 +03:00
										 |  |  | 		// Parse the user supplied genesis spec if not mainnet | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 		genesis = new(core.Genesis) | 
					
						
							|  |  |  | 		if err := json.Unmarshal([]byte(config.EthereumGenesis), genesis); err != nil { | 
					
						
							| 
									
										
										
										
											2017-04-10 13:24:12 +03:00
										 |  |  | 			return nil, fmt.Errorf("invalid genesis spec: %v", err) | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-04-09 11:09:58 +02:00
										 |  |  | 		// If we have the Ropsten testnet, hard code the chain configs too | 
					
						
							|  |  |  | 		if config.EthereumGenesis == RopstenGenesis() { | 
					
						
							|  |  |  | 			genesis.Config = params.RopstenChainConfig | 
					
						
							| 
									
										
										
										
											2017-04-10 13:24:12 +03:00
										 |  |  | 			if config.EthereumNetworkID == 1 { | 
					
						
							|  |  |  | 				config.EthereumNetworkID = 3 | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-11-08 12:06:01 +01:00
										 |  |  | 		// If we have the Sepolia testnet, hard code the chain configs too | 
					
						
							|  |  |  | 		if config.EthereumGenesis == SepoliaGenesis() { | 
					
						
							|  |  |  | 			genesis.Config = params.SepoliaChainConfig | 
					
						
							|  |  |  | 			if config.EthereumNetworkID == 1 { | 
					
						
							|  |  |  | 				config.EthereumNetworkID = 11155111 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-04-09 11:09:58 +02:00
										 |  |  | 		// If we have the Rinkeby testnet, hard code the chain configs too | 
					
						
							|  |  |  | 		if config.EthereumGenesis == RinkebyGenesis() { | 
					
						
							|  |  |  | 			genesis.Config = params.RinkebyChainConfig | 
					
						
							|  |  |  | 			if config.EthereumNetworkID == 1 { | 
					
						
							|  |  |  | 				config.EthereumNetworkID = 4 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// If we have the Goerli testnet, hard code the chain configs too | 
					
						
							|  |  |  | 		if config.EthereumGenesis == GoerliGenesis() { | 
					
						
							|  |  |  | 			genesis.Config = params.GoerliChainConfig | 
					
						
							|  |  |  | 			if config.EthereumNetworkID == 1 { | 
					
						
							|  |  |  | 				config.EthereumNetworkID = 5 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | 	// Register the Ethereum protocol if requested | 
					
						
							|  |  |  | 	if config.EthereumEnabled { | 
					
						
							| 
									
										
										
										
											2021-02-05 20:51:15 +08:00
										 |  |  | 		ethConf := ethconfig.Defaults | 
					
						
							| 
									
										
										
										
											2017-04-12 16:27:23 +02:00
										 |  |  | 		ethConf.Genesis = genesis | 
					
						
							|  |  |  | 		ethConf.SyncMode = downloader.LightSync | 
					
						
							| 
									
										
										
										
											2017-04-25 14:31:15 +03:00
										 |  |  | 		ethConf.NetworkId = uint64(config.EthereumNetworkID) | 
					
						
							| 
									
										
										
										
											2017-04-12 16:27:23 +02:00
										 |  |  | 		ethConf.DatabaseCache = config.EthereumDatabaseCache | 
					
						
							| 
									
										
										
										
											2020-08-03 19:40:46 +02:00
										 |  |  | 		lesBackend, err := les.New(rawStack, ðConf) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | 			return nil, fmt.Errorf("ethereum init: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-11-25 17:55:06 +02:00
										 |  |  | 		// If netstats reporting is requested, do it | 
					
						
							|  |  |  | 		if config.EthereumNetStats != "" { | 
					
						
							| 
									
										
										
										
											2020-08-03 19:40:46 +02:00
										 |  |  | 			if err := ethstats.New(rawStack, lesBackend.ApiBackend, lesBackend.Engine(), config.EthereumNetStats); err != nil { | 
					
						
							| 
									
										
										
										
											2016-11-25 17:55:06 +02:00
										 |  |  | 				return nil, fmt.Errorf("netstats init: %v", err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-08 14:09:26 +02:00
										 |  |  | 	return &Node{rawStack}, nil | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-03 19:40:46 +02:00
										 |  |  | // Close terminates a running node along with all it's services, tearing internal state | 
					
						
							|  |  |  | // down. It is not possible to restart a closed node. | 
					
						
							| 
									
										
										
										
											2019-02-07 11:40:36 +01:00
										 |  |  | func (n *Node) Close() error { | 
					
						
							|  |  |  | 	return n.node.Close() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | // Start creates a live P2P node and starts running it. | 
					
						
							|  |  |  | func (n *Node) Start() error { | 
					
						
							| 
									
										
										
										
											2020-08-03 19:40:46 +02:00
										 |  |  | 	// TODO: recreate the node so it can be started multiple times | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | 	return n.node.Start() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-03 19:40:46 +02:00
										 |  |  | // Stop terminates a running node along with all its services. If the node was not started, | 
					
						
							|  |  |  | // an error is returned. It is not possible to restart a stopped node. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Deprecated: use Close() | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | func (n *Node) Stop() error { | 
					
						
							| 
									
										
										
										
											2020-08-03 19:40:46 +02:00
										 |  |  | 	return n.node.Close() | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetEthereumClient retrieves a client to access the Ethereum subsystem. | 
					
						
							| 
									
										
										
										
											2016-12-08 14:09:26 +02:00
										 |  |  | func (n *Node) GetEthereumClient() (client *EthereumClient, _ error) { | 
					
						
							| 
									
										
										
										
											2016-09-05 19:07:57 +03:00
										 |  |  | 	rpc, err := n.node.Attach() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return &EthereumClient{ethclient.NewClient(rpc)}, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetNodeInfo gathers and returns a collection of metadata known about the host. | 
					
						
							|  |  |  | func (n *Node) GetNodeInfo() *NodeInfo { | 
					
						
							|  |  |  | 	return &NodeInfo{n.node.Server().NodeInfo()} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetPeersInfo returns an array of metadata objects describing connected peers. | 
					
						
							|  |  |  | func (n *Node) GetPeersInfo() *PeerInfos { | 
					
						
							|  |  |  | 	return &PeerInfos{n.node.Server().PeersInfo()} | 
					
						
							|  |  |  | } |