Improve statusd CLI usage (#441)
This PR refactors CLI API, removes obsolete commands and splits status code into smaller pieces: * get rid of subcommands API (no ./status <command>) * get rid of custom cli app package * use stdlib flag package for handling command line flags * move cross-compilation / mobile related code to lib/ package * move wnode command into separate binary (cmd/node-status, name is subject to discuss) * remove faucet command as obsolete * update/add docs/READMES/wikis for new command line flags It makes statusd code much simpler and smaller, separates concerns (lib, wnode and statusd are different things).
This commit is contained in:
parent
987cdd6221
commit
4536e99275
|
@ -5,6 +5,12 @@
|
|||
# git config --global core.excludesfile ~/.gitignore_global
|
||||
|
||||
/statusd-data
|
||||
/cmd/statusd/statusd-data
|
||||
/cmd/statusd/statusd
|
||||
|
||||
/wnode-status-data
|
||||
/cmd/wnode-status/wnode-status-data
|
||||
/cmd/wnode-status/wnode-status
|
||||
|
||||
/tmp
|
||||
*/**/*un~
|
||||
|
|
25
Makefile
25
Makefile
|
@ -1,6 +1,9 @@
|
|||
.PHONY: statusgo all test xgo clean help
|
||||
.PHONY: statusgo-android statusgo-ios
|
||||
|
||||
help: ##@other Show this help
|
||||
@perl -e '$(HELP_FUN)' $(MAKEFILE_LIST)
|
||||
|
||||
include ./static/tools/mk/lint.mk
|
||||
|
||||
GOBIN = build/bin
|
||||
|
@ -28,32 +31,32 @@ HELP_FUN = \
|
|||
print "\n"; \
|
||||
}
|
||||
|
||||
help: ##@other Show this help
|
||||
@perl -e '$(HELP_FUN)' $(MAKEFILE_LIST)
|
||||
|
||||
# Main targets
|
||||
|
||||
UNIT_TEST_PACKAGES := $(shell go list ./... | grep -v /vendor | grep -v /e2e | grep -v /cmd)
|
||||
|
||||
statusgo: ##@build Build status-go as statusd server
|
||||
build/env.sh go build -i -o $(GOBIN)/statusd -v $(shell build/testnet-flags.sh) ./cmd/statusd
|
||||
@echo "\nCompilation done.\nRun \"build/bin/statusd help\" to view available commands."
|
||||
@echo "\nCompilation done.\nRun \"build/bin/statusd -h\" to view available commands."
|
||||
|
||||
wnode-status: ##@build Build wnode-status (Whisper 5 debug tool)
|
||||
build/env.sh go build -i -o $(GOBIN)/wnode-status -v $(shell build/testnet-flags.sh) ./cmd/wnode-status
|
||||
|
||||
statusgo-cross: statusgo-android statusgo-ios
|
||||
@echo "Full cross compilation done."
|
||||
@ls -ld $(GOBIN)/statusgo-*
|
||||
|
||||
statusgo-android: xgo ##@cross-compile Build status-go for Android
|
||||
build/env.sh $(GOBIN)/xgo --image farazdagi/xgo --go=$(GO) -out statusgo --dest=$(GOBIN) --targets=android-16/aar -v $(shell build/testnet-flags.sh) ./cmd/statusd
|
||||
build/env.sh $(GOBIN)/xgo --image farazdagi/xgo --go=$(GO) -out statusgo --dest=$(GOBIN) --targets=android-16/aar -v $(shell build/testnet-flags.sh) ./lib
|
||||
@echo "Android cross compilation done."
|
||||
|
||||
statusgo-ios: xgo ##@cross-compile Build status-go for iOS
|
||||
build/env.sh $(GOBIN)/xgo --image farazdagi/xgo --go=$(GO) -out statusgo --dest=$(GOBIN) --targets=ios-9.3/framework -v $(shell build/testnet-flags.sh) ./cmd/statusd
|
||||
build/env.sh $(GOBIN)/xgo --image farazdagi/xgo --go=$(GO) -out statusgo --dest=$(GOBIN) --targets=ios-9.3/framework -v $(shell build/testnet-flags.sh) ./lib
|
||||
@echo "iOS framework cross compilation done."
|
||||
|
||||
statusgo-ios-simulator: xgo ##@cross-compile Build status-go for iOS Simulator
|
||||
@build/env.sh docker pull farazdagi/xgo-ios-simulator
|
||||
build/env.sh $(GOBIN)/xgo --image farazdagi/xgo-ios-simulator --go=$(GO) -out statusgo --dest=$(GOBIN) --targets=ios-9.3/framework -v $(shell build/testnet-flags.sh) ./cmd/statusd
|
||||
build/env.sh $(GOBIN)/xgo --image farazdagi/xgo-ios-simulator --go=$(GO) -out statusgo --dest=$(GOBIN) --targets=ios-9.3/framework -v $(shell build/testnet-flags.sh) ./lib
|
||||
@echo "iOS framework cross compilation done."
|
||||
|
||||
xgo:
|
||||
|
@ -66,15 +69,15 @@ statusgo-mainnet:
|
|||
@echo "Run \"build/bin/statusgo\" to view available commands"
|
||||
|
||||
statusgo-android-mainnet: xgo
|
||||
build/env.sh $(GOBIN)/xgo --image farazdagi/xgo --go=$(GO) -out statusgo --dest=$(GOBIN) --targets=android-16/aar -v $(shell build/mainnet-flags.sh) ./cmd/statusd
|
||||
build/env.sh $(GOBIN)/xgo --image farazdagi/xgo --go=$(GO) -out statusgo --dest=$(GOBIN) --targets=android-16/aar -v $(shell build/mainnet-flags.sh) ./lib
|
||||
@echo "Android cross compilation done (mainnet)."
|
||||
|
||||
statusgo-ios-mainnet: xgo
|
||||
build/env.sh $(GOBIN)/xgo --image farazdagi/xgo --go=$(GO) -out statusgo --dest=$(GOBIN) --targets=ios-9.3/framework -v $(shell build/mainnet-flags.sh) ./cmd/statusd
|
||||
build/env.sh $(GOBIN)/xgo --image farazdagi/xgo --go=$(GO) -out statusgo --dest=$(GOBIN) --targets=ios-9.3/framework -v $(shell build/mainnet-flags.sh) ./lib
|
||||
@echo "iOS framework cross compilation done (mainnet)."
|
||||
|
||||
statusgo-ios-simulator-mainnet: xgo
|
||||
build/env.sh $(GOBIN)/xgo --image farazdagi/xgo-ios-simulator --go=$(GO) -out statusgo --dest=$(GOBIN) --targets=ios-9.3/framework -v $(shell build/mainnet-flags.sh) ./cmd/statusd
|
||||
build/env.sh $(GOBIN)/xgo --image farazdagi/xgo-ios-simulator --go=$(GO) -out statusgo --dest=$(GOBIN) --targets=ios-9.3/framework -v $(shell build/mainnet-flags.sh) ./lib
|
||||
@echo "iOS framework cross compilation done (mainnet)."
|
||||
|
||||
generate: ##@other Regenerate assets and other auto-generated stuff
|
||||
|
@ -109,7 +112,7 @@ test-e2e: ##@tests Run e2e tests
|
|||
build/env.sh go test -timeout 20m ./e2e/rpc/... -network=$(networkid)
|
||||
build/env.sh go test -timeout 20m ./e2e/whisper/... -network=$(networkid)
|
||||
build/env.sh go test -timeout 10m ./e2e/transactions/... -network=$(networkid)
|
||||
build/env.sh go test -timeout 40m ./cmd/statusd -network=$(networkid)
|
||||
build/env.sh go test -timeout 40m ./lib -network=$(networkid)
|
||||
|
||||
ci: lint mock-install mock test-unit test-e2e ##@tests Run all linters and tests at once
|
||||
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/status-im/status-go/geth/params"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
)
|
||||
|
||||
var (
|
||||
faucetCommand = cli.Command{
|
||||
Action: faucetCommandHandler,
|
||||
Name: "faucet",
|
||||
Usage: "Starts faucet node (light node used by faucet service to request Ether)",
|
||||
Flags: []cli.Flag{
|
||||
HTTPPortFlag,
|
||||
HTTPEnabledFlag,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// faucetCommandHandler handles `statusd faucet` command
|
||||
func faucetCommandHandler(ctx *cli.Context) error {
|
||||
config, err := parseFaucetCommandConfig(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can not parse config: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("Starting Status Faucet node..")
|
||||
if err = statusAPI.StartNode(config); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// wait till node has been stopped
|
||||
node, err := statusAPI.NodeManager().Node()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
node.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseFaucetCommandConfig parses incoming CLI options and returns node configuration object
|
||||
func parseFaucetCommandConfig(ctx *cli.Context) (*params.NodeConfig, error) {
|
||||
nodeConfig, err := makeNodeConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// select sub-protocols
|
||||
nodeConfig.LightEthConfig.Enabled = true
|
||||
nodeConfig.WhisperConfig.Enabled = false
|
||||
nodeConfig.SwarmConfig.Enabled = false
|
||||
|
||||
// RPC configuration
|
||||
nodeConfig.APIModules = "eth"
|
||||
nodeConfig.HTTPHost = "0.0.0.0" // allow to connect from anywhere
|
||||
nodeConfig.HTTPPort = ctx.Int(HTTPPortFlag.Name)
|
||||
nodeConfig.RPCEnabled = ctx.Bool(HTTPEnabledFlag.Name)
|
||||
|
||||
// extra options
|
||||
nodeConfig.BootClusterConfig.Enabled = true
|
||||
|
||||
return nodeConfig, nil
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/status-im/status-go/geth/params"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
)
|
||||
|
||||
var (
|
||||
lesCommand = cli.Command{
|
||||
Action: lesCommandHandler,
|
||||
Name: "les",
|
||||
Usage: "Starts Light Ethereum node",
|
||||
Flags: []cli.Flag{
|
||||
WhisperEnabledFlag,
|
||||
SwarmEnabledFlag,
|
||||
HTTPEnabledFlag,
|
||||
HTTPPortFlag,
|
||||
IPCEnabledFlag,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// lesCommandHandler handles `statusd les` command
|
||||
func lesCommandHandler(ctx *cli.Context) error {
|
||||
config, err := parseLESCommandConfig(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can not parse config: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("Starting Light Status node..")
|
||||
if err = statusAPI.StartNode(config); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// wait till node has been stopped
|
||||
node, err := statusAPI.NodeManager().Node()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
node.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseLESCommandConfig parses incoming CLI options and returns node configuration object
|
||||
func parseLESCommandConfig(ctx *cli.Context) (*params.NodeConfig, error) {
|
||||
nodeConfig, err := makeNodeConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Enabled sub-protocols
|
||||
nodeConfig.LightEthConfig.Enabled = true
|
||||
nodeConfig.RPCEnabled = ctx.Bool(HTTPEnabledFlag.Name)
|
||||
nodeConfig.WhisperConfig.Enabled = ctx.Bool(WhisperEnabledFlag.Name)
|
||||
nodeConfig.SwarmConfig.Enabled = ctx.Bool(SwarmEnabledFlag.Name)
|
||||
|
||||
// RPC configuration
|
||||
if !ctx.Bool(HTTPEnabledFlag.Name) {
|
||||
nodeConfig.HTTPHost = "" // HTTP RPC is disabled
|
||||
}
|
||||
nodeConfig.HTTPPort = ctx.Int(HTTPPortFlag.Name)
|
||||
nodeConfig.IPCEnabled = ctx.Bool(IPCEnabledFlag.Name)
|
||||
|
||||
return nodeConfig, nil
|
||||
}
|
|
@ -1,174 +1,142 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/status-im/status-go/geth/api"
|
||||
"github.com/status-im/status-go/geth/params"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
)
|
||||
|
||||
var (
|
||||
gitCommit = "rely on linker: -ldflags -X main.GitCommit"
|
||||
buildStamp = "rely on linker: -ldflags -X main.buildStamp"
|
||||
app = makeApp(gitCommit)
|
||||
statusAPI = api.NewStatusAPI()
|
||||
gitCommit = "N/A" // rely on linker: -ldflags -X main.GitCommit"
|
||||
buildStamp = "N/A" // rely on linker: -ldflags -X main.buildStamp"
|
||||
)
|
||||
|
||||
var (
|
||||
// ProdModeFlag is whether we need dev or production settings
|
||||
ProdModeFlag = cli.BoolFlag{
|
||||
Name: "production",
|
||||
Usage: "Whether production settings should be loaded",
|
||||
}
|
||||
|
||||
// NodeKeyFileFlag is a node key file to be used as node's private key
|
||||
NodeKeyFileFlag = cli.StringFlag{
|
||||
Name: "nodekey",
|
||||
Usage: "P2P node key file (private key)",
|
||||
}
|
||||
|
||||
// DataDirFlag defines data directory for the node
|
||||
DataDirFlag = cli.StringFlag{
|
||||
Name: "datadir",
|
||||
Usage: "Data directory for the databases and keystore",
|
||||
Value: params.DataDir,
|
||||
}
|
||||
|
||||
// NetworkIDFlag defines network ID
|
||||
NetworkIDFlag = cli.IntFlag{
|
||||
Name: "networkid",
|
||||
Usage: "Network identifier (integer, 1=Homestead, 3=Ropsten, 4=Rinkeby)",
|
||||
Value: params.RopstenNetworkID,
|
||||
}
|
||||
|
||||
// WhisperEnabledFlag flags whether Whisper is enabled or not
|
||||
WhisperEnabledFlag = cli.BoolFlag{
|
||||
Name: "shh",
|
||||
Usage: "SHH protocol enabled",
|
||||
}
|
||||
|
||||
// SwarmEnabledFlag flags whether Swarm is enabled or not
|
||||
SwarmEnabledFlag = cli.BoolFlag{
|
||||
Name: "swarm",
|
||||
Usage: "Swarm protocol enabled",
|
||||
}
|
||||
|
||||
// HTTPEnabledFlag defines whether HTTP RPC endpoint should be opened or not
|
||||
HTTPEnabledFlag = cli.BoolFlag{
|
||||
Name: "http",
|
||||
Usage: "HTTP RPC enpoint enabled (default: false)",
|
||||
}
|
||||
|
||||
// HTTPPortFlag defines HTTP RPC port to use (if HTTP RPC is enabled)
|
||||
HTTPPortFlag = cli.IntFlag{
|
||||
Name: "httpport",
|
||||
Usage: "HTTP RPC server's listening port",
|
||||
Value: params.HTTPPort,
|
||||
}
|
||||
|
||||
// IPCEnabledFlag flags whether IPC is enabled or not
|
||||
IPCEnabledFlag = cli.BoolFlag{
|
||||
Name: "ipc",
|
||||
Usage: "IPC RPC enpoint enabled",
|
||||
}
|
||||
|
||||
// LogLevelFlag defines a log reporting level
|
||||
LogLevelFlag = cli.StringFlag{
|
||||
Name: "log",
|
||||
Usage: `Log level, one of: "ERROR", "WARN", "INFO", "DEBUG", and "TRACE"`,
|
||||
Value: "",
|
||||
}
|
||||
|
||||
// LogFileFlag defines a log filename
|
||||
LogFileFlag = cli.StringFlag{
|
||||
Name: "logfile",
|
||||
Usage: `Path to the log file`,
|
||||
Value: "",
|
||||
}
|
||||
prodMode = flag.Bool("production", false, "Whether production settings should be loaded")
|
||||
nodeKeyFile = flag.String("nodekey", "", "P2P node key file (private key)")
|
||||
dataDir = flag.String("datadir", params.DataDir, "Data directory for the databases and keystore")
|
||||
networkID = flag.Int("networkid", params.RopstenNetworkID, "Network identifier (integer, 1=Homestead, 3=Ropsten, 4=Rinkeby, 777=StatusChain)")
|
||||
whisperEnabled = flag.Bool("shh", false, "SHH protocol enabled")
|
||||
swarmEnabled = flag.Bool("swarm", false, "Swarm protocol enabled")
|
||||
httpEnabled = flag.Bool("http", false, "HTTP RPC endpoint enabled (default: false)")
|
||||
httpPort = flag.Int("httpport", params.HTTPPort, "HTTP RPC server's listening port")
|
||||
ipcEnabled = flag.Bool("ipc", false, "IPC RPC endpoint enabled")
|
||||
logLevel = flag.String("log", "INFO", `Log level, one of: "ERROR", "WARN", "INFO", "DEBUG", and "TRACE"`)
|
||||
logFile = flag.String("logfile", "", "Path to the log file")
|
||||
version = flag.Bool("version", false, "Print version")
|
||||
)
|
||||
|
||||
func init() {
|
||||
// setup the app
|
||||
app.Action = cli.ShowAppHelp
|
||||
app.HideVersion = true // separate command prints version
|
||||
app.Commands = []cli.Command{
|
||||
versionCommand,
|
||||
faucetCommand,
|
||||
lesCommand,
|
||||
wnodeCommand,
|
||||
}
|
||||
app.Flags = []cli.Flag{
|
||||
ProdModeFlag,
|
||||
NodeKeyFileFlag,
|
||||
DataDirFlag,
|
||||
NetworkIDFlag,
|
||||
LogLevelFlag,
|
||||
LogFileFlag,
|
||||
}
|
||||
app.Before = func(ctx *cli.Context) error {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
return nil
|
||||
}
|
||||
app.After = func(ctx *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
flag.Usage = printUsage
|
||||
flag.Parse()
|
||||
|
||||
// makeApp creates an app with sane defaults.
|
||||
func makeApp(gitCommit string) *cli.App {
|
||||
app := cli.NewApp()
|
||||
app.Name = filepath.Base(os.Args[0])
|
||||
app.Author = ""
|
||||
//app.Authors = nil
|
||||
app.Email = ""
|
||||
app.Version = params.Version
|
||||
if gitCommit != "" {
|
||||
app.Version += "-" + gitCommit[:8]
|
||||
config, err := makeNodeConfig()
|
||||
if err != nil {
|
||||
log.Fatalf("Making config failed: %v", err)
|
||||
return
|
||||
}
|
||||
app.Usage = "CLI for Status nodes management"
|
||||
return app
|
||||
|
||||
if *version {
|
||||
printVersion(config, gitCommit, buildStamp)
|
||||
return
|
||||
}
|
||||
|
||||
backend := api.NewStatusBackend()
|
||||
started, err := backend.StartNode(config)
|
||||
if err != nil {
|
||||
log.Fatalf("Node start failed: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// wait till node is started
|
||||
<-started
|
||||
|
||||
// wait till node has been stopped
|
||||
node, err := backend.NodeManager().Node()
|
||||
if err != nil {
|
||||
log.Fatalf("Getting node failed: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
node.Wait()
|
||||
}
|
||||
|
||||
// makeNodeConfig parses incoming CLI options and returns node configuration object
|
||||
func makeNodeConfig(ctx *cli.Context) (*params.NodeConfig, error) {
|
||||
nodeConfig, err := params.NewNodeConfig(
|
||||
ctx.GlobalString(DataDirFlag.Name),
|
||||
ctx.GlobalUint64(NetworkIDFlag.Name),
|
||||
!ctx.GlobalBool(ProdModeFlag.Name))
|
||||
func makeNodeConfig() (*params.NodeConfig, error) {
|
||||
devMode := !*prodMode
|
||||
nodeConfig, err := params.NewNodeConfig(*dataDir, uint64(*networkID), devMode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodeConfig.NodeKeyFile = ctx.GlobalString(NodeKeyFileFlag.Name)
|
||||
// TODO(divan): move this logic into params package
|
||||
if *nodeKeyFile != "" {
|
||||
nodeConfig.NodeKeyFile = *nodeKeyFile
|
||||
}
|
||||
|
||||
if logLevel := ctx.GlobalString(LogLevelFlag.Name); logLevel != "" {
|
||||
nodeConfig.LogLevel = logLevel
|
||||
if *logLevel != "" {
|
||||
nodeConfig.LogLevel = *logLevel
|
||||
}
|
||||
if logFile := ctx.GlobalString(LogFileFlag.Name); logFile != "" {
|
||||
nodeConfig.LogFile = logFile
|
||||
if *logFile != "" {
|
||||
nodeConfig.LogFile = *logFile
|
||||
}
|
||||
|
||||
nodeConfig.LightEthConfig.Enabled = true
|
||||
nodeConfig.RPCEnabled = *httpEnabled
|
||||
nodeConfig.WhisperConfig.Enabled = *whisperEnabled
|
||||
nodeConfig.SwarmConfig.Enabled = *swarmEnabled
|
||||
|
||||
// RPC configuration
|
||||
if !*httpEnabled {
|
||||
nodeConfig.HTTPHost = "" // HTTP RPC is disabled
|
||||
}
|
||||
nodeConfig.HTTPPort = *httpPort
|
||||
nodeConfig.IPCEnabled = *ipcEnabled
|
||||
|
||||
return nodeConfig, nil
|
||||
}
|
||||
|
||||
// printNodeConfig prints node config
|
||||
func printNodeConfig(ctx *cli.Context) {
|
||||
nodeConfig, err := makeNodeConfig(ctx)
|
||||
if err != nil {
|
||||
fmt.Printf("Loaded Config: failed (err: %v)", err)
|
||||
return
|
||||
// printVersion prints verbose output about version and config.
|
||||
func printVersion(config *params.NodeConfig, gitCommit, buildStamp string) {
|
||||
if gitCommit != "" && len(gitCommit) > 8 {
|
||||
params.Version += "-" + gitCommit[:8]
|
||||
}
|
||||
nodeConfig.LightEthConfig.Genesis = "SKIP"
|
||||
fmt.Println("Loaded Config: ", nodeConfig)
|
||||
|
||||
fmt.Println(strings.Title(params.ClientIdentifier))
|
||||
fmt.Println("Version:", params.Version)
|
||||
if gitCommit != "" {
|
||||
fmt.Println("Git Commit:", gitCommit)
|
||||
}
|
||||
if buildStamp != "" {
|
||||
fmt.Println("Build Stamp:", buildStamp)
|
||||
}
|
||||
|
||||
fmt.Println("Network Id:", config.NetworkID)
|
||||
fmt.Println("Go Version:", runtime.Version())
|
||||
fmt.Println("OS:", runtime.GOOS)
|
||||
fmt.Printf("GOPATH=%s\n", os.Getenv("GOPATH"))
|
||||
fmt.Printf("GOROOT=%s\n", runtime.GOROOT())
|
||||
|
||||
config.LightEthConfig.Genesis = "SKIP"
|
||||
fmt.Println("Loaded Config: ", config)
|
||||
}
|
||||
|
||||
func printUsage() {
|
||||
fmt.Fprintln(os.Stderr, "Usage: statusd [options]")
|
||||
fmt.Fprintf(os.Stderr, `
|
||||
Examples:
|
||||
statusd # run status node with defaults
|
||||
statusd -networkid 4 # run node on Rinkeby network
|
||||
statusd -datadir /dir # specify different dir for data
|
||||
statusd -ipc # enable IPC for usage with "geth attach"
|
||||
|
||||
Options:
|
||||
`)
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/status-im/status-go/geth/params"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
)
|
||||
|
||||
var (
|
||||
versionCommand = cli.Command{
|
||||
Action: versionCommandHandler,
|
||||
Name: "version",
|
||||
Usage: "Print app version",
|
||||
}
|
||||
)
|
||||
|
||||
// versionCommandHandler displays app version
|
||||
func versionCommandHandler(ctx *cli.Context) error {
|
||||
fmt.Println(strings.Title(params.ClientIdentifier))
|
||||
fmt.Println("Version:", params.Version)
|
||||
if gitCommit != "" {
|
||||
fmt.Println("Git Commit:", gitCommit)
|
||||
}
|
||||
if buildStamp != "" {
|
||||
fmt.Println("Build Stamp:", buildStamp)
|
||||
}
|
||||
|
||||
fmt.Println("Network Id:", ctx.GlobalInt(NetworkIDFlag.Name))
|
||||
fmt.Println("Go Version:", runtime.Version())
|
||||
fmt.Println("OS:", runtime.GOOS)
|
||||
fmt.Printf("GOPATH=%s\n", os.Getenv("GOPATH"))
|
||||
fmt.Printf("GOROOT=%s\n", runtime.GOROOT())
|
||||
|
||||
printNodeConfig(ctx)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,269 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/status-im/status-go/geth/account"
|
||||
"github.com/status-im/status-go/geth/common"
|
||||
"github.com/status-im/status-go/geth/params"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
)
|
||||
|
||||
var (
|
||||
// WhisperEchoModeFlag enables/disables Echo mode (arguments are printed for diagnostics)
|
||||
WhisperEchoModeFlag = cli.BoolTFlag{
|
||||
Name: "echo",
|
||||
Usage: "Echo mode, prints some arguments for diagnostics (default: true)",
|
||||
}
|
||||
|
||||
// WhisperBootstrapNodeFlag marks node as not actively listening for incoming connections
|
||||
WhisperBootstrapNodeFlag = cli.BoolTFlag{
|
||||
Name: "bootstrap",
|
||||
Usage: "Don't actively connect to peers, wait for incoming connections (default: true)",
|
||||
}
|
||||
|
||||
// WhisperNotificationServerNodeFlag enables/disables Push Notifications services
|
||||
WhisperNotificationServerNodeFlag = cli.BoolFlag{
|
||||
Name: "notify",
|
||||
Usage: "Node is capable of sending Push Notifications",
|
||||
}
|
||||
|
||||
// WhisperForwarderNodeFlag enables/disables message forwarding
|
||||
// (when neither sends nor decrypts envelopes, just forwards them)
|
||||
WhisperForwarderNodeFlag = cli.BoolFlag{
|
||||
Name: "forward",
|
||||
Usage: "Only forward messages, neither send nor decrypt messages",
|
||||
}
|
||||
|
||||
// WhisperMailserverNodeFlag enables/disables Inboxing services
|
||||
WhisperMailserverNodeFlag = cli.BoolFlag{
|
||||
Name: "mailserver",
|
||||
Usage: "Delivers expired messages on demand",
|
||||
}
|
||||
|
||||
// WhisperIdentityFile is path to file containing private key of the node (for asymmetric encryption)
|
||||
WhisperIdentityFile = cli.StringFlag{
|
||||
Name: "identity",
|
||||
Usage: "Protocol identity file (private key used for asymmetric encryption)",
|
||||
}
|
||||
|
||||
// WhisperPasswordFile is password used to do a symmetric encryption
|
||||
WhisperPasswordFile = cli.StringFlag{
|
||||
Name: "password",
|
||||
Usage: "Password file (password is used for symmetric encryption)",
|
||||
}
|
||||
|
||||
// WhisperPortFlag defines port on which Whisper protocol is listening
|
||||
WhisperPortFlag = cli.IntFlag{
|
||||
Name: "port",
|
||||
Usage: "Whisper node's listening port",
|
||||
Value: params.WhisperPort,
|
||||
}
|
||||
|
||||
// WhisperPoWFlag is the minimum PoW required by the node
|
||||
WhisperPoWFlag = cli.Float64Flag{
|
||||
Name: "pow",
|
||||
Usage: "PoW for messages to be added to queue, in float format",
|
||||
Value: params.WhisperMinimumPoW,
|
||||
}
|
||||
|
||||
// WhisperTTLFlag defines node's default TTL for envelopes
|
||||
WhisperTTLFlag = cli.IntFlag{
|
||||
Name: "ttl",
|
||||
Usage: "Time to live for messages, in seconds",
|
||||
Value: params.WhisperTTL,
|
||||
}
|
||||
|
||||
// WhisperInjectTestAccounts if set, then test accounts will be imported
|
||||
// into node's key store, and then will be injected as key pairs (identities)
|
||||
// into the Whisper as well.
|
||||
WhisperInjectTestAccounts = cli.BoolTFlag{
|
||||
Name: "injectaccounts",
|
||||
Usage: "Whether test account should be injected or not (default: true)",
|
||||
}
|
||||
|
||||
// FirebaseAuthorizationKey path to file containing FCM password
|
||||
FirebaseAuthorizationKey = cli.StringFlag{
|
||||
Name: "firebaseauth",
|
||||
Usage: "FCM Authorization Key used for sending Push Notifications",
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
wnodeCommand = cli.Command{
|
||||
Action: wnode,
|
||||
Name: "wnode",
|
||||
Usage: "Starts Whisper/5 node",
|
||||
Flags: []cli.Flag{
|
||||
WhisperEchoModeFlag,
|
||||
WhisperBootstrapNodeFlag,
|
||||
WhisperNotificationServerNodeFlag,
|
||||
WhisperForwarderNodeFlag,
|
||||
WhisperMailserverNodeFlag,
|
||||
WhisperIdentityFile,
|
||||
WhisperPasswordFile,
|
||||
WhisperPoWFlag,
|
||||
WhisperPortFlag,
|
||||
WhisperTTLFlag,
|
||||
WhisperInjectTestAccounts,
|
||||
FirebaseAuthorizationKey,
|
||||
HTTPEnabledFlag,
|
||||
HTTPPortFlag,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// version displays app version
|
||||
func wnode(ctx *cli.Context) error {
|
||||
config, err := makeWhisperNodeConfig(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can not parse config: %v", err)
|
||||
}
|
||||
|
||||
wnodePrintHeader(config)
|
||||
|
||||
// import test accounts
|
||||
if ctx.BoolT(WhisperInjectTestAccounts.Name) {
|
||||
if err = common.ImportTestAccount(filepath.Join(config.DataDir, "keystore"), "test-account1.pk"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = common.ImportTestAccount(filepath.Join(config.DataDir, "keystore"), "test-account2.pk"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err = statusAPI.StartNode(config); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// inject test accounts into Whisper
|
||||
if ctx.BoolT(WhisperInjectTestAccounts.Name) {
|
||||
testConfig, _ := common.LoadTestConfig()
|
||||
if err = injectAccountIntoWhisper(testConfig.Account1.Address, testConfig.Account1.Password); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = injectAccountIntoWhisper(testConfig.Account2.Address, testConfig.Account2.Password); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// wait till node has been stopped
|
||||
node, err := statusAPI.NodeManager().Node()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
node.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// wnodePrintHeader prints command header
|
||||
func wnodePrintHeader(nodeConfig *params.NodeConfig) {
|
||||
fmt.Println("Starting Whisper/5 node..")
|
||||
|
||||
whisperConfig := nodeConfig.WhisperConfig
|
||||
|
||||
if whisperConfig.EchoMode {
|
||||
fmt.Printf("Whisper Config: %s\n", whisperConfig)
|
||||
}
|
||||
}
|
||||
|
||||
// makeWhisperNodeConfig parses incoming CLI options and returns node configuration object
|
||||
func makeWhisperNodeConfig(ctx *cli.Context) (*params.NodeConfig, error) {
|
||||
nodeConfig, err := makeNodeConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodeConfig.LightEthConfig.Enabled = false
|
||||
|
||||
whisperConfig := nodeConfig.WhisperConfig
|
||||
|
||||
whisperConfig.Enabled = true
|
||||
whisperConfig.IdentityFile = ctx.String(WhisperIdentityFile.Name)
|
||||
whisperConfig.PasswordFile = ctx.String(WhisperPasswordFile.Name)
|
||||
whisperConfig.EchoMode = ctx.BoolT(WhisperEchoModeFlag.Name)
|
||||
whisperConfig.BootstrapNode = ctx.BoolT(WhisperBootstrapNodeFlag.Name)
|
||||
whisperConfig.ForwarderNode = ctx.Bool(WhisperForwarderNodeFlag.Name)
|
||||
whisperConfig.NotificationServerNode = ctx.Bool(WhisperNotificationServerNodeFlag.Name)
|
||||
whisperConfig.MailServerNode = ctx.Bool(WhisperMailserverNodeFlag.Name)
|
||||
whisperConfig.Port = ctx.Int(WhisperPortFlag.Name)
|
||||
whisperConfig.TTL = ctx.Int(WhisperTTLFlag.Name)
|
||||
whisperConfig.MinimumPoW = ctx.Float64(WhisperPoWFlag.Name)
|
||||
|
||||
if whisperConfig.MailServerNode && len(whisperConfig.PasswordFile) == 0 {
|
||||
return nil, errors.New("mail server requires --password to be specified")
|
||||
}
|
||||
|
||||
if whisperConfig.NotificationServerNode && len(whisperConfig.IdentityFile) == 0 {
|
||||
return nil, errors.New("notification server requires either --identity file to be specified")
|
||||
}
|
||||
|
||||
if len(whisperConfig.PasswordFile) > 0 { // make sure that we can load password file
|
||||
if whisperConfig.PasswordFile, err = filepath.Abs(whisperConfig.PasswordFile); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err = whisperConfig.ReadPasswordFile(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(whisperConfig.IdentityFile) > 0 { // make sure that we can load identity file
|
||||
if whisperConfig.IdentityFile, err = filepath.Abs(whisperConfig.IdentityFile); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err = whisperConfig.ReadIdentityFile(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
firebaseConfig := whisperConfig.FirebaseConfig
|
||||
firebaseConfig.AuthorizationKeyFile = ctx.String(FirebaseAuthorizationKey.Name)
|
||||
if len(firebaseConfig.AuthorizationKeyFile) > 0 { // make sure authorization key can be loaded
|
||||
if firebaseConfig.AuthorizationKeyFile, err = filepath.Abs(firebaseConfig.AuthorizationKeyFile); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := firebaseConfig.ReadAuthorizationKeyFile(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// RPC configuration
|
||||
if !ctx.Bool(HTTPEnabledFlag.Name) {
|
||||
nodeConfig.HTTPHost = "" // HTTP RPC is disabled
|
||||
}
|
||||
nodeConfig.HTTPPort = ctx.Int(HTTPPortFlag.Name)
|
||||
|
||||
return nodeConfig, nil
|
||||
}
|
||||
|
||||
// injectAccountIntoWhisper adds key pair into Whisper. Similar to Select/Login,
|
||||
// but allows multiple accounts to be injected.
|
||||
func injectAccountIntoWhisper(address, password string) error {
|
||||
nodeManager := statusAPI.NodeManager()
|
||||
keyStore, err := nodeManager.AccountKeyStore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
acct, err := common.ParseAccountString(address)
|
||||
if err != nil {
|
||||
return account.ErrAddressToAccountMappingFailure
|
||||
}
|
||||
|
||||
_, accountKey, err := keyStore.AccountDecryptedKey(acct, password)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %v", account.ErrAccountToKeyMappingFailure.Error(), err)
|
||||
}
|
||||
|
||||
whisperService, err := nodeManager.WhisperService()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = whisperService.AddKeyPair(accountKey.PrivateKey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/status-im/status-go/geth/params"
|
||||
)
|
||||
|
||||
// makeNodeConfig creates node configuration object from flags
|
||||
func makeNodeConfig() (*params.NodeConfig, error) {
|
||||
devMode := !*prodMode
|
||||
nodeConfig, err := params.NewNodeConfig(*dataDir, uint64(*networkID), devMode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO(divan): move this logic into params package?
|
||||
if *nodeKeyFile != "" {
|
||||
nodeConfig.NodeKeyFile = *nodeKeyFile
|
||||
}
|
||||
|
||||
// disable log
|
||||
nodeConfig.LogLevel = "CRIT"
|
||||
nodeConfig.LogFile = ""
|
||||
|
||||
// disable les and swarm for wnode
|
||||
nodeConfig.LightEthConfig.Enabled = false
|
||||
nodeConfig.SwarmConfig.Enabled = false
|
||||
|
||||
nodeConfig.RPCEnabled = *httpEnabled
|
||||
|
||||
// whisper configuration
|
||||
whisperConfig := nodeConfig.WhisperConfig
|
||||
|
||||
whisperConfig.Enabled = true
|
||||
whisperConfig.IdentityFile = *identity
|
||||
whisperConfig.PasswordFile = *password
|
||||
whisperConfig.EchoMode = *echo
|
||||
whisperConfig.BootstrapNode = *bootstrap
|
||||
whisperConfig.ForwarderNode = *forward
|
||||
whisperConfig.NotificationServerNode = *notify
|
||||
whisperConfig.MailServerNode = *mailserver
|
||||
whisperConfig.Port = *port
|
||||
whisperConfig.TTL = *ttl
|
||||
whisperConfig.MinimumPoW = *pow
|
||||
|
||||
if whisperConfig.MailServerNode && whisperConfig.PasswordFile == "" {
|
||||
return nil, errors.New("mail server requires -password to be specified")
|
||||
}
|
||||
|
||||
if whisperConfig.NotificationServerNode && whisperConfig.IdentityFile == "" {
|
||||
return nil, errors.New("notification server requires either -identity file to be specified")
|
||||
}
|
||||
|
||||
if whisperConfig.PasswordFile != "" {
|
||||
if err := verifyPasswordFile(whisperConfig); err != nil {
|
||||
return nil, fmt.Errorf("read password file: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if whisperConfig.IdentityFile != "" {
|
||||
if err := verifyIdentityFile(whisperConfig); err != nil {
|
||||
return nil, fmt.Errorf("read identity file: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// firebase configuration
|
||||
firebaseConfig := whisperConfig.FirebaseConfig
|
||||
firebaseConfig.AuthorizationKeyFile = *firebaseAuth
|
||||
if len(firebaseConfig.AuthorizationKeyFile) > 0 { // make sure authorization key can be loaded
|
||||
if firebaseConfig.AuthorizationKeyFile, err = filepath.Abs(firebaseConfig.AuthorizationKeyFile); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := firebaseConfig.ReadAuthorizationKeyFile(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// RPC configuration
|
||||
if !*httpEnabled {
|
||||
nodeConfig.HTTPHost = "" // HTTP RPC is disabled
|
||||
}
|
||||
nodeConfig.HTTPPort = *httpPort
|
||||
nodeConfig.IPCEnabled = *ipcEnabled
|
||||
|
||||
return nodeConfig, nil
|
||||
}
|
||||
|
||||
// verifyPasswordFile verifies that we can load password file
|
||||
func verifyPasswordFile(config *params.WhisperConfig) error {
|
||||
// TODO(divan): why do we need it here?
|
||||
absPath, err := filepath.Abs(config.PasswordFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config.PasswordFile = absPath
|
||||
_, err = config.ReadPasswordFile()
|
||||
return err
|
||||
}
|
||||
|
||||
// verifyIdentityFile verifies that we can load identity file
|
||||
func verifyIdentityFile(config *params.WhisperConfig) error {
|
||||
// TODO(divan): why do we need it here?
|
||||
absPath, err := filepath.Abs(config.IdentityFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config.IdentityFile = absPath
|
||||
_, err = config.ReadIdentityFile()
|
||||
return err
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/status-im/status-go/geth/api"
|
||||
"github.com/status-im/status-go/geth/params"
|
||||
)
|
||||
|
||||
var (
|
||||
prodMode = flag.Bool("production", false, "Whether production settings should be loaded")
|
||||
nodeKeyFile = flag.String("nodekey", "", "P2P node key file (private key)")
|
||||
dataDir = flag.String("datadir", "wnode-status-data", "Data directory for the databases and keystore")
|
||||
networkID = flag.Int("networkid", params.RopstenNetworkID, "Network identifier (integer, 1=Homestead, 3=Ropsten, 4=Rinkeby)")
|
||||
httpEnabled = flag.Bool("http", false, "HTTP RPC enpoint enabled (default: false)")
|
||||
httpPort = flag.Int("httpport", params.HTTPPort, "HTTP RPC server's listening port")
|
||||
ipcEnabled = flag.Bool("ipc", false, "IPC RPC enpoint enabled")
|
||||
|
||||
// wnode specific flags
|
||||
echo = flag.Bool("echo", true, "Echo mode, prints some arguments for diagnostics")
|
||||
bootstrap = flag.Bool("bootstrap", true, "Don't actively connect to peers, wait for incoming connections")
|
||||
notify = flag.Bool("notify", false, "Node is capable of sending Push Notifications")
|
||||
forward = flag.Bool("forward", false, "Only forward messages, neither send nor decrypt messages")
|
||||
mailserver = flag.Bool("mailserver", false, "Delivers expired messages on demand")
|
||||
identity = flag.String("identity", "", "Protocol identity file (private key used for asymmetric encryption)")
|
||||
password = flag.String("password", "", "Password file (password is used for symmetric encryption)")
|
||||
port = flag.Int("port", params.WhisperPort, "Whisper node's listening port")
|
||||
pow = flag.Float64("pow", params.WhisperMinimumPoW, "PoW for messages to be added to queue, in float format")
|
||||
ttl = flag.Int("ttl", params.WhisperTTL, "Time to live for messages, in seconds")
|
||||
injectAccounts = flag.Bool("injectaccounts", true, "Whether test account should be injected or not")
|
||||
firebaseAuth = flag.String("firebaseauth", "", "FCM Authorization Key used for sending Push Notifications")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
config, err := makeNodeConfig()
|
||||
if err != nil {
|
||||
log.Fatalf("Making config failed: %v", err)
|
||||
}
|
||||
|
||||
printHeader(config)
|
||||
|
||||
if *injectAccounts {
|
||||
if err := LoadTestAccounts(config.DataDir); err != nil {
|
||||
log.Fatalf("Failed to load test accounts: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
backend := api.NewStatusBackend()
|
||||
started, err := backend.StartNode(config)
|
||||
if err != nil {
|
||||
log.Fatalf("Node start failed: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// wait till node is started
|
||||
<-started
|
||||
|
||||
if *injectAccounts {
|
||||
if err := InjectTestAccounts(backend.NodeManager()); err != nil {
|
||||
log.Fatalf("Failed to inject accounts: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// wait till node has been stopped
|
||||
node, err := backend.NodeManager().Node()
|
||||
if err != nil {
|
||||
log.Fatalf("Getting node failed: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
node.Wait()
|
||||
}
|
||||
|
||||
// printHeader prints command header
|
||||
func printHeader(config *params.NodeConfig) {
|
||||
fmt.Println("Starting Whisper/5 node..")
|
||||
if config.WhisperConfig.EchoMode {
|
||||
fmt.Printf("Whisper Config: %s\n", config.WhisperConfig)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/status-im/status-go/geth/account"
|
||||
"github.com/status-im/status-go/geth/common"
|
||||
)
|
||||
|
||||
// LoadTestAccounts loads public key files for test accounts
|
||||
func LoadTestAccounts(dataDir string) error {
|
||||
files := []string{"test-account1.pk", "test-account2.pk"}
|
||||
dir := filepath.Join(dataDir, "keystore")
|
||||
for _, filename := range files {
|
||||
if err := common.ImportTestAccount(dir, filename); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// InjectTestAccounts injects test accounts into running node
|
||||
func InjectTestAccounts(node common.NodeManager) error {
|
||||
testConfig, err := common.LoadTestConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = injectAccountIntoWhisper(node, testConfig.Account1.Address,
|
||||
testConfig.Account1.Password); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = injectAccountIntoWhisper(node, testConfig.Account2.Address,
|
||||
testConfig.Account2.Password); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// injectAccountIntoWhisper adds key pair into Whisper. Similar to Select/Login,
|
||||
// but allows multiple accounts to be injected.
|
||||
func injectAccountIntoWhisper(node common.NodeManager, address, password string) error {
|
||||
keyStore, err := node.AccountKeyStore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
acct, err := common.ParseAccountString(address)
|
||||
if err != nil {
|
||||
return account.ErrAddressToAccountMappingFailure
|
||||
}
|
||||
|
||||
_, accountKey, err := keyStore.AccountDecryptedKey(acct, password)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %v", account.ErrAccountToKeyMappingFailure.Error(), err)
|
||||
}
|
||||
|
||||
whisperService, err := node.WhisperService()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = whisperService.AddKeyPair(accountKey.PrivateKey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package main
|
||||
|
||||
import "github.com/status-im/status-go/geth/api"
|
||||
|
||||
var statusAPI = api.NewStatusAPI()
|
||||
|
||||
// Technically this package supposed to be a lib for
|
||||
// cross-compilation and usage with Android/iOS, but
|
||||
// without main it produces cryptic errors.
|
||||
// TODO(divan): investigate the cause of the errors
|
||||
// and change this package to be a library if possible.
|
||||
func main() {
|
||||
}
|
|
@ -10,9 +10,9 @@ describe('Whisper Tests', function () {
|
|||
node1.setProvider(new web3.providers.HttpProvider('http://localhost:8645'));
|
||||
node2.setProvider(new web3.providers.HttpProvider('http://localhost:8745'));
|
||||
|
||||
console.log('Node is expected: statusd --datadir app1 wnode --http --httpport 8645');
|
||||
console.log('Node is expected: statusd --datadir app2 wnode --http --httpport 8745');
|
||||
console.log('Node is expected: statusd --datadir wnode1 wnode --notify --injectaccounts=false --identity ./static/keys/wnodekey --firebaseauth ./static/keys/firebaseauthkey');
|
||||
console.log('Node is expected: wnode-status -datadir app1 wnode -http -httpport 8645');
|
||||
console.log('Node is expected: wnode-status -datadir app2 wnode -http -httpport 8745');
|
||||
console.log('Node is expected: wnode-status -datadir wnode1 wnode -notify -injectaccounts=false -identity ./static/keys/wnodekey -firebaseauth ./static/keys/firebaseauthkey');
|
||||
|
||||
// some common vars
|
||||
var topic1 = '0xdeadbeef'; // each topic 4 bytes, as hex
|
||||
|
|
Loading…
Reference in New Issue