aboutsummaryrefslogblamecommitdiffstats
path: root/mobile/geth.go
blob: 4d1f48ec3d695f09fea40f8f9aeaa05a316a8e88 (plain) (tree)

























                                                                                  




                                                    

                                               

                                                 
                                                           











































                                                                                             
                                                     


                                    
                                                    






















                                                                                  


                                                                              

                                            









                                                                                                                    








                                                       




                                                                                                                          

                                                                        
                                                      











                                                                                                   
                                                                

                                                                                               
                                                    





                                                                        
                                                                                                                                        


































                                                                                 
// 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 (
    "fmt"
    "math/big"
    "path/filepath"

    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/core"
    "github.com/ethereum/go-ethereum/core/state"
    "github.com/ethereum/go-ethereum/eth"
    "github.com/ethereum/go-ethereum/ethclient"
    "github.com/ethereum/go-ethereum/les"
    "github.com/ethereum/go-ethereum/light"
    "github.com/ethereum/go-ethereum/node"
    "github.com/ethereum/go-ethereum/p2p/nat"
    "github.com/ethereum/go-ethereum/whisper/whisperv2"
)

// 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.
    EthereumNetworkID int

    // EthereumChainConfig is the default parameters of the blockchain to use. If no
    // configuration is specified, it defaults to the main network.
    EthereumChainConfig *ChainConfig

    // 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

    // EthereumTestnetNonces specifies whether to use account nonces from the testnet
    // range (2^20) or from the mainnet one (0).
    EthereumTestnetNonces bool

    // EthereumDatabaseCache is the system memory in MB to allocate for database caching.
    // A minimum of 16MB is always reserved.
    EthereumDatabaseCache int

    // WhisperEnabled specifies whether the node should run the Whisper protocol.
    WhisperEnabled bool
}

// 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{
    BootstrapNodes:        FoundationBootnodes(),
    MaxPeers:              25,
    EthereumEnabled:       true,
    EthereumNetworkID:     1,
    EthereumChainConfig:   MainnetChainConfig(),
    EthereumDatabaseCache: 16,
}

// NewNodeConfig creates a new node option set, initialized to the default values.
func NewNodeConfig() *NodeConfig {
    config := *defaultNodeConfig
    return &config
}

// Node represents a Geth Ethereum node instance.
type Node struct {
    node *node.Node
}

// NewNode creates and configures a new Geth node.
func NewNode(datadir string, config *NodeConfig) (*Node, error) {
    // If no or partial configurations were specified, use defaults
    if config == nil {
        config = NewNodeConfig()
    }
    if config.MaxPeers == 0 {
        config.MaxPeers = defaultNodeConfig.MaxPeers
    }
    if config.BootstrapNodes == nil || config.BootstrapNodes.Size() == 0 {
        config.BootstrapNodes = defaultNodeConfig.BootstrapNodes
    }
    // Create the empty networking stack
    nodeConf := &node.Config{
        Name:             clientIdentifier,
        DataDir:          datadir,
        KeyStoreDir:      filepath.Join(datadir, "keystore"), // Mobile should never use internal keystores!
        NoDiscovery:      true,
        DiscoveryV5:      true,
        DiscoveryV5Addr:  ":0",
        BootstrapNodesV5: config.BootstrapNodes.nodes,
        ListenAddr:       ":0",
        NAT:              nat.Any(),
        MaxPeers:         config.MaxPeers,
    }
    stack, err := node.New(nodeConf)
    if err != nil {
        return nil, err
    }
    // Register the Ethereum protocol if requested
    if config.EthereumEnabled {
        ethConf := &eth.Config{
            ChainConfig: &core.ChainConfig{
                HomesteadBlock:           big.NewInt(config.EthereumChainConfig.HomesteadBlock),
                DAOForkBlock:             big.NewInt(config.EthereumChainConfig.DAOForkBlock),
                DAOForkSupport:           config.EthereumChainConfig.DAOForkSupport,
                HomesteadGasRepriceBlock: big.NewInt(config.EthereumChainConfig.HomesteadGasRepriceBlock),
                HomesteadGasRepriceHash:  config.EthereumChainConfig.HomesteadGasRepriceHash.hash,
            },
            Genesis:                 config.EthereumGenesis,
            LightMode:               true,
            DatabaseCache:           config.EthereumDatabaseCache,
            NetworkId:               config.EthereumNetworkID,
            GasPrice:                new(big.Int).Mul(big.NewInt(20), common.Shannon),
            GpoMinGasPrice:          new(big.Int).Mul(big.NewInt(20), common.Shannon),
            GpoMaxGasPrice:          new(big.Int).Mul(big.NewInt(500), common.Shannon),
            GpoFullBlockRatio:       80,
            GpobaseStepDown:         10,
            GpobaseStepUp:           100,
            GpobaseCorrectionFactor: 110,
        }
        if config.EthereumTestnetNonces {
            state.StartingNonce = 1048576 // (2**20)
            light.StartingNonce = 1048576 // (2**20)
        }
        if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
            return les.New(ctx, ethConf)
        }); err != nil {
            return nil, fmt.Errorf("ethereum init: %v", err)
        }
    }
    // Register the Whisper protocol if requested
    if config.WhisperEnabled {
        if err := stack.Register(func(*node.ServiceContext) (node.Service, error) { return whisperv2.New(), nil }); err != nil {
            return nil, fmt.Errorf("whisper init: %v", err)
        }
    }
    return &Node{stack}, nil
}

// Start creates a live P2P node and starts running it.
func (n *Node) Start() error {
    return n.node.Start()
}

// Stop terminates a running node along with all it's services. In the node was
// not started, an error is returned.
func (n *Node) Stop() error {
    return n.node.Stop()
}

// GetEthereumClient retrieves a client to access the Ethereum subsystem.
func (n *Node) GetEthereumClient() (*EthereumClient, error) {
    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()}
}