Commit 9287808c authored by Ralph Pichler's avatar Ralph Pichler Committed by GitHub

add init command (#944)

parent 6888fcc2
...@@ -96,6 +96,10 @@ func newCommand(opts ...option) (c *command, err error) { ...@@ -96,6 +96,10 @@ func newCommand(opts ...option) (c *command, err error) {
return nil, err return nil, err
} }
if err := c.initInitCmd(); err != nil {
return nil, err
}
c.initVersionCmd() c.initVersionCmd()
if err := c.initConfigurateOptionsCmd(); err != nil { if err := c.initConfigurateOptionsCmd(); err != nil {
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package cmd
import (
"fmt"
"io/ioutil"
"strings"
"github.com/ethersphere/bee/pkg/logging"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
func (c *command) initInitCmd() (err error) {
cmd := &cobra.Command{
Use: "init",
Short: "Initialise a Swarm node",
RunE: func(cmd *cobra.Command, args []string) (err error) {
if len(args) > 0 {
return cmd.Help()
}
var logger logging.Logger
switch v := strings.ToLower(c.config.GetString(optionNameVerbosity)); v {
case "0", "silent":
logger = logging.New(ioutil.Discard, 0)
case "1", "error":
logger = logging.New(cmd.OutOrStdout(), logrus.ErrorLevel)
case "2", "warn":
logger = logging.New(cmd.OutOrStdout(), logrus.WarnLevel)
case "3", "info":
logger = logging.New(cmd.OutOrStdout(), logrus.InfoLevel)
case "4", "debug":
logger = logging.New(cmd.OutOrStdout(), logrus.DebugLevel)
case "5", "trace":
logger = logging.New(cmd.OutOrStdout(), logrus.TraceLevel)
default:
return fmt.Errorf("unknown verbosity level %q", v)
}
_, err = c.configureSigner(cmd, logger)
return err
},
PreRunE: func(cmd *cobra.Command, args []string) error {
return c.config.BindPFlags(cmd.Flags())
},
}
c.setAllFlags(cmd)
c.root.AddCommand(cmd)
return nil
}
...@@ -94,6 +94,98 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz ...@@ -94,6 +94,98 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz
debugAPIAddr = "" debugAPIAddr = ""
} }
signerConfig, err := c.configureSigner(cmd, logger)
if err != nil {
return err
}
b, err := node.NewBee(c.config.GetString(optionNameP2PAddr), signerConfig.address, *signerConfig.publicKey, signerConfig.keystore, signerConfig.signer, c.config.GetUint64(optionNameNetworkID), logger, signerConfig.libp2pPrivateKey, node.Options{
DataDir: c.config.GetString(optionNameDataDir),
DBCapacity: c.config.GetUint64(optionNameDBCapacity),
Password: signerConfig.password,
APIAddr: c.config.GetString(optionNameAPIAddr),
DebugAPIAddr: debugAPIAddr,
Addr: c.config.GetString(optionNameP2PAddr),
NATAddr: c.config.GetString(optionNameNATAddr),
EnableWS: c.config.GetBool(optionNameP2PWSEnable),
EnableQUIC: c.config.GetBool(optionNameP2PQUICEnable),
WelcomeMessage: c.config.GetString(optionWelcomeMessage),
Bootnodes: c.config.GetStringSlice(optionNameBootnodes),
CORSAllowedOrigins: c.config.GetStringSlice(optionCORSAllowedOrigins),
Standalone: c.config.GetBool(optionNameStandalone),
TracingEnabled: c.config.GetBool(optionNameTracingEnabled),
TracingEndpoint: c.config.GetString(optionNameTracingEndpoint),
TracingServiceName: c.config.GetString(optionNameTracingServiceName),
Logger: logger,
GlobalPinningEnabled: c.config.GetBool(optionNameGlobalPinningEnabled),
PaymentThreshold: c.config.GetUint64(optionNamePaymentThreshold),
PaymentTolerance: c.config.GetUint64(optionNamePaymentTolerance),
PaymentEarly: c.config.GetUint64(optionNamePaymentEarly),
ResolverConnectionCfgs: resolverCfgs,
GatewayMode: c.config.GetBool(optionNameGatewayMode),
SwapEndpoint: c.config.GetString(optionNameSwapEndpoint),
SwapFactoryAddress: c.config.GetString(optionNameSwapFactoryAddress),
SwapInitialDeposit: c.config.GetUint64(optionNameSwapInitialDeposit),
SwapEnable: c.config.GetBool(optionNameSwapEnable),
})
if err != nil {
return err
}
// Wait for termination or interrupt signals.
// We want to clean up things at the end.
interruptChannel := make(chan os.Signal, 1)
signal.Notify(interruptChannel, syscall.SIGINT, syscall.SIGTERM)
// Block main goroutine until it is interrupted
sig := <-interruptChannel
logger.Debugf("received signal: %v", sig)
logger.Info("shutting down")
// Shutdown
done := make(chan struct{})
go func() {
defer close(done)
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
if err := b.Shutdown(ctx); err != nil {
logger.Errorf("shutdown: %v", err)
}
}()
// If shutdown function is blocking too long,
// allow process termination by receiving another signal.
select {
case sig := <-interruptChannel:
logger.Debugf("received signal: %v", sig)
case <-done:
}
return nil
},
PreRunE: func(cmd *cobra.Command, args []string) error {
return c.config.BindPFlags(cmd.Flags())
},
}
c.setAllFlags(cmd)
c.root.AddCommand(cmd)
return nil
}
type signerConfig struct {
keystore keystore.Service
signer crypto.Signer
address swarm.Address
publicKey *ecdsa.PublicKey
libp2pPrivateKey *ecdsa.PrivateKey
password string
}
func (c *command) configureSigner(cmd *cobra.Command, logger logging.Logger) (config *signerConfig, err error) {
var keystore keystore.Service var keystore keystore.Service
if c.config.GetString(optionNameDataDir) == "" { if c.config.GetString(optionNameDataDir) == "" {
keystore = memkeystore.New() keystore = memkeystore.New()
...@@ -102,83 +194,82 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz ...@@ -102,83 +194,82 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz
keystore = filekeystore.New(filepath.Join(c.config.GetString(optionNameDataDir), "keys")) keystore = filekeystore.New(filepath.Join(c.config.GetString(optionNameDataDir), "keys"))
} }
var signer crypto.Signer
var address swarm.Address
var password string var password string
var publicKey *ecdsa.PublicKey
if p := c.config.GetString(optionNamePassword); p != "" { if p := c.config.GetString(optionNamePassword); p != "" {
password = p password = p
} else if pf := c.config.GetString(optionNamePasswordFile); pf != "" { } else if pf := c.config.GetString(optionNamePasswordFile); pf != "" {
b, err := ioutil.ReadFile(pf) b, err := ioutil.ReadFile(pf)
if err != nil { if err != nil {
return err return nil, err
} }
password = string(bytes.Trim(b, "\n")) password = string(bytes.Trim(b, "\n"))
} else { } else {
exists, err := keystore.Exists("swarm") exists, err := keystore.Exists("swarm")
if err != nil { if err != nil {
return err return nil, err
} }
if exists { if exists {
password, err = terminalPromptPassword(cmd, c.passwordReader, "Password") password, err = terminalPromptPassword(cmd, c.passwordReader, "Password")
if err != nil { if err != nil {
return err return nil, err
} }
} else { } else {
password, err = terminalPromptCreatePassword(cmd, c.passwordReader) password, err = terminalPromptCreatePassword(cmd, c.passwordReader)
if err != nil { if err != nil {
return err return nil, err
} }
} }
} }
var signer crypto.Signer
var address swarm.Address
var publicKey *ecdsa.PublicKey
if c.config.GetBool(optionNameClefSignerEnable) { if c.config.GetBool(optionNameClefSignerEnable) {
endpoint := c.config.GetString(optionNameClefSignerEndpoint) endpoint := c.config.GetString(optionNameClefSignerEndpoint)
if endpoint == "" { if endpoint == "" {
endpoint, err = clef.DefaultIpcPath() endpoint, err = clef.DefaultIpcPath()
if err != nil { if err != nil {
return err return nil, err
} }
} }
externalSigner, err := external.NewExternalSigner(endpoint) externalSigner, err := external.NewExternalSigner(endpoint)
if err != nil { if err != nil {
return err return nil, err
} }
clefRPC, err := rpc.Dial(endpoint) clefRPC, err := rpc.Dial(endpoint)
if err != nil { if err != nil {
return err return nil, err
} }
signer, err = clef.NewSigner(externalSigner, clefRPC, crypto.Recover) signer, err = clef.NewSigner(externalSigner, clefRPC, crypto.Recover)
if err != nil { if err != nil {
return err return nil, err
} }
publicKey, err = signer.PublicKey() publicKey, err = signer.PublicKey()
if err != nil { if err != nil {
return err return nil, err
} }
address, err = crypto.NewOverlayAddress(*publicKey, c.config.GetUint64(optionNameNetworkID)) address, err = crypto.NewOverlayAddress(*publicKey, c.config.GetUint64(optionNameNetworkID))
if err != nil { if err != nil {
return err return nil, err
} }
logger.Infof("using swarm network address through clef: %s", address) logger.Infof("using swarm network address through clef: %s", address)
} else { } else {
swarmPrivateKey, created, err := keystore.Key("swarm", password) swarmPrivateKey, created, err := keystore.Key("swarm", password)
if err != nil { if err != nil {
return fmt.Errorf("swarm key: %w", err) return nil, fmt.Errorf("swarm key: %w", err)
} }
signer = crypto.NewDefaultSigner(swarmPrivateKey) signer = crypto.NewDefaultSigner(swarmPrivateKey)
publicKey = &swarmPrivateKey.PublicKey publicKey = &swarmPrivateKey.PublicKey
address, err = crypto.NewOverlayAddress(*publicKey, c.config.GetUint64(optionNameNetworkID)) address, err = crypto.NewOverlayAddress(*publicKey, c.config.GetUint64(optionNameNetworkID))
if err != nil { if err != nil {
return err return nil, err
} }
if created { if created {
...@@ -190,79 +281,22 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz ...@@ -190,79 +281,22 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz
logger.Infof("swarm public key %x", crypto.EncodeSecp256k1PublicKey(publicKey)) logger.Infof("swarm public key %x", crypto.EncodeSecp256k1PublicKey(publicKey))
b, err := node.NewBee(c.config.GetString(optionNameP2PAddr), address, *publicKey, keystore, signer, c.config.GetUint64(optionNameNetworkID), logger, node.Options{ libp2pPrivateKey, created, err := keystore.Key("libp2p", password)
DataDir: c.config.GetString(optionNameDataDir),
DBCapacity: c.config.GetUint64(optionNameDBCapacity),
Password: password,
APIAddr: c.config.GetString(optionNameAPIAddr),
DebugAPIAddr: debugAPIAddr,
Addr: c.config.GetString(optionNameP2PAddr),
NATAddr: c.config.GetString(optionNameNATAddr),
EnableWS: c.config.GetBool(optionNameP2PWSEnable),
EnableQUIC: c.config.GetBool(optionNameP2PQUICEnable),
WelcomeMessage: c.config.GetString(optionWelcomeMessage),
Bootnodes: c.config.GetStringSlice(optionNameBootnodes),
CORSAllowedOrigins: c.config.GetStringSlice(optionCORSAllowedOrigins),
Standalone: c.config.GetBool(optionNameStandalone),
TracingEnabled: c.config.GetBool(optionNameTracingEnabled),
TracingEndpoint: c.config.GetString(optionNameTracingEndpoint),
TracingServiceName: c.config.GetString(optionNameTracingServiceName),
Logger: logger,
GlobalPinningEnabled: c.config.GetBool(optionNameGlobalPinningEnabled),
PaymentThreshold: c.config.GetUint64(optionNamePaymentThreshold),
PaymentTolerance: c.config.GetUint64(optionNamePaymentTolerance),
PaymentEarly: c.config.GetUint64(optionNamePaymentEarly),
ResolverConnectionCfgs: resolverCfgs,
GatewayMode: c.config.GetBool(optionNameGatewayMode),
SwapEndpoint: c.config.GetString(optionNameSwapEndpoint),
SwapFactoryAddress: c.config.GetString(optionNameSwapFactoryAddress),
SwapInitialDeposit: c.config.GetUint64(optionNameSwapInitialDeposit),
SwapEnable: c.config.GetBool(optionNameSwapEnable),
})
if err != nil { if err != nil {
return err return nil, fmt.Errorf("libp2p key: %w", err)
} }
if created {
// Wait for termination or interrupt signals. logger.Debugf("new libp2p key created")
// We want to clean up things at the end. } else {
interruptChannel := make(chan os.Signal, 1) logger.Debugf("using existing libp2p key")
signal.Notify(interruptChannel, syscall.SIGINT, syscall.SIGTERM)
// Block main goroutine until it is interrupted
sig := <-interruptChannel
logger.Debugf("received signal: %v", sig)
logger.Info("shutting down")
// Shutdown
done := make(chan struct{})
go func() {
defer close(done)
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
if err := b.Shutdown(ctx); err != nil {
logger.Errorf("shutdown: %v", err)
}
}()
// If shutdown function is blocking too long,
// allow process termination by receiving another signal.
select {
case sig := <-interruptChannel:
logger.Debugf("received signal: %v", sig)
case <-done:
}
return nil
},
PreRunE: func(cmd *cobra.Command, args []string) error {
return c.config.BindPFlags(cmd.Flags())
},
} }
c.setAllFlags(cmd) return &signerConfig{
c.root.AddCommand(cmd) keystore: keystore,
return nil signer: signer,
address: address,
publicKey: publicKey,
libp2pPrivateKey: libp2pPrivateKey,
password: password,
}, nil
} }
...@@ -111,7 +111,7 @@ type Options struct { ...@@ -111,7 +111,7 @@ type Options struct {
SwapEnable bool SwapEnable bool
} }
func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, keystore keystore.Service, signer crypto.Signer, networkID uint64, logger logging.Logger, o Options) (*Bee, error) { func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, keystore keystore.Service, signer crypto.Signer, networkID uint64, logger logging.Logger, libp2pPrivateKey *ecdsa.PrivateKey, o Options) (*Bee, error) {
tracer, tracerCloser, err := tracing.NewTracer(&tracing.Options{ tracer, tracerCloser, err := tracing.NewTracer(&tracing.Options{
Enabled: o.TracingEnabled, Enabled: o.TracingEnabled,
Endpoint: o.TracingEndpoint, Endpoint: o.TracingEndpoint,
...@@ -129,17 +129,6 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, ...@@ -129,17 +129,6 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
tracerCloser: tracerCloser, tracerCloser: tracerCloser,
} }
// Construct P2P service.
libp2pPrivateKey, created, err := keystore.Key("libp2p", o.Password)
if err != nil {
return nil, fmt.Errorf("libp2p key: %w", err)
}
if created {
logger.Debugf("new libp2p key created")
} else {
logger.Debugf("using existing libp2p key")
}
var stateStore storage.StateStorer var stateStore storage.StateStorer
if o.DataDir == "" { if o.DataDir == "" {
stateStore = mockinmem.NewStateStore() stateStore = mockinmem.NewStateStore()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment