first commit

This commit is contained in:
Patrick O'Grady
2021-12-15 12:28:56 -08:00
commit f6aef56afd
480 changed files with 118919 additions and 0 deletions
+66
View File
@@ -0,0 +1,66 @@
// (c) 2019-2020, Ava Labs, Inc.
//
// This file is a derived work, based on the go-ethereum library whose original
// notices appear below.
//
// It is distributed under a license compatible with the licensing terms of the
// original code from which it is derived.
//
// Much love to the original authors for their work.
// **********
// Copyright 2015 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/>.
package node
import (
"github.com/ava-labs/subnet-evm/internal/debug"
"github.com/ava-labs/subnet-evm/rpc"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
)
// apis returns the collection of built-in RPC APIs.
func (n *Node) apis() []rpc.API {
return []rpc.API{
{
Namespace: "debug",
Version: "1.0",
Service: debug.Handler,
}, {
Namespace: "web3",
Version: "1.0",
Service: &publicWeb3API{n},
Public: true,
},
}
}
// publicWeb3API offers helper utils
type publicWeb3API struct {
stack *Node
}
// ClientVersion returns the node name
func (s *publicWeb3API) ClientVersion() string {
return s.stack.config.SubnetEVMVersion
}
// Sha3 applies the ethereum sha3 implementation on the input.
// It assumes the input is hex encoded.
func (s *publicWeb3API) Sha3(input hexutil.Bytes) hexutil.Bytes {
return crypto.Keccak256(input)
}
+246
View File
@@ -0,0 +1,246 @@
// (c) 2019-2020, Ava Labs, Inc.
//
// This file is a derived work, based on the go-ethereum library whose original
// notices appear below.
//
// It is distributed under a license compatible with the licensing terms of the
// original code from which it is derived.
//
// Much love to the original authors for their work.
// **********
// Copyright 2014 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/>.
package node
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/ava-labs/subnet-evm/accounts"
"github.com/ava-labs/subnet-evm/accounts/external"
"github.com/ava-labs/subnet-evm/accounts/keystore"
"github.com/ava-labs/subnet-evm/rpc"
"github.com/ethereum/go-ethereum/log"
)
// Config represents a small collection of configuration values to fine tune the
// P2P network layer of a protocol stack. These values can be further extended by
// all registered services.
type Config struct {
// KeyStoreDir is the file system folder that contains private keys. The directory can
// be specified as a relative path, in which case it is resolved relative to the
// current directory.
//
// If KeyStoreDir is empty, the default location is the "keystore" subdirectory of
// DataDir. If DataDir is unspecified and KeyStoreDir is empty, an ephemeral directory
// is created by New and destroyed when the node is stopped.
KeyStoreDir string `toml:",omitempty"`
// ExternalSigner specifies an external URI for a clef-type signer
ExternalSigner string `toml:",omitempty"`
// UseLightweightKDF lowers the memory and CPU requirements of the key store
// scrypt KDF at the expense of security.
UseLightweightKDF bool `toml:",omitempty"`
// InsecureUnlockAllowed allows user to unlock accounts in unsafe http environment.
InsecureUnlockAllowed bool `toml:",omitempty"`
// HTTPHost is the host interface on which to start the HTTP RPC server. If this
// field is empty, no HTTP API endpoint will be started.
HTTPHost string
// HTTPPort is the TCP port number on which to start the HTTP RPC server. The
// default zero value is/ valid and will pick a port number randomly (useful
// for ephemeral nodes).
HTTPPort int `toml:",omitempty"`
// HTTPCors is the Cross-Origin Resource Sharing header to send to requesting
// clients. Please be aware that CORS is a browser enforced security, it's fully
// useless for custom HTTP clients.
HTTPCors []string `toml:",omitempty"`
// HTTPVirtualHosts is the list of virtual hostnames which are allowed on incoming requests.
// This is by default {'localhost'}. Using this prevents attacks like
// DNS rebinding, which bypasses SOP by simply masquerading as being within the same
// origin. These attacks do not utilize CORS, since they are not cross-domain.
// By explicitly checking the Host-header, the server will not allow requests
// made against the server with a malicious host domain.
// Requests using ip address directly are not affected
HTTPVirtualHosts []string `toml:",omitempty"`
// HTTPModules is a list of API modules to expose via the HTTP RPC interface.
// If the module list is empty, all RPC API endpoints designated public will be
// exposed.
HTTPModules []string
// HTTPTimeouts allows for customization of the timeout values used by the HTTP RPC
// interface.
HTTPTimeouts rpc.HTTPTimeouts
// WSHost is the host interface on which to start the websocket RPC server. If
// this field is empty, no websocket API endpoint will be started.
WSHost string
// WSPort is the TCP port number on which to start the websocket RPC server. The
// default zero value is/ valid and will pick a port number randomly (useful for
// ephemeral nodes).
WSPort int `toml:",omitempty"`
// WSOrigins is the list of domain to accept websocket requests from. Please be
// aware that the server can only act upon the HTTP request the client sends and
// cannot verify the validity of the request header.
WSOrigins []string `toml:",omitempty"`
// WSModules is a list of API modules to expose via the websocket RPC interface.
// If the module list is empty, all RPC API endpoints designated public will be
// exposed.
WSModules []string
// WSExposeAll exposes all API modules via the WebSocket RPC interface rather
// than just the public ones.
//
// *WARNING* Only set this if the node is running in a trusted network, exposing
// private APIs to untrusted users is a major security risk.
WSExposeAll bool `toml:",omitempty"`
// GraphQLCors is the Cross-Origin Resource Sharing header to send to requesting
// clients. Please be aware that CORS is a browser enforced security, it's fully
// useless for custom HTTP clients.
GraphQLCors []string `toml:",omitempty"`
// GraphQLVirtualHosts is the list of virtual hostnames which are allowed on incoming requests.
// This is by default {'localhost'}. Using this prevents attacks like
// DNS rebinding, which bypasses SOP by simply masquerading as being within the same
// origin. These attacks do not utilize CORS, since they are not cross-domain.
// By explicitly checking the Host-header, the server will not allow requests
// made against the server with a malicious host domain.
// Requests using ip address directly are not affected
GraphQLVirtualHosts []string `toml:",omitempty"`
SubnetEVMVersion string
}
// HTTPEndpoint resolves an HTTP endpoint based on the configured host interface
// and port parameters.
func (c *Config) HTTPEndpoint() string {
if c.HTTPHost == "" {
return ""
}
return fmt.Sprintf("%s:%d", c.HTTPHost, c.HTTPPort)
}
// DefaultHTTPEndpoint returns the HTTP endpoint used by default.
func DefaultHTTPEndpoint() string {
config := &Config{HTTPHost: DefaultHTTPHost, HTTPPort: DefaultHTTPPort}
return config.HTTPEndpoint()
}
// WSEndpoint resolves a websocket endpoint based on the configured host interface
// and port parameters.
func (c *Config) WSEndpoint() string {
if c.WSHost == "" {
return ""
}
return fmt.Sprintf("%s:%d", c.WSHost, c.WSPort)
}
// DefaultWSEndpoint returns the websocket endpoint used by default.
func DefaultWSEndpoint() string {
config := &Config{WSHost: DefaultWSHost, WSPort: DefaultWSPort}
return config.WSEndpoint()
}
// ExtRPCEnabled returns the indicator whether node enables the external
// RPC(http, ws or graphql).
func (c *Config) ExtRPCEnabled() bool {
return c.HTTPHost != "" || c.WSHost != ""
}
// KeyDirConfig determines the settings for keydirectory
func (c *Config) KeyDirConfig() (string, error) {
var (
keydir string
err error
)
switch {
case filepath.IsAbs(c.KeyStoreDir):
keydir = c.KeyStoreDir
case c.KeyStoreDir != "":
keydir, err = filepath.Abs(c.KeyStoreDir)
}
return keydir, err
}
// getKeyStoreDir retrieves the key directory and will create
// and ephemeral one if necessary.
func getKeyStoreDir(conf *Config) (string, bool, error) {
keydir, err := conf.KeyDirConfig()
if err != nil {
return "", false, err
}
isEphemeral := false
if keydir == "" {
// There is no datadir.
keydir, err = ioutil.TempDir("", "subnet-evm-keystore")
isEphemeral = true
}
if err != nil {
return "", false, err
}
if err := os.MkdirAll(keydir, 0700); err != nil {
return "", false, err
}
return keydir, isEphemeral, nil
}
func makeAccountManager(conf *Config) (*accounts.Manager, error) {
scryptN := keystore.StandardScryptN
scryptP := keystore.StandardScryptP
if conf.UseLightweightKDF {
scryptN = keystore.LightScryptN
scryptP = keystore.LightScryptP
}
keydir, _, err := getKeyStoreDir(conf)
if err != nil {
return nil, err
}
// Assemble the account manager and supported backends
var backends []accounts.Backend
if len(conf.ExternalSigner) > 0 {
log.Info("Using external signer", "url", conf.ExternalSigner)
if extapi, err := external.NewExternalBackend(conf.ExternalSigner); err == nil {
backends = append(backends, extapi)
} else {
return nil, fmt.Errorf("error connecting to external signer: %v", err)
}
}
if len(backends) == 0 {
// For now, we're using EITHER external signer OR local signers.
// If/when we implement some form of lockfile for USB and keystore wallets,
// we can have both, but it's very confusing for the user to see the same
// accounts in both externally and locally, plus very racey.
backends = append(backends, keystore.NewKeyStore(keydir, scryptN, scryptP))
}
return accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: conf.InsecureUnlockAllowed}, backends...), nil
}
+51
View File
@@ -0,0 +1,51 @@
// (c) 2019-2020, Ava Labs, Inc.
//
// This file is a derived work, based on the go-ethereum library whose original
// notices appear below.
//
// It is distributed under a license compatible with the licensing terms of the
// original code from which it is derived.
//
// Much love to the original authors for their work.
// **********
// 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/>.
package node
import (
"github.com/ava-labs/subnet-evm/rpc"
)
const (
DefaultHTTPHost = "localhost" // Default host interface for the HTTP RPC server
DefaultHTTPPort = 8545 // Default TCP port for the HTTP RPC server
DefaultWSHost = "localhost" // Default host interface for the websocket RPC server
DefaultWSPort = 8546 // Default TCP port for the websocket RPC server
DefaultGraphQLHost = "localhost" // Default host interface for the GraphQL server
DefaultGraphQLPort = 8547 // Default TCP port for the GraphQL server
)
// DefaultConfig contains reasonable default settings.
var DefaultConfig = Config{
HTTPPort: DefaultHTTPPort,
HTTPModules: []string{"net", "web3"},
HTTPVirtualHosts: []string{"localhost"},
HTTPTimeouts: rpc.DefaultHTTPTimeouts,
WSPort: DefaultWSPort,
WSModules: []string{"net", "web3"},
GraphQLVirtualHosts: []string{"localhost"},
}
+35
View File
@@ -0,0 +1,35 @@
// (c) 2019-2020, Ava Labs, Inc.
//
// This file is a derived work, based on the go-ethereum library whose original
// notices appear below.
//
// It is distributed under a license compatible with the licensing terms of the
// original code from which it is derived.
//
// Much love to the original authors for their work.
// **********
// Copyright 2015 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/>.
package node
import (
"errors"
)
var (
ErrNodeStopped = errors.New("node not started")
)
+133
View File
@@ -0,0 +1,133 @@
// (c) 2019-2020, Ava Labs, Inc.
//
// This file is a derived work, based on the go-ethereum library whose original
// notices appear below.
//
// It is distributed under a license compatible with the licensing terms of the
// original code from which it is derived.
//
// Much love to the original authors for their work.
// **********
// Copyright 2015 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/>.
package node
import (
"sync"
"github.com/ava-labs/subnet-evm/accounts"
"github.com/ava-labs/subnet-evm/rpc"
"github.com/ethereum/go-ethereum/event"
)
// Node is a container on which services can be registered.
type Node struct {
eventmux *event.TypeMux
config *Config
accman *accounts.Manager
// log log.Logger
// ephemKeystore string // if non-empty, the key directory that will be removed by Stop
// dirLock fileutil.Releaser // prevents concurrent use of instance directory
// stop chan struct{} // Channel to wait for termination notifications
// server *p2p.Server // Currently running P2P networking layer
// startStopLock sync.Mutex // Start/Stop are protected by an additional lock
// state int // Tracks state of node lifecycle
lock sync.Mutex
rpcAPIs []rpc.API // List of APIs currently provided by the node
// inprocHandler *rpc.Server // In-process RPC request handler to process the API requests
// databases map[*closeTrackingDB]struct{} // All open databases
subnetEVMVersion string
}
// const (
// initializingState = iota
// closedState
// )
// func (n *Node) openDataDir() error {
// if n.config.DataDir == "" {
// return nil // ephemeral
// }
//
// instdir := filepath.Join(n.config.DataDir, n.config.name())
// if err := os.MkdirAll(instdir, 0700); err != nil {
// return err
// }
// // Lock the instance directory to prevent concurrent use by another instance as well as
// // accidental use of the instance directory as a database.
// release, _, err := fileutil.Flock(filepath.Join(instdir, "LOCK"))
// if err != nil {
// return convertFileLockError(err)
// }
// n.dirLock = release
// return nil
// }
// New creates a new P2P node, ready for protocol registration.
func New(conf *Config) (*Node, error) {
// Copy config and resolve the datadir so future changes to the current
// working directory don't affect the node.
confCopy := *conf
conf = &confCopy
node := &Node{
config: conf,
eventmux: new(event.TypeMux),
}
// Register built-in APIs.
node.rpcAPIs = append(node.rpcAPIs, node.apis()...)
// Ensure that the AccountManager method works before the node has started. We rely on
// this in cmd/geth.
am, err := makeAccountManager(conf)
if err != nil {
return nil, err
}
node.accman = am
// Configure RPC servers.
return node, nil
}
// Config returns the configuration of node.
func (n *Node) Config() *Config {
return n.config
}
// AccountManager retrieves the account manager used by the protocol stack.
func (n *Node) AccountManager() *accounts.Manager {
return n.accman
}
// EventMux retrieves the event multiplexer used by all the network services in
// the current protocol stack.
func (n *Node) EventMux() *event.TypeMux {
return n.eventmux
}
// RegisterAPIs registers the APIs a service provides on the node.
func (n *Node) RegisterAPIs(apis []rpc.API) {
n.lock.Lock()
defer n.lock.Unlock()
n.rpcAPIs = append(n.rpcAPIs, apis...)
}