github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/cmd/swarm/config.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:31</date> 10 //</624342605144002560> 11 12 13 package main 14 15 import ( 16 "errors" 17 "fmt" 18 "io" 19 "os" 20 "reflect" 21 "strconv" 22 "strings" 23 "time" 24 "unicode" 25 26 cli "gopkg.in/urfave/cli.v1" 27 28 "github.com/ethereum/go-ethereum/cmd/utils" 29 "github.com/ethereum/go-ethereum/common" 30 "github.com/ethereum/go-ethereum/log" 31 "github.com/ethereum/go-ethereum/node" 32 "github.com/naoina/toml" 33 34 bzzapi "github.com/ethereum/go-ethereum/swarm/api" 35 ) 36 37 var ( 38 // 39 DumpConfigCommand = cli.Command{ 40 Action: utils.MigrateFlags(dumpConfig), 41 Name: "dumpconfig", 42 Usage: "Show configuration values", 43 ArgsUsage: "", 44 Flags: app.Flags, 45 Category: "MISCELLANEOUS COMMANDS", 46 Description: `The dumpconfig command shows configuration values.`, 47 } 48 49 // 50 SwarmTomlConfigPathFlag = cli.StringFlag{ 51 Name: "config", 52 Usage: "TOML configuration file", 53 } 54 ) 55 56 // 57 const ( 58 SWARM_ENV_CHEQUEBOOK_ADDR = "SWARM_CHEQUEBOOK_ADDR" 59 SWARM_ENV_ACCOUNT = "SWARM_ACCOUNT" 60 SWARM_ENV_LISTEN_ADDR = "SWARM_LISTEN_ADDR" 61 SWARM_ENV_PORT = "SWARM_PORT" 62 SWARM_ENV_NETWORK_ID = "SWARM_NETWORK_ID" 63 SWARM_ENV_SWAP_ENABLE = "SWARM_SWAP_ENABLE" 64 SWARM_ENV_SWAP_API = "SWARM_SWAP_API" 65 SWARM_ENV_SYNC_DISABLE = "SWARM_SYNC_DISABLE" 66 SWARM_ENV_SYNC_UPDATE_DELAY = "SWARM_ENV_SYNC_UPDATE_DELAY" 67 SWARM_ENV_LIGHT_NODE_ENABLE = "SWARM_LIGHT_NODE_ENABLE" 68 SWARM_ENV_DELIVERY_SKIP_CHECK = "SWARM_DELIVERY_SKIP_CHECK" 69 SWARM_ENV_ENS_API = "SWARM_ENS_API" 70 SWARM_ENV_ENS_ADDR = "SWARM_ENS_ADDR" 71 SWARM_ENV_CORS = "SWARM_CORS" 72 SWARM_ENV_BOOTNODES = "SWARM_BOOTNODES" 73 SWARM_ENV_PSS_ENABLE = "SWARM_PSS_ENABLE" 74 SWARM_ENV_STORE_PATH = "SWARM_STORE_PATH" 75 SWARM_ENV_STORE_CAPACITY = "SWARM_STORE_CAPACITY" 76 SWARM_ENV_STORE_CACHE_CAPACITY = "SWARM_STORE_CACHE_CAPACITY" 77 SWARM_ACCESS_PASSWORD = "SWARM_ACCESS_PASSWORD" 78 GETH_ENV_DATADIR = "GETH_DATADIR" 79 ) 80 81 //这些设置确保toml键使用与go struct字段相同的名称。 82 var tomlSettings = toml.Config{ 83 NormFieldName: func(rt reflect.Type, key string) string { 84 return key 85 }, 86 FieldToKey: func(rt reflect.Type, field string) string { 87 return field 88 }, 89 MissingField: func(rt reflect.Type, field string) error { 90 link := "" 91 if unicode.IsUpper(rune(rt.Name()[0])) && rt.PkgPath() != "main" { 92 link = fmt.Sprintf(", check github.com/ethereum/go-ethereum/swarm/api/config.go for available fields") 93 } 94 return fmt.Errorf("field '%s' is not defined in %s%s", field, rt.String(), link) 95 }, 96 } 97 98 // 99 func buildConfig(ctx *cli.Context) (config *bzzapi.Config, err error) { 100 // 101 config = bzzapi.NewConfig() 102 // 103 config, err = configFileOverride(config, ctx) 104 if err != nil { 105 return nil, err 106 } 107 //覆盖环境变量提供的设置 108 config = envVarsOverride(config) 109 // 110 config = cmdLineOverride(config, ctx) 111 // 112 err = validateConfig(config) 113 114 return 115 } 116 117 // 118 func initSwarmNode(config *bzzapi.Config, stack *node.Node, ctx *cli.Context) { 119 //此时,应在配置中设置所有变量。 120 // 121 prvkey := getAccount(config.BzzAccount, ctx, stack) 122 // 123 config.Path = stack.InstanceDir() 124 // 125 config.Init(prvkey) 126 // 127 log.Debug("Starting Swarm with the following parameters:") 128 // 129 log.Debug(printConfig(config)) 130 } 131 132 // 133 func configFileOverride(config *bzzapi.Config, ctx *cli.Context) (*bzzapi.Config, error) { 134 var err error 135 136 // 137 if ctx.GlobalIsSet(SwarmTomlConfigPathFlag.Name) { 138 var filepath string 139 if filepath = ctx.GlobalString(SwarmTomlConfigPathFlag.Name); filepath == "" { 140 utils.Fatalf("Config file flag provided with invalid file path") 141 } 142 var f *os.File 143 f, err = os.Open(filepath) 144 if err != nil { 145 return nil, err 146 } 147 defer f.Close() 148 149 // 150 // 151 // 152 err = tomlSettings.NewDecoder(f).Decode(&config) 153 //将文件名添加到具有行号的错误中。 154 if _, ok := err.(*toml.LineError); ok { 155 err = errors.New(filepath + ", " + err.Error()) 156 } 157 } 158 return config, err 159 } 160 161 // 162 // 163 func cmdLineOverride(currentConfig *bzzapi.Config, ctx *cli.Context) *bzzapi.Config { 164 165 if keyid := ctx.GlobalString(SwarmAccountFlag.Name); keyid != "" { 166 currentConfig.BzzAccount = keyid 167 } 168 169 if chbookaddr := ctx.GlobalString(ChequebookAddrFlag.Name); chbookaddr != "" { 170 currentConfig.Contract = common.HexToAddress(chbookaddr) 171 } 172 173 if networkid := ctx.GlobalString(SwarmNetworkIdFlag.Name); networkid != "" { 174 if id, _ := strconv.Atoi(networkid); id != 0 { 175 currentConfig.NetworkID = uint64(id) 176 } 177 } 178 179 if ctx.GlobalIsSet(utils.DataDirFlag.Name) { 180 if datadir := ctx.GlobalString(utils.DataDirFlag.Name); datadir != "" { 181 currentConfig.Path = datadir 182 } 183 } 184 185 bzzport := ctx.GlobalString(SwarmPortFlag.Name) 186 if len(bzzport) > 0 { 187 currentConfig.Port = bzzport 188 } 189 190 if bzzaddr := ctx.GlobalString(SwarmListenAddrFlag.Name); bzzaddr != "" { 191 currentConfig.ListenAddr = bzzaddr 192 } 193 194 if ctx.GlobalIsSet(SwarmSwapEnabledFlag.Name) { 195 currentConfig.SwapEnabled = true 196 } 197 198 if ctx.GlobalIsSet(SwarmSyncDisabledFlag.Name) { 199 currentConfig.SyncEnabled = false 200 } 201 202 if d := ctx.GlobalDuration(SwarmSyncUpdateDelay.Name); d > 0 { 203 currentConfig.SyncUpdateDelay = d 204 } 205 206 if ctx.GlobalIsSet(SwarmLightNodeEnabled.Name) { 207 currentConfig.LightNodeEnabled = true 208 } 209 210 if ctx.GlobalIsSet(SwarmDeliverySkipCheckFlag.Name) { 211 currentConfig.DeliverySkipCheck = true 212 } 213 214 currentConfig.SwapAPI = ctx.GlobalString(SwarmSwapAPIFlag.Name) 215 if currentConfig.SwapEnabled && currentConfig.SwapAPI == "" { 216 utils.Fatalf(SWARM_ERR_SWAP_SET_NO_API) 217 } 218 219 if ctx.GlobalIsSet(EnsAPIFlag.Name) { 220 ensAPIs := ctx.GlobalStringSlice(EnsAPIFlag.Name) 221 //保留向后兼容性以禁用ens with--ens api=“” 222 if len(ensAPIs) == 1 && ensAPIs[0] == "" { 223 ensAPIs = nil 224 } 225 currentConfig.EnsAPIs = ensAPIs 226 } 227 228 if cors := ctx.GlobalString(CorsStringFlag.Name); cors != "" { 229 currentConfig.Cors = cors 230 } 231 232 if storePath := ctx.GlobalString(SwarmStorePath.Name); storePath != "" { 233 currentConfig.LocalStoreParams.ChunkDbPath = storePath 234 } 235 236 if storeCapacity := ctx.GlobalUint64(SwarmStoreCapacity.Name); storeCapacity != 0 { 237 currentConfig.LocalStoreParams.DbCapacity = storeCapacity 238 } 239 240 if storeCacheCapacity := ctx.GlobalUint(SwarmStoreCacheCapacity.Name); storeCacheCapacity != 0 { 241 currentConfig.LocalStoreParams.CacheCapacity = storeCacheCapacity 242 } 243 244 return currentConfig 245 246 } 247 248 // 249 // 250 func envVarsOverride(currentConfig *bzzapi.Config) (config *bzzapi.Config) { 251 252 if keyid := os.Getenv(SWARM_ENV_ACCOUNT); keyid != "" { 253 currentConfig.BzzAccount = keyid 254 } 255 256 if chbookaddr := os.Getenv(SWARM_ENV_CHEQUEBOOK_ADDR); chbookaddr != "" { 257 currentConfig.Contract = common.HexToAddress(chbookaddr) 258 } 259 260 if networkid := os.Getenv(SWARM_ENV_NETWORK_ID); networkid != "" { 261 if id, _ := strconv.Atoi(networkid); id != 0 { 262 currentConfig.NetworkID = uint64(id) 263 } 264 } 265 266 if datadir := os.Getenv(GETH_ENV_DATADIR); datadir != "" { 267 currentConfig.Path = datadir 268 } 269 270 bzzport := os.Getenv(SWARM_ENV_PORT) 271 if len(bzzport) > 0 { 272 currentConfig.Port = bzzport 273 } 274 275 if bzzaddr := os.Getenv(SWARM_ENV_LISTEN_ADDR); bzzaddr != "" { 276 currentConfig.ListenAddr = bzzaddr 277 } 278 279 if swapenable := os.Getenv(SWARM_ENV_SWAP_ENABLE); swapenable != "" { 280 if swap, err := strconv.ParseBool(swapenable); err != nil { 281 currentConfig.SwapEnabled = swap 282 } 283 } 284 285 if syncdisable := os.Getenv(SWARM_ENV_SYNC_DISABLE); syncdisable != "" { 286 if sync, err := strconv.ParseBool(syncdisable); err != nil { 287 currentConfig.SyncEnabled = !sync 288 } 289 } 290 291 if v := os.Getenv(SWARM_ENV_DELIVERY_SKIP_CHECK); v != "" { 292 if skipCheck, err := strconv.ParseBool(v); err != nil { 293 currentConfig.DeliverySkipCheck = skipCheck 294 } 295 } 296 297 if v := os.Getenv(SWARM_ENV_SYNC_UPDATE_DELAY); v != "" { 298 if d, err := time.ParseDuration(v); err != nil { 299 currentConfig.SyncUpdateDelay = d 300 } 301 } 302 303 if lne := os.Getenv(SWARM_ENV_LIGHT_NODE_ENABLE); lne != "" { 304 if lightnode, err := strconv.ParseBool(lne); err != nil { 305 currentConfig.LightNodeEnabled = lightnode 306 } 307 } 308 309 if swapapi := os.Getenv(SWARM_ENV_SWAP_API); swapapi != "" { 310 currentConfig.SwapAPI = swapapi 311 } 312 313 if currentConfig.SwapEnabled && currentConfig.SwapAPI == "" { 314 utils.Fatalf(SWARM_ERR_SWAP_SET_NO_API) 315 } 316 317 if ensapi := os.Getenv(SWARM_ENV_ENS_API); ensapi != "" { 318 currentConfig.EnsAPIs = strings.Split(ensapi, ",") 319 } 320 321 if ensaddr := os.Getenv(SWARM_ENV_ENS_ADDR); ensaddr != "" { 322 currentConfig.EnsRoot = common.HexToAddress(ensaddr) 323 } 324 325 if cors := os.Getenv(SWARM_ENV_CORS); cors != "" { 326 currentConfig.Cors = cors 327 } 328 329 return currentConfig 330 } 331 332 //dumpconfig是dumpconfig命令。 333 //将默认配置写入stdout 334 func dumpConfig(ctx *cli.Context) error { 335 cfg, err := buildConfig(ctx) 336 if err != nil { 337 utils.Fatalf(fmt.Sprintf("Uh oh - dumpconfig triggered an error %v", err)) 338 } 339 comment := "" 340 out, err := tomlSettings.Marshal(&cfg) 341 if err != nil { 342 return err 343 } 344 io.WriteString(os.Stdout, comment) 345 os.Stdout.Write(out) 346 return nil 347 } 348 349 // 350 func validateConfig(cfg *bzzapi.Config) (err error) { 351 for _, ensAPI := range cfg.EnsAPIs { 352 if ensAPI != "" { 353 if err := validateEnsAPIs(ensAPI); err != nil { 354 return fmt.Errorf("invalid format [tld:][contract-addr@]url for ENS API endpoint configuration %q: %v", ensAPI, err) 355 } 356 } 357 } 358 return nil 359 } 360 361 //验证ENSAPI配置参数 362 func validateEnsAPIs(s string) (err error) { 363 // 364 if strings.HasPrefix(s, "@") { 365 return errors.New("missing contract address") 366 } 367 // 368 if strings.HasSuffix(s, "@") { 369 return errors.New("missing url") 370 } 371 // 372 if strings.HasPrefix(s, ":") { 373 return errors.New("missing tld") 374 } 375 // 376 if strings.HasSuffix(s, ":") { 377 return errors.New("missing url") 378 } 379 return nil 380 } 381 382 //将配置打印为字符串 383 func printConfig(config *bzzapi.Config) string { 384 out, err := tomlSettings.Marshal(&config) 385 if err != nil { 386 return fmt.Sprintf("Something is not right with the configuration: %v", err) 387 } 388 return string(out) 389 } 390