github.com/MetalBlockchain/subnet-evm@v0.4.9/node/config.go (about)

     1  // (c) 2019-2020, Ava Labs, Inc.
     2  //
     3  // This file is a derived work, based on the go-ethereum library whose original
     4  // notices appear below.
     5  //
     6  // It is distributed under a license compatible with the licensing terms of the
     7  // original code from which it is derived.
     8  //
     9  // Much love to the original authors for their work.
    10  // **********
    11  // Copyright 2014 The go-ethereum Authors
    12  // This file is part of the go-ethereum library.
    13  //
    14  // The go-ethereum library is free software: you can redistribute it and/or modify
    15  // it under the terms of the GNU Lesser General Public License as published by
    16  // the Free Software Foundation, either version 3 of the License, or
    17  // (at your option) any later version.
    18  //
    19  // The go-ethereum library is distributed in the hope that it will be useful,
    20  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    22  // GNU Lesser General Public License for more details.
    23  //
    24  // You should have received a copy of the GNU Lesser General Public License
    25  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    26  
    27  package node
    28  
    29  import (
    30  	"fmt"
    31  	"os"
    32  	"path/filepath"
    33  
    34  	"github.com/MetalBlockchain/subnet-evm/accounts"
    35  	"github.com/MetalBlockchain/subnet-evm/accounts/external"
    36  	"github.com/MetalBlockchain/subnet-evm/accounts/keystore"
    37  	"github.com/MetalBlockchain/subnet-evm/rpc"
    38  	"github.com/ethereum/go-ethereum/log"
    39  )
    40  
    41  // Config represents a small collection of configuration values to fine tune the
    42  // P2P network layer of a protocol stack. These values can be further extended by
    43  // all registered services.
    44  type Config struct {
    45  	// KeyStoreDir is the file system folder that contains private keys. The directory can
    46  	// be specified as a relative path, in which case it is resolved relative to the
    47  	// current directory.
    48  	//
    49  	// If KeyStoreDir is empty, the default location is the "keystore" subdirectory of
    50  	// DataDir. If DataDir is unspecified and KeyStoreDir is empty, an ephemeral directory
    51  	// is created by New and destroyed when the node is stopped.
    52  	KeyStoreDir string `toml:",omitempty"`
    53  
    54  	// ExternalSigner specifies an external URI for a clef-type signer
    55  	ExternalSigner string `toml:",omitempty"`
    56  
    57  	// UseLightweightKDF lowers the memory and CPU requirements of the key store
    58  	// scrypt KDF at the expense of security.
    59  	UseLightweightKDF bool `toml:",omitempty"`
    60  
    61  	// InsecureUnlockAllowed allows user to unlock accounts in unsafe http environment.
    62  	InsecureUnlockAllowed bool `toml:",omitempty"`
    63  
    64  	// HTTPHost is the host interface on which to start the HTTP RPC server. If this
    65  	// field is empty, no HTTP API endpoint will be started.
    66  	HTTPHost string
    67  
    68  	// HTTPPort is the TCP port number on which to start the HTTP RPC server. The
    69  	// default zero value is/ valid and will pick a port number randomly (useful
    70  	// for ephemeral nodes).
    71  	HTTPPort int `toml:",omitempty"`
    72  
    73  	// HTTPCors is the Cross-Origin Resource Sharing header to send to requesting
    74  	// clients. Please be aware that CORS is a browser enforced security, it's fully
    75  	// useless for custom HTTP clients.
    76  	HTTPCors []string `toml:",omitempty"`
    77  
    78  	// HTTPVirtualHosts is the list of virtual hostnames which are allowed on incoming requests.
    79  	// This is by default {'localhost'}. Using this prevents attacks like
    80  	// DNS rebinding, which bypasses SOP by simply masquerading as being within the same
    81  	// origin. These attacks do not utilize CORS, since they are not cross-domain.
    82  	// By explicitly checking the Host-header, the server will not allow requests
    83  	// made against the server with a malicious host domain.
    84  	// Requests using ip address directly are not affected
    85  	HTTPVirtualHosts []string `toml:",omitempty"`
    86  
    87  	// HTTPModules is a list of API modules to expose via the HTTP RPC interface.
    88  	// If the module list is empty, all RPC API endpoints designated public will be
    89  	// exposed.
    90  	HTTPModules []string
    91  
    92  	// HTTPTimeouts allows for customization of the timeout values used by the HTTP RPC
    93  	// interface.
    94  	HTTPTimeouts rpc.HTTPTimeouts
    95  
    96  	// WSHost is the host interface on which to start the websocket RPC server. If
    97  	// this field is empty, no websocket API endpoint will be started.
    98  	WSHost string
    99  
   100  	// WSPort is the TCP port number on which to start the websocket RPC server. The
   101  	// default zero value is/ valid and will pick a port number randomly (useful for
   102  	// ephemeral nodes).
   103  	WSPort int `toml:",omitempty"`
   104  
   105  	// WSOrigins is the list of domain to accept websocket requests from. Please be
   106  	// aware that the server can only act upon the HTTP request the client sends and
   107  	// cannot verify the validity of the request header.
   108  	WSOrigins []string `toml:",omitempty"`
   109  
   110  	// WSModules is a list of API modules to expose via the websocket RPC interface.
   111  	// If the module list is empty, all RPC API endpoints designated public will be
   112  	// exposed.
   113  	WSModules []string
   114  
   115  	// WSExposeAll exposes all API modules via the WebSocket RPC interface rather
   116  	// than just the public ones.
   117  	//
   118  	// *WARNING* Only set this if the node is running in a trusted network, exposing
   119  	// private APIs to untrusted users is a major security risk.
   120  	WSExposeAll bool `toml:",omitempty"`
   121  
   122  	// GraphQLCors is the Cross-Origin Resource Sharing header to send to requesting
   123  	// clients. Please be aware that CORS is a browser enforced security, it's fully
   124  	// useless for custom HTTP clients.
   125  	GraphQLCors []string `toml:",omitempty"`
   126  
   127  	// GraphQLVirtualHosts is the list of virtual hostnames which are allowed on incoming requests.
   128  	// This is by default {'localhost'}. Using this prevents attacks like
   129  	// DNS rebinding, which bypasses SOP by simply masquerading as being within the same
   130  	// origin. These attacks do not utilize CORS, since they are not cross-domain.
   131  	// By explicitly checking the Host-header, the server will not allow requests
   132  	// made against the server with a malicious host domain.
   133  	// Requests using ip address directly are not affected
   134  	GraphQLVirtualHosts []string `toml:",omitempty"`
   135  
   136  	SubnetEVMVersion string
   137  }
   138  
   139  // HTTPEndpoint resolves an HTTP endpoint based on the configured host interface
   140  // and port parameters.
   141  func (c *Config) HTTPEndpoint() string {
   142  	if c.HTTPHost == "" {
   143  		return ""
   144  	}
   145  	return fmt.Sprintf("%s:%d", c.HTTPHost, c.HTTPPort)
   146  }
   147  
   148  // DefaultHTTPEndpoint returns the HTTP endpoint used by default.
   149  func DefaultHTTPEndpoint() string {
   150  	config := &Config{HTTPHost: DefaultHTTPHost, HTTPPort: DefaultHTTPPort}
   151  	return config.HTTPEndpoint()
   152  }
   153  
   154  // WSEndpoint resolves a websocket endpoint based on the configured host interface
   155  // and port parameters.
   156  func (c *Config) WSEndpoint() string {
   157  	if c.WSHost == "" {
   158  		return ""
   159  	}
   160  	return fmt.Sprintf("%s:%d", c.WSHost, c.WSPort)
   161  }
   162  
   163  // DefaultWSEndpoint returns the websocket endpoint used by default.
   164  func DefaultWSEndpoint() string {
   165  	config := &Config{WSHost: DefaultWSHost, WSPort: DefaultWSPort}
   166  	return config.WSEndpoint()
   167  }
   168  
   169  // ExtRPCEnabled returns the indicator whether node enables the external
   170  // RPC(http, ws or graphql).
   171  func (c *Config) ExtRPCEnabled() bool {
   172  	return c.HTTPHost != "" || c.WSHost != ""
   173  }
   174  
   175  // KeyDirConfig determines the settings for keydirectory
   176  func (c *Config) KeyDirConfig() (string, error) {
   177  	var (
   178  		keydir string
   179  		err    error
   180  	)
   181  	switch {
   182  	case filepath.IsAbs(c.KeyStoreDir):
   183  		keydir = c.KeyStoreDir
   184  	case c.KeyStoreDir != "":
   185  		keydir, err = filepath.Abs(c.KeyStoreDir)
   186  	}
   187  	return keydir, err
   188  }
   189  
   190  // getKeyStoreDir retrieves the key directory and will create
   191  // and ephemeral one if necessary.
   192  func getKeyStoreDir(conf *Config) (string, bool, error) {
   193  	keydir, err := conf.KeyDirConfig()
   194  	if err != nil {
   195  		return "", false, err
   196  	}
   197  	isEphemeral := false
   198  	if keydir == "" {
   199  		// There is no datadir.
   200  		keydir, err = os.MkdirTemp("", "subnet-evm-keystore")
   201  		isEphemeral = true
   202  	}
   203  
   204  	if err != nil {
   205  		return "", false, err
   206  	}
   207  	if err := os.MkdirAll(keydir, 0700); err != nil {
   208  		return "", false, err
   209  	}
   210  
   211  	return keydir, isEphemeral, nil
   212  }
   213  
   214  func makeAccountManager(conf *Config) (*accounts.Manager, error) {
   215  	scryptN := keystore.StandardScryptN
   216  	scryptP := keystore.StandardScryptP
   217  	if conf.UseLightweightKDF {
   218  		scryptN = keystore.LightScryptN
   219  		scryptP = keystore.LightScryptP
   220  	}
   221  
   222  	keydir, _, err := getKeyStoreDir(conf)
   223  	if err != nil {
   224  		return nil, err
   225  	}
   226  	// Assemble the account manager and supported backends
   227  	var backends []accounts.Backend
   228  	if len(conf.ExternalSigner) > 0 {
   229  		log.Info("Using external signer", "url", conf.ExternalSigner)
   230  		if extapi, err := external.NewExternalBackend(conf.ExternalSigner); err == nil {
   231  			backends = append(backends, extapi)
   232  		} else {
   233  			return nil, fmt.Errorf("error connecting to external signer: %v", err)
   234  		}
   235  	}
   236  	if len(backends) == 0 {
   237  		// For now, we're using EITHER external signer OR local signers.
   238  		// If/when we implement some form of lockfile for USB and keystore wallets,
   239  		// we can have both, but it's very confusing for the user to see the same
   240  		// accounts in both externally and locally, plus very racey.
   241  		backends = append(backends, keystore.NewKeyStore(keydir, scryptN, scryptP))
   242  	}
   243  
   244  	return accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: conf.InsecureUnlockAllowed}, backends...), nil
   245  }