diff --git a/cmd/config/init/DALightClient.go b/cmd/config/init/DALightClient.go index 2179b982..ea75f86b 100644 --- a/cmd/config/init/DALightClient.go +++ b/cmd/config/init/DALightClient.go @@ -3,6 +3,7 @@ package initconfig import ( "os/exec" "path/filepath" + "github.com/dymensionxyz/roller/cmd/consts" ) diff --git a/cmd/consts/consts.go b/cmd/consts/consts.go index 1fb08633..bde59811 100644 --- a/cmd/consts/consts.go +++ b/cmd/consts/consts.go @@ -1,15 +1,23 @@ package consts +import "fmt" + +const binsDir = "/usr/local/bin" + +var internalBinsDir = fmt.Sprintf("%s/roller_bins", binsDir) + var Executables = struct { Celestia string RollappEVM string Relayer string Dymension string + CelKey string }{ - Celestia: "/usr/local/bin/roller_bins/celestia", - RollappEVM: "/usr/local/bin/rollapp_evm", - Relayer: "/usr/local/bin/roller_bins/rly", - Dymension: "/usr/local/bin/roller_bins/dymd", + Celestia: fmt.Sprintf("%s/celestia", internalBinsDir), + CelKey: fmt.Sprintf("%s/cel-key", internalBinsDir), + RollappEVM: fmt.Sprintf("%s/rollapp_evm", binsDir), + Relayer: fmt.Sprintf("%s/rly", internalBinsDir), + Dymension: fmt.Sprintf("%s/dymd", internalBinsDir), } var KeyNames = struct { diff --git a/cmd/da-light-client/da_light_client.go b/cmd/da-light-client/da_light_client.go new file mode 100644 index 00000000..8988fdd0 --- /dev/null +++ b/cmd/da-light-client/da_light_client.go @@ -0,0 +1,15 @@ +package da_light_client + +import ( + da_start "github.com/dymensionxyz/roller/cmd/da-light-client/start" + "github.com/spf13/cobra" +) + +func DALightClientCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "da-light-client", + Short: "Commands for running and managing the data availability light client.", + } + cmd.AddCommand(da_start.Cmd()) + return cmd +} diff --git a/cmd/da-light-client/start/start.go b/cmd/da-light-client/start/start.go new file mode 100644 index 00000000..20ed3392 --- /dev/null +++ b/cmd/da-light-client/start/start.go @@ -0,0 +1,58 @@ +package start + +import ( + "fmt" + "os/exec" + "path/filepath" + + initconfig "github.com/dymensionxyz/roller/cmd/config/init" + "github.com/dymensionxyz/roller/cmd/consts" + "github.com/dymensionxyz/roller/cmd/utils" + "github.com/spf13/cobra" +) + +const rpcEndpointFlag = "--rpc-endpoint" + +func Cmd() *cobra.Command { + runCmd := &cobra.Command{ + Use: "start", + Short: "Runs the rollapp sequencer.", + Run: func(cmd *cobra.Command, args []string) { + home := cmd.Flag(utils.FlagNames.Home).Value.String() + rollappConfig, err := initconfig.LoadConfigFromTOML(home) + utils.PrettifyErrorIfExists(err) + rpcEndpoint := cmd.Flag(rpcEndpointFlag).Value.String() + startRollappCmd := getStartCelestiaLCCmd(rollappConfig, rpcEndpoint) + utils.RunBashCmdAsync(startRollappCmd, printOutput, parseError) + }, + } + utils.AddGlobalFlags(runCmd) + addFlags(runCmd) + return runCmd +} + +func addFlags(cmd *cobra.Command) { + cmd.Flags().StringP(rpcEndpointFlag, "", "consensus-full-arabica-8.celestia-arabica.com", + "The DA rpc endpoint to connect to.") +} + +func printOutput() { + fmt.Println("💈 The data availability light node is running on your local machine!") + fmt.Println("💈 Light node endpoint: http://127.0.0.1:26659") +} + +func parseError(errMsg string) string { + return errMsg +} + +func getStartCelestiaLCCmd(rollappConfig initconfig.InitConfig, rpcEndpoint string) *exec.Cmd { + return exec.Command( + consts.Executables.Celestia, "light", "start", + "--core.ip", rpcEndpoint, + "--node.store", filepath.Join(rollappConfig.Home, consts.ConfigDirName.DALightNode), + "--gateway", + "--gateway.addr", "127.0.0.1", + "--gateway.port", "26659", + "--p2p.network", "arabica", + ) +} diff --git a/cmd/root.go b/cmd/root.go index d156a707..1a246d6d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -4,8 +4,9 @@ import ( "os" "github.com/dymensionxyz/roller/cmd/config" + da_light_client "github.com/dymensionxyz/roller/cmd/da-light-client" "github.com/dymensionxyz/roller/cmd/register" - "github.com/dymensionxyz/roller/cmd/run" + "github.com/dymensionxyz/roller/cmd/sequencer" "github.com/dymensionxyz/roller/cmd/version" "github.com/spf13/cobra" ) @@ -29,5 +30,6 @@ func init() { rootCmd.AddCommand(config.ConfigCmd()) rootCmd.AddCommand(version.VersionCmd()) rootCmd.AddCommand(register.RegisterCmd()) - rootCmd.AddCommand(run.RunCmd()) + rootCmd.AddCommand(da_light_client.DALightClientCmd()) + rootCmd.AddCommand(sequencer.SequencerCmd()) } diff --git a/cmd/sequencer/sequencer.go b/cmd/sequencer/sequencer.go new file mode 100644 index 00000000..96a03c5b --- /dev/null +++ b/cmd/sequencer/sequencer.go @@ -0,0 +1,15 @@ +package sequencer + +import ( + sequnecer_start "github.com/dymensionxyz/roller/cmd/sequencer/start" + "github.com/spf13/cobra" +) + +func SequencerCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "sequencer", + Short: "Commands for running and managing the RollApp sequnecer.", + } + cmd.AddCommand(sequnecer_start.StartCmd()) + return cmd +} diff --git a/cmd/run/run.go b/cmd/sequencer/start/start.go similarity index 51% rename from cmd/run/run.go rename to cmd/sequencer/start/start.go index 770f808f..b85a9bc2 100644 --- a/cmd/run/run.go +++ b/cmd/sequencer/start/start.go @@ -1,51 +1,64 @@ -package run +package sequnecer_start import ( "fmt" - "github.com/dymensionxyz/roller/cmd/consts" "os/exec" "path/filepath" + "strings" + initconfig "github.com/dymensionxyz/roller/cmd/config/init" + "github.com/dymensionxyz/roller/cmd/consts" "github.com/dymensionxyz/roller/cmd/utils" "github.com/spf13/cobra" ) -const daLightClientEndpointFlag = "da-light-client-endpoint" - -func RunCmd() *cobra.Command { +func StartCmd() *cobra.Command { runCmd := &cobra.Command{ - Use: "run", + Use: "start", Short: "Runs the rollapp sequencer.", Run: func(cmd *cobra.Command, args []string) { home := cmd.Flag(utils.FlagNames.Home).Value.String() rollappConfig, err := initconfig.LoadConfigFromTOML(home) utils.PrettifyErrorIfExists(err) - startRollappCmd := getStartRollapCmd(rollappConfig, cmd.Flag(daLightClientEndpointFlag).Value.String()) - startRollappErr := startRollappCmd.Start() - utils.PrettifyErrorIfExists(startRollappErr) - fmt.Println("💈 The Rollapp sequencer is running on your local machine!") - fmt.Println("💈 EVM RPC: http://0.0.0.0:8545") - fmt.Println("💈 Node RPC: http://0.0.0.0:26657") - fmt.Println("💈 Rest API: http://0.0.0.0:1317") - err = startRollappCmd.Wait() - utils.PrettifyErrorIfExists(err) + LightNodeEndpoint := cmd.Flag(FlagNames.DAEndpoint).Value.String() + startRollappCmd := getStartRollapCmd(rollappConfig, LightNodeEndpoint) + utils.RunBashCmdAsync(startRollappCmd, printOutput, parseError) }, } - addFlags(runCmd) utils.AddGlobalFlags(runCmd) + runCmd.Flags().StringP(FlagNames.DAEndpoint, "", "http://localhost:26659", "The data availability light node endpoint.") return runCmd } -func addFlags(cmd *cobra.Command) { - cmd.Flags().StringP(daLightClientEndpointFlag, "", "http://localhost:26659", "The DA light client endpoint.") +var FlagNames = struct { + DAEndpoint string +}{ + DAEndpoint: "da-endpoint", } -func getStartRollapCmd(rollappConfig initconfig.InitConfig, daLightClientEndpoint string) *exec.Cmd { - daConfig := fmt.Sprintf(`{"base_url": "%s", "timeout": 60000000000, "fee":20000, "gas_limit": 20000000, "namespace_id":[0,0,0,0,0,0,255,255]}`, daLightClientEndpoint) +func printOutput() { + fmt.Println("💈 The Rollapp sequencer is running on your local machine!") + fmt.Println("💈 EVM RPC: http://0.0.0.0:8545") + fmt.Println("💈 Node RPC: http://0.0.0.0:26657") + fmt.Println("💈 Rest API: http://0.0.0.0:1317") +} + +func parseError(errMsg string) string { + lines := strings.Split(errMsg, "\n") + if len(lines) > 0 && lines[0] == "Error: failed to initialize database: resource temporarily unavailable" { + return "The Rollapp sequencer is already running. Only one sequencer can run on the machine at any given time." + } + return errMsg +} + +func getStartRollapCmd(rollappConfig initconfig.InitConfig, lightNodeEndpoint string) *exec.Cmd { + daConfig := fmt.Sprintf(`{"base_url": "%s", "timeout": 60000000000, "fee":20000, "gas_limit": 20000000, "namespace_id":[0,0,0,0,0,0,255,255]}`, + lightNodeEndpoint) rollappConfigDir := filepath.Join(rollappConfig.Home, consts.ConfigDirName.Rollapp) - settlementConfig := fmt.Sprintf(`{"node_address": "%s", "rollapp_id": "%s", "dym_account_name": "%s", "keyring_home_dir": "%s", "keyring_backend":"test", "gas_fees": "2000000udym"}`, - rollappConfig.HubData.RPC_URL, rollappConfig.RollappID, consts.KeyNames.HubSequencer, rollappConfigDir) + + // TODO: Update the gas_fees to 2000000udym before 35-c launch. + settlementConfig := fmt.Sprintf(`{"node_address": "%s", "rollapp_id": "%s", "dym_account_name": "%s", "keyring_home_dir": "%s", "keyring_backend":"test", "gas_fees": "0udym"}`, rollappConfig.HubData.RPC_URL, rollappConfig.RollappID, consts.KeyNames.HubSequencer, rollappConfigDir) return exec.Command( rollappConfig.RollappBinary, "start", diff --git a/cmd/utils/bash_commands.go b/cmd/utils/bash_commands.go new file mode 100644 index 00000000..3d7f1880 --- /dev/null +++ b/cmd/utils/bash_commands.go @@ -0,0 +1,23 @@ +package utils + +import ( + "bytes" + "errors" + "os/exec" +) + +func RunBashCmdAsync(cmd *exec.Cmd, printOutput func(), parseError func(errMsg string) string) { + var stderr bytes.Buffer + cmd.Stderr = &stderr + err := cmd.Start() + if err != nil { + errMsg := parseError(stderr.String()) + PrettifyErrorIfExists(errors.New(errMsg)) + } + printOutput() + err = cmd.Wait() + if err != nil { + errMsg := parseError(stderr.String()) + PrettifyErrorIfExists(errors.New(errMsg)) + } +} diff --git a/cmd/utils/error_handling.go b/cmd/utils/error_handling.go index 9eaa8ac0..b84c305c 100644 --- a/cmd/utils/error_handling.go +++ b/cmd/utils/error_handling.go @@ -1,9 +1,8 @@ package utils import ( - "os" - "github.com/fatih/color" + "os" ) func PrettifyErrorIfExists(err error) { diff --git a/cmd/utils/keys.go b/cmd/utils/keys.go index a6a2a4f3..596464f4 100644 --- a/cmd/utils/keys.go +++ b/cmd/utils/keys.go @@ -1,11 +1,46 @@ package utils import ( + "bytes" + "encoding/json" + "errors" + "os/exec" + "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/bech32" + "github.com/dymensionxyz/roller/cmd/consts" ) +type KeyInfo struct { + Address string `json:"address"` +} + +func GetCelestiaAddress(keyringDir string) (string, error) { + cmd := exec.Command( + consts.Executables.CelKey, + "show", consts.KeyNames.DALightNode, "--node.type", "light", "--keyring-dir", keyringDir, "--keyring-backend", "test", "--output", "json", + ) + + var out bytes.Buffer + var stderr bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &stderr + + err := cmd.Run() + if err != nil { + return "", errors.New(stderr.String()) + } + + var key = &KeyInfo{} + err = json.Unmarshal(out.Bytes(), key) + if err != nil { + return "", err + } + + return key.Address, nil +} + type KeyConfig struct { Dir string ID string @@ -41,6 +76,5 @@ func GetAddress(keyConfig KeyConfig) (string, error) { if err != nil { return "", err } - return formattedAddress, nil } diff --git a/go.mod b/go.mod index 49e94026..6b36e61e 100644 --- a/go.mod +++ b/go.mod @@ -65,7 +65,6 @@ require ( github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/magiconair/properties v1.8.6 // indirect - github.com/manifoldco/promptui v0.9.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect