github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/cmd/geth/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 19:16:32</date> 10 //</624450068384059392> 11 12 13 package main 14 15 import ( 16 "bufio" 17 "errors" 18 "fmt" 19 "math/big" 20 "os" 21 "reflect" 22 "unicode" 23 24 cli "gopkg.in/urfave/cli.v1" 25 26 "github.com/ethereum/go-ethereum/cmd/utils" 27 "github.com/ethereum/go-ethereum/dashboard" 28 "github.com/ethereum/go-ethereum/eth" 29 "github.com/ethereum/go-ethereum/node" 30 "github.com/ethereum/go-ethereum/params" 31 whisper "github.com/ethereum/go-ethereum/whisper/whisperv6" 32 "github.com/naoina/toml" 33 ) 34 35 var ( 36 dumpConfigCommand = cli.Command{ 37 Action: utils.MigrateFlags(dumpConfig), 38 Name: "dumpconfig", 39 Usage: "Show configuration values", 40 ArgsUsage: "", 41 Flags: append(append(nodeFlags, rpcFlags...), whisperFlags...), 42 Category: "MISCELLANEOUS COMMANDS", 43 Description: `The dumpconfig command shows configuration values.`, 44 } 45 46 configFileFlag = cli.StringFlag{ 47 Name: "config", 48 Usage: "TOML configuration file", 49 } 50 ) 51 52 //这些设置确保toml键使用与go struct字段相同的名称。 53 var tomlSettings = toml.Config{ 54 NormFieldName: func(rt reflect.Type, key string) string { 55 return key 56 }, 57 FieldToKey: func(rt reflect.Type, field string) string { 58 return field 59 }, 60 MissingField: func(rt reflect.Type, field string) error { 61 link := "" 62 if unicode.IsUpper(rune(rt.Name()[0])) && rt.PkgPath() != "main" { 63 link = fmt.Sprintf(", see https://godoc.org/%s%s,用于可用字段“,rt.pkgpath(),rt.name()) 64 } 65 return fmt.Errorf("field '%s' is not defined in %s%s", field, rt.String(), link) 66 }, 67 } 68 69 type ethstatsConfig struct { 70 URL string `toml:",omitempty"` 71 } 72 73 type gethConfig struct { 74 Eth eth.Config 75 Shh whisper.Config 76 Node node.Config 77 Ethstats ethstatsConfig 78 Dashboard dashboard.Config 79 } 80 81 func loadConfig(file string, cfg *gethConfig) error { 82 f, err := os.Open(file) 83 if err != nil { 84 return err 85 } 86 defer f.Close() 87 88 err = tomlSettings.NewDecoder(bufio.NewReader(f)).Decode(cfg) 89 //将文件名添加到具有行号的错误中。 90 if _, ok := err.(*toml.LineError); ok { 91 err = errors.New(file + ", " + err.Error()) 92 } 93 return err 94 } 95 96 func defaultNodeConfig() node.Config { 97 cfg := node.DefaultConfig 98 cfg.Name = clientIdentifier 99 cfg.Version = params.VersionWithCommit(gitCommit) 100 cfg.HTTPModules = append(cfg.HTTPModules, "eth", "shh") 101 cfg.WSModules = append(cfg.WSModules, "eth", "shh") 102 cfg.IPCPath = "geth.ipc" 103 return cfg 104 } 105 106 func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) { 107 //加载默认值。 108 cfg := gethConfig{ 109 Eth: eth.DefaultConfig, 110 Shh: whisper.DefaultConfig, 111 Node: defaultNodeConfig(), 112 Dashboard: dashboard.DefaultConfig, 113 } 114 115 //加载配置文件。 116 if file := ctx.GlobalString(configFileFlag.Name); file != "" { 117 if err := loadConfig(file, &cfg); err != nil { 118 utils.Fatalf("%v", err) 119 } 120 } 121 122 //应用标志。 123 utils.SetNodeConfig(ctx, &cfg.Node) 124 stack, err := node.New(&cfg.Node) 125 if err != nil { 126 utils.Fatalf("Failed to create the protocol stack: %v", err) 127 } 128 utils.SetEthConfig(ctx, stack, &cfg.Eth) 129 if ctx.GlobalIsSet(utils.EthStatsURLFlag.Name) { 130 cfg.Ethstats.URL = ctx.GlobalString(utils.EthStatsURLFlag.Name) 131 } 132 133 utils.SetShhConfig(ctx, stack, &cfg.Shh) 134 utils.SetDashboardConfig(ctx, &cfg.Dashboard) 135 136 return stack, cfg 137 } 138 139 //如果设置了其中一个耳语标志,则EnableShipper返回true。 140 func enableWhisper(ctx *cli.Context) bool { 141 for _, flag := range whisperFlags { 142 if ctx.GlobalIsSet(flag.GetName()) { 143 return true 144 } 145 } 146 return false 147 } 148 149 func makeFullNode(ctx *cli.Context) *node.Node { 150 stack, cfg := makeConfigNode(ctx) 151 if ctx.GlobalIsSet(utils.ConstantinopleOverrideFlag.Name) { 152 cfg.Eth.ConstantinopleOverride = new(big.Int).SetUint64(ctx.GlobalUint64(utils.ConstantinopleOverrideFlag.Name)) 153 } 154 utils.RegisterEthService(stack, &cfg.Eth) 155 156 if ctx.GlobalBool(utils.DashboardEnabledFlag.Name) { 157 utils.RegisterDashboardService(stack, &cfg.Dashboard, gitCommit) 158 } 159 //必须通过指定至少1个耳语标志或在DEV模式下显式启用耳语 160 shhEnabled := enableWhisper(ctx) 161 shhAutoEnabled := !ctx.GlobalIsSet(utils.WhisperEnabledFlag.Name) && ctx.GlobalIsSet(utils.DeveloperFlag.Name) 162 if shhEnabled || shhAutoEnabled { 163 if ctx.GlobalIsSet(utils.WhisperMaxMessageSizeFlag.Name) { 164 cfg.Shh.MaxMessageSize = uint32(ctx.Int(utils.WhisperMaxMessageSizeFlag.Name)) 165 } 166 if ctx.GlobalIsSet(utils.WhisperMinPOWFlag.Name) { 167 cfg.Shh.MinimumAcceptedPOW = ctx.Float64(utils.WhisperMinPOWFlag.Name) 168 } 169 if ctx.GlobalIsSet(utils.WhisperRestrictConnectionBetweenLightClientsFlag.Name) { 170 cfg.Shh.RestrictConnectionBetweenLightClients = true 171 } 172 utils.RegisterShhService(stack, &cfg.Shh) 173 } 174 175 //如果需要,添加ethereum stats守护进程。 176 if cfg.Ethstats.URL != "" { 177 utils.RegisterEthStatsService(stack, cfg.Ethstats.URL) 178 } 179 return stack 180 } 181 182 //dumpconfig是dumpconfig命令。 183 func dumpConfig(ctx *cli.Context) error { 184 _, cfg := makeConfigNode(ctx) 185 comment := "" 186 187 if cfg.Eth.Genesis != nil { 188 cfg.Eth.Genesis = nil 189 comment += "# Note: this config doesn't contain the genesis block.\n\n" 190 } 191 192 out, err := tomlSettings.Marshal(&cfg) 193 if err != nil { 194 return err 195 } 196 197 dump := os.Stdout 198 if ctx.NArg() > 0 { 199 dump, err = os.OpenFile(ctx.Args().Get(0), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) 200 if err != nil { 201 return err 202 } 203 defer dump.Close() 204 } 205 dump.WriteString(comment) 206 dump.Write(out) 207 208 return nil 209 } 210