cmd/statusd: expose LES, SHH, Swarm. Closes #128

This commit is contained in:
Victor Farazdagi 2017-03-28 12:04:52 +03:00
parent 27700f5763
commit b130d586ca
11 changed files with 256 additions and 57 deletions

View File

@ -5,25 +5,24 @@ GOBIN = build/bin
GO ?= latest GO ?= latest
statusgo: statusgo:
build/env.sh go build -i -o $(GOBIN)/statusgo -v $(shell build/testnet-flags.sh) ./cmd/status build/env.sh go build -i -o $(GOBIN)/statusd -v $(shell build/testnet-flags.sh) ./cmd/statusd
@echo "status go compilation done." @echo "\nCompilation done.\nRun \"build/bin/statusd help\" to view available commands."
@echo "Run \"build/bin/statusgo\" to view available commands"
statusgo-cross: statusgo-android statusgo-ios statusgo-cross: statusgo-android statusgo-ios
@echo "Full cross compilation done." @echo "Full cross compilation done."
@ls -ld $(GOBIN)/statusgo-* @ls -ld $(GOBIN)/statusgo-*
statusgo-android: xgo statusgo-android: xgo
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/status 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
@echo "Android cross compilation done." @echo "Android cross compilation done."
statusgo-ios: xgo statusgo-ios: xgo
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/status 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
@echo "iOS framework cross compilation done." @echo "iOS framework cross compilation done."
statusgo-ios-simulator: xgo statusgo-ios-simulator: xgo
@build/env.sh docker pull farazdagi/xgo-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/status 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
@echo "iOS framework cross compilation done." @echo "iOS framework cross compilation done."
xgo: xgo:
@ -31,20 +30,20 @@ xgo:
build/env.sh go get github.com/karalabe/xgo build/env.sh go get github.com/karalabe/xgo
statusgo-mainnet: statusgo-mainnet:
build/env.sh go build -i -o $(GOBIN)/statusgo -v $(shell build/mainnet-flags.sh) ./cmd/status build/env.sh go build -i -o $(GOBIN)/statusgo -v $(shell build/mainnet-flags.sh) ./cmd/statusd
@echo "status go compilation done (mainnet)." @echo "status go compilation done (mainnet)."
@echo "Run \"build/bin/statusgo\" to view available commands" @echo "Run \"build/bin/statusgo\" to view available commands"
statusgo-android-mainnet: xgo 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/status 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
@echo "Android cross compilation done (mainnet)." @echo "Android cross compilation done (mainnet)."
statusgo-ios-mainnet: xgo 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/status 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
@echo "iOS framework cross compilation done (mainnet)." @echo "iOS framework cross compilation done (mainnet)."
statusgo-ios-simulator-mainnet: xgo 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/status 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
@echo "iOS framework cross compilation done (mainnet)." @echo "iOS framework cross compilation done (mainnet)."
ci: ci:
@ -63,7 +62,7 @@ test:
@build/env.sh tail -n +2 coverage.out >> coverage-all.out @build/env.sh tail -n +2 coverage.out >> coverage-all.out
build/env.sh go test -coverprofile=coverage.out -covermode=set ./extkeys build/env.sh go test -coverprofile=coverage.out -covermode=set ./extkeys
@build/env.sh tail -n +2 coverage.out >> coverage-all.out @build/env.sh tail -n +2 coverage.out >> coverage-all.out
build/env.sh go test -coverprofile=coverage.out -covermode=set ./cmd/status build/env.sh go test -coverprofile=coverage.out -covermode=set ./cmd/statusd
@build/env.sh tail -n +2 coverage.out >> coverage-all.out @build/env.sh tail -n +2 coverage.out >> coverage-all.out
@build/env.sh go tool cover -html=coverage-all.out -o coverage.html @build/env.sh go tool cover -html=coverage-all.out -o coverage.html
@build/env.sh go tool cover -func=coverage-all.out @build/env.sh go tool cover -func=coverage-all.out
@ -89,7 +88,7 @@ test-extkeys:
@build/env.sh go tool cover -func=coverage.out @build/env.sh go tool cover -func=coverage.out
test-cmd: test-cmd:
build/env.sh go test -v -coverprofile=coverage.out ./cmd/status build/env.sh go test -v -coverprofile=coverage.out ./cmd/statusd
@build/env.sh go tool cover -html=coverage.out -o coverage.html @build/env.sh go tool cover -html=coverage.out -o coverage.html
@build/env.sh go tool cover -func=coverage.out @build/env.sh go tool cover -func=coverage.out

View File

@ -1,26 +0,0 @@
package main
import (
"fmt"
"github.com/status-im/status-go/geth/params"
)
var (
gitCommit = "rely on linker: -ldflags -X main.GitCommit"
buildStamp = "rely on linker: -ldflags -X main.buildStamp"
)
func main() {
nodeConfig, err := params.NewNodeConfig(".ethereumcmd", params.TestNetworkId)
if err != nil {
panic(err)
}
netVersion := "mainnet"
if nodeConfig.TestNet {
netVersion = "testnet"
}
fmt.Printf("%s\nVersion: %s\nGit Commit: %s\nBuild Date: %s\nNetwork: %s\n",
nodeConfig.Name, params.Version, gitCommit, buildStamp, netVersion)
}

183
cmd/statusd/main.go Normal file
View File

@ -0,0 +1,183 @@
package main
import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/status-im/status-go/geth"
"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)
)
var (
DataDirFlag = cli.StringFlag{
Name: "datadir",
Usage: "Data directory for the databases and keystore",
Value: params.DefaultDataDir,
}
NetworkIdFlag = cli.IntFlag{
Name: "networkid",
Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten)",
Value: params.TestNetworkId,
}
LightEthEnabledFlag = cli.BoolFlag{
Name: "les",
Usage: "LES protocol enabled",
}
WhisperEnabledFlag = cli.BoolFlag{
Name: "shh",
Usage: "SHH protocol enabled",
}
SwarmEnabledFlag = cli.BoolFlag{
Name: "swarm",
Usage: "Swarm protocol enabled",
}
HTTPEnabledFlag = cli.BoolFlag{
Name: "http",
Usage: "HTTP RPC enpoint enabled",
}
HTTPPortFlag = cli.IntFlag{
Name: "httpport",
Usage: "HTTP RPC server's listening port",
Value: params.DefaultHTTPPort,
}
IPCEnabledFlag = cli.BoolFlag{
Name: "ipc",
Usage: "IPC RPC enpoint enabled",
}
LogLevelFlag = cli.StringFlag{
Name: "log",
Usage: `Log level, one of: ""ERROR", "WARNING", "INFO", "DEBUG", and "DETAIL"`,
Value: "INFO",
}
TestAccountKey = cli.StringFlag{
Name: "accountkey",
Usage: "Test account PK (will be loaded into accounts cache, and injected to Whisper)",
}
TestAccountPasswd = cli.StringFlag{
Name: "accountpasswd",
Usage: "Test account password",
}
)
func init() {
// setup the app
app.Action = statusd
app.HideVersion = true // separate command prints version
app.Commands = []cli.Command{
{
Action: version,
Name: "version",
Usage: "Print app version",
},
}
app.Flags = []cli.Flag{
DataDirFlag,
NetworkIdFlag,
LightEthEnabledFlag,
WhisperEnabledFlag,
SwarmEnabledFlag,
HTTPEnabledFlag,
HTTPPortFlag,
IPCEnabledFlag,
LogLevelFlag,
}
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)
}
}
// statusd runs Status node
func statusd(ctx *cli.Context) error {
config, err := makeNodeConfig(ctx)
if err != nil {
fmt.Fprintf(os.Stderr, "can not parse config: %v", err)
return err
}
if err := geth.CreateAndRunNode(config); err != nil {
return err
}
// wait till node has been stopped
geth.NodeManagerInstance().Node().GethStack().Wait()
return nil
}
// 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.GlobalInt(NetworkIdFlag.Name))
if err != nil {
return nil, err
}
if !ctx.GlobalBool(HTTPEnabledFlag.Name) {
nodeConfig.HTTPHost = "" // HTTP RPC is disabled
}
nodeConfig.IPCEnabled = ctx.GlobalBool(IPCEnabledFlag.Name)
nodeConfig.LightEthConfig.Enabled = ctx.GlobalBool(LightEthEnabledFlag.Name)
nodeConfig.WhisperConfig.Enabled = ctx.GlobalBool(WhisperEnabledFlag.Name)
nodeConfig.SwarmConfig.Enabled = ctx.GlobalBool(SwarmEnabledFlag.Name)
nodeConfig.HTTPPort = ctx.GlobalInt(HTTPPortFlag.Name)
if logLevel := ctx.GlobalString(LogLevelFlag.Name); len(logLevel) > 0 {
nodeConfig.LogEnabled = true
nodeConfig.LogLevel = logLevel
}
return nodeConfig, nil
}
// version displays app version
func version(ctx *cli.Context) error {
fmt.Println(strings.Title(params.DefaultClientIdentifier))
fmt.Println("Version:", params.Version)
if gitCommit != "" {
fmt.Println("Git Commit:", gitCommit)
}
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())
return nil
}
// 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]
}
app.Usage = "Status CLI"
return app
}

View File

