diff --git a/app/app.go b/app/app.go index 387537f2f..a828290b3 100644 --- a/app/app.go +++ b/app/app.go @@ -40,8 +40,8 @@ var ( // DefaultCLIHome is the default home directories for the application CLI DefaultCLIHome = os.ExpandEnv("$HOME/.mesg-cli") - // DefaultNodeHome sets the folder where the applcation data and configuration will be stored - DefaultNodeHome = os.ExpandEnv("$HOME/.mesg/tendermint") + // DefaultNodeHome sets the folder where the application data and configuration will be stored + DefaultNodeHome = os.ExpandEnv("$HOME/.mesg-node") // ModuleBasics The module BasicManager is in charge of setting up basic, // non-dependant module elements, such as codec registration diff --git a/cmd/mesg-cli/main.go b/cmd/mesg-cli/main.go index 02fe1f197..b9f23e06e 100644 --- a/cmd/mesg-cli/main.go +++ b/cmd/mesg-cli/main.go @@ -52,6 +52,8 @@ func main() { queryCmd(cdc), txCmd(cdc), flags.LineBreak, + orchestratorCmd(cdc), + flags.LineBreak, lcd.ServeCommand(cdc, registerRoutes), flags.LineBreak, keys.Commands(), diff --git a/cmd/mesg-cli/orchestrator.go b/cmd/mesg-cli/orchestrator.go new file mode 100644 index 000000000..181de34be --- /dev/null +++ b/cmd/mesg-cli/orchestrator.go @@ -0,0 +1,141 @@ +package main + +import ( + "fmt" + "os" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/crypto/keys" + "github.com/mesg-foundation/engine/cosmos" + "github.com/mesg-foundation/engine/event/publisher" + "github.com/mesg-foundation/engine/ext/xsignal" + "github.com/mesg-foundation/engine/orchestrator" + "github.com/mesg-foundation/engine/server/grpc" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/tendermint/tendermint/libs/log" +) + +const ( + accName = "orchestrator" + accPass = "password" +) + +func orchestratorCmd(cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "orchestrator", + Short: "Orchestrator subcommands", + } + cmd.AddCommand(flags.GetCommands( + startOrchestratorCmd(cdc), + )...) + return cmd +} + +func startOrchestratorCmd(cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "start", + Short: "Start the Orchestrator", + RunE: func(cmd *cobra.Command, args []string) error { + cliCtx := context.NewCLIContext().WithCodec(cdc) + + if viper.GetString(flagMnemonic) == "" { + return fmt.Errorf("mnemonic is required. use flag --mnemonic or config file") + } + if cliCtx.ChainID == "" { + return fmt.Errorf("chain-id is required. use flag --chain-id or config file") + } + + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "orchestrator") + client, err := cliCtx.GetNode() + if err != nil { + return err + } + + // init rpc client + logger.Info("starting rpc client") + if err := client.Start(); err != nil { + return err + } + defer func() { + logger.Info("stopping rpc client") + if err := client.Stop(); err != nil { + logger.Error(err.Error()) + } + }() + + kb := cosmos.NewInMemoryKeybase() + if _, err := kb.CreateAccount(accName, viper.GetString(flagMnemonic), "", accPass, keys.CreateHDPath(viper.GetUint32(flagAccNumber), viper.GetUint32(flagAccIndex)).String(), cosmos.DefaultAlgo); err != nil { + fmt.Println("keybase error") + return err + } + + // create rpc client + rpc, err := cosmos.NewRPC(client, cdc, kb, cliCtx.ChainID, accName, accPass, viper.GetString(flagGasPrices)) + if err != nil { + return err + } + + // init event publisher + ep := publisher.New(rpc) + + // init gRPC server. + logger.Info("starting grpc server") + server := grpc.New(rpc, ep, viper.GetStringSlice(flagAuthorizedPubKeys)) + defer func() { + logger.Info("stopping grpc server") + server.Close() + }() + + go func() { + if err := server.Serve(viper.GetString(flagGrpcAddr)); err != nil { + logger.Error(err.Error()) + panic(err) + } + }() + + // orchestrator + logger.Info("starting orchestrator") + orch := orchestrator.New(rpc, ep, viper.GetString(flagExecPrice)) + defer func() { + logger.Info("stopping orchestrator") + orch.Stop() + }() + go func() { + if err := orch.Start(); err != nil { + logger.Error(err.Error()) + panic(err) + } + }() + go func() { + for err := range orch.ErrC { + logger.Error(err.Error()) + } + }() + + <-xsignal.WaitForInterrupt() + + return nil + }, + } + cmd.Flags().String(flagGrpcAddr, ":50052", "The address for the gRPC server to expose") + cmd.Flags().String(flagAuthorizedPubKeys, "", "The authorized pubkeys to communicate with the gRPC server") + cmd.Flags().String(flagMnemonic, "", "The account's mnemonic that will be used to sign transactions") + cmd.Flags().String(flagGasPrices, "1.0atto", "The gas price to sign tx") + cmd.Flags().String(flagExecPrice, "10000atto", "The execution price to create execution") + cmd.Flags().String(flagAccNumber, "0", "The account number of the hd path to use to derive the mnemonic") + cmd.Flags().String(flagAccIndex, "0", "The account index of the hd path to use to derive the mnemonic") + return cmd +} + +const ( + flagGrpcAddr = "grpc-addr" + flagAuthorizedPubKeys = "authorized-pubkeys" + flagMnemonic = "mnemonic" + flagGasPrices = "gas-prices" + flagExecPrice = "exec-price" + flagAccNumber = "acc-number" + flagAccIndex = "acc-index" +) diff --git a/cmd/mesg-daemon/main.go b/cmd/mesg-daemon/main.go index 1904a3c91..0e332b27e 100644 --- a/cmd/mesg-daemon/main.go +++ b/cmd/mesg-daemon/main.go @@ -60,7 +60,7 @@ func main() { server.AddCommands(ctx, cdc, rootCmd, newApp, exportAppStateAndTMValidators) // prepare and add flags - executor := cli.PrepareBaseCmd(rootCmd, "AU", app.DefaultNodeHome) + executor := cli.PrepareBaseCmd(rootCmd, "MESG", app.DefaultNodeHome) rootCmd.PersistentFlags().UintVar(&invCheckPeriod, flagInvCheckPeriod, 0, "Assert registered invariants every N blocks") if err := executor.Execute(); err != nil { diff --git a/cosmos/keybase.go b/cosmos/keybase.go index 548195135..42b3b8164 100644 --- a/cosmos/keybase.go +++ b/cosmos/keybase.go @@ -38,6 +38,14 @@ func NewKeybase(dir string) (*Keybase, error) { }, nil } +// NewInMemoryKeybase initializes a in memory keybase. +func NewInMemoryKeybase() *Keybase { + return &Keybase{ + kb: clientkey.NewInMemoryKeyBase(), + privKeysCache: make(map[[sha256.Size]byte]crypto.PrivKey), + } +} + // NewMnemonic returns a new mnemonic phrase. func (kb *Keybase) NewMnemonic() (string, error) { // read entropy seed straight from crypto.Rand and convert to mnemonic diff --git a/ext/xstrings/strings.go b/ext/xstrings/strings.go index 21025e14b..3bc93fc34 100644 --- a/ext/xstrings/strings.go +++ b/ext/xstrings/strings.go @@ -1,6 +1,14 @@ package xstrings -import "math/rand" +import ( + "math/rand" + + "github.com/mesg-foundation/engine/ext/xrand" +) + +func init() { + xrand.SeedInit() +} // SliceContains returns true if slice a contains e element, false otherwise. func SliceContains(a []string, e string) bool { diff --git a/orchestrator/orchestrator.go b/orchestrator/orchestrator.go index a9f12b0d9..0af227a51 100644 --- a/orchestrator/orchestrator.go +++ b/orchestrator/orchestrator.go @@ -11,6 +11,7 @@ import ( "github.com/mesg-foundation/engine/event" "github.com/mesg-foundation/engine/event/publisher" "github.com/mesg-foundation/engine/execution" + "github.com/mesg-foundation/engine/ext/xrand" "github.com/mesg-foundation/engine/ext/xstrings" "github.com/mesg-foundation/engine/hash" "github.com/mesg-foundation/engine/process" @@ -22,6 +23,10 @@ import ( "github.com/sirupsen/logrus" ) +func init() { + xrand.SeedInit() +} + // New creates a new Process instance func New(rpc *cosmos.RPC, ep *publisher.EventPublisher, execPrice string) *Orchestrator { return &Orchestrator{