Merge pull request #137 from farazdagi/feature/status-go-cmd

cmd/status: statusd command implemented
This commit is contained in:
Roman Volosovskyi 2017-04-02 13:09:47 +03:00 committed by GitHub
commit 8ef220619c
11 changed files with 256 additions and 57 deletions

View File

@ -5,25 +5,24 @@ GOBIN = build/bin
GO ?= latest
statusgo:
build/env.sh go build -i -o $(GOBIN)/statusgo -v $(shell build/testnet-flags.sh) ./cmd/status
@echo "status go compilation done."
@echo "Run \"build/bin/statusgo\" to view available commands"
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."
statusgo-cross: statusgo-android statusgo-ios
@echo "Full cross compilation done."
@ls -ld $(GOBIN)/statusgo-*
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."
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."
statusgo-ios-simulator: xgo
@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."
xgo:
@ -31,20 +30,20 @@ xgo:
build/env.sh go get github.com/karalabe/xgo
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 "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/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)."
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)."
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)."
ci:
@ -63,7 +62,7 @@ test:
@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 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 go tool cover -html=coverage-all.out -o coverage.html
@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
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 -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"
"os"
"path"
"path/filepath"
"reflect"
"runtime"
"runtime/debug"
@ -15,6 +16,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/les"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p/discover"
@ -57,6 +59,11 @@ func (n *Node) GethStack() *node.Node {
// MakeNode create a geth node entity
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
glog.CopyStandardLogTo("INFO")
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.
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{
Etherbase: common.Address{},
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.
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) {
return whisper.New(), nil
}

View File

@ -115,15 +115,13 @@ func (m *NodeManager) RunNode() {
}
// setup handlers
lightEthereum, err := m.LightEthereumService()
if err != nil {
panic("service stack misses LES")
if lightEthereum, err := m.LightEthereumService(); err == nil {
lightEthereum.StatusBackend.SetTransactionQueueHandler(onSendTransactionRequest)
lightEthereum.StatusBackend.SetAccountsFilterHandler(onAccountsListRequest)
lightEthereum.StatusBackend.SetTransactionReturnHandler(onSendTransactionReturn)
}
lightEthereum.StatusBackend.SetTransactionQueueHandler(onSendTransactionRequest)
lightEthereum.StatusBackend.SetAccountsFilterHandler(onAccountsListRequest)
lightEthereum.StatusBackend.SetTransactionReturnHandler(onSendTransactionReturn)
var err error
m.services.rpcClient, err = m.node.geth.Attach()
if err != nil {
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()
}
// HasNode checks whether manager has initialized node attached
// NodeInited checks whether manager has initialized node attached
func (m *NodeManager) NodeInited() bool {
if m == nil || !m.node.Inited() {
return false
@ -273,6 +271,15 @@ func (m *NodeManager) NodeInited() bool {
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
func (m *NodeManager) AccountManager() (*accounts.Manager, error) {
if m == nil || !m.NodeInited() {

View File

@ -63,6 +63,9 @@ type ChainConfig struct {
// LightEthConfig holds LES-related configuration
// Status nodes are always lightweight clients (due to mobile platform constraints)
type LightEthConfig struct {
// Enabled flag specifies whether protocol is enabled
Enabled bool
// Genesis is JSON to seed the chain database with
Genesis string
@ -71,10 +74,16 @@ type LightEthConfig struct {
}
// 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
type SwarmConfig struct{}
type SwarmConfig struct {
// Enabled flag specifies whether protocol is enabled
Enabled bool
}
// NodeConfig stores configuration options for a node
type NodeConfig struct {
@ -143,13 +152,13 @@ type NodeConfig struct {
*ChainConfig `json:"ChainConfig,"`
// LightEthConfig extra configuration for LES
*LightEthConfig `json:"LightEthConfig,"`
LightEthConfig *LightEthConfig `json:"LightEthConfig,"`
// WhisperConfig extra configuration for SHH
*WhisperConfig `json:"WhisperConfig,"`
WhisperConfig *WhisperConfig `json:"WhisperConfig,"`
// SwarmConfig extra configuration for Swarm and ENS
*SwarmConfig `json:"SwarmConfig,"`
SwarmConfig *SwarmConfig `json:"SwarmConfig,"`
}
// NewNodeConfig creates new node configuration object
@ -171,10 +180,13 @@ func NewNodeConfig(dataDir string, networkId int) (*NodeConfig, error) {
LogLevel: DefaultLogLevel,
ChainConfig: &ChainConfig{},
LightEthConfig: &LightEthConfig{
Enabled: true,
DatabaseCache: DefaultDatabaseCache,
},
WhisperConfig: &WhisperConfig{},
SwarmConfig: &SwarmConfig{},
WhisperConfig: &WhisperConfig{
Enabled: true,
},
SwarmConfig: &SwarmConfig{},
}
nodeConfig.populateChainConfig()
@ -206,7 +218,7 @@ func (c *NodeConfig) populateChainConfig() {
c.ChainConfig.EIP158Block = params.TestnetChainConfig.EIP158Block
c.ChainConfig.ChainId = params.TestnetChainConfig.ChainId
c.Genesis = core.DefaultTestnetGenesisBlock()
c.LightEthConfig.Genesis = core.DefaultTestnetGenesisBlock()
} else {
// Homestead fork
c.ChainConfig.HomesteadBlock = params.MainNetHomesteadBlock
@ -223,7 +235,7 @@ func (c *NodeConfig) populateChainConfig() {
c.ChainConfig.EIP158Block = params.MainNetSpuriousDragon
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 = "StatusIM"
// DefaultDataDir is default data directory used by statusd executable
DefaultDataDir = "statusd-data"
// DefaultIPCFile is filename of exposed IPC RPC Server
DefaultIPCFile = "geth.ipc"

File diff suppressed because one or more lines are too long