github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/cmd/u2u/launcher/config.go (about)

     1  package launcher
     2  
     3  import (
     4  	"bufio"
     5  	"errors"
     6  	"fmt"
     7  	"math/big"
     8  	"os"
     9  	"path"
    10  	"path/filepath"
    11  	"reflect"
    12  	"strings"
    13  
    14  	"github.com/naoina/toml"
    15  	"github.com/syndtr/goleveldb/leveldb/opt"
    16  	"github.com/unicornultrafoundation/go-helios/consensus"
    17  	"github.com/unicornultrafoundation/go-helios/utils/cachescale"
    18  	"github.com/unicornultrafoundation/go-u2u/cmd/utils"
    19  	"github.com/unicornultrafoundation/go-u2u/common"
    20  	"github.com/unicornultrafoundation/go-u2u/log"
    21  	"github.com/unicornultrafoundation/go-u2u/node"
    22  	"github.com/unicornultrafoundation/go-u2u/p2p/enode"
    23  	"github.com/unicornultrafoundation/go-u2u/params"
    24  	"gopkg.in/urfave/cli.v1"
    25  
    26  	"github.com/unicornultrafoundation/go-u2u/evmcore"
    27  	"github.com/unicornultrafoundation/go-u2u/gossip"
    28  	"github.com/unicornultrafoundation/go-u2u/gossip/emitter"
    29  	"github.com/unicornultrafoundation/go-u2u/gossip/gasprice"
    30  	"github.com/unicornultrafoundation/go-u2u/integration"
    31  	"github.com/unicornultrafoundation/go-u2u/integration/makefakegenesis"
    32  	"github.com/unicornultrafoundation/go-u2u/monitoring"
    33  	"github.com/unicornultrafoundation/go-u2u/u2u/genesis"
    34  	"github.com/unicornultrafoundation/go-u2u/u2u/genesisstore"
    35  	futils "github.com/unicornultrafoundation/go-u2u/utils"
    36  	"github.com/unicornultrafoundation/go-u2u/utils/memory"
    37  	"github.com/unicornultrafoundation/go-u2u/vecmt"
    38  )
    39  
    40  var (
    41  	dumpConfigCommand = cli.Command{
    42  		Action:      utils.MigrateFlags(dumpConfig),
    43  		Name:        "dumpconfig",
    44  		Usage:       "Show configuration values",
    45  		ArgsUsage:   "",
    46  		Flags:       append(nodeFlags, testFlags...),
    47  		Category:    "MISCELLANEOUS COMMANDS",
    48  		Description: `The dumpconfig command shows configuration values.`,
    49  	}
    50  	checkConfigCommand = cli.Command{
    51  		Action:      utils.MigrateFlags(checkConfig),
    52  		Name:        "checkconfig",
    53  		Usage:       "Checks configuration file",
    54  		ArgsUsage:   "",
    55  		Flags:       append(nodeFlags, testFlags...),
    56  		Category:    "MISCELLANEOUS COMMANDS",
    57  		Description: `The checkconfig checks configuration file.`,
    58  	}
    59  
    60  	configFileFlag = cli.StringFlag{
    61  		Name:  "config",
    62  		Usage: "TOML configuration file",
    63  	}
    64  
    65  	// DataDirFlag defines directory to store state and user's wallets
    66  	DataDirFlag = utils.DirectoryFlag{
    67  		Name:  "datadir",
    68  		Usage: "Data directory for the databases and keystore",
    69  		Value: utils.DirectoryString(DefaultDataDir()),
    70  	}
    71  
    72  	CacheFlag = cli.IntFlag{
    73  		Name:  "cache",
    74  		Usage: "Megabytes of memory allocated to internal caching",
    75  		Value: DefaultCacheSize,
    76  	}
    77  	// GenesisFlag specifies network genesis configuration
    78  	GenesisFlag = cli.StringFlag{
    79  		Name:  "genesis",
    80  		Usage: "'path to genesis file' - sets the network genesis configuration.",
    81  	}
    82  	ExperimentalGenesisFlag = cli.BoolFlag{
    83  		Name:  "genesis.allowExperimental",
    84  		Usage: "Allow to use experimental genesis file.",
    85  	}
    86  
    87  	RPCGlobalGasCapFlag = cli.Uint64Flag{
    88  		Name:  "rpc.gascap",
    89  		Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)",
    90  		Value: gossip.DefaultConfig(cachescale.Identity).RPCGasCap,
    91  	}
    92  	RPCGlobalTxFeeCapFlag = cli.Float64Flag{
    93  		Name:  "rpc.txfeecap",
    94  		Usage: "Sets a cap on transaction fee (in U2U) that can be sent via the RPC APIs (0 = no cap)",
    95  		Value: gossip.DefaultConfig(cachescale.Identity).RPCTxFeeCap,
    96  	}
    97  	RPCGlobalTimeoutFlag = cli.DurationFlag{
    98  		Name:  "rpc.timeout",
    99  		Usage: "Time limit for RPC calls execution",
   100  		Value: gossip.DefaultConfig(cachescale.Identity).RPCTimeout,
   101  	}
   102  
   103  	SyncModeFlag = cli.StringFlag{
   104  		Name:  "syncmode",
   105  		Usage: `Blockchain sync mode ("full" or "snap")`,
   106  		Value: "full",
   107  	}
   108  
   109  	GCModeFlag = cli.StringFlag{
   110  		Name:  "gcmode",
   111  		Usage: `Blockchain garbage collection mode ("light", "full", "archive")`,
   112  		Value: "archive",
   113  	}
   114  
   115  	ExitWhenAgeFlag = cli.DurationFlag{
   116  		Name:  "exitwhensynced.age",
   117  		Usage: "Exits after synchronisation reaches the required age",
   118  	}
   119  	ExitWhenEpochFlag = cli.Uint64Flag{
   120  		Name:  "exitwhensynced.epoch",
   121  		Usage: "Exits after synchronisation reaches the required epoch",
   122  	}
   123  
   124  	// TxTracerFlag enables transaction tracing recording
   125  	EnableTxTracerFlag = cli.BoolFlag{
   126  		Name:  "enabletxtracer",
   127  		Usage: "DO NOT RUN THIS OPTION AS VALIDATOR. Enable node records inner transaction traces for debugging purpose",
   128  	}
   129  
   130  	DBMigrationModeFlag = cli.StringFlag{
   131  		Name:  "db.migration.mode",
   132  		Usage: "MultiDB migration mode ('reformat' or 'rebuild')",
   133  	}
   134  	DBPresetFlag = cli.StringFlag{
   135  		Name:  "db.preset",
   136  		Usage: "DBs layout preset ('pebble' or 'legacy-pebble')",
   137  	}
   138  
   139  	// MonitoringFlag defines APIs endpoint to mornitor metrics
   140  	EnableMonitorFlag = cli.BoolFlag{
   141  		Name:  "monitor",
   142  		Usage: "Enable the monitor servers",
   143  	}
   144  	PrometheusMonitoringPortFlag = cli.IntFlag{
   145  		Name:  "monitor.prometheus.port",
   146  		Usage: "Opens Prometheus API port to mornitor metrics",
   147  		Value: monitoring.DefaultConfig.Port,
   148  	}
   149  )
   150  
   151  type GenesisTemplate struct {
   152  	Name   string
   153  	Header genesis.Header
   154  	Hashes genesis.Hashes
   155  }
   156  
   157  const (
   158  	// DefaultCacheSize is calculated as memory consumption in a worst case scenario with default configuration
   159  	// Average memory consumption might be 3-5 times lower than the maximum
   160  	DefaultCacheSize  = 3600
   161  	ConstantCacheSize = 400
   162  )
   163  
   164  // These settings ensure that TOML keys use the same names as Go struct fields.
   165  var tomlSettings = toml.Config{
   166  	NormFieldName: func(rt reflect.Type, key string) string {
   167  		return key
   168  	},
   169  	FieldToKey: func(rt reflect.Type, field string) string {
   170  		return field
   171  	},
   172  	MissingField: func(rt reflect.Type, field string) error {
   173  		return fmt.Errorf("field '%s' is not defined in %s", field, rt.String())
   174  	},
   175  }
   176  
   177  type config struct {
   178  	Node           node.Config
   179  	U2U            gossip.Config
   180  	Emitter        emitter.Config
   181  	TxPool         evmcore.TxPoolConfig
   182  	U2UStore       gossip.StoreConfig
   183  	Hashgraph      consensus.Config
   184  	HashgraphStore consensus.StoreConfig
   185  	VectorClock    vecmt.IndexConfig
   186  	DBs            integration.DBsConfig
   187  	Monitoring     monitoring.Config
   188  }
   189  
   190  func (c *config) AppConfigs() integration.Configs {
   191  	return integration.Configs{
   192  		U2U:            c.U2U,
   193  		U2UStore:       c.U2UStore,
   194  		Hashgraph:      c.Hashgraph,
   195  		HashgraphStore: c.HashgraphStore,
   196  		VectorClock:    c.VectorClock,
   197  		DBs:            c.DBs,
   198  	}
   199  }
   200  
   201  func loadAllConfigs(file string, cfg *config) error {
   202  	f, err := os.Open(file)
   203  	if err != nil {
   204  		return err
   205  	}
   206  	defer f.Close()
   207  
   208  	err = tomlSettings.NewDecoder(bufio.NewReader(f)).Decode(cfg)
   209  	// Add file name to errors that have a line number.
   210  	if _, ok := err.(*toml.LineError); ok {
   211  		err = errors.New(file + ", " + err.Error())
   212  	}
   213  	if err != nil {
   214  		return errors.New(fmt.Sprintf("TOML config file error: %v.\n"+
   215  			"Use 'dumpconfig' command to get an example config file.\n"+
   216  			"If node was recently upgraded and a previous network config file is used, then check updates for the config file.", err))
   217  	}
   218  	return err
   219  }
   220  
   221  func mayGetGenesisStore(ctx *cli.Context) *genesisstore.Store {
   222  	switch {
   223  	case ctx.GlobalIsSet(FakeNetFlag.Name):
   224  		_, num, err := parseFakeGen(ctx.GlobalString(FakeNetFlag.Name))
   225  		if err != nil {
   226  			log.Crit("Invalid flag", "flag", FakeNetFlag.Name, "err", err)
   227  		}
   228  		return makefakegenesis.FakeGenesisStore(num, futils.ToU2U(1000000000), futils.ToU2U(5000000))
   229  	case ctx.GlobalIsSet(GenesisFlag.Name):
   230  		genesisPath := ctx.GlobalString(GenesisFlag.Name)
   231  
   232  		f, err := os.Open(genesisPath)
   233  		if err != nil {
   234  			utils.Fatalf("Failed to open genesis file: %v", err)
   235  		}
   236  		genesisStore, genesisHashes, err := genesisstore.OpenGenesisStore(f)
   237  		if err != nil {
   238  			utils.Fatalf("Failed to read genesis file: %v", err)
   239  		}
   240  
   241  		// check if it's a trusted preset
   242  		{
   243  			g := genesisStore.Genesis()
   244  			gHeader := genesis.Header{
   245  				GenesisID:   g.GenesisID,
   246  				NetworkID:   g.NetworkID,
   247  				NetworkName: g.NetworkName,
   248  			}
   249  			for _, allowed := range AllowedU2UGenesis {
   250  				if allowed.Hashes.Equal(genesisHashes) && allowed.Header.Equal(gHeader) {
   251  					log.Info("Genesis file is a known preset", "name", allowed.Name)
   252  					goto notExperimental
   253  				}
   254  			}
   255  			if ctx.GlobalBool(ExperimentalGenesisFlag.Name) {
   256  				log.Warn("Genesis file doesn't refer to any trusted preset")
   257  			} else {
   258  				utils.Fatalf("Genesis file doesn't refer to any trusted preset. Enable experimental genesis with --genesis.allowExperimental")
   259  			}
   260  		notExperimental:
   261  		}
   262  		return genesisStore
   263  	}
   264  	return nil
   265  }
   266  
   267  func setBootnodes(ctx *cli.Context, urls []string, cfg *node.Config) {
   268  	cfg.P2P.BootstrapNodesV5 = []*enode.Node{}
   269  	for _, url := range urls {
   270  		if url != "" {
   271  			node, err := enode.Parse(enode.ValidSchemes, url)
   272  			if err != nil {
   273  				log.Error("Bootstrap URL invalid", "enode", url, "err", err)
   274  				continue
   275  			}
   276  			cfg.P2P.BootstrapNodesV5 = append(cfg.P2P.BootstrapNodesV5, node)
   277  		}
   278  	}
   279  	cfg.P2P.BootstrapNodes = cfg.P2P.BootstrapNodesV5
   280  }
   281  
   282  func setDataDir(ctx *cli.Context, cfg *node.Config) {
   283  	defaultDataDir := DefaultDataDir()
   284  
   285  	switch {
   286  	case ctx.GlobalIsSet(DataDirFlag.Name):
   287  		cfg.DataDir = ctx.GlobalString(DataDirFlag.Name)
   288  	case ctx.GlobalIsSet(FakeNetFlag.Name):
   289  		_, num, err := parseFakeGen(ctx.GlobalString(FakeNetFlag.Name))
   290  		if err != nil {
   291  			log.Crit("Invalid flag", "flag", FakeNetFlag.Name, "err", err)
   292  		}
   293  		cfg.DataDir = filepath.Join(defaultDataDir, fmt.Sprintf("fakenet-%d", num))
   294  	}
   295  }
   296  
   297  func setGPO(ctx *cli.Context, cfg *gasprice.Config) {}
   298  
   299  func setTxPool(ctx *cli.Context, cfg *evmcore.TxPoolConfig) {
   300  	if ctx.GlobalIsSet(utils.TxPoolLocalsFlag.Name) {
   301  		locals := strings.Split(ctx.GlobalString(utils.TxPoolLocalsFlag.Name), ",")
   302  		for _, account := range locals {
   303  			if trimmed := strings.TrimSpace(account); !common.IsHexAddress(trimmed) {
   304  				utils.Fatalf("Invalid account in --txpool.locals: %s", trimmed)
   305  			} else {
   306  				cfg.Locals = append(cfg.Locals, common.HexToAddress(account))
   307  			}
   308  		}
   309  	}
   310  	if ctx.GlobalIsSet(utils.TxPoolNoLocalsFlag.Name) {
   311  		cfg.NoLocals = ctx.GlobalBool(utils.TxPoolNoLocalsFlag.Name)
   312  	}
   313  	if ctx.GlobalIsSet(utils.TxPoolJournalFlag.Name) {
   314  		cfg.Journal = ctx.GlobalString(utils.TxPoolJournalFlag.Name)
   315  	}
   316  	if ctx.GlobalIsSet(utils.TxPoolRejournalFlag.Name) {
   317  		cfg.Rejournal = ctx.GlobalDuration(utils.TxPoolRejournalFlag.Name)
   318  	}
   319  	if ctx.GlobalIsSet(utils.TxPoolPriceLimitFlag.Name) {
   320  		cfg.PriceLimit = ctx.GlobalUint64(utils.TxPoolPriceLimitFlag.Name)
   321  	}
   322  	if ctx.GlobalIsSet(utils.TxPoolPriceBumpFlag.Name) {
   323  		cfg.PriceBump = ctx.GlobalUint64(utils.TxPoolPriceBumpFlag.Name)
   324  	}
   325  	if ctx.GlobalIsSet(utils.TxPoolAccountSlotsFlag.Name) {
   326  		cfg.AccountSlots = ctx.GlobalUint64(utils.TxPoolAccountSlotsFlag.Name)
   327  	}
   328  	if ctx.GlobalIsSet(utils.TxPoolGlobalSlotsFlag.Name) {
   329  		cfg.GlobalSlots = ctx.GlobalUint64(utils.TxPoolGlobalSlotsFlag.Name)
   330  	}
   331  	if ctx.GlobalIsSet(utils.TxPoolAccountQueueFlag.Name) {
   332  		cfg.AccountQueue = ctx.GlobalUint64(utils.TxPoolAccountQueueFlag.Name)
   333  	}
   334  	if ctx.GlobalIsSet(utils.TxPoolGlobalQueueFlag.Name) {
   335  		cfg.GlobalQueue = ctx.GlobalUint64(utils.TxPoolGlobalQueueFlag.Name)
   336  	}
   337  	if ctx.GlobalIsSet(utils.TxPoolLifetimeFlag.Name) {
   338  		cfg.Lifetime = ctx.GlobalDuration(utils.TxPoolLifetimeFlag.Name)
   339  	}
   340  }
   341  
   342  func gossipConfigWithFlags(ctx *cli.Context, src gossip.Config) (gossip.Config, error) {
   343  	cfg := src
   344  
   345  	setGPO(ctx, &cfg.GPO)
   346  
   347  	if ctx.GlobalIsSet(RPCGlobalGasCapFlag.Name) {
   348  		cfg.RPCGasCap = ctx.GlobalUint64(RPCGlobalGasCapFlag.Name)
   349  	}
   350  	if ctx.GlobalIsSet(RPCGlobalTxFeeCapFlag.Name) {
   351  		cfg.RPCTxFeeCap = ctx.GlobalFloat64(RPCGlobalTxFeeCapFlag.Name)
   352  	}
   353  	if ctx.GlobalIsSet(RPCGlobalTimeoutFlag.Name) {
   354  		cfg.RPCTimeout = ctx.GlobalDuration(RPCGlobalTimeoutFlag.Name)
   355  	}
   356  	if ctx.GlobalIsSet(SyncModeFlag.Name) {
   357  		if syncmode := ctx.GlobalString(SyncModeFlag.Name); syncmode != "full" && syncmode != "snap" {
   358  			utils.Fatalf("--%s must be either 'full' or 'snap'", SyncModeFlag.Name)
   359  		}
   360  		cfg.AllowSnapsync = ctx.GlobalString(SyncModeFlag.Name) == "snap"
   361  	}
   362  	if ctx.GlobalIsSet(utils.AllowUnprotectedTxs.Name) {
   363  		cfg.AllowUnprotectedTxs = ctx.GlobalBool(utils.AllowUnprotectedTxs.Name)
   364  	}
   365  
   366  	return cfg, nil
   367  }
   368  
   369  func gossipStoreConfigWithFlags(ctx *cli.Context, src gossip.StoreConfig) (gossip.StoreConfig, error) {
   370  	cfg := src
   371  	if ctx.GlobalIsSet(utils.GCModeFlag.Name) {
   372  		if gcmode := ctx.GlobalString(utils.GCModeFlag.Name); gcmode != "light" && gcmode != "full" && gcmode != "archive" {
   373  			utils.Fatalf("--%s must be 'light', 'full' or 'archive'", GCModeFlag.Name)
   374  		}
   375  		cfg.EVM.Cache.TrieDirtyDisabled = ctx.GlobalString(utils.GCModeFlag.Name) == "archive"
   376  		cfg.EVM.Cache.GreedyGC = ctx.GlobalString(utils.GCModeFlag.Name) == "full"
   377  	}
   378  	return cfg, nil
   379  }
   380  
   381  func setDBConfig(ctx *cli.Context, cfg integration.DBsConfig, cacheRatio cachescale.Func) integration.DBsConfig {
   382  	if ctx.GlobalIsSet(DBPresetFlag.Name) {
   383  		preset := ctx.GlobalString(DBPresetFlag.Name)
   384  		cfg = setDBConfigStr(cfg, cacheRatio, preset)
   385  	}
   386  	if ctx.GlobalIsSet(DBMigrationModeFlag.Name) {
   387  		cfg.MigrationMode = ctx.GlobalString(DBMigrationModeFlag.Name)
   388  	}
   389  	return cfg
   390  }
   391  
   392  func setDBConfigStr(cfg integration.DBsConfig, cacheRatio cachescale.Func, preset string) integration.DBsConfig {
   393  	switch preset {
   394  	case "pebble":
   395  		cfg = integration.Pbl1DBsConfig(cacheRatio.U64, uint64(utils.MakeDatabaseHandles()))
   396  	case "legacy-pebble":
   397  		cfg = integration.PblLegacyDBsConfig(cacheRatio.U64, uint64(utils.MakeDatabaseHandles()))
   398  	default:
   399  		utils.Fatalf("--%s must be 'pebble' or 'legacy-pebble'", DBPresetFlag.Name)
   400  	}
   401  	// sanity check
   402  	if preset != reversePresetName(cfg.Routing) {
   403  		log.Error("Preset name cannot be reversed")
   404  	}
   405  	return cfg
   406  }
   407  
   408  func reversePresetName(cfg integration.RoutingConfig) string {
   409  	pbl1 := integration.Pbl1RoutingConfig()
   410  	pblLegacy := integration.PblLegacyRoutingConfig()
   411  	if cfg.Equal(pbl1) {
   412  		return "pebble"
   413  	}
   414  	if cfg.Equal(pblLegacy) {
   415  		return "legacy-pebble"
   416  	}
   417  	return ""
   418  }
   419  
   420  func memorizeDBPreset(cfg *config) {
   421  	preset := reversePresetName(cfg.DBs.Routing)
   422  	pPath := path.Join(cfg.Node.DataDir, "chaindata", "preset")
   423  	if len(preset) != 0 {
   424  		futils.FilePut(pPath, []byte(preset), true)
   425  	} else {
   426  		_ = os.Remove(pPath)
   427  	}
   428  }
   429  
   430  func setDBConfigDefault(cfg config, cacheRatio cachescale.Func) config {
   431  	if len(cfg.DBs.Routing.Table) == 0 && len(cfg.DBs.GenesisCache.Table) == 0 && len(cfg.DBs.RuntimeCache.Table) == 0 {
   432  		// Substitute memorized db preset from datadir, unless already set
   433  		datadirPreset := futils.FileGet(path.Join(cfg.Node.DataDir, "chaindata", "preset"))
   434  		if len(datadirPreset) != 0 {
   435  			cfg.DBs = setDBConfigStr(cfg.DBs, cacheRatio, string(datadirPreset))
   436  		}
   437  	}
   438  	// apply default for DB config if it wasn't touched by config file or flags, and there's no datadir's default value
   439  	dbDefault := integration.DefaultDBsConfig(cacheRatio.U64, uint64(utils.MakeDatabaseHandles()))
   440  	if len(cfg.DBs.Routing.Table) == 0 {
   441  		cfg.DBs.Routing = dbDefault.Routing
   442  	}
   443  	if len(cfg.DBs.GenesisCache.Table) == 0 {
   444  		cfg.DBs.GenesisCache = dbDefault.GenesisCache
   445  	}
   446  	if len(cfg.DBs.RuntimeCache.Table) == 0 {
   447  		cfg.DBs.RuntimeCache = dbDefault.RuntimeCache
   448  	}
   449  	return cfg
   450  }
   451  
   452  func setMonitoringConfig(ctx *cli.Context, cfg monitoring.Config) monitoring.Config {
   453  	// apply config for monitoring
   454  	cfg.Port = ctx.GlobalInt(PrometheusMonitoringPortFlag.Name)
   455  
   456  	return cfg
   457  }
   458  
   459  func nodeConfigWithFlags(ctx *cli.Context, cfg node.Config) node.Config {
   460  	utils.SetNodeConfig(ctx, &cfg)
   461  
   462  	setDataDir(ctx, &cfg)
   463  	return cfg
   464  }
   465  
   466  func cacheScaler(ctx *cli.Context) cachescale.Func {
   467  	targetCache := ctx.GlobalInt(CacheFlag.Name)
   468  	baseSize := DefaultCacheSize
   469  	totalMemory := int(memory.TotalMemory() / opt.MiB)
   470  	maxCache := totalMemory * 3 / 5
   471  	if maxCache < baseSize {
   472  		maxCache = baseSize
   473  	}
   474  	if !ctx.GlobalIsSet(CacheFlag.Name) {
   475  		recommendedCache := totalMemory / 2
   476  		if recommendedCache > baseSize {
   477  			log.Warn(fmt.Sprintf("Please add '--%s %d' flag to allocate more cache for U2U Client. Total memory is %d MB.", CacheFlag.Name, recommendedCache, totalMemory))
   478  		}
   479  		return cachescale.Identity
   480  	}
   481  	if targetCache < baseSize {
   482  		log.Crit("Invalid flag", "flag", CacheFlag.Name, "err", fmt.Sprintf("minimum cache size is %d MB", baseSize))
   483  	}
   484  	if totalMemory != 0 && targetCache > maxCache {
   485  		log.Warn(fmt.Sprintf("Requested cache size exceeds 60%% of available memory. Reducing cache size to %d MB.", maxCache))
   486  		targetCache = maxCache
   487  	}
   488  	return cachescale.Ratio{
   489  		Base:   uint64(baseSize - ConstantCacheSize),
   490  		Target: uint64(targetCache - ConstantCacheSize),
   491  	}
   492  }
   493  
   494  func mayMakeAllConfigs(ctx *cli.Context) (*config, error) {
   495  	// Defaults (low priority)
   496  	cacheRatio := cacheScaler(ctx)
   497  	cfg := config{
   498  		Node:           defaultNodeConfig(),
   499  		U2U:            gossip.DefaultConfig(cacheRatio),
   500  		Emitter:        emitter.DefaultConfig(),
   501  		TxPool:         evmcore.DefaultTxPoolConfig,
   502  		U2UStore:       gossip.DefaultStoreConfig(cacheRatio),
   503  		Hashgraph:      consensus.DefaultConfig(),
   504  		HashgraphStore: consensus.DefaultStoreConfig(cacheRatio),
   505  		VectorClock:    vecmt.DefaultConfig(cacheRatio),
   506  	}
   507  
   508  	if ctx.GlobalIsSet(FakeNetFlag.Name) {
   509  		_, num, _ := parseFakeGen(ctx.GlobalString(FakeNetFlag.Name))
   510  		cfg.Emitter = emitter.FakeConfig(num)
   511  		setBootnodes(ctx, []string{}, &cfg.Node)
   512  	} else {
   513  		// "asDefault" means set network defaults
   514  		cfg.Node.P2P.BootstrapNodes = asDefault
   515  		cfg.Node.P2P.BootstrapNodesV5 = asDefault
   516  	}
   517  
   518  	// Load config file (medium priority)
   519  	if file := ctx.GlobalString(configFileFlag.Name); file != "" {
   520  		if err := loadAllConfigs(file, &cfg); err != nil {
   521  			return &cfg, err
   522  		}
   523  	}
   524  
   525  	// Apply flags (high priority)
   526  	var err error
   527  	cfg.U2U, err = gossipConfigWithFlags(ctx, cfg.U2U)
   528  	if err != nil {
   529  		return nil, err
   530  	}
   531  	cfg.U2UStore, err = gossipStoreConfigWithFlags(ctx, cfg.U2UStore)
   532  	if err != nil {
   533  		return nil, err
   534  	}
   535  	cfg.Node = nodeConfigWithFlags(ctx, cfg.Node)
   536  	cfg.DBs = setDBConfig(ctx, cfg.DBs, cacheRatio)
   537  
   538  	err = setValidator(ctx, &cfg.Emitter)
   539  	if err != nil {
   540  		return nil, err
   541  	}
   542  	if cfg.Emitter.Validator.ID != 0 && len(cfg.Emitter.PrevEmittedEventFile.Path) == 0 {
   543  		cfg.Emitter.PrevEmittedEventFile.Path = cfg.Node.ResolvePath(path.Join("emitter", fmt.Sprintf("last-%d", cfg.Emitter.Validator.ID)))
   544  	}
   545  	setTxPool(ctx, &cfg.TxPool)
   546  
   547  	// Process DBs defaults in the end because they are applied only in absence of config or flags
   548  	cfg = setDBConfigDefault(cfg, cacheRatio)
   549  	// Sanitize GPO config
   550  	if cfg.U2U.GPO.MinGasTip == nil || cfg.U2U.GPO.MinGasTip.Sign() == 0 {
   551  		cfg.U2U.GPO.MinGasTip = new(big.Int).SetUint64(cfg.TxPool.PriceLimit)
   552  	}
   553  	if cfg.U2U.GPO.MinGasTip.Cmp(new(big.Int).SetUint64(cfg.TxPool.PriceLimit)) < 0 {
   554  		log.Warn(fmt.Sprintf("GPO minimum gas tip (U2U.GPO.MinGasTip=%s) is lower than txpool minimum gas tip (TxPool.PriceLimit=%d)", cfg.U2U.GPO.MinGasTip.String(), cfg.TxPool.PriceLimit))
   555  	}
   556  
   557  	if err := cfg.U2U.Validate(); err != nil {
   558  		return nil, err
   559  	}
   560  
   561  	if ctx.GlobalIsSet(EnableTxTracerFlag.Name) {
   562  		cfg.U2UStore.TraceTransactions = true
   563  	}
   564  
   565  	if ctx.GlobalIsSet(EnableMonitorFlag.Name) {
   566  		cfg.Monitoring = setMonitoringConfig(ctx, cfg.Monitoring)
   567  	}
   568  
   569  	return &cfg, nil
   570  }
   571  
   572  func makeAllConfigs(ctx *cli.Context) *config {
   573  	cfg, err := mayMakeAllConfigs(ctx)
   574  	if err != nil {
   575  		utils.Fatalf("%v", err)
   576  	}
   577  	return cfg
   578  }
   579  
   580  func defaultNodeConfig() node.Config {
   581  	cfg := NodeDefaultConfig
   582  	cfg.Name = clientIdentifier
   583  	cfg.Version = params.VersionWithCommit(gitCommit, gitDate)
   584  	cfg.HTTPModules = append(cfg.HTTPModules, "eth", "dag", "abft", "web3")
   585  	cfg.WSModules = append(cfg.WSModules, "eth", "dag", "abft", "web3")
   586  	cfg.IPCPath = "u2u.ipc"
   587  	cfg.DataDir = DefaultDataDir()
   588  	return cfg
   589  }
   590  
   591  // dumpConfig is the dumpconfig command.
   592  func dumpConfig(ctx *cli.Context) error {
   593  	cfg := makeAllConfigs(ctx)
   594  	comment := ""
   595  
   596  	out, err := tomlSettings.Marshal(&cfg)
   597  	if err != nil {
   598  		return err
   599  	}
   600  
   601  	dump := os.Stdout
   602  	if ctx.NArg() > 0 {
   603  		dump, err = os.OpenFile(ctx.Args().Get(0), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
   604  		if err != nil {
   605  			return err
   606  		}
   607  		defer dump.Close()
   608  	}
   609  	dump.WriteString(comment)
   610  	dump.Write(out)
   611  
   612  	return nil
   613  }
   614  
   615  func checkConfig(ctx *cli.Context) error {
   616  	_, err := mayMakeAllConfigs(ctx)
   617  	return err
   618  }