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