@ -6,6 +6,7 @@ import (
"io" "io"
"os" "os"
"path" "path"
"path/filepath"
"reflect" "reflect"
"runtime" "runtime"
"runtime/debug" "runtime/debug"
@ -15,6 +16,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/les" "github.com/ethereum/go-ethereum/les"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/discover"
@ -57,6 +59,11 @@ func (n *Node) GethStack() *node.Node {
// MakeNode create a geth node entity // MakeNode create a geth node entity
func MakeNode(config *params.NodeConfig) *Node { func MakeNode(config *params.NodeConfig) *Node {
// make sure data directory exists
if err := os.MkdirAll(filepath.Join(config.DataDir), os.ModePerm); err != nil {
Fatalf(err)
}
// setup logging // setup logging
glog.CopyStandardLogTo("INFO") glog.CopyStandardLogTo("INFO")
glog.SetToStderr(true) glog.SetToStderr(true)
@ -115,6 +122,11 @@ func MakeNode(config *params.NodeConfig) *Node {
// activateEthService configures and registers the eth.Ethereum service with a given node. // activateEthService configures and registers the eth.Ethereum service with a given node.
func activateEthService(stack *node.Node, config *params.NodeConfig) error { func activateEthService(stack *node.Node, config *params.NodeConfig) error {
if !config.LightEthConfig.Enabled {
glog.V(logger.Info).Infoln("LES protocol is disabled")
return nil
}
ethConf := &eth.Config{ ethConf := &eth.Config{
Etherbase: common.Address{}, Etherbase: common.Address{},
ChainConfig: makeChainConfig(config), ChainConfig: makeChainConfig(config),
@ -148,6 +160,10 @@ func activateEthService(stack *node.Node, config *params.NodeConfig) error {
// activateShhService configures Whisper and adds it to the given node. // activateShhService configures Whisper and adds it to the given node.
func activateShhService(stack *node.Node, config *params.NodeConfig) error { func activateShhService(stack *node.Node, config *params.NodeConfig) error {
if !config.WhisperConfig.Enabled {
glog.V(logger.Info).Infoln("SHH protocol is disabled")
return nil
}
serviceConstructor := func(*node.ServiceContext) (node.Service, error) { serviceConstructor := func(*node.ServiceContext) (node.Service, error) {
return whisper.New(), nil return whisper.New(), nil
} }

View File

@ -115,15 +115,13 @@ func (m *NodeManager) RunNode() {
} }
// setup handlers // setup handlers
lightEthereum, err := m.LightEthereumService() if lightEthereum, err := m.LightEthereumService(); err == nil {
if err != nil {
panic("service stack misses LES")
}
lightEthereum.StatusBackend.SetTransactionQueueHandler(onSendTransactionRequest) lightEthereum.StatusBackend.SetTransactionQueueHandler(onSendTransactionRequest)
lightEthereum.StatusBackend.SetAccountsFilterHandler(onAccountsListRequest) lightEthereum.StatusBackend.SetAccountsFilterHandler(onAccountsListRequest)
lightEthereum.StatusBackend.SetTransactionReturnHandler(onSendTransactionReturn) lightEthereum.StatusBackend.SetTransactionReturnHandler(onSendTransactionReturn)
}
var err error
m.services.rpcClient, err = m.node.geth.Attach() m.services.rpcClient, err = m.node.geth.Attach()
if err != nil { if err != nil {
glog.V(logger.Warn).Infoln("cannot get RPC client service:", ErrInvalidClient) glog.V(logger.Warn).Infoln("cannot get RPC client service:", ErrInvalidClient)
@ -264,7 +262,7 @@ func (m *NodeManager) StopNodeRPCServer() (bool, error) {
return m.api.StopRPC() return m.api.StopRPC()
} }
// HasNode checks whether manager has initialized node attached // NodeInited checks whether manager has initialized node attached
func (m *NodeManager) NodeInited() bool { func (m *NodeManager) NodeInited() bool {
if m == nil || !m.node.Inited() { if m == nil || !m.node.Inited() {
return false return false
@ -273,6 +271,15 @@ func (m *NodeManager) NodeInited() bool {
return true return true
} }
// Node returns attached node if it has been initialized
func (m *NodeManager) Node() *Node {
if !m.NodeInited() {
return nil
}
return m.node
}
// AccountManager exposes reference to accounts manager // AccountManager exposes reference to accounts manager
func (m *NodeManager) AccountManager() (*accounts.Manager, error) { func (m *NodeManager) AccountManager() (*accounts.Manager, error) {
if m == nil || !m.NodeInited() { if m == nil || !m.NodeInited() {

View File

@ -63,6 +63,9 @@ type ChainConfig struct {
// LightEthConfig holds LES-related configuration // LightEthConfig holds LES-related configuration
// Status nodes are always lightweight clients (due to mobile platform constraints) // Status nodes are always lightweight clients (due to mobile platform constraints)
type LightEthConfig struct { type LightEthConfig struct {
// Enabled flag specifies whether protocol is enabled
Enabled bool
// Genesis is JSON to seed the chain database with // Genesis is JSON to seed the chain database with
Genesis string Genesis string
@ -71,10 +74,16 @@ type LightEthConfig struct {
} }
// WhisperConfig holds SHH-related configuration // WhisperConfig holds SHH-related configuration
type WhisperConfig struct{} type WhisperConfig struct {
// Enabled flag specifies whether protocol is enabled
Enabled bool
}
// SwarmConfig holds Swarm-related configuration // SwarmConfig holds Swarm-related configuration
type SwarmConfig struct{} type SwarmConfig struct {
// Enabled flag specifies whether protocol is enabled
Enabled bool
}
// NodeConfig stores configuration options for a node // NodeConfig stores configuration options for a node
type NodeConfig struct { type NodeConfig struct {
@ -143,13 +152,13 @@ type NodeConfig struct {
*ChainConfig `json:"ChainConfig,"` *ChainConfig `json:"ChainConfig,"`
// LightEthConfig extra configuration for LES // LightEthConfig extra configuration for LES
*LightEthConfig `json:"LightEthConfig,"` LightEthConfig *LightEthConfig `json:"LightEthConfig,"`
// WhisperConfig extra configuration for SHH // WhisperConfig extra configuration for SHH
*WhisperConfig `json:"WhisperConfig,"` WhisperConfig *WhisperConfig `json:"WhisperConfig,"`
// SwarmConfig extra configuration for Swarm and ENS // SwarmConfig extra configuration for Swarm and ENS
*SwarmConfig `json:"SwarmConfig,"` SwarmConfig *SwarmConfig `json:"SwarmConfig,"`
} }
// NewNodeConfig creates new node configuration object // NewNodeConfig creates new node configuration object
@ -171,9 +180,12 @@ func NewNodeConfig(dataDir string, networkId int) (*NodeConfig, error) {
LogLevel: DefaultLogLevel, LogLevel: DefaultLogLevel,
ChainConfig: &ChainConfig{}, ChainConfig: &ChainConfig{},
LightEthConfig: &LightEthConfig{ LightEthConfig: &LightEthConfig{
Enabled: true,
DatabaseCache: DefaultDatabaseCache, DatabaseCache: DefaultDatabaseCache,
}, },
WhisperConfig: &WhisperConfig{}, WhisperConfig: &WhisperConfig{
Enabled: true,
},
SwarmConfig: &SwarmConfig{}, SwarmConfig: &SwarmConfig{},
} }
@ -206,7 +218,7 @@ func (c *NodeConfig) populateChainConfig() {
c.ChainConfig.EIP158Block = params.TestnetChainConfig.EIP158Block c.ChainConfig.EIP158Block = params.TestnetChainConfig.EIP158Block
c.ChainConfig.ChainId = params.TestnetChainConfig.ChainId c.ChainConfig.ChainId = params.TestnetChainConfig.ChainId
c.Genesis = core.DefaultTestnetGenesisBlock() c.LightEthConfig.Genesis = core.DefaultTestnetGenesisBlock()
} else { } else {
// Homestead fork // Homestead fork
c.ChainConfig.HomesteadBlock = params.MainNetHomesteadBlock c.ChainConfig.HomesteadBlock = params.MainNetHomesteadBlock
@ -223,7 +235,7 @@ func (c *NodeConfig) populateChainConfig() {
c.ChainConfig.EIP158Block = params.MainNetSpuriousDragon c.ChainConfig.EIP158Block = params.MainNetSpuriousDragon
c.ChainConfig.ChainId = params.MainNetChainID c.ChainConfig.ChainId = params.MainNetChainID
c.Genesis = core.DefaultGenesisBlock() c.LightEthConfig.Genesis = core.DefaultGenesisBlock()
} }
} }

View File

@ -10,6 +10,9 @@ const (
// DefaultClientIdentifier is client identifier to advertise over the network // DefaultClientIdentifier is client identifier to advertise over the network
DefaultClientIdentifier = "StatusIM" DefaultClientIdentifier = "StatusIM"
// DefaultDataDir is default data directory used by statusd executable
DefaultDataDir = "statusd-data"
// DefaultIPCFile is filename of exposed IPC RPC Server // DefaultIPCFile is filename of exposed IPC RPC Server
DefaultIPCFile = "geth.ipc" DefaultIPCFile = "geth.ipc"

File diff suppressed because one or more lines are too long