mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-15 00:13:46 +00:00
Add hcl/json config file
This commit is contained in:
parent
c9cc1412a2
commit
51de433242
6 changed files with 373 additions and 157 deletions
|
|
@ -165,7 +165,7 @@ func (c *Command) Run(args []string) int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.setupMetrics(config.Metrics); err != nil {
|
if err := c.setupTelemetry(config.Telemetry); err != nil {
|
||||||
c.UI.Error(err.Error())
|
c.UI.Error(err.Error())
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
@ -221,7 +221,7 @@ func (c *Command) unlockAccounts(borKeystore *keystore.KeyStore) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Command) setupMetrics(config *MetricsConfig) error {
|
func (c *Command) setupTelemetry(config *TelemetryConfig) error {
|
||||||
metrics.Enabled = config.Enabled
|
metrics.Enabled = config.Enabled
|
||||||
metrics.EnabledExpensive = config.Expensive
|
metrics.EnabledExpensive = config.Expensive
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math"
|
"math"
|
||||||
|
|
@ -26,6 +25,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
"github.com/ethereum/go-ethereum/p2p/nat"
|
"github.com/ethereum/go-ethereum/p2p/nat"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/hashicorp/hcl/v2/hclsimple"
|
||||||
"github.com/imdario/mergo"
|
"github.com/imdario/mergo"
|
||||||
"github.com/mitchellh/go-homedir"
|
"github.com/mitchellh/go-homedir"
|
||||||
gopsutil "github.com/shirou/gopsutil/mem"
|
gopsutil "github.com/shirou/gopsutil/mem"
|
||||||
|
|
@ -34,146 +34,319 @@ import (
|
||||||
type Config struct {
|
type Config struct {
|
||||||
chain *chains.Chain
|
chain *chains.Chain
|
||||||
|
|
||||||
Chain string `json:"chain"`
|
// Chain is the chain to sync with
|
||||||
Debug bool `json:""`
|
Chain string `hcl:"chain,optional"`
|
||||||
Whitelist map[string]string `json:""`
|
|
||||||
LogLevel string `json:"log-level"`
|
// Whitelist is a list of required (block number, hash) pairs to accept
|
||||||
DataDir string `json:"data-dir"`
|
Whitelist map[string]string `hcl:"whitelist,optional"`
|
||||||
P2P *P2PConfig `json:""`
|
|
||||||
SyncMode string `json:"sync-mode"`
|
// LogLevel is the level of the logs to put out
|
||||||
GcMode string `json:"gc-mode"`
|
LogLevel string `hcl:"log-level,optional"`
|
||||||
Snapshot bool `json:"snapshot"`
|
|
||||||
Heimdall *HeimdallConfig `json:"heimdall"`
|
// DataDir is the directory to store the state in
|
||||||
TxPool *TxPoolConfig `json:"txpool"`
|
DataDir string `hcl:"data-dir,optional"`
|
||||||
Sealer *SealerConfig `json:"sealer"`
|
|
||||||
JsonRPC *JsonRPCConfig `json:"jsonrpc"`
|
// SyncMode selects the sync protocol
|
||||||
Gpo *GpoConfig `json:"gpo"`
|
SyncMode string `hcl:"sync-mode,optional"`
|
||||||
Ethstats string `json:"ethstats"`
|
|
||||||
Metrics *MetricsConfig `json:""`
|
// GcMode selects the garbage collection mode for the trie
|
||||||
Cache *CacheConfig `json:""`
|
GcMode string `hcl:"gc-mode,optional"`
|
||||||
Accounts *AccountsConfig `json:""`
|
|
||||||
|
// XXX
|
||||||
|
Snapshot bool `hcl:"snapshot,optional"`
|
||||||
|
|
||||||
|
// Ethstats is the address of the ethstats server to send telemetry
|
||||||
|
Ethstats string `hcl:"ethstats,optional"`
|
||||||
|
|
||||||
|
// P2P has the p2p network related settings
|
||||||
|
P2P *P2PConfig `hcl:"p2p,block"`
|
||||||
|
|
||||||
|
// Heimdall has the heimdall connection related settings
|
||||||
|
Heimdall *HeimdallConfig `hcl:"heimdall,block"`
|
||||||
|
|
||||||
|
// TxPool has the transaction pool related settings
|
||||||
|
TxPool *TxPoolConfig `hcl:"txpool,block"`
|
||||||
|
|
||||||
|
// Sealer has the validator related settings
|
||||||
|
Sealer *SealerConfig `hcl:"sealer,block"`
|
||||||
|
|
||||||
|
// JsonRPC has the json-rpc related settings
|
||||||
|
JsonRPC *JsonRPCConfig `hcl:"jsonrpc,block"`
|
||||||
|
|
||||||
|
// Gpo has the gas price oracle related settings
|
||||||
|
Gpo *GpoConfig `hcl:"gpo,block"`
|
||||||
|
|
||||||
|
// Telemetry has the telemetry related settings
|
||||||
|
Telemetry *TelemetryConfig `hcl:"telemetry,block"`
|
||||||
|
|
||||||
|
// Cache has the cache related settings
|
||||||
|
Cache *CacheConfig `hcl:"cache,block"`
|
||||||
|
|
||||||
|
// Account has the validator account related settings
|
||||||
|
Accounts *AccountsConfig `hcl:"accounts,block"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type P2PConfig struct {
|
type P2PConfig struct {
|
||||||
MaxPeers uint64 `json:"max_peers"`
|
// MaxPeers sets the maximum number of connected peers
|
||||||
MaxPendPeers uint64 `json:"max_pend_peers"`
|
MaxPeers uint64 `hcl:"max-peers,optional"`
|
||||||
Bind string `json:""`
|
|
||||||
Port uint64 `json:""`
|
// MaxPendPeers sets the maximum number of pending connected peers
|
||||||
NoDiscover bool `json:""`
|
MaxPendPeers uint64 `hcl:"max-pend-peers,optional"`
|
||||||
NAT string `json:""`
|
|
||||||
Discovery *P2PDiscovery `json:""`
|
// Bind is the bind address
|
||||||
|
Bind string `hcl:"bind,optional"`
|
||||||
|
|
||||||
|
// Port is the port number
|
||||||
|
Port uint64 `hcl:"port,optional"`
|
||||||
|
|
||||||
|
// NoDiscover is used to disable discovery
|
||||||
|
NoDiscover bool `hcl:"no-discover,optional"`
|
||||||
|
|
||||||
|
// NAT it used to set NAT options
|
||||||
|
NAT string `hcl:"nat,optional"`
|
||||||
|
|
||||||
|
// Discovery has the p2p discovery related settings
|
||||||
|
Discovery *P2PDiscovery `hcl:"discovery,block"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type P2PDiscovery struct {
|
type P2PDiscovery struct {
|
||||||
V5Enabled bool `json:""`
|
// V5Enabled is used to enable disc v5 discovery mode
|
||||||
Bootnodes []string `json:""`
|
V5Enabled bool `hcl:"v5-enabled,optional"`
|
||||||
BootnodesV4 []string `json:""`
|
|
||||||
BootnodesV5 []string `json:""`
|
// Bootnodes is the list of initial bootnodes
|
||||||
StaticNodes []string `json:""`
|
Bootnodes []string `hcl:"bootnodes,optional"`
|
||||||
TrustedNodes []string `json:""`
|
|
||||||
DNS []string `json:""`
|
// BootnodesV4 is the list of initial v4 bootnodes
|
||||||
|
BootnodesV4 []string `hcl:"bootnodesv4,optional"`
|
||||||
|
|
||||||
|
// BootnodesV5 is the list of initial v5 bootnodes
|
||||||
|
BootnodesV5 []string `hcl:"bootnodesv5,optional"`
|
||||||
|
|
||||||
|
// StaticNodes is the list of static nodes
|
||||||
|
StaticNodes []string `hcl:"static-nodes,optional"`
|
||||||
|
|
||||||
|
// TrustedNodes is the list of trusted nodes
|
||||||
|
TrustedNodes []string `hcl:"trusted-nodes,optional"`
|
||||||
|
|
||||||
|
// DNS is the list of enrtree:// URLs which will be queried for nodes to connect to
|
||||||
|
DNS []string `hcl:"dns,optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type HeimdallConfig struct {
|
type HeimdallConfig struct {
|
||||||
URL string `json:""`
|
// URL is the url of the heimdall server
|
||||||
Without bool `json:""`
|
URL string `hcl:"url,optional"`
|
||||||
|
|
||||||
|
// Without is used to disable remote heimdall during testing
|
||||||
|
Without bool `hcl:"without,optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type TxPoolConfig struct {
|
type TxPoolConfig struct {
|
||||||
Locals []string `json:""`
|
// Locals are the addresses that should be treated by default as local
|
||||||
NoLocals bool `json:""`
|
Locals []string `hcl:"locals,optional"`
|
||||||
Journal string `json:""`
|
|
||||||
Rejournal time.Duration `json:""`
|
// NoLocals enables whether local transaction handling should be disabled
|
||||||
PriceLimit uint64 `json:""`
|
NoLocals bool `hcl:"no-locals,optional"`
|
||||||
PriceBump uint64 `json:""`
|
|
||||||
AccountSlots uint64 `json:""`
|
// Journal is the path to store local transactions to survive node restarts
|
||||||
GlobalSlots uint64 `json:""`
|
Journal string `hcl:"journal,optional"`
|
||||||
AccountQueue uint64 `json:""`
|
|
||||||
GlobalQueue uint64 `json:""`
|
// Rejournal is the time interval to regenerate the local transaction journal
|
||||||
LifeTime time.Duration `json:""`
|
Rejournal time.Duration
|
||||||
|
RejournalRaw string `hcl:"rejournal,optional"`
|
||||||
|
|
||||||
|
// PriceLimit is the minimum gas price to enforce for acceptance into the pool
|
||||||
|
PriceLimit uint64 `hcl:"price-limit,optional"`
|
||||||
|
|
||||||
|
// PriceBump is the minimum price bump percentage to replace an already existing transaction (nonce)
|
||||||
|
PriceBump uint64 `hcl:"price-bump,optional"`
|
||||||
|
|
||||||
|
// AccountSlots is the number of executable transaction slots guaranteed per account
|
||||||
|
AccountSlots uint64 `hcl:"account-slots,optional"`
|
||||||
|
|
||||||
|
// GlobalSlots is the maximum number of executable transaction slots for all accounts
|
||||||
|
GlobalSlots uint64 `hcl:"global-slots,optional"`
|
||||||
|
|
||||||
|
// AccountQueue is the maximum number of non-executable transaction slots permitted per account
|
||||||
|
AccountQueue uint64 `hcl:"account-queue,optional"`
|
||||||
|
|
||||||
|
// GlobalQueueis the maximum number of non-executable transaction slots for all accounts
|
||||||
|
GlobalQueue uint64 `hcl:"global-queue,optional"`
|
||||||
|
|
||||||
|
// Lifetime is the maximum amount of time non-executable transaction are queued
|
||||||
|
LifeTime time.Duration
|
||||||
|
LifeTimeRaw string `hcl:"lifetime,optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SealerConfig struct {
|
type SealerConfig struct {
|
||||||
Enabled bool `json:""`
|
// Enabled is used to enable validator mode
|
||||||
Etherbase string `json:""`
|
Enabled bool `hcl:"enabled,optional"`
|
||||||
ExtraData string `json:""`
|
|
||||||
GasCeil uint64 `json:""`
|
// Etherbase is the address of the validator
|
||||||
GasPrice *big.Int `json:""`
|
Etherbase string `hcl:"etherbase,optional"`
|
||||||
|
|
||||||
|
// ExtraData is the block extra data set by the miner
|
||||||
|
ExtraData string `hcl:"extra-data,optional"`
|
||||||
|
|
||||||
|
// GasCeil is the target gas ceiling for mined blocks.
|
||||||
|
GasCeil uint64 `hcl:"gas-ceil,optional"`
|
||||||
|
|
||||||
|
// GasPrice is the minimum gas price for mining a transaction
|
||||||
|
GasPrice *big.Int `hcl:"gas-price,optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type JsonRPCConfig struct {
|
type JsonRPCConfig struct {
|
||||||
IPCDisable bool `json:""`
|
// IPCDisable enables whether ipc is enabled or not
|
||||||
IPCPath string `json:""`
|
IPCDisable bool `hcl:"ipc-disable,optional"`
|
||||||
|
|
||||||
Modules []string `json:""`
|
// IPCPath is the path of the ipc endpoint
|
||||||
VHost []string `json:""`
|
IPCPath string `hcl:"ipc-path,optional"`
|
||||||
Cors []string `json:""`
|
|
||||||
|
|
||||||
GasCap uint64 `json:""`
|
// Modules is the list of enabled api modules
|
||||||
TxFeeCap float64 `json:""`
|
Modules []string `hcl:"modules,optional"`
|
||||||
|
|
||||||
Http *APIConfig `json:""`
|
// VHost is the list of valid virtual hosts
|
||||||
Ws *APIConfig `json:""`
|
VHost []string `hcl:"vhost,optional"`
|
||||||
Graphql *APIConfig `json:""`
|
|
||||||
|
// Cors is the list of Cors endpoints
|
||||||
|
Cors []string `hcl:"cors,optional"`
|
||||||
|
|
||||||
|
// GasCap is the global gas cap for eth-call variants.
|
||||||
|
GasCap uint64 `hcl:"gas-cap,optional"`
|
||||||
|
|
||||||
|
// TxFeeCap is the global transaction fee cap for send-transaction variants
|
||||||
|
TxFeeCap float64 `hcl:"tx-fee-cap,optional"`
|
||||||
|
|
||||||
|
// Http has the json-rpc http related settings
|
||||||
|
Http *APIConfig `hcl:"http,block"`
|
||||||
|
|
||||||
|
// Http has the json-rpc websocket related settings
|
||||||
|
Ws *APIConfig `hcl:"ws,block"`
|
||||||
|
|
||||||
|
// Http has the json-rpc graphql related settings
|
||||||
|
Graphql *APIConfig `hcl:"graphql,block"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type APIConfig struct {
|
type APIConfig struct {
|
||||||
Enabled bool `json:""`
|
// Enabled selects whether the api is enabled
|
||||||
Port uint64 `json:""`
|
Enabled bool `hcl:"enabled,optional"`
|
||||||
Prefix string `json:""`
|
|
||||||
Host string `json:""`
|
// Port is the port number for this api
|
||||||
|
Port uint64 `hcl:"port,optional"`
|
||||||
|
|
||||||
|
// Prefix is the http prefix to expose this api
|
||||||
|
Prefix string `hcl:"prefix,optional"`
|
||||||
|
|
||||||
|
// Host is the address to bind the api
|
||||||
|
Host string `hcl:"host,optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GpoConfig struct {
|
type GpoConfig struct {
|
||||||
Blocks uint64 `json:""`
|
// Blocks is the number of blocks to track to compute the price oracle
|
||||||
Percentile uint64 `json:""`
|
Blocks uint64 `hcl:"blocks,optional"`
|
||||||
MaxPrice *big.Int `json:""`
|
|
||||||
IgnorePrice *big.Int `json:""`
|
// Percentile sets the weights to new blocks
|
||||||
|
Percentile uint64 `hcl:"percentile,optional"`
|
||||||
|
|
||||||
|
// MaxPrice is an upper bound gas price
|
||||||
|
MaxPrice *big.Int `hcl:"max-price,optional"`
|
||||||
|
|
||||||
|
// IgnorePrice is a lower bound gas price
|
||||||
|
IgnorePrice *big.Int `hcl:"ignore-price,optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MetricsConfig struct {
|
type TelemetryConfig struct {
|
||||||
Enabled bool `json:""`
|
// Enabled enables metrics
|
||||||
Expensive bool `json:""`
|
Enabled bool `hcl:"enabled,optional"`
|
||||||
InfluxDB *InfluxDBConfig `json:""`
|
|
||||||
|
// Expensive enables expensive metrics
|
||||||
|
Expensive bool `hcl:"expensive,optional"`
|
||||||
|
|
||||||
|
// InfluxDB has the influxdb related settings
|
||||||
|
InfluxDB *InfluxDBConfig `hcl:"influx,block"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type InfluxDBConfig struct {
|
type InfluxDBConfig struct {
|
||||||
V1Enabled bool `json:""`
|
// V1Enabled enables influx v1 mode
|
||||||
Endpoint string `json:""`
|
V1Enabled bool `hcl:"v1-enabled,optional"`
|
||||||
Database string `json:""`
|
|
||||||
Username string `json:""`
|
// Endpoint is the url endpoint of the influxdb service
|
||||||
Password string `json:""`
|
Endpoint string `hcl:"endpoint,optional"`
|
||||||
Tags map[string]string `json:""`
|
|
||||||
V2Enabled bool `json:""`
|
// Database is the name of the database in Influxdb to store the metrics.
|
||||||
Token string `json:""`
|
Database string `hcl:"database,optional"`
|
||||||
Bucket string `json:""`
|
|
||||||
Organization string `json:""`
|
// Enabled is the username to authorize access to Influxdb
|
||||||
|
Username string `hcl:"username,optional"`
|
||||||
|
|
||||||
|
// Password is the password to authorize access to Influxdb
|
||||||
|
Password string `hcl:"password,optional"`
|
||||||
|
|
||||||
|
// Tags are tags attaches to all generated metrics
|
||||||
|
Tags map[string]string `hcl:"tags,optional"`
|
||||||
|
|
||||||
|
// Enabled enables influx v2 mode
|
||||||
|
V2Enabled bool `hcl:"v2-enabled,optional"`
|
||||||
|
|
||||||
|
// Token is the token to authorize access to Influxdb V2.
|
||||||
|
Token string `hcl:"token,optional"`
|
||||||
|
|
||||||
|
// Bucket is the bucket to store metrics in Influxdb V2.
|
||||||
|
Bucket string `hcl:"bucket,optional"`
|
||||||
|
|
||||||
|
// Organization is the name of the organization for Influxdb V2.
|
||||||
|
Organization string `hcl:"organization,optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CacheConfig struct {
|
type CacheConfig struct {
|
||||||
Cache uint64 `json:""`
|
// Cache is the amount of cache of the node
|
||||||
PercGc uint64 `json:""`
|
Cache uint64 `hcl:"cache,optional"`
|
||||||
PercSnapshot uint64 `json:""`
|
|
||||||
PercDatabase uint64 `json:""`
|
// PercGc is percentage of cache used for garbage collection
|
||||||
PercTrie uint64 `json:""`
|
PercGc uint64 `hcl:"perc-gc,optional"`
|
||||||
Journal string `json:""`
|
|
||||||
Rejournal time.Duration `json:""`
|
// PercSnapshot is percentage of cache used for snapshots
|
||||||
NoPrefetch bool `json:""`
|
PercSnapshot uint64 `hcl:"perc-snapshot,optional"`
|
||||||
Preimages bool `json:""`
|
|
||||||
TxLookupLimit uint64 `json:""`
|
// PercDatabase is percentage of cache used for the database
|
||||||
|
PercDatabase uint64 `hcl:"perc-database,optional"`
|
||||||
|
|
||||||
|
// PercTrie is percentage of cache used for the trie
|
||||||
|
PercTrie uint64 `hcl:"perc-trie,optional"`
|
||||||
|
|
||||||
|
// Journal is the disk journal directory for trie cache to survive node restarts
|
||||||
|
Journal string `hcl:"journal,optional"`
|
||||||
|
|
||||||
|
// Rejournal is the time interval to regenerate the journal for clean cache
|
||||||
|
Rejournal time.Duration
|
||||||
|
RejournalRaw string `hcl:"rejournal,optional"`
|
||||||
|
|
||||||
|
// NoPrefetch is used to disable prefetch of tries
|
||||||
|
NoPrefetch bool `hcl:"no-prefetch,optional"`
|
||||||
|
|
||||||
|
// Preimages is used to enable the track of hash preimages
|
||||||
|
Preimages bool `hcl:"preimages,optional"`
|
||||||
|
|
||||||
|
// TxLookupLimit sets the maximum number of blocks from head whose tx indices are reserved.
|
||||||
|
TxLookupLimit uint64 `hcl:"tx-lookup-limit,optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AccountsConfig struct {
|
type AccountsConfig struct {
|
||||||
Unlock []string `json:""`
|
// Unlock is the list of addresses to unlock in the node
|
||||||
PasswordFile string `json:""`
|
Unlock []string `hcl:"unlock,optional"`
|
||||||
AllowInsecureUnlock bool `json:""`
|
|
||||||
UseLightweightKDF bool `json:""`
|
// PasswordFile is the file where the account passwords are stored
|
||||||
|
PasswordFile string `hcl:"password-file,optional"`
|
||||||
|
|
||||||
|
// AllowInsecureUnlock allows user to unlock accounts in unsafe http environment.
|
||||||
|
AllowInsecureUnlock bool `hcl:"allow-insecure-unlock,optional"`
|
||||||
|
|
||||||
|
// UseLightweightKDF enables a faster but less secure encryption of accounts
|
||||||
|
UseLightweightKDF bool `hcl:"use-lightweight-kdf,optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefaultConfig() *Config {
|
func DefaultConfig() *Config {
|
||||||
return &Config{
|
return &Config{
|
||||||
Chain: "mainnet",
|
Chain: "mainnet",
|
||||||
Debug: false,
|
|
||||||
Whitelist: map[string]string{},
|
Whitelist: map[string]string{},
|
||||||
LogLevel: "INFO",
|
LogLevel: "INFO",
|
||||||
DataDir: defaultDataDir(),
|
DataDir: defaultDataDir(),
|
||||||
|
|
@ -252,7 +425,7 @@ func DefaultConfig() *Config {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Ethstats: "",
|
Ethstats: "",
|
||||||
Metrics: &MetricsConfig{
|
Telemetry: &TelemetryConfig{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
Expensive: false,
|
Expensive: false,
|
||||||
InfluxDB: &InfluxDBConfig{
|
InfluxDB: &InfluxDBConfig{
|
||||||
|
|
@ -289,26 +462,52 @@ func DefaultConfig() *Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func readConfigFile(path string) (*Config, error) {
|
func (c *Config) fillTimeDurations() error {
|
||||||
data, err := ioutil.ReadFile(path)
|
tds := []struct {
|
||||||
if err != nil {
|
path string
|
||||||
return nil, err
|
td *time.Duration
|
||||||
|
str *string
|
||||||
|
}{
|
||||||
|
{"txpool.lifetime", &c.TxPool.LifeTime, &c.TxPool.LifeTimeRaw},
|
||||||
|
{"txpool.rejournal", &c.TxPool.Rejournal, &c.TxPool.RejournalRaw},
|
||||||
|
{"cache.rejournal", &c.Cache.Rejournal, &c.Cache.RejournalRaw},
|
||||||
}
|
}
|
||||||
// TODO: Use hcl as config format
|
|
||||||
|
for _, x := range tds {
|
||||||
|
if x.td != nil && x.str != nil && *x.str != "" {
|
||||||
|
d, err := time.ParseDuration(*x.str)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%s can't parse time duration %s", x.path, *x.str)
|
||||||
|
}
|
||||||
|
*x.str = ""
|
||||||
|
*x.td = d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readConfigFile(path string) (*Config, error) {
|
||||||
ext := filepath.Ext(path)
|
ext := filepath.Ext(path)
|
||||||
if ext == ".toml" {
|
if ext == ".toml" {
|
||||||
|
// read file and apply the legacy config
|
||||||
|
data, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return readLegacyConfig(data)
|
return readLegacyConfig(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// read configuration file
|
config := &Config{
|
||||||
if ext != ".json" {
|
TxPool: &TxPoolConfig{},
|
||||||
return nil, fmt.Errorf("suffix of %s is not json", path)
|
Cache: &CacheConfig{},
|
||||||
}
|
}
|
||||||
var config Config
|
if err := hclsimple.DecodeFile(path, nil, config); err != nil {
|
||||||
if err := json.Unmarshal(data, &config); err != nil {
|
return nil, fmt.Errorf("failed to decode config file '%s': %v", path, err)
|
||||||
|
}
|
||||||
|
if err := config.fillTimeDurations(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) loadChain() error {
|
func (c *Config) loadChain() error {
|
||||||
|
|
@ -343,6 +542,14 @@ func (c *Config) buildEth() (*ethconfig.Config, error) {
|
||||||
n.HeimdallURL = c.Heimdall.URL
|
n.HeimdallURL = c.Heimdall.URL
|
||||||
n.WithoutHeimdall = c.Heimdall.Without
|
n.WithoutHeimdall = c.Heimdall.Without
|
||||||
|
|
||||||
|
// gas price oracle
|
||||||
|
{
|
||||||
|
n.GPO.Blocks = int(c.Gpo.Blocks)
|
||||||
|
n.GPO.Percentile = int(c.Gpo.Percentile)
|
||||||
|
n.GPO.MaxPrice = c.Gpo.MaxPrice
|
||||||
|
n.GPO.IgnorePrice = c.Gpo.IgnorePrice
|
||||||
|
}
|
||||||
|
|
||||||
// txpool options
|
// txpool options
|
||||||
{
|
{
|
||||||
n.TxPool.NoLocals = c.TxPool.NoLocals
|
n.TxPool.NoLocals = c.TxPool.NoLocals
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -23,8 +21,8 @@ func TestConfigDefault(t *testing.T) {
|
||||||
|
|
||||||
func TestConfigMerge(t *testing.T) {
|
func TestConfigMerge(t *testing.T) {
|
||||||
c0 := &Config{
|
c0 := &Config{
|
||||||
Chain: "0",
|
Chain: "0",
|
||||||
Debug: true,
|
Snapshot: true,
|
||||||
Whitelist: map[string]string{
|
Whitelist: map[string]string{
|
||||||
"a": "b",
|
"a": "b",
|
||||||
},
|
},
|
||||||
|
|
@ -54,8 +52,8 @@ func TestConfigMerge(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
expected := &Config{
|
expected := &Config{
|
||||||
Chain: "1",
|
Chain: "1",
|
||||||
Debug: true,
|
Snapshot: true,
|
||||||
Whitelist: map[string]string{
|
Whitelist: map[string]string{
|
||||||
"a": "b",
|
"a": "b",
|
||||||
"b": "c",
|
"b": "c",
|
||||||
|
|
@ -77,31 +75,29 @@ func TestConfigMerge(t *testing.T) {
|
||||||
assert.Equal(t, c0, expected)
|
assert.Equal(t, c0, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigHcl(t *testing.T) {
|
func TestConfigLoadFile(t *testing.T) {
|
||||||
readConfig := func(data string, format string) *Config {
|
readFile := func(path string) {
|
||||||
tmpDir, err := ioutil.TempDir("/tmp", "test-config")
|
config, err := readConfigFile(path)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, config, &Config{
|
||||||
filename := filepath.Join(tmpDir, "config."+format)
|
DataDir: "./data",
|
||||||
assert.NoError(t, ioutil.WriteFile(filename, []byte(data), 0755))
|
P2P: &P2PConfig{
|
||||||
|
MaxPeers: 30,
|
||||||
config, err := readConfigFile(filename)
|
},
|
||||||
assert.NoError(t, err)
|
TxPool: &TxPoolConfig{
|
||||||
return config
|
LifeTime: time.Duration(1 * time.Second),
|
||||||
|
},
|
||||||
|
Cache: &CacheConfig{},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := `{
|
// read file in hcl format
|
||||||
"datadir": "datadir",
|
t.Run("hcl", func(t *testing.T) {
|
||||||
"p2p": {
|
readFile("./testdata/simple.hcl")
|
||||||
"max_peers": 30
|
})
|
||||||
}
|
// read file in json format
|
||||||
}`
|
t.Run("json", func(t *testing.T) {
|
||||||
config := readConfig(cfg, "json")
|
readFile("./testdata/simple.json")
|
||||||
assert.Equal(t, config, &Config{
|
|
||||||
DataDir: "datadir",
|
|
||||||
P2P: &P2PConfig{
|
|
||||||
MaxPeers: 30,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,6 @@ func (c *Command) Flags() *flagset.Flagset {
|
||||||
|
|
||||||
f := flagset.NewFlagSet("server")
|
f := flagset.NewFlagSet("server")
|
||||||
|
|
||||||
f.BoolFlag(&flagset.BoolFlag{
|
|
||||||
Name: "debug",
|
|
||||||
Usage: "Path of the file to apply",
|
|
||||||
Value: &c.cliConfig.Debug,
|
|
||||||
})
|
|
||||||
f.StringFlag(&flagset.StringFlag{
|
f.StringFlag(&flagset.StringFlag{
|
||||||
Name: "chain",
|
Name: "chain",
|
||||||
Usage: "Name of the chain to sync",
|
Usage: "Name of the chain to sync",
|
||||||
|
|
@ -364,63 +359,63 @@ func (c *Command) Flags() *flagset.Flagset {
|
||||||
f.BoolFlag(&flagset.BoolFlag{
|
f.BoolFlag(&flagset.BoolFlag{
|
||||||
Name: "metrics",
|
Name: "metrics",
|
||||||
Usage: "Enable metrics collection and reporting",
|
Usage: "Enable metrics collection and reporting",
|
||||||
Value: &c.cliConfig.Metrics.Enabled,
|
Value: &c.cliConfig.Telemetry.Enabled,
|
||||||
})
|
})
|
||||||
f.BoolFlag(&flagset.BoolFlag{
|
f.BoolFlag(&flagset.BoolFlag{
|
||||||
Name: "metrics.expensive",
|
Name: "metrics.expensive",
|
||||||
Usage: "Enable expensive metrics collection and reporting",
|
Usage: "Enable expensive metrics collection and reporting",
|
||||||
Value: &c.cliConfig.Metrics.Expensive,
|
Value: &c.cliConfig.Telemetry.Expensive,
|
||||||
})
|
})
|
||||||
f.BoolFlag(&flagset.BoolFlag{
|
f.BoolFlag(&flagset.BoolFlag{
|
||||||
Name: "metrics.influxdb",
|
Name: "metrics.influxdb",
|
||||||
Usage: "Enable metrics export/push to an external InfluxDB database (v1)",
|
Usage: "Enable metrics export/push to an external InfluxDB database (v1)",
|
||||||
Value: &c.cliConfig.Metrics.InfluxDB.V1Enabled,
|
Value: &c.cliConfig.Telemetry.InfluxDB.V1Enabled,
|
||||||
})
|
})
|
||||||
f.StringFlag(&flagset.StringFlag{
|
f.StringFlag(&flagset.StringFlag{
|
||||||
Name: "metrics.influxdb.endpoint",
|
Name: "metrics.influxdb.endpoint",
|
||||||
Usage: "InfluxDB API endpoint to report metrics to",
|
Usage: "InfluxDB API endpoint to report metrics to",
|
||||||
Value: &c.cliConfig.Metrics.InfluxDB.Endpoint,
|
Value: &c.cliConfig.Telemetry.InfluxDB.Endpoint,
|
||||||
})
|
})
|
||||||
f.StringFlag(&flagset.StringFlag{
|
f.StringFlag(&flagset.StringFlag{
|
||||||
Name: "metrics.influxdb.database",
|
Name: "metrics.influxdb.database",
|
||||||
Usage: "InfluxDB database name to push reported metrics to",
|
Usage: "InfluxDB database name to push reported metrics to",
|
||||||
Value: &c.cliConfig.Metrics.InfluxDB.Database,
|
Value: &c.cliConfig.Telemetry.InfluxDB.Database,
|
||||||
})
|
})
|
||||||
f.StringFlag(&flagset.StringFlag{
|
f.StringFlag(&flagset.StringFlag{
|
||||||
Name: "metrics.influxdb.username",
|
Name: "metrics.influxdb.username",
|
||||||
Usage: "Username to authorize access to the database",
|
Usage: "Username to authorize access to the database",
|
||||||
Value: &c.cliConfig.Metrics.InfluxDB.Username,
|
Value: &c.cliConfig.Telemetry.InfluxDB.Username,
|
||||||
})
|
})
|
||||||
f.StringFlag(&flagset.StringFlag{
|
f.StringFlag(&flagset.StringFlag{
|
||||||
Name: "metrics.influxdb.password",
|
Name: "metrics.influxdb.password",
|
||||||
Usage: "Password to authorize access to the database",
|
Usage: "Password to authorize access to the database",
|
||||||
Value: &c.cliConfig.Metrics.InfluxDB.Password,
|
Value: &c.cliConfig.Telemetry.InfluxDB.Password,
|
||||||
})
|
})
|
||||||
f.MapStringFlag(&flagset.MapStringFlag{
|
f.MapStringFlag(&flagset.MapStringFlag{
|
||||||
Name: "metrics.influxdb.tags",
|
Name: "metrics.influxdb.tags",
|
||||||
Usage: "Comma-separated InfluxDB tags (key/values) attached to all measurements",
|
Usage: "Comma-separated InfluxDB tags (key/values) attached to all measurements",
|
||||||
Value: &c.cliConfig.Metrics.InfluxDB.Tags,
|
Value: &c.cliConfig.Telemetry.InfluxDB.Tags,
|
||||||
})
|
})
|
||||||
// influx db v2
|
// influx db v2
|
||||||
f.BoolFlag(&flagset.BoolFlag{
|
f.BoolFlag(&flagset.BoolFlag{
|
||||||
Name: "metrics.influxdbv2",
|
Name: "metrics.influxdbv2",
|
||||||
Usage: "Enable metrics export/push to an external InfluxDB v2 database",
|
Usage: "Enable metrics export/push to an external InfluxDB v2 database",
|
||||||
Value: &c.cliConfig.Metrics.InfluxDB.V2Enabled,
|
Value: &c.cliConfig.Telemetry.InfluxDB.V2Enabled,
|
||||||
})
|
})
|
||||||
f.StringFlag(&flagset.StringFlag{
|
f.StringFlag(&flagset.StringFlag{
|
||||||
Name: "metrics.influxdb.token",
|
Name: "metrics.influxdb.token",
|
||||||
Usage: "Token to authorize access to the database (v2 only)",
|
Usage: "Token to authorize access to the database (v2 only)",
|
||||||
Value: &c.cliConfig.Metrics.InfluxDB.Token,
|
Value: &c.cliConfig.Telemetry.InfluxDB.Token,
|
||||||
})
|
})
|
||||||
f.StringFlag(&flagset.StringFlag{
|
f.StringFlag(&flagset.StringFlag{
|
||||||
Name: "metrics.influxdb.bucket",
|
Name: "metrics.influxdb.bucket",
|
||||||
Usage: "InfluxDB bucket name to push reported metrics to (v2 only)",
|
Usage: "InfluxDB bucket name to push reported metrics to (v2 only)",
|
||||||
Value: &c.cliConfig.Metrics.InfluxDB.Bucket,
|
Value: &c.cliConfig.Telemetry.InfluxDB.Bucket,
|
||||||
})
|
})
|
||||||
f.StringFlag(&flagset.StringFlag{
|
f.StringFlag(&flagset.StringFlag{
|
||||||
Name: "metrics.influxdb.organization",
|
Name: "metrics.influxdb.organization",
|
||||||
Usage: "InfluxDB organization name (v2 only)",
|
Usage: "InfluxDB organization name (v2 only)",
|
||||||
Value: &c.cliConfig.Metrics.InfluxDB.Organization,
|
Value: &c.cliConfig.Telemetry.InfluxDB.Organization,
|
||||||
})
|
})
|
||||||
|
|
||||||
// account
|
// account
|
||||||
|
|
|
||||||
9
command/server/testdata/simple.hcl
vendored
Normal file
9
command/server/testdata/simple.hcl
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
data-dir = "./data"
|
||||||
|
|
||||||
|
p2p {
|
||||||
|
max-peers = 30
|
||||||
|
}
|
||||||
|
|
||||||
|
txpool {
|
||||||
|
lifetime = "1s"
|
||||||
|
}
|
||||||
9
command/server/testdata/simple.json
vendored
Normal file
9
command/server/testdata/simple.json
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"data-dir": "./data",
|
||||||
|
"p2p": {
|
||||||
|
"max-peers": 30
|
||||||
|
},
|
||||||
|
"txpool": {
|
||||||
|
"lifetime": "1s"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue