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