2016-09-22 03:24:31 +03:00
// Copyright 2016 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
package main
import (
"crypto/ecdsa"
"fmt"
"io/ioutil"
"os"
2017-02-06 21:08:38 +03:00
"os/signal"
2016-09-22 03:24:31 +03:00
"runtime"
2017-08-11 14:29:05 +03:00
"sort"
2016-09-22 03:24:31 +03:00
"strconv"
2016-11-28 15:29:33 +03:00
"strings"
2017-02-06 21:08:38 +03:00
"syscall"
2016-09-22 03:24:31 +03:00
"github.com/ethereum/go-ethereum/accounts"
2017-01-24 12:49:20 +03:00
"github.com/ethereum/go-ethereum/accounts/keystore"
2016-09-22 03:24:31 +03:00
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/console"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/internal/debug"
2017-02-22 15:10:07 +03:00
"github.com/ethereum/go-ethereum/log"
2016-09-22 03:24:31 +03:00
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/swarm"
bzzapi "github.com/ethereum/go-ethereum/swarm/api"
2018-02-23 16:19:59 +03:00
swarmmetrics "github.com/ethereum/go-ethereum/swarm/metrics"
2018-07-13 18:40:28 +03:00
"github.com/ethereum/go-ethereum/swarm/tracing"
2018-07-30 11:56:40 +03:00
sv "github.com/ethereum/go-ethereum/swarm/version"
2017-12-12 00:56:06 +03:00
2016-09-22 03:24:31 +03:00
"gopkg.in/urfave/cli.v1"
)
2017-04-12 17:27:23 +03:00
const clientIdentifier = "swarm"
2018-06-20 15:06:27 +03:00
const helpTemplate = ` NAME :
{ { . HelpName } } - { { . Usage } }
USAGE :
{ { if . UsageText } } { { . UsageText } } { { else } } { { . HelpName } } { { if . VisibleFlags } } [ command options ] { { end } } { { if . ArgsUsage } } { { . ArgsUsage } } { { else } } [ arguments ... ] { { end } } { { end } } { { if . Category } }
CATEGORY :
{ { . Category } } { { end } } { { if . Description } }
DESCRIPTION :
{ { . Description } } { { end } } { { if . VisibleFlags } }
OPTIONS :
{ { range . VisibleFlags } } { { . } }
{ { end } } { { end } }
`
2016-09-22 03:24:31 +03:00
var (
2016-12-13 11:49:02 +03:00
gitCommit string // Git SHA1 commit hash of the release (set via linker flags)
testbetBootNodes = [ ] string {
2016-12-13 15:08:41 +03:00
"enode://ec8ae764f7cb0417bdfb009b9d0f18ab3818a3a4e8e7c67dd5f18971a93510a2e6f43cd0b69a27e439a9629457ea804104f37c85e41eed057d3faabbf7744cdf@13.74.157.139:30429" ,
"enode://c2e1fceb3bf3be19dff71eec6cccf19f2dbf7567ee017d130240c670be8594bc9163353ca55dd8df7a4f161dd94b36d0615c17418b5a3cdcbb4e9d99dfa4de37@13.74.157.139:30430" ,
"enode://fe29b82319b734ce1ec68b84657d57145fee237387e63273989d354486731e59f78858e452ef800a020559da22dcca759536e6aa5517c53930d29ce0b1029286@13.74.157.139:30431" ,
"enode://1d7187e7bde45cf0bee489ce9852dd6d1a0d9aa67a33a6b8e6db8a4fbc6fcfa6f0f1a5419343671521b863b187d1c73bad3603bae66421d157ffef357669ddb8@13.74.157.139:30432" ,
"enode://0e4cba800f7b1ee73673afa6a4acead4018f0149d2e3216be3f133318fd165b324cd71b81fbe1e80deac8dbf56e57a49db7be67f8b9bc81bd2b7ee496434fb5d@13.74.157.139:30433" ,
2016-12-13 11:49:02 +03:00
}
2016-09-22 03:24:31 +03:00
)
var (
ChequebookAddrFlag = cli . StringFlag {
2017-12-12 00:56:06 +03:00
Name : "chequebook" ,
Usage : "chequebook contract address" ,
EnvVar : SWARM_ENV_CHEQUEBOOK_ADDR ,
2016-09-22 03:24:31 +03:00
}
SwarmAccountFlag = cli . StringFlag {
2017-12-12 00:56:06 +03:00
Name : "bzzaccount" ,
Usage : "Swarm account key file" ,
EnvVar : SWARM_ENV_ACCOUNT ,
2016-09-22 03:24:31 +03:00
}
2017-05-22 09:56:40 +03:00
SwarmListenAddrFlag = cli . StringFlag {
2017-12-12 00:56:06 +03:00
Name : "httpaddr" ,
Usage : "Swarm HTTP API listening interface" ,
EnvVar : SWARM_ENV_LISTEN_ADDR ,
2017-05-22 09:56:40 +03:00
}
2016-09-22 03:24:31 +03:00
SwarmPortFlag = cli . StringFlag {
2017-12-12 00:56:06 +03:00
Name : "bzzport" ,
Usage : "Swarm local http api port" ,
EnvVar : SWARM_ENV_PORT ,
2016-09-22 03:24:31 +03:00
}
2016-11-28 15:29:33 +03:00
SwarmNetworkIdFlag = cli . IntFlag {
2017-12-12 00:56:06 +03:00
Name : "bzznetworkid" ,
Usage : "Network identifier (integer, default 3=swarm testnet)" ,
EnvVar : SWARM_ENV_NETWORK_ID ,
2016-11-28 15:29:33 +03:00
}
2017-01-05 13:57:41 +03:00
SwarmSwapEnabledFlag = cli . BoolFlag {
2017-12-12 00:56:06 +03:00
Name : "swap" ,
Usage : "Swarm SWAP enabled (default false)" ,
EnvVar : SWARM_ENV_SWAP_ENABLE ,
2016-09-22 03:24:31 +03:00
}
2017-06-18 01:25:39 +03:00
SwarmSwapAPIFlag = cli . StringFlag {
2017-12-12 00:56:06 +03:00
Name : "swap-api" ,
Usage : "URL of the Ethereum API provider to use to settle SWAP payments" ,
EnvVar : SWARM_ENV_SWAP_API ,
2017-06-18 01:25:39 +03:00
}
2018-06-20 15:06:27 +03:00
SwarmSyncDisabledFlag = cli . BoolTFlag {
Name : "nosync" ,
Usage : "Disable swarm syncing" ,
EnvVar : SWARM_ENV_SYNC_DISABLE ,
}
SwarmSyncUpdateDelay = cli . DurationFlag {
Name : "sync-update-delay" ,
Usage : "Duration for sync subscriptions update after no new peers are added (default 15s)" ,
EnvVar : SWARM_ENV_SYNC_UPDATE_DELAY ,
}
SwarmDeliverySkipCheckFlag = cli . BoolFlag {
Name : "delivery-skip-check" ,
Usage : "Skip chunk delivery check (default false)" ,
EnvVar : SWARM_ENV_DELIVERY_SKIP_CHECK ,
2016-09-22 03:24:31 +03:00
}
2017-12-04 14:44:24 +03:00
EnsAPIFlag = cli . StringSliceFlag {
2017-12-12 00:56:06 +03:00
Name : "ens-api" ,
2017-12-13 12:23:11 +03:00
Usage : "ENS API endpoint for a TLD and with contract address, can be repeated, format [tld:][contract-addr@]url" ,
2017-12-12 00:56:06 +03:00
EnvVar : SWARM_ENV_ENS_API ,
2016-09-22 03:24:31 +03:00
}
2016-12-10 20:45:52 +03:00
SwarmApiFlag = cli . StringFlag {
Name : "bzzapi" ,
Usage : "Swarm HTTP endpoint" ,
Value : "http://127.0.0.1:8500" ,
}
2018-06-20 15:06:27 +03:00
SwarmRecursiveFlag = cli . BoolFlag {
2016-12-10 20:45:52 +03:00
Name : "recursive" ,
Usage : "Upload directories recursively" ,
}
SwarmWantManifestFlag = cli . BoolTFlag {
Name : "manifest" ,
2018-07-09 15:11:49 +03:00
Usage : "Automatic manifest upload (default true)" ,
2016-12-10 20:45:52 +03:00
}
2016-12-13 14:48:30 +03:00
SwarmUploadDefaultPath = cli . StringFlag {
Name : "defaultpath" ,
Usage : "path to file served for empty url path (none)" ,
}
2017-04-06 15:21:16 +03:00
SwarmUpFromStdinFlag = cli . BoolFlag {
Name : "stdin" ,
Usage : "reads data to be uploaded from stdin" ,
}
SwarmUploadMimeType = cli . StringFlag {
Name : "mime" ,
2018-07-09 15:11:49 +03:00
Usage : "Manually specify MIME type" ,
2017-04-06 15:21:16 +03:00
}
2018-06-20 15:06:27 +03:00
SwarmEncryptedFlag = cli . BoolFlag {
Name : "encrypt" ,
Usage : "use encrypted upload" ,
}
2017-01-05 13:57:41 +03:00
CorsStringFlag = cli . StringFlag {
2017-12-12 00:56:06 +03:00
Name : "corsdomain" ,
Usage : "Domain on which to send Access-Control-Allow-Origin header (multiple domains can be supplied separated by a ',')" ,
EnvVar : SWARM_ENV_CORS ,
2017-01-05 13:57:41 +03:00
}
2018-06-20 15:06:27 +03:00
SwarmStorePath = cli . StringFlag {
Name : "store.path" ,
Usage : "Path to leveldb chunk DB (default <$GETH_ENV_DIR>/swarm/bzz-<$BZZ_KEY>/chunks)" ,
EnvVar : SWARM_ENV_STORE_PATH ,
2017-06-30 12:10:41 +03:00
}
2018-06-20 15:06:27 +03:00
SwarmStoreCapacity = cli . Uint64Flag {
Name : "store.size" ,
Usage : "Number of chunks (5M is roughly 20-25GB) (default 5000000)" ,
EnvVar : SWARM_ENV_STORE_CAPACITY ,
}
SwarmStoreCacheCapacity = cli . UintFlag {
Name : "store.cache.size" ,
Usage : "Number of recent chunks cached in memory (default 5000)" ,
EnvVar : SWARM_ENV_STORE_CACHE_CAPACITY ,
2017-12-05 00:41:21 +03:00
}
2018-07-21 22:49:36 +03:00
SwarmResourceMultihashFlag = cli . BoolFlag {
Name : "multihash" ,
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" ,
}
SwarmResourceNameFlag = cli . StringFlag {
Name : "name" ,
Usage : "User-defined name for the new resource" ,
}
SwarmResourceDataOnCreateFlag = cli . StringFlag {
Name : "data" ,
Usage : "Initializes the resource with the given hex-encoded data. Data must be prefixed by 0x" ,
}
2016-09-22 03:24:31 +03:00
)
2017-12-12 00:56:06 +03:00
//declare a few constant error messages, useful for later error check comparisons in test
var (
SWARM_ERR_NO_BZZACCOUNT = "bzzaccount option is required but not set; check your config file, command line or environment variables"
SWARM_ERR_SWAP_SET_NO_API = "SWAP is enabled but --swap-api is not set"
)
2018-07-17 08:04:43 +03:00
// this help command gets added to any subcommand that does not define it explicitly
var defaultSubcommandHelp = cli . Command {
Action : func ( ctx * cli . Context ) { cli . ShowCommandHelpAndExit ( ctx , "" , 1 ) } ,
CustomHelpTemplate : helpTemplate ,
Name : "help" ,
Usage : "shows this help" ,
Hidden : true ,
}
2017-04-12 17:27:23 +03:00
var defaultNodeConfig = node . DefaultConfig
// This init function sets defaults so cmd/swarm can run alongside geth.
2016-09-22 03:24:31 +03:00
func init ( ) {
2017-04-12 17:27:23 +03:00
defaultNodeConfig . Name = clientIdentifier
2018-07-30 11:56:40 +03:00
defaultNodeConfig . Version = sv . VersionWithCommit ( gitCommit )
2017-04-12 17:27:23 +03:00
defaultNodeConfig . P2P . ListenAddr = ":30399"
defaultNodeConfig . IPCPath = "bzzd.ipc"
// Set flag defaults for --help display.
2016-09-22 03:24:31 +03:00
utils . ListenPortFlag . Value = 30399
2017-04-12 17:27:23 +03:00
}
2016-09-22 03:24:31 +03:00
2017-04-12 17:27:23 +03:00
var app = utils . NewApp ( gitCommit , "Ethereum Swarm" )
// This init function creates the cli.App.
func init ( ) {
2016-09-22 03:24:31 +03:00
app . Action = bzzd
2016-12-10 20:45:52 +03:00
app . HideVersion = true // we have a command to print the version
app . Copyright = "Copyright 2013-2016 The go-ethereum Authors"
app . Commands = [ ] cli . Command {
2017-01-06 17:52:03 +03:00
{
2018-06-20 15:06:27 +03:00
Action : version ,
CustomHelpTemplate : helpTemplate ,
Name : "version" ,
Usage : "Print version numbers" ,
Description : "The output of this command is supposed to be machine-readable" ,
2016-12-10 20:45:52 +03:00
} ,
2017-01-06 17:52:03 +03:00
{
2018-06-20 15:06:27 +03:00
Action : upload ,
CustomHelpTemplate : helpTemplate ,
Name : "up" ,
Usage : "uploads a file or directory to swarm using the HTTP API" ,
ArgsUsage : "<file>" ,
Flags : [ ] cli . Flag { SwarmEncryptedFlag } ,
Description : "uploads a file or directory to swarm using the HTTP API and prints the root hash" ,
2017-04-05 01:20:07 +03:00
} ,
2018-07-21 22:49:36 +03:00
{
CustomHelpTemplate : helpTemplate ,
Name : "resource" ,
Usage : "(Advanced) Create and update Mutable Resources" ,
ArgsUsage : "<create|update|info>" ,
Description : "Works with Mutable Resource Updates" ,
Subcommands : [ ] cli . Command {
{
Action : resourceCreate ,
CustomHelpTemplate : helpTemplate ,
Name : "create" ,
Usage : "creates a new Mutable Resource" ,
ArgsUsage : "<frequency>" ,
Description : "creates a new Mutable Resource" ,
Flags : [ ] cli . Flag { SwarmResourceNameFlag , SwarmResourceDataOnCreateFlag , SwarmResourceMultihashFlag } ,
} ,
{
Action : resourceUpdate ,
CustomHelpTemplate : helpTemplate ,
Name : "update" ,
Usage : "updates the content of an existing Mutable Resource" ,
ArgsUsage : "<Manifest Address or ENS domain> <0x Hex data>" ,
Description : "updates the content of an existing Mutable Resource" ,
Flags : [ ] cli . Flag { SwarmResourceMultihashFlag } ,
} ,
{
Action : resourceInfo ,
CustomHelpTemplate : helpTemplate ,
Name : "info" ,
Usage : "obtains information about an existing Mutable Resource" ,
ArgsUsage : "<Manifest Address or ENS domain>" ,
Description : "obtains information about an existing Mutable Resource" ,
} ,
} ,
} ,
2017-04-05 01:20:07 +03:00
{
2018-06-20 15:06:27 +03:00
Action : list ,
CustomHelpTemplate : helpTemplate ,
Name : "ls" ,
Usage : "list files and directories contained in a manifest" ,
ArgsUsage : "<manifest> [<prefix>]" ,
Description : "Lists files and directories contained in a manifest" ,
2016-12-10 20:45:52 +03:00
} ,
2017-01-06 17:52:03 +03:00
{
2018-06-20 15:06:27 +03:00
Action : hash ,
CustomHelpTemplate : helpTemplate ,
Name : "hash" ,
Usage : "print the swarm hash of a file or directory" ,
ArgsUsage : "<file>" ,
Description : "Prints the swarm hash of file or directory" ,
2016-12-10 20:45:52 +03:00
} ,
2017-02-13 05:33:05 +03:00
{
2018-06-20 15:06:27 +03:00
Action : download ,
Name : "down" ,
Flags : [ ] cli . Flag { SwarmRecursiveFlag } ,
Usage : "downloads a swarm manifest or a file inside a manifest" ,
ArgsUsage : " <uri> [<dir>]" ,
2017-02-13 05:33:05 +03:00
Description : `
2018-06-20 15:06:27 +03:00
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 .
2017-02-13 05:33:05 +03:00
` ,
2018-06-20 15:06:27 +03:00
} ,
{
Name : "manifest" ,
CustomHelpTemplate : helpTemplate ,
Usage : "perform operations on swarm manifests" ,
ArgsUsage : "COMMAND" ,
Description : "Updates a MANIFEST by adding/removing/updating the hash of a path.\nCOMMAND could be: add, update, remove" ,
2017-02-13 05:33:05 +03:00
Subcommands : [ ] cli . Command {
{
2018-06-20 15:06:27 +03:00
Action : add ,
CustomHelpTemplate : helpTemplate ,
Name : "add" ,
Usage : "add a new path to the manifest" ,
ArgsUsage : "<MANIFEST> <path> <hash> [<content-type>]" ,
Description : "Adds a new path to the manifest" ,
2017-02-13 05:33:05 +03:00
} ,
{
2018-06-20 15:06:27 +03:00
Action : update ,
CustomHelpTemplate : helpTemplate ,
Name : "update" ,
Usage : "update the hash for an already existing path in the manifest" ,
ArgsUsage : "<MANIFEST> <path> <newhash> [<newcontent-type>]" ,
Description : "Update the hash for an already existing path in the manifest" ,
2017-02-13 05:33:05 +03:00
} ,
{
2018-06-20 15:06:27 +03:00
Action : remove ,
CustomHelpTemplate : helpTemplate ,
Name : "remove" ,
Usage : "removes a path from the manifest" ,
ArgsUsage : "<MANIFEST> <path>" ,
Description : "Removes a path from the manifest" ,
2017-02-13 05:33:05 +03:00
} ,
} ,
} ,
2017-02-13 15:20:50 +03:00
{
2018-06-20 15:06:27 +03:00
Name : "fs" ,
CustomHelpTemplate : helpTemplate ,
Usage : "perform FUSE operations" ,
ArgsUsage : "fs COMMAND" ,
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" ,
2017-07-31 14:23:44 +03:00
Subcommands : [ ] cli . Command {
{
2018-06-20 15:06:27 +03:00
Action : mount ,
CustomHelpTemplate : helpTemplate ,
Name : "mount" ,
Flags : [ ] cli . Flag { utils . IPCPathFlag } ,
Usage : "mount a swarm hash to a mount point" ,
ArgsUsage : "swarm fs mount --ipcpath <path to bzzd.ipc> <manifest hash> <mount point>" ,
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" ,
} ,
{
Action : unmount ,
CustomHelpTemplate : helpTemplate ,
Name : "unmount" ,
Flags : [ ] cli . Flag { utils . IPCPathFlag } ,
Usage : "unmount a swarmfs mount" ,
ArgsUsage : "swarm fs unmount --ipcpath <path to bzzd.ipc> <mount point>" ,
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" ,
} ,
{
Action : listMounts ,
CustomHelpTemplate : helpTemplate ,
Name : "list" ,
Flags : [ ] cli . Flag { utils . IPCPathFlag } ,
Usage : "list swarmfs mounts" ,
ArgsUsage : "swarm fs list --ipcpath <path to bzzd.ipc>" ,
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" ,
} ,
} ,
} ,
{
Name : "db" ,
CustomHelpTemplate : helpTemplate ,
Usage : "manage the local chunk database" ,
ArgsUsage : "db COMMAND" ,
Description : "Manage the local chunk database" ,
Subcommands : [ ] cli . Command {
{
Action : dbExport ,
CustomHelpTemplate : helpTemplate ,
Name : "export" ,
Usage : "export a local chunk database as a tar archive (use - to send to stdout)" ,
ArgsUsage : "<chunkdb> <file>" ,
2017-07-31 14:23:44 +03:00
Description : `
Export a local chunk database as a tar archive ( use - to send to stdout ) .
swarm db export ~ / . ethereum / swarm / bzz - KEY / chunks chunks . tar
The export may be quite large , consider piping the output through the Unix
pv ( 1 ) tool to get a progress bar :
swarm db export ~ / . ethereum / swarm / bzz - KEY / chunks - | pv > chunks . tar
` ,
} ,
{
2018-06-20 15:06:27 +03:00
Action : dbImport ,
CustomHelpTemplate : helpTemplate ,
Name : "import" ,
Usage : "import chunks from a tar archive into a local chunk database (use - to read from stdin)" ,
ArgsUsage : "<chunkdb> <file>" ,
2017-07-31 14:23:44 +03:00
Description : `
Import chunks from a tar archive into a local chunk database ( use - to read from stdin ) .
swarm db import ~ / . ethereum / swarm / bzz - KEY / chunks chunks . tar
The import may be quite large , consider piping the input through the Unix
pv ( 1 ) tool to get a progress bar :
pv chunks . tar | swarm db import ~ / . ethereum / swarm / bzz - KEY / chunks -
` ,
} ,
{
2018-06-20 15:06:27 +03:00
Action : dbClean ,
CustomHelpTemplate : helpTemplate ,
Name : "clean" ,
Usage : "remove corrupt entries from a local chunk database" ,
ArgsUsage : "<chunkdb>" ,
Description : "Remove corrupt entries from a local chunk database" ,
2017-07-31 14:23:44 +03:00
} ,
} ,
} ,
2018-06-20 15:06:27 +03:00
2017-12-12 00:56:06 +03:00
// See config.go
DumpConfigCommand ,
2016-12-10 20:45:52 +03:00
}
2018-07-17 08:04:43 +03:00
// append a hidden help subcommand to all commands that have subcommands
// if a help command was already defined above, that one will take precedence.
addDefaultHelpSubcommands ( app . Commands )
2017-08-11 14:29:05 +03:00
sort . Sort ( cli . CommandsByName ( app . Commands ) )
2016-12-10 20:45:52 +03:00
2016-09-22 03:24:31 +03:00
app . Flags = [ ] cli . Flag {
utils . IdentityFlag ,
utils . DataDirFlag ,
utils . BootnodesFlag ,
utils . KeyStoreDirFlag ,
utils . ListenPortFlag ,
2016-11-28 15:29:33 +03:00
utils . NoDiscoverFlag ,
utils . DiscoveryV5Flag ,
2016-11-22 22:52:31 +03:00
utils . NetrestrictFlag ,
2016-09-22 03:24:31 +03:00
utils . NodeKeyFileFlag ,
utils . NodeKeyHexFlag ,
2016-11-28 15:29:33 +03:00
utils . MaxPeersFlag ,
utils . NATFlag ,
2016-09-22 03:24:31 +03:00
utils . IPCDisabledFlag ,
utils . IPCPathFlag ,
2017-04-12 03:03:42 +03:00
utils . PasswordFileFlag ,
2016-09-22 03:24:31 +03:00
// bzzd-specific flags
2017-01-05 13:57:41 +03:00
CorsStringFlag ,
2017-06-18 01:25:39 +03:00
EnsAPIFlag ,
2017-12-12 00:56:06 +03:00
SwarmTomlConfigPathFlag ,
2017-01-05 13:57:41 +03:00
SwarmSwapEnabledFlag ,
2017-06-18 01:25:39 +03:00
SwarmSwapAPIFlag ,
2018-06-20 15:06:27 +03:00
SwarmSyncDisabledFlag ,
SwarmSyncUpdateDelay ,
SwarmDeliverySkipCheckFlag ,
2017-05-22 09:56:40 +03:00
SwarmListenAddrFlag ,
2016-09-22 03:24:31 +03:00
SwarmPortFlag ,
SwarmAccountFlag ,
2016-11-28 15:29:33 +03:00
SwarmNetworkIdFlag ,
2016-09-22 03:24:31 +03:00
ChequebookAddrFlag ,
2016-12-10 20:45:52 +03:00
// upload flags
SwarmApiFlag ,
2018-06-20 15:06:27 +03:00
SwarmRecursiveFlag ,
2016-12-10 20:45:52 +03:00
SwarmWantManifestFlag ,
2016-12-13 14:48:30 +03:00
SwarmUploadDefaultPath ,
2017-04-06 15:21:16 +03:00
SwarmUpFromStdinFlag ,
SwarmUploadMimeType ,
2018-06-20 15:06:27 +03:00
// storage flags
SwarmStorePath ,
SwarmStoreCapacity ,
SwarmStoreCacheCapacity ,
}
rpcFlags := [ ] cli . Flag {
utils . WSEnabledFlag ,
utils . WSListenAddrFlag ,
utils . WSPortFlag ,
utils . WSApiFlag ,
utils . WSAllowedOriginsFlag ,
}
app . Flags = append ( app . Flags , rpcFlags ... )
2016-09-22 03:24:31 +03:00
app . Flags = append ( app . Flags , debug . Flags ... )
2018-02-23 16:19:59 +03:00
app . Flags = append ( app . Flags , swarmmetrics . Flags ... )
2018-07-13 18:40:28 +03:00
app . Flags = append ( app . Flags , tracing . Flags ... )
2016-09-22 03:24:31 +03:00
app . Before = func ( ctx * cli . Context ) error {
runtime . GOMAXPROCS ( runtime . NumCPU ( ) )
cmd, dashboard, log: log collection and exploration (#17097)
* cmd, dashboard, internal, log, node: logging feature
* cmd, dashboard, internal, log: requested changes
* dashboard, vendor: gofmt, govendor, use vendored file watcher
* dashboard, log: gofmt -s -w, goimports
* dashboard, log: gosimple
2018-07-11 10:59:04 +03:00
if err := debug . Setup ( ctx , "" ) ; err != nil {
2018-02-23 16:19:59 +03:00
return err
}
swarmmetrics . Setup ( ctx )
2018-07-13 18:40:28 +03:00
tracing . Setup ( ctx )
2018-02-23 16:19:59 +03:00
return nil
2016-09-22 03:24:31 +03:00
}
app . After = func ( ctx * cli . Context ) error {
debug . Exit ( )
return nil
}
}
func main ( ) {
if err := app . Run ( os . Args ) ; err != nil {
fmt . Fprintln ( os . Stderr , err )
os . Exit ( 1 )
}
}
2016-12-10 20:45:52 +03:00
func version ( ctx * cli . Context ) error {
2018-07-30 11:56:40 +03:00
fmt . Println ( strings . Title ( clientIdentifier ) )
fmt . Println ( "Version:" , sv . VersionWithMeta )
2016-12-10 20:45:52 +03:00
if gitCommit != "" {
fmt . Println ( "Git Commit:" , gitCommit )
}
fmt . Println ( "Go Version:" , runtime . Version ( ) )
fmt . Println ( "OS:" , runtime . GOOS )
return nil
}
2016-09-22 03:24:31 +03:00
func bzzd ( ctx * cli . Context ) error {
2017-12-12 00:56:06 +03:00
//build a valid bzzapi.Config from all available sources:
//default config, file config, command line and env vars
bzzconfig , err := buildConfig ( ctx )
if err != nil {
utils . Fatalf ( "unable to configure swarm: %v" , err )
2017-06-30 12:10:41 +03:00
}
2017-04-12 17:27:23 +03:00
cfg := defaultNodeConfig
2018-06-20 15:06:27 +03:00
//pss operates on ws
cfg . WSModules = append ( cfg . WSModules , "pss" )
2017-12-12 00:56:06 +03:00
//geth only supports --datadir via command line
//in order to be consistent within swarm, if we pass --datadir via environment variable
//or via config file, we get the same directory for geth and swarm
if _ , err := os . Stat ( bzzconfig . Path ) ; err == nil {
cfg . DataDir = bzzconfig . Path
}
//setup the ethereum node
2017-04-12 17:27:23 +03:00
utils . SetNodeConfig ( ctx , & cfg )
stack , err := node . New ( & cfg )
if err != nil {
utils . Fatalf ( "can't create node: %v" , err )
}
2017-12-12 00:56:06 +03:00
//a few steps need to be done after the config phase is completed,
//due to overriding behavior
initSwarmNode ( bzzconfig , stack , ctx )
//register BZZ as node.Service in the ethereum node
2018-06-20 15:06:27 +03:00
registerBzzService ( bzzconfig , stack )
2017-12-12 00:56:06 +03:00
//start the node
2016-09-22 03:24:31 +03:00
utils . StartNode ( stack )
2017-04-12 17:27:23 +03:00
2017-02-06 21:08:38 +03:00
go func ( ) {
sigc := make ( chan os . Signal , 1 )
signal . Notify ( sigc , syscall . SIGTERM )
defer signal . Stop ( sigc )
<- sigc
2017-03-02 16:06:16 +03:00
log . Info ( "Got sigterm, shutting swarm down..." )
2017-02-06 21:08:38 +03:00
stack . Stop ( )
} ( )
2017-04-12 17:27:23 +03:00
2016-09-22 03:24:31 +03:00
// Add bootnodes as initial peers.
2017-12-12 00:56:06 +03:00
if bzzconfig . BootNodes != "" {
bootnodes := strings . Split ( bzzconfig . BootNodes , "," )
2016-11-28 15:29:33 +03:00
injectBootnodes ( stack . Server ( ) , bootnodes )
2016-09-22 03:24:31 +03:00
} else {
2018-06-20 15:06:27 +03:00
if bzzconfig . NetworkID == 3 {
2016-12-13 11:49:02 +03:00
injectBootnodes ( stack . Server ( ) , testbetBootNodes )
}
2016-09-22 03:24:31 +03:00
}
stack . Wait ( )
return nil
}
2018-06-20 15:06:27 +03:00
func registerBzzService ( bzzconfig * bzzapi . Config , stack * node . Node ) {
2017-12-12 00:56:06 +03:00
//define the swarm service boot function
2018-06-20 15:06:27 +03:00
boot := func ( _ * node . ServiceContext ) ( node . Service , error ) {
// In production, mockStore must be always nil.
return swarm . NewSwarm ( bzzconfig , nil )
2016-09-22 03:24:31 +03:00
}
2017-12-12 00:56:06 +03:00
//register within the ethereum node
2016-09-22 03:24:31 +03:00
if err := stack . Register ( boot ) ; err != nil {
2017-02-22 18:22:50 +03:00
utils . Fatalf ( "Failed to register the Swarm service: %v" , err )
2016-09-22 03:24:31 +03:00
}
}
2017-12-12 00:56:06 +03:00
func getAccount ( bzzaccount string , ctx * cli . Context , stack * node . Node ) * ecdsa . PrivateKey {
//an account is mandatory
if bzzaccount == "" {
utils . Fatalf ( SWARM_ERR_NO_BZZACCOUNT )
2016-09-22 03:24:31 +03:00
}
// Try to load the arg as a hex key file.
2017-12-12 00:56:06 +03:00
if key , err := crypto . LoadECDSA ( bzzaccount ) ; err == nil {
2017-03-02 16:06:16 +03:00
log . Info ( "Swarm account key loaded" , "address" , crypto . PubkeyToAddress ( key . PublicKey ) )
2016-09-22 03:24:31 +03:00
return key
}
// Otherwise try getting it from the keystore.
2017-01-24 12:49:20 +03:00
am := stack . AccountManager ( )
2017-02-07 13:47:34 +03:00
ks := am . Backends ( keystore . KeyStoreType ) [ 0 ] . ( * keystore . KeyStore )
2017-01-24 12:49:20 +03:00
2017-12-12 00:56:06 +03:00
return decryptStoreAccount ( ks , bzzaccount , utils . MakePasswordList ( ctx ) )
2016-09-22 03:24:31 +03:00
}
2018-07-21 22:49:36 +03:00
// getPrivKey returns the private key of the specified bzzaccount
// Used only by client commands, such as `resource`
func getPrivKey ( ctx * cli . Context ) * ecdsa . PrivateKey {
// booting up the swarm node just as we do in bzzd action
bzzconfig , err := buildConfig ( ctx )
if err != nil {
utils . Fatalf ( "unable to configure swarm: %v" , err )
}
cfg := defaultNodeConfig
if _ , err := os . Stat ( bzzconfig . Path ) ; err == nil {
cfg . DataDir = bzzconfig . Path
}
utils . SetNodeConfig ( ctx , & cfg )
stack , err := node . New ( & cfg )
if err != nil {
utils . Fatalf ( "can't create node: %v" , err )
}
return getAccount ( bzzconfig . BzzAccount , ctx , stack )
}
2017-04-12 03:03:42 +03:00
func decryptStoreAccount ( ks * keystore . KeyStore , account string , passwords [ ] string ) * ecdsa . PrivateKey {
2016-09-22 03:24:31 +03:00
var a accounts . Account
var err error
if common . IsHexAddress ( account ) {
2017-01-24 12:49:20 +03:00
a , err = ks . Find ( accounts . Account { Address : common . HexToAddress ( account ) } )
} else if ix , ixerr := strconv . Atoi ( account ) ; ixerr == nil && ix > 0 {
if accounts := ks . Accounts ( ) ; len ( accounts ) > ix {
a = accounts [ ix ]
} else {
err = fmt . Errorf ( "index %d higher than number of accounts %d" , ix , len ( accounts ) )
}
2016-09-22 03:24:31 +03:00
} else {
2017-02-22 18:22:50 +03:00
utils . Fatalf ( "Can't find swarm account key %s" , account )
2016-09-22 03:24:31 +03:00
}
if err != nil {
2017-12-12 00:56:06 +03:00
utils . Fatalf ( "Can't find swarm account key: %v - Is the provided bzzaccount(%s) from the right datadir/Path?" , err , account )
2016-09-22 03:24:31 +03:00
}
2017-02-08 16:53:02 +03:00
keyjson , err := ioutil . ReadFile ( a . URL . Path )
2016-09-22 03:24:31 +03:00
if err != nil {
2017-02-22 18:22:50 +03:00
utils . Fatalf ( "Can't load swarm account key: %v" , err )
2016-09-22 03:24:31 +03:00
}
2017-04-12 03:03:42 +03:00
for i := 0 ; i < 3 ; i ++ {
password := getPassPhrase ( fmt . Sprintf ( "Unlocking swarm account %s [%d/3]" , a . Address . Hex ( ) , i + 1 ) , i , passwords )
key , err := keystore . DecryptKey ( keyjson , password )
2016-09-22 03:24:31 +03:00
if err == nil {
return key . PrivateKey
}
}
2017-02-22 18:22:50 +03:00
utils . Fatalf ( "Can't decrypt swarm account key" )
2016-09-22 03:24:31 +03:00
return nil
}
2017-04-12 03:03:42 +03:00
// getPassPhrase retrieves the password associated with bzz account, either by fetching
// from a list of pre-loaded passwords, or by requesting it interactively from user.
func getPassPhrase ( prompt string , i int , passwords [ ] string ) string {
// non-interactive
if len ( passwords ) > 0 {
if i < len ( passwords ) {
return passwords [ i ]
}
return passwords [ len ( passwords ) - 1 ]
}
// fallback to interactive mode
2016-09-22 03:24:31 +03:00
if prompt != "" {
fmt . Println ( prompt )
}
password , err := console . Stdin . PromptPassword ( "Passphrase: " )
if err != nil {
2017-02-22 18:22:50 +03:00
utils . Fatalf ( "Failed to read passphrase: %v" , err )
2016-09-22 03:24:31 +03:00
}
return password
}
func injectBootnodes ( srv * p2p . Server , nodes [ ] string ) {
for _ , url := range nodes {
n , err := discover . ParseNode ( url )
if err != nil {
2017-03-02 16:06:16 +03:00
log . Error ( "Invalid swarm bootnode" , "err" , err )
2016-11-28 15:29:33 +03:00
continue
2016-09-22 03:24:31 +03:00
}
srv . AddPeer ( n )
}
}
2018-07-17 08:04:43 +03:00
// addDefaultHelpSubcommand scans through defined CLI commands and adds
// a basic help subcommand to each
// if a help command is already defined, it will take precedence over the default.
func addDefaultHelpSubcommands ( commands [ ] cli . Command ) {
for i := range commands {
cmd := & commands [ i ]
if cmd . Subcommands != nil {
cmd . Subcommands = append ( cmd . Subcommands , defaultSubcommandHelp )
addDefaultHelpSubcommands ( cmd . Subcommands )
}
}
}