2017-03-15 21:03:01 +00:00
|
|
|
package params
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2017-03-18 18:23:58 +00:00
|
|
|
"errors"
|
2017-03-15 21:03:01 +00:00
|
|
|
"io/ioutil"
|
2017-03-18 18:23:58 +00:00
|
|
|
"math/big"
|
2017-03-15 21:03:01 +00:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
|
|
"github.com/ethereum/go-ethereum/core"
|
|
|
|
"github.com/ethereum/go-ethereum/logger"
|
|
|
|
"github.com/ethereum/go-ethereum/logger/glog"
|
|
|
|
"github.com/ethereum/go-ethereum/params"
|
|
|
|
)
|
|
|
|
|
|
|
|
// default node configuration options
|
|
|
|
var (
|
|
|
|
UseMainnetFlag = "false" // to be overridden via -ldflags '-X geth/params.UseMainnetFlag'
|
|
|
|
UseMainnet = false
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
if UseMainnetFlag == "true" { // set at compile time, here we make sure to set corresponding boolean flag
|
|
|
|
UseMainnet = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
ErrMissingDataDir = errors.New("missing required 'DataDir' parameter")
|
|
|
|
ErrMissingNetworkId = errors.New("missing required 'NetworkId' parameter")
|
|
|
|
)
|
|
|
|
|
|
|
|
// ChainConfig holds core blockchain settings. It is stored in the database on a per block basis.
|
|
|
|
type ChainConfig struct {
|
|
|
|
// ChainId identifies the current chain and is used for replay protection
|
|
|
|
ChainId *big.Int
|
|
|
|
|
|
|
|
// HomesteadBlock is Homestead switch block (nil = no fork, 0 = already homestead)
|
|
|
|
HomesteadBlock *big.Int
|
|
|
|
|
|
|
|
// DAOForkBlock TheDAO hard-fork switch block (nil = no fork)
|
|
|
|
DAOForkBlock *big.Int
|
|
|
|
|
|
|
|
// DAOForkSupport Whether the nodes supports or opposes the DAO hard-fork
|
|
|
|
DAOForkSupport bool
|
|
|
|
|
|
|
|
// EIP150Block is EIP150 HF block (nil = no fork)
|
|
|
|
EIP150Block *big.Int
|
|
|
|
|
|
|
|
// EIP150Hash is EIP150 HF hash (fast sync aid)
|
|
|
|
EIP150Hash common.Hash
|
|
|
|
|
|
|
|
// EIP155Block is EIP155 HF block
|
|
|
|
EIP155Block *big.Int
|
|
|
|
|
|
|
|
// EIP158Block is EIP158 HF block
|
|
|
|
EIP158Block *big.Int
|
|
|
|
}
|
|
|
|
|
|
|
|
// LightEthConfig holds LES-related configuration
|
|
|
|
// Status nodes are always lightweight clients (due to mobile platform constraints)
|
|
|
|
type LightEthConfig struct {
|
2017-03-28 09:04:52 +00:00
|
|
|
// Enabled flag specifies whether protocol is enabled
|
|
|
|
Enabled bool
|
|
|
|
|
2017-03-15 21:03:01 +00:00
|
|
|
// Genesis is JSON to seed the chain database with
|
|
|
|
Genesis string
|
|
|
|
|
|
|
|
// DatabaseCache is memory (in MBs) allocated to internal caching (min 16MB / database forced)
|
|
|
|
DatabaseCache int
|
|
|
|
}
|
|
|
|
|
|
|
|
// WhisperConfig holds SHH-related configuration
|
2017-03-28 09:04:52 +00:00
|
|
|
type WhisperConfig struct {
|
|
|
|
// Enabled flag specifies whether protocol is enabled
|
|
|
|
Enabled bool
|
2017-04-09 22:16:05 +00:00
|
|
|
|
|
|
|
// EchoMode if mode is on, prints some arguments for diagnostics
|
|
|
|
EchoMode bool
|
|
|
|
|
|
|
|
// BootstrapNode whether node doesn't actively connect to peers, and waits for incoming connections
|
|
|
|
BootstrapNode bool
|
|
|
|
|
|
|
|
// ForwarderNode is mode when node only forwards messages, neither sends nor decrypts messages
|
|
|
|
ForwarderNode bool
|
|
|
|
|
|
|
|
// MailServerNode is mode when node is capable of delivering expired messages on demand
|
|
|
|
MailServerNode bool
|
|
|
|
|
|
|
|
// MailServerPassword is password for MailServer's symmetric key
|
|
|
|
MailServerPassword string
|
|
|
|
|
|
|
|
// NotificationServerNode is mode when node is capable of sending Push (and probably other kinds) Notifications
|
|
|
|
NotificationServerNode bool
|
|
|
|
|
|
|
|
// NotificationServerPassword is password for NotificationServer's symmetric key (used in discovery)
|
|
|
|
NotificationServerPassword string
|
|
|
|
|
|
|
|
// DataDir is the file system folder Whisper should use for any data storage needs.
|
|
|
|
DataDir string
|
|
|
|
|
|
|
|
// Port Whisper node's listening port
|
|
|
|
Port int
|
|
|
|
|
|
|
|
// MinimumPoW minimum PoW for Whisper messages
|
|
|
|
MinimumPoW float64
|
|
|
|
|
|
|
|
// TTL time to live for messages, in seconds
|
|
|
|
TTL int
|
2017-03-28 09:04:52 +00:00
|
|
|
}
|
2017-03-15 21:03:01 +00:00
|
|
|
|
|
|
|
// SwarmConfig holds Swarm-related configuration
|
2017-03-28 09:04:52 +00:00
|
|
|
type SwarmConfig struct {
|
|
|
|
// Enabled flag specifies whether protocol is enabled
|
|
|
|
Enabled bool
|
|
|
|
}
|
2017-03-15 21:03:01 +00:00
|
|
|
|
|
|
|
// NodeConfig stores configuration options for a node
|
|
|
|
type NodeConfig struct {
|
|
|
|
// TestNet flag whether given configuration describes a test or mainnet
|
|
|
|
TestNet bool
|
|
|
|
|
|
|
|
// NetworkId sets network to use for selecting peers to connect to
|
|
|
|
NetworkId int
|
|
|
|
|
|
|
|
// DataDir is the file system folder the node should use for any data storage needs.
|
|
|
|
DataDir string
|
|
|
|
|
2017-04-09 22:16:05 +00:00
|
|
|
// PrivateKeyFile is a filename with node ID (private key)
|
|
|
|
// This file should contain a valid secp256k1 private key that will be used for both
|
|
|
|
// remote peer identification as well as network traffic encryption.
|
|
|
|
NodeKeyFile string
|
|
|
|
|
2017-03-15 21:03:01 +00:00
|
|
|
// Name sets the instance name of the node. It must not contain the / character.
|
|
|
|
Name string
|
|
|
|
|
|
|
|
// Version exposes program's version. It is used in the devp2p node identifier.
|
|
|
|
Version string
|
|
|
|
|
|
|
|
// APIModules is a comma-separated list of API modules exposed via *any* (HTTP/WS/IPC) RPC interface.
|
|
|
|
APIModules string
|
|
|
|
|
|
|
|
// HTTPHost is the host interface on which to start the HTTP RPC server.
|
|
|
|
// Pass empty string if no HTTP RPC interface needs to be started.
|
|
|
|
HTTPHost string
|
|
|
|
|
|
|
|
// HTTPPort is the TCP port number on which to start the Geth's HTTP RPC server.
|
|
|
|
HTTPPort int
|
|
|
|
|
|
|
|
// WSHost is a host interface for the WebSocket RPC server
|
|
|
|
WSHost string
|
|
|
|
|
|
|
|
// WSPort is the TCP port number on which to start the Geth's WebSocket RPC server.
|
|
|
|
WSPort int
|
|
|
|
|
|
|
|
// WSEnabled specifies whether WS-RPC Server is enabled or not
|
|
|
|
WSEnabled bool
|
|
|
|
|
|
|
|
// IPCFile is filename of exposed IPC RPC Server
|
|
|
|
IPCFile string
|
|
|
|
|
|
|
|
// IPCEnabled specifies whether IPC-RPC Server is enabled or not
|
|
|
|
IPCEnabled bool
|
|
|
|
|
|
|
|
// TLSEnabled specifies whether TLS support should be enabled on node or not
|
|
|
|
// TLS support is only planned in go-ethereum, so we are using our own patch.
|
|
|
|
TLSEnabled bool
|
|
|
|
|
|
|
|
// MaxPeers is the maximum number of (global) peers that can be connected.
|
|
|
|
// Set to zero, if only static or trusted peers are allowed to connect.
|
|
|
|
MaxPeers int
|
|
|
|
|
|
|
|
// MaxPendingPeers is the maximum number of peers that can be pending in the
|
|
|
|
// handshake phase, counted separately for inbound and outbound connections.
|
|
|
|
MaxPendingPeers int
|
|
|
|
|
2017-03-18 19:00:40 +00:00
|
|
|
// LogToFile specified whether logs should be saved into file
|
|
|
|
LogEnabled bool
|
|
|
|
|
|
|
|
// LogFile is filename where exposed logs get written to
|
|
|
|
LogFile string
|
|
|
|
|
|
|
|
// LogLevel defines minimum log level. Valid names are "ERROR", "WARNING", "INFO", "DEBUG", and "DETAIL".
|
|
|
|
LogLevel string
|
|
|
|
|
2017-03-15 21:03:01 +00:00
|
|
|
// ChainConfig extra configuration for blockchain
|
|
|
|
*ChainConfig `json:"ChainConfig,"`
|
|
|
|
|
|
|
|
// LightEthConfig extra configuration for LES
|
2017-03-28 09:04:52 +00:00
|
|
|
LightEthConfig *LightEthConfig `json:"LightEthConfig,"`
|
2017-03-15 21:03:01 +00:00
|
|
|
|
|
|
|
// WhisperConfig extra configuration for SHH
|
2017-03-28 09:04:52 +00:00
|
|
|
WhisperConfig *WhisperConfig `json:"WhisperConfig,"`
|
2017-03-15 21:03:01 +00:00
|
|
|
|
|
|
|
// SwarmConfig extra configuration for Swarm and ENS
|
2017-03-28 09:04:52 +00:00
|
|
|
SwarmConfig *SwarmConfig `json:"SwarmConfig,"`
|
2017-03-15 21:03:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewNodeConfig creates new node configuration object
|
|
|
|
func NewNodeConfig(dataDir string, networkId int) (*NodeConfig, error) {
|
|
|
|
nodeConfig := &NodeConfig{
|
|
|
|
NetworkId: networkId,
|
|
|
|
DataDir: dataDir,
|
2017-04-09 22:16:05 +00:00
|
|
|
Name: ClientIdentifier,
|
2017-03-15 21:03:01 +00:00
|
|
|
Version: Version,
|
2017-04-09 22:16:05 +00:00
|
|
|
HTTPHost: HTTPHost,
|
|
|
|
HTTPPort: HTTPPort,
|
|
|
|
APIModules: APIModules,
|
|
|
|
WSHost: WSHost,
|
|
|
|
WSPort: WSPort,
|
|
|
|
MaxPeers: MaxPeers,
|
|
|
|
MaxPendingPeers: MaxPendingPeers,
|
|
|
|
IPCFile: IPCFile,
|
|
|
|
LogFile: LogFile,
|
|
|
|
LogLevel: LogLevel,
|
2017-03-15 21:03:01 +00:00
|
|
|
ChainConfig: &ChainConfig{},
|
|
|
|
LightEthConfig: &LightEthConfig{
|
2017-03-28 09:04:52 +00:00
|
|
|
Enabled: true,
|
2017-04-09 22:16:05 +00:00
|
|
|
DatabaseCache: DatabaseCache,
|
2017-03-15 21:03:01 +00:00
|
|
|
},
|
2017-03-28 09:04:52 +00:00
|
|
|
WhisperConfig: &WhisperConfig{
|
2017-04-09 22:16:05 +00:00
|
|
|
Enabled: true,
|
|
|
|
DataDir: filepath.Join(dataDir, "wnode"),
|
|
|
|
Port: WhisperPort,
|
|
|
|
MinimumPoW: WhisperMinimumPoW,
|
|
|
|
TTL: WhisperTTL,
|
2017-03-28 09:04:52 +00:00
|
|
|
},
|
|
|
|
SwarmConfig: &SwarmConfig{},
|
2017-03-15 21:03:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nodeConfig.populateChainConfig()
|
|
|
|
|
|
|
|
return nodeConfig, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// populateChainConfig does necessary adjustments to config object (depending on network node will be runnin on)
|
|
|
|
func (c *NodeConfig) populateChainConfig() {
|
|
|
|
c.TestNet = false
|
|
|
|
if c.NetworkId == TestNetworkId {
|
|
|
|
c.TestNet = true
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.TestNet {
|
|
|
|
// Homestead fork
|
|
|
|
c.ChainConfig.HomesteadBlock = params.TestnetChainConfig.HomesteadBlock
|
|
|
|
|
|
|
|
// DAO fork
|
|
|
|
c.ChainConfig.DAOForkBlock = params.TestnetChainConfig.DAOForkBlock
|
|
|
|
c.ChainConfig.DAOForkSupport = params.TestnetChainConfig.DAOForkSupport
|
|
|
|
|
|
|
|
// DoS reprice fork
|
|
|
|
c.ChainConfig.EIP150Block = params.TestnetChainConfig.EIP150Block
|
|
|
|
c.ChainConfig.EIP150Hash = params.TestnetChainConfig.EIP150Hash
|
|
|
|
|
|
|
|
// DoS state cleanup fork
|
|
|
|
c.ChainConfig.EIP155Block = params.TestnetChainConfig.EIP155Block
|
|
|
|
c.ChainConfig.EIP158Block = params.TestnetChainConfig.EIP158Block
|
|
|
|
c.ChainConfig.ChainId = params.TestnetChainConfig.ChainId
|
|
|
|
|
2017-03-28 09:04:52 +00:00
|
|
|
c.LightEthConfig.Genesis = core.DefaultTestnetGenesisBlock()
|
2017-03-15 21:03:01 +00:00
|
|
|
} else {
|
|
|
|
// Homestead fork
|
|
|
|
c.ChainConfig.HomesteadBlock = params.MainNetHomesteadBlock
|
|
|
|
// DAO fork
|
|
|
|
c.ChainConfig.DAOForkBlock = params.MainNetDAOForkBlock
|
|
|
|
c.ChainConfig.DAOForkSupport = true
|
|
|
|
|
|
|
|
// DoS reprice fork
|
|
|
|
c.ChainConfig.EIP150Block = params.MainNetHomesteadGasRepriceBlock
|
|
|
|
c.ChainConfig.EIP150Hash = params.MainNetHomesteadGasRepriceHash
|
|
|
|
|
|
|
|
// DoS state cleanup fork
|
|
|
|
c.ChainConfig.EIP155Block = params.MainNetSpuriousDragon
|
|
|
|
c.ChainConfig.EIP158Block = params.MainNetSpuriousDragon
|
|
|
|
c.ChainConfig.ChainId = params.MainNetChainID
|
|
|
|
|
2017-03-28 09:04:52 +00:00
|
|
|
c.LightEthConfig.Genesis = core.DefaultGenesisBlock()
|
2017-03-15 21:03:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// LoadNodeConfig parses incoming JSON and returned it as Config
|
|
|
|
func LoadNodeConfig(configJSON string) (*NodeConfig, error) {
|
|
|
|
nodeConfig, err := NewNodeConfig("", 0)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
decoder := json.NewDecoder(strings.NewReader(configJSON))
|
|
|
|
//decoder.UseNumber()
|
|
|
|
|
|
|
|
// override default configuration with values by JSON input
|
|
|
|
if err := decoder.Decode(&nodeConfig); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// repopulate
|
|
|
|
nodeConfig.populateChainConfig()
|
|
|
|
|
|
|
|
if len(nodeConfig.DataDir) == 0 {
|
|
|
|
return nil, ErrMissingDataDir
|
|
|
|
}
|
|
|
|
|
|
|
|
if nodeConfig.NetworkId <= 0 {
|
|
|
|
return nil, ErrMissingNetworkId
|
|
|
|
}
|
|
|
|
|
|
|
|
return nodeConfig, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Save dumps configuration to the disk
|
|
|
|
func (c *NodeConfig) Save() error {
|
|
|
|
data, err := json.MarshalIndent(c, "", " ")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := os.MkdirAll(c.DataDir, os.ModePerm); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
configFilePath := filepath.Join(c.DataDir, "config.json")
|
|
|
|
if err := ioutil.WriteFile(configFilePath, data, os.ModePerm); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
glog.V(logger.Info).Infof("config file saved: %v", configFilePath)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// String dumps config object as nicely indented JSON
|
|
|
|
func (c *NodeConfig) String() string {
|
|
|
|
data, _ := json.MarshalIndent(c, "", " ")
|
|
|
|
return string(data)
|
|
|
|
}
|
2017-04-09 22:16:05 +00:00
|
|
|
|
|
|
|
// String dumps config object as nicely indented JSON
|
|
|
|
func (c *WhisperConfig) String() string {
|
|
|
|
data, _ := json.MarshalIndent(c, "", " ")
|
|
|
|
return string(data)
|
|
|
|
}
|
|
|
|
|
|
|
|
// String dumps config object as nicely indented JSON
|
|
|
|
func (c *SwarmConfig) String() string {
|
|
|
|
data, _ := json.MarshalIndent(c, "", " ")
|
|
|
|
return string(data)
|
|
|
|
}
|