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 }