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