github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/cmd/swarm/main.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 //版权所有2016 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 "crypto/ecdsa" 29 "fmt" 30 "io/ioutil" 31 "os" 32 "os/signal" 33 "runtime" 34 "sort" 35 "strconv" 36 "strings" 37 "syscall" 38 39 "github.com/ethereum/go-ethereum/accounts" 40 "github.com/ethereum/go-ethereum/accounts/keystore" 41 "github.com/ethereum/go-ethereum/cmd/utils" 42 "github.com/ethereum/go-ethereum/common" 43 "github.com/ethereum/go-ethereum/console" 44 "github.com/ethereum/go-ethereum/crypto" 45 "github.com/ethereum/go-ethereum/internal/debug" 46 "github.com/ethereum/go-ethereum/log" 47 "github.com/ethereum/go-ethereum/node" 48 "github.com/ethereum/go-ethereum/p2p/discover" 49 "github.com/ethereum/go-ethereum/swarm" 50 bzzapi "github.com/ethereum/go-ethereum/swarm/api" 51 swarmmetrics "github.com/ethereum/go-ethereum/swarm/metrics" 52 "github.com/ethereum/go-ethereum/swarm/tracing" 53 sv "github.com/ethereum/go-ethereum/swarm/version" 54 55 "gopkg.in/urfave/cli.v1" 56 ) 57 58 const clientIdentifier = "swarm" 59 const helpTemplate = `NAME: 60 {{.HelpName}} - {{.Usage}} 61 62 USAGE: 63 {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}} 64 65 CATEGORY: 66 {{.Category}}{{end}}{{if .Description}} 67 68 DESCRIPTION: 69 {{.Description}}{{end}}{{if .VisibleFlags}} 70 71 OPTIONS: 72 {{range .VisibleFlags}}{{.}} 73 {{end}}{{end}} 74 ` 75 76 var ( 77 gitCommit string //git sha1提交发布的哈希(通过链接器标志设置) 78 ) 79 80 var ( 81 ChequebookAddrFlag = cli.StringFlag{ 82 Name: "chequebook", 83 Usage: "chequebook contract address", 84 EnvVar: SWARM_ENV_CHEQUEBOOK_ADDR, 85 } 86 SwarmAccountFlag = cli.StringFlag{ 87 Name: "bzzaccount", 88 Usage: "Swarm account key file", 89 EnvVar: SWARM_ENV_ACCOUNT, 90 } 91 SwarmListenAddrFlag = cli.StringFlag{ 92 Name: "httpaddr", 93 Usage: "Swarm HTTP API listening interface", 94 EnvVar: SWARM_ENV_LISTEN_ADDR, 95 } 96 SwarmPortFlag = cli.StringFlag{ 97 Name: "bzzport", 98 Usage: "Swarm local http api port", 99 EnvVar: SWARM_ENV_PORT, 100 } 101 SwarmNetworkIdFlag = cli.IntFlag{ 102 Name: "bzznetworkid", 103 Usage: "Network identifier (integer, default 3=swarm testnet)", 104 EnvVar: SWARM_ENV_NETWORK_ID, 105 } 106 SwarmSwapEnabledFlag = cli.BoolFlag{ 107 Name: "swap", 108 Usage: "Swarm SWAP enabled (default false)", 109 EnvVar: SWARM_ENV_SWAP_ENABLE, 110 } 111 SwarmSwapAPIFlag = cli.StringFlag{ 112 Name: "swap-api", 113 Usage: "URL of the Ethereum API provider to use to settle SWAP payments", 114 EnvVar: SWARM_ENV_SWAP_API, 115 } 116 SwarmSyncDisabledFlag = cli.BoolTFlag{ 117 Name: "nosync", 118 Usage: "Disable swarm syncing", 119 EnvVar: SWARM_ENV_SYNC_DISABLE, 120 } 121 SwarmSyncUpdateDelay = cli.DurationFlag{ 122 Name: "sync-update-delay", 123 Usage: "Duration for sync subscriptions update after no new peers are added (default 15s)", 124 EnvVar: SWARM_ENV_SYNC_UPDATE_DELAY, 125 } 126 SwarmLightNodeEnabled = cli.BoolFlag{ 127 Name: "lightnode", 128 Usage: "Enable Swarm LightNode (default false)", 129 EnvVar: SWARM_ENV_LIGHT_NODE_ENABLE, 130 } 131 SwarmDeliverySkipCheckFlag = cli.BoolFlag{ 132 Name: "delivery-skip-check", 133 Usage: "Skip chunk delivery check (default false)", 134 EnvVar: SWARM_ENV_DELIVERY_SKIP_CHECK, 135 } 136 EnsAPIFlag = cli.StringSliceFlag{ 137 Name: "ens-api", 138 Usage: "ENS API endpoint for a TLD and with contract address, can be repeated, format [tld:][contract-addr@]url", 139 EnvVar: SWARM_ENV_ENS_API, 140 } 141 SwarmApiFlag = cli.StringFlag{ 142 Name: "bzzapi", 143 Usage: "Swarm HTTP endpoint", 144 Value: "http:// 145 } 146 SwarmRecursiveFlag = cli.BoolFlag{ 147 Name: "recursive", 148 Usage: "Upload directories recursively", 149 } 150 SwarmWantManifestFlag = cli.BoolTFlag{ 151 Name: "manifest", 152 Usage: "Automatic manifest upload (default true)", 153 } 154 SwarmUploadDefaultPath = cli.StringFlag{ 155 Name: "defaultpath", 156 Usage: "path to file served for empty url path (none)", 157 } 158 SwarmAccessGrantKeyFlag = cli.StringFlag{ 159 Name: "grant-key", 160 Usage: "grants a given public key access to an ACT", 161 } 162 SwarmAccessGrantKeysFlag = cli.StringFlag{ 163 Name: "grant-keys", 164 Usage: "grants a given list of public keys in the following file (separated by line breaks) access to an ACT", 165 } 166 SwarmUpFromStdinFlag = cli.BoolFlag{ 167 Name: "stdin", 168 Usage: "reads data to be uploaded from stdin", 169 } 170 SwarmUploadMimeType = cli.StringFlag{ 171 Name: "mime", 172 Usage: "Manually specify MIME type", 173 } 174 SwarmEncryptedFlag = cli.BoolFlag{ 175 Name: "encrypt", 176 Usage: "use encrypted upload", 177 } 178 SwarmAccessPasswordFlag = cli.StringFlag{ 179 Name: "password", 180 Usage: "Password", 181 EnvVar: SWARM_ACCESS_PASSWORD, 182 } 183 SwarmDryRunFlag = cli.BoolFlag{ 184 Name: "dry-run", 185 Usage: "dry-run", 186 } 187 CorsStringFlag = cli.StringFlag{ 188 Name: "corsdomain", 189 Usage: "Domain on which to send Access-Control-Allow-Origin header (multiple domains can be supplied separated by a ',')", 190 EnvVar: SWARM_ENV_CORS, 191 } 192 SwarmStorePath = cli.StringFlag{ 193 Name: "store.path", 194 Usage: "Path to leveldb chunk DB (default <$GETH_ENV_DIR>/swarm/bzz-<$BZZ_KEY>/chunks)", 195 EnvVar: SWARM_ENV_STORE_PATH, 196 } 197 SwarmStoreCapacity = cli.Uint64Flag{ 198 Name: "store.size", 199 Usage: "Number of chunks (5M is roughly 20-25GB) (default 5000000)", 200 EnvVar: SWARM_ENV_STORE_CAPACITY, 201 } 202 SwarmStoreCacheCapacity = cli.UintFlag{ 203 Name: "store.cache.size", 204 Usage: "Number of recent chunks cached in memory (default 5000)", 205 EnvVar: SWARM_ENV_STORE_CACHE_CAPACITY, 206 } 207 SwarmResourceMultihashFlag = cli.BoolFlag{ 208 Name: "multihash", 209 Usage: "Determines how to interpret data for a resource update. If not present, data will be interpreted as raw, literal data that will be included in the resource", 210 } 211 SwarmResourceNameFlag = cli.StringFlag{ 212 Name: "name", 213 Usage: "User-defined name for the new resource", 214 } 215 SwarmResourceDataOnCreateFlag = cli.StringFlag{ 216 Name: "data", 217 Usage: "Initializes the resource with the given hex-encoded data. Data must be prefixed by 0x", 218 } 219 ) 220 221 //声明几个常量错误消息,对以后测试中的错误检查比较很有用 222 var ( 223 SWARM_ERR_NO_BZZACCOUNT = "bzzaccount option is required but not set; check your config file, command line or environment variables" 224 SWARM_ERR_SWAP_SET_NO_API = "SWAP is enabled but --swap-api is not set" 225 ) 226 227 // 228 var defaultSubcommandHelp = cli.Command{ 229 Action: func(ctx *cli.Context) { cli.ShowCommandHelpAndExit(ctx, "", 1) }, 230 CustomHelpTemplate: helpTemplate, 231 Name: "help", 232 Usage: "shows this help", 233 Hidden: true, 234 } 235 236 var defaultNodeConfig = node.DefaultConfig 237 238 // 239 func init() { 240 defaultNodeConfig.Name = clientIdentifier 241 defaultNodeConfig.Version = sv.VersionWithCommit(gitCommit) 242 defaultNodeConfig.P2P.ListenAddr = ":30399" 243 defaultNodeConfig.IPCPath = "bzzd.ipc" 244 // 245 utils.ListenPortFlag.Value = 30399 246 } 247 248 var app = utils.NewApp(gitCommit, "Ethereum Swarm") 249 250 //这个init函数创建cli.app。 251 func init() { 252 app.Action = bzzd 253 app.HideVersion = true //我们有打印版本的命令 254 app.Copyright = "Copyright 2013-2016 The go-ethereum Authors" 255 app.Commands = []cli.Command{ 256 { 257 Action: version, 258 CustomHelpTemplate: helpTemplate, 259 Name: "version", 260 Usage: "Print version numbers", 261 Description: "The output of this command is supposed to be machine-readable", 262 }, 263 { 264 Action: upload, 265 CustomHelpTemplate: helpTemplate, 266 Name: "up", 267 Usage: "uploads a file or directory to swarm using the HTTP API", 268 ArgsUsage: "<file>", 269 Flags: []cli.Flag{SwarmEncryptedFlag}, 270 Description: "uploads a file or directory to swarm using the HTTP API and prints the root hash", 271 }, 272 { 273 CustomHelpTemplate: helpTemplate, 274 Name: "access", 275 Usage: "encrypts a reference and embeds it into a root manifest", 276 ArgsUsage: "<ref>", 277 Description: "encrypts a reference and embeds it into a root manifest", 278 Subcommands: []cli.Command{ 279 { 280 CustomHelpTemplate: helpTemplate, 281 Name: "new", 282 Usage: "encrypts a reference and embeds it into a root manifest", 283 ArgsUsage: "<ref>", 284 Description: "encrypts a reference and embeds it into a root access manifest and prints the resulting manifest", 285 Subcommands: []cli.Command{ 286 { 287 Action: accessNewPass, 288 CustomHelpTemplate: helpTemplate, 289 Flags: []cli.Flag{ 290 utils.PasswordFileFlag, 291 SwarmDryRunFlag, 292 }, 293 Name: "pass", 294 Usage: "encrypts a reference with a password and embeds it into a root manifest", 295 ArgsUsage: "<ref>", 296 Description: "encrypts a reference and embeds it into a root access manifest and prints the resulting manifest", 297 }, 298 { 299 Action: accessNewPK, 300 CustomHelpTemplate: helpTemplate, 301 Flags: []cli.Flag{ 302 utils.PasswordFileFlag, 303 SwarmDryRunFlag, 304 SwarmAccessGrantKeyFlag, 305 }, 306 Name: "pk", 307 Usage: "encrypts a reference with the node's private key and a given grantee's public key and embeds it into a root manifest", 308 ArgsUsage: "<ref>", 309 Description: "encrypts a reference and embeds it into a root access manifest and prints the resulting manifest", 310 }, 311 { 312 Action: accessNewACT, 313 CustomHelpTemplate: helpTemplate, 314 Flags: []cli.Flag{ 315 SwarmAccessGrantKeysFlag, 316 SwarmDryRunFlag, 317 }, 318 Name: "act", 319 Usage: "encrypts a reference with the node's private key and a given grantee's public key and embeds it into a root manifest", 320 ArgsUsage: "<ref>", 321 Description: "encrypts a reference and embeds it into a root access manifest and prints the resulting manifest", 322 }, 323 }, 324 }, 325 }, 326 }, 327 { 328 CustomHelpTemplate: helpTemplate, 329 Name: "resource", 330 Usage: "(Advanced) Create and update Mutable Resources", 331 ArgsUsage: "<create|update|info>", 332 Description: "Works with Mutable Resource Updates", 333 Subcommands: []cli.Command{ 334 { 335 Action: resourceCreate, 336 CustomHelpTemplate: helpTemplate, 337 Name: "create", 338 Usage: "creates a new Mutable Resource", 339 ArgsUsage: "<frequency>", 340 Description: "creates a new Mutable Resource", 341 Flags: []cli.Flag{SwarmResourceNameFlag, SwarmResourceDataOnCreateFlag, SwarmResourceMultihashFlag}, 342 }, 343 { 344 Action: resourceUpdate, 345 CustomHelpTemplate: helpTemplate, 346 Name: "update", 347 Usage: "updates the content of an existing Mutable Resource", 348 ArgsUsage: "<Manifest Address or ENS domain> <0x Hex data>", 349 Description: "updates the content of an existing Mutable Resource", 350 Flags: []cli.Flag{SwarmResourceMultihashFlag}, 351 }, 352 { 353 Action: resourceInfo, 354 CustomHelpTemplate: helpTemplate, 355 Name: "info", 356 Usage: "obtains information about an existing Mutable Resource", 357 ArgsUsage: "<Manifest Address or ENS domain>", 358 Description: "obtains information about an existing Mutable Resource", 359 }, 360 }, 361 }, 362 { 363 Action: list, 364 CustomHelpTemplate: helpTemplate, 365 Name: "ls", 366 Usage: "list files and directories contained in a manifest", 367 ArgsUsage: "<manifest> [<prefix>]", 368 Description: "Lists files and directories contained in a manifest", 369 }, 370 { 371 Action: hash, 372 CustomHelpTemplate: helpTemplate, 373 Name: "hash", 374 Usage: "print the swarm hash of a file or directory", 375 ArgsUsage: "<file>", 376 Description: "Prints the swarm hash of file or directory", 377 }, 378 { 379 Action: download, 380 Name: "down", 381 Flags: []cli.Flag{SwarmRecursiveFlag, SwarmAccessPasswordFlag}, 382 Usage: "downloads a swarm manifest or a file inside a manifest", 383 ArgsUsage: " <uri> [<dir>]", 384 Description: `Downloads a swarm bzz uri to the given dir. When no dir is provided, working directory is assumed. --recursive flag is expected when downloading a manifest with multiple entries.`, 385 }, 386 { 387 Name: "manifest", 388 CustomHelpTemplate: helpTemplate, 389 Usage: "perform operations on swarm manifests", 390 ArgsUsage: "COMMAND", 391 Description: "Updates a MANIFEST by adding/removing/updating the hash of a path.\nCOMMAND could be: add, update, remove", 392 Subcommands: []cli.Command{ 393 { 394 Action: manifestAdd, 395 CustomHelpTemplate: helpTemplate, 396 Name: "add", 397 Usage: "add a new path to the manifest", 398 ArgsUsage: "<MANIFEST> <path> <hash>", 399 Description: "Adds a new path to the manifest", 400 }, 401 { 402 Action: manifestUpdate, 403 CustomHelpTemplate: helpTemplate, 404 Name: "update", 405 Usage: "update the hash for an already existing path in the manifest", 406 ArgsUsage: "<MANIFEST> <path> <newhash>", 407 Description: "Update the hash for an already existing path in the manifest", 408 }, 409 { 410 Action: manifestRemove, 411 CustomHelpTemplate: helpTemplate, 412 Name: "remove", 413 Usage: "removes a path from the manifest", 414 ArgsUsage: "<MANIFEST> <path>", 415 Description: "Removes a path from the manifest", 416 }, 417 }, 418 }, 419 { 420 Name: "fs", 421 CustomHelpTemplate: helpTemplate, 422 Usage: "perform FUSE operations", 423 ArgsUsage: "fs COMMAND", 424 Description: "Performs FUSE operations by mounting/unmounting/listing mount points. This assumes you already have a Swarm node running locally. For all operation you must reference the correct path to bzzd.ipc in order to communicate with the node", 425 Subcommands: []cli.Command{ 426 { 427 Action: mount, 428 CustomHelpTemplate: helpTemplate, 429 Name: "mount", 430 Flags: []cli.Flag{utils.IPCPathFlag}, 431 Usage: "mount a swarm hash to a mount point", 432 ArgsUsage: "swarm fs mount --ipcpath <path to bzzd.ipc> <manifest hash> <mount point>", 433 Description: "Mounts a Swarm manifest hash to a given mount point. This assumes you already have a Swarm node running locally. You must reference the correct path to your bzzd.ipc file", 434 }, 435 { 436 Action: unmount, 437 CustomHelpTemplate: helpTemplate, 438 Name: "unmount", 439 Flags: []cli.Flag{utils.IPCPathFlag}, 440 Usage: "unmount a swarmfs mount", 441 ArgsUsage: "swarm fs unmount --ipcpath <path to bzzd.ipc> <mount point>", 442 Description: "Unmounts a swarmfs mount residing at <mount point>. This assumes you already have a Swarm node running locally. You must reference the correct path to your bzzd.ipc file", 443 }, 444 { 445 Action: listMounts, 446 CustomHelpTemplate: helpTemplate, 447 Name: "list", 448 Flags: []cli.Flag{utils.IPCPathFlag}, 449 Usage: "list swarmfs mounts", 450 ArgsUsage: "swarm fs list --ipcpath <path to bzzd.ipc>", 451 Description: "Lists all mounted swarmfs volumes. This assumes you already have a Swarm node running locally. You must reference the correct path to your bzzd.ipc file", 452 }, 453 }, 454 }, 455 { 456 Name: "db", 457 CustomHelpTemplate: helpTemplate, 458 Usage: "manage the local chunk database", 459 ArgsUsage: "db COMMAND", 460 Description: "Manage the local chunk database", 461 Subcommands: []cli.Command{ 462 { 463 Action: dbExport, 464 CustomHelpTemplate: helpTemplate, 465 Name: "export", 466 Usage: "export a local chunk database as a tar archive (use - to send to stdout)", 467 ArgsUsage: "<chunkdb> <file>", 468 Description: ` 469 Export a local chunk database as a tar archive (use - to send to stdout). 470 471 swarm db export ~/.ethereum/swarm/bzz-KEY/chunks chunks.tar 472 473 The export may be quite large, consider piping the output through the Unix 474 pv(1) tool to get a progress bar: 475 476 swarm db export ~/.ethereum/swarm/bzz-KEY/chunks - | pv > chunks.tar 477 `, 478 }, 479 { 480 Action: dbImport, 481 CustomHelpTemplate: helpTemplate, 482 Name: "import", 483 Usage: "import chunks from a tar archive into a local chunk database (use - to read from stdin)", 484 ArgsUsage: "<chunkdb> <file>", 485 Description: `Import chunks from a tar archive into a local chunk database (use - to read from stdin). 486 487 swarm db import ~/.ethereum/swarm/bzz-KEY/chunks chunks.tar 488 489 The import may be quite large, consider piping the input through the Unix 490 pv(1) tool to get a progress bar: 491 492 pv chunks.tar | swarm db import ~/.ethereum/swarm/bzz-KEY/chunks -`, 493 }, 494 { 495 Action: dbClean, 496 CustomHelpTemplate: helpTemplate, 497 Name: "clean", 498 Usage: "remove corrupt entries from a local chunk database", 499 ArgsUsage: "<chunkdb>", 500 Description: "Remove corrupt entries from a local chunk database", 501 }, 502 }, 503 }, 504 505 //参见CONG.GO 506 DumpConfigCommand, 507 } 508 509 // 510 // 511 addDefaultHelpSubcommands(app.Commands) 512 513 sort.Sort(cli.CommandsByName(app.Commands)) 514 515 app.Flags = []cli.Flag{ 516 utils.IdentityFlag, 517 utils.DataDirFlag, 518 utils.BootnodesFlag, 519 utils.KeyStoreDirFlag, 520 utils.ListenPortFlag, 521 utils.NoDiscoverFlag, 522 utils.DiscoveryV5Flag, 523 utils.NetrestrictFlag, 524 utils.NodeKeyFileFlag, 525 utils.NodeKeyHexFlag, 526 utils.MaxPeersFlag, 527 utils.NATFlag, 528 utils.IPCDisabledFlag, 529 utils.IPCPathFlag, 530 utils.PasswordFileFlag, 531 // 532 CorsStringFlag, 533 EnsAPIFlag, 534 SwarmTomlConfigPathFlag, 535 SwarmSwapEnabledFlag, 536 SwarmSwapAPIFlag, 537 SwarmSyncDisabledFlag, 538 SwarmSyncUpdateDelay, 539 SwarmLightNodeEnabled, 540 SwarmDeliverySkipCheckFlag, 541 SwarmListenAddrFlag, 542 SwarmPortFlag, 543 SwarmAccountFlag, 544 SwarmNetworkIdFlag, 545 ChequebookAddrFlag, 546 //上传标志 547 SwarmApiFlag, 548 SwarmRecursiveFlag, 549 SwarmWantManifestFlag, 550 SwarmUploadDefaultPath, 551 SwarmUpFromStdinFlag, 552 SwarmUploadMimeType, 553 //存储标志 554 SwarmStorePath, 555 SwarmStoreCapacity, 556 SwarmStoreCacheCapacity, 557 } 558 rpcFlags := []cli.Flag{ 559 utils.WSEnabledFlag, 560 utils.WSListenAddrFlag, 561 utils.WSPortFlag, 562 utils.WSApiFlag, 563 utils.WSAllowedOriginsFlag, 564 } 565 app.Flags = append(app.Flags, rpcFlags...) 566 app.Flags = append(app.Flags, debug.Flags...) 567 app.Flags = append(app.Flags, swarmmetrics.Flags...) 568 app.Flags = append(app.Flags, tracing.Flags...) 569 app.Before = func(ctx *cli.Context) error { 570 runtime.GOMAXPROCS(runtime.NumCPU()) 571 if err := debug.Setup(ctx, ""); err != nil { 572 return err 573 } 574 swarmmetrics.Setup(ctx) 575 tracing.Setup(ctx) 576 return nil 577 } 578 app.After = func(ctx *cli.Context) error { 579 debug.Exit() 580 return nil 581 } 582 } 583 584 func main() { 585 if err := app.Run(os.Args); err != nil { 586 fmt.Fprintln(os.Stderr, err) 587 os.Exit(1) 588 } 589 } 590 591 func version(ctx *cli.Context) error { 592 fmt.Println(strings.Title(clientIdentifier)) 593 fmt.Println("Version:", sv.VersionWithMeta) 594 if gitCommit != "" { 595 fmt.Println("Git Commit:", gitCommit) 596 } 597 fmt.Println("Go Version:", runtime.Version()) 598 fmt.Println("OS:", runtime.GOOS) 599 return nil 600 } 601 602 func bzzd(ctx *cli.Context) error { 603 // 604 // 605 606 bzzconfig, err := buildConfig(ctx) 607 if err != nil { 608 utils.Fatalf("unable to configure swarm: %v", err) 609 } 610 611 cfg := defaultNodeConfig 612 613 // 614 cfg.WSModules = append(cfg.WSModules, "pss") 615 616 // 617 //为了在Swarm中保持一致,如果我们通过环境变量传递--datadir 618 // 619 if _, err := os.Stat(bzzconfig.Path); err == nil { 620 cfg.DataDir = bzzconfig.Path 621 } 622 623 // 624 setSwarmBootstrapNodes(ctx, &cfg) 625 // 626 utils.SetNodeConfig(ctx, &cfg) 627 stack, err := node.New(&cfg) 628 if err != nil { 629 utils.Fatalf("can't create node: %v", err) 630 } 631 632 // 633 // 634 initSwarmNode(bzzconfig, stack, ctx) 635 //在以太坊节点中将bzz注册为node.service 636 registerBzzService(bzzconfig, stack) 637 // 638 utils.StartNode(stack) 639 640 go func() { 641 sigc := make(chan os.Signal, 1) 642 signal.Notify(sigc, syscall.SIGTERM) 643 defer signal.Stop(sigc) 644 <-sigc 645 log.Info("Got sigterm, shutting swarm down...") 646 stack.Stop() 647 }() 648 649 stack.Wait() 650 return nil 651 } 652 653 func registerBzzService(bzzconfig *bzzapi.Config, stack *node.Node) { 654 //定义Swarm服务引导功能 655 boot := func(_ *node.ServiceContext) (node.Service, error) { 656 // 657 return swarm.NewSwarm(bzzconfig, nil) 658 } 659 // 660 if err := stack.Register(boot); err != nil { 661 utils.Fatalf("Failed to register the Swarm service: %v", err) 662 } 663 } 664 665 func getAccount(bzzaccount string, ctx *cli.Context, stack *node.Node) *ecdsa.PrivateKey { 666 // 667 if bzzaccount == "" { 668 utils.Fatalf(SWARM_ERR_NO_BZZACCOUNT) 669 } 670 //尝试将arg作为十六进制密钥文件加载。 671 if key, err := crypto.LoadECDSA(bzzaccount); err == nil { 672 log.Info("Swarm account key loaded", "address", crypto.PubkeyToAddress(key.PublicKey)) 673 return key 674 } 675 // 676 am := stack.AccountManager() 677 ks := am.Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 678 679 return decryptStoreAccount(ks, bzzaccount, utils.MakePasswordList(ctx)) 680 } 681 682 //getprivkey返回指定bzzaccount的私钥 683 // 684 func getPrivKey(ctx *cli.Context) *ecdsa.PrivateKey { 685 //像在bzzd操作中一样启动群节点 686 bzzconfig, err := buildConfig(ctx) 687 if err != nil { 688 utils.Fatalf("unable to configure swarm: %v", err) 689 } 690 cfg := defaultNodeConfig 691 if _, err := os.Stat(bzzconfig.Path); err == nil { 692 cfg.DataDir = bzzconfig.Path 693 } 694 utils.SetNodeConfig(ctx, &cfg) 695 stack, err := node.New(&cfg) 696 if err != nil { 697 utils.Fatalf("can't create node: %v", err) 698 } 699 return getAccount(bzzconfig.BzzAccount, ctx, stack) 700 } 701 702 func decryptStoreAccount(ks *keystore.KeyStore, account string, passwords []string) *ecdsa.PrivateKey { 703 var a accounts.Account 704 var err error 705 if common.IsHexAddress(account) { 706 a, err = ks.Find(accounts.Account{Address: common.HexToAddress(account)}) 707 } else if ix, ixerr := strconv.Atoi(account); ixerr == nil && ix > 0 { 708 if accounts := ks.Accounts(); len(accounts) > ix { 709 a = accounts[ix] 710 } else { 711 err = fmt.Errorf("index %d higher than number of accounts %d", ix, len(accounts)) 712 } 713 } else { 714 utils.Fatalf("Can't find swarm account key %s", account) 715 } 716 if err != nil { 717 utils.Fatalf("Can't find swarm account key: %v - Is the provided bzzaccount(%s) from the right datadir/Path?", err, account) 718 } 719 keyjson, err := ioutil.ReadFile(a.URL.Path) 720 if err != nil { 721 utils.Fatalf("Can't load swarm account key: %v", err) 722 } 723 for i := 0; i < 3; i++ { 724 password := getPassPhrase(fmt.Sprintf("Unlocking swarm account %s [%d/3]", a.Address.Hex(), i+1), i, passwords) 725 key, err := keystore.DecryptKey(keyjson, password) 726 if err == nil { 727 return key.PrivateKey 728 } 729 } 730 utils.Fatalf("Can't decrypt swarm account key") 731 return nil 732 } 733 734 //getpassphrase通过获取与bzz帐户关联的密码 735 // 736 func getPassPhrase(prompt string, i int, passwords []string) string { 737 //非交互式 738 if len(passwords) > 0 { 739 if i < len(passwords) { 740 return passwords[i] 741 } 742 return passwords[len(passwords)-1] 743 } 744 745 //回退到交互模式 746 if prompt != "" { 747 fmt.Println(prompt) 748 } 749 password, err := console.Stdin.PromptPassword("Passphrase: ") 750 if err != nil { 751 utils.Fatalf("Failed to read passphrase: %v", err) 752 } 753 return password 754 } 755 756 //adddefaulthelpsubcommand通过定义的cli命令扫描并添加 757 // 758 // 759 func addDefaultHelpSubcommands(commands []cli.Command) { 760 for i := range commands { 761 cmd := &commands[i] 762 if cmd.Subcommands != nil { 763 cmd.Subcommands = append(cmd.Subcommands, defaultSubcommandHelp) 764 addDefaultHelpSubcommands(cmd.Subcommands) 765 } 766 } 767 } 768 769 func setSwarmBootstrapNodes(ctx *cli.Context, cfg *node.Config) { 770 if ctx.GlobalIsSet(utils.BootnodesFlag.Name) || ctx.GlobalIsSet(utils.BootnodesV4Flag.Name) { 771 return 772 } 773 774 cfg.P2P.BootstrapNodes = []*discover.Node{} 775 776 for _, url := range SwarmBootnodes { 777 node, err := discover.ParseNode(url) 778 if err != nil { 779 log.Error("Bootstrap URL invalid", "enode", url, "err", err) 780 } 781 cfg.P2P.BootstrapNodes = append(cfg.P2P.BootstrapNodes, node) 782 } 783 log.Debug("added default swarm bootnodes", "length", len(cfg.P2P.BootstrapNodes)) 784 }