Skip to content

Commit

Permalink
Add commands for running evm and da layer
Browse files Browse the repository at this point in the history
  • Loading branch information
jerargus committed Nov 29, 2023
1 parent c30d024 commit a585138
Show file tree
Hide file tree
Showing 7 changed files with 224 additions and 24 deletions.
21 changes: 0 additions & 21 deletions cmd/world/cardinal/cardinal.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
package cardinal

import (
"errors"

"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"pkg.world.dev/world-cli/common/config"
"pkg.world.dev/world-cli/common/dependency"
"pkg.world.dev/world-cli/tea/style"
)

func init() {
// Register subcommands - `world cardinal [subcommand]`
BaseCmd.AddCommand(createCmd, startCmd, devCmd, restartCmd, purgeCmd, stopCmd)
BaseCmd.Flags().String("config", "", "a toml encoded config file")
}

// BaseCmd is the base command for the cardinal subcommand
Expand All @@ -38,20 +34,3 @@ var BaseCmd = &cobra.Command{
}
},
}

func getConfig(cmd *cobra.Command) (cfg config.Config, err error) {
if !cmd.Flags().Changed("config") {
// The config flag was not set. Attempt to find the config via environment variables or in the local directory
return config.LoadConfig("")
}
// The config flag was explicitly set
configFile, err := cmd.Flags().GetString("config")
if err != nil {
return cfg, err
}
if configFile == "" {
return cfg, errors.New("config cannot be empty")
}
return config.LoadConfig(configFile)

}
3 changes: 2 additions & 1 deletion cmd/world/cardinal/restart.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cardinal

import (
"github.com/spf13/cobra"
"pkg.world.dev/world-cli/common/config"
"pkg.world.dev/world-cli/common/tea_cmd"
)

Expand All @@ -20,7 +21,7 @@ This will restart the following Docker services:
- Cardinal (Core game logic)
- Nakama (Relay)`,
RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := getConfig(cmd)
cfg, err := config.GetConfig(cmd)
if err != nil {
return err
}
Expand Down
3 changes: 2 additions & 1 deletion cmd/world/cardinal/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"

"github.com/spf13/cobra"
"pkg.world.dev/world-cli/common/config"
"pkg.world.dev/world-cli/common/tea_cmd"
)

Expand Down Expand Up @@ -36,7 +37,7 @@ This will start the following Docker services and its dependencies:
- Redis (Cardinal dependency)
- Postgres (Nakama dependency)`,
RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := getConfig(cmd)
cfg, err := config.GetConfig(cmd)
if err != nil {
return err
}
Expand Down
187 changes: 187 additions & 0 deletions cmd/world/evm/evm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
package evm

import (
"bytes"
"fmt"
"os/exec"
"time"

"github.com/spf13/cobra"
"pkg.world.dev/world-cli/common/config"
"pkg.world.dev/world-cli/common/tea_cmd"
)

func EVMCmds() *cobra.Command {
evmRootCmd := &cobra.Command{
Use: "evm",
Short: "EVM base shard commands.",
Long: "Commands for provisioning the EVM Base Shard.",
}
evmRootCmd.AddGroup(&cobra.Group{
ID: "EVM",
Title: "EVM Base Shard Commands",
})
evmRootCmd.AddCommand(
StartEVM(),
StartDA(),
StopAll(),
)
return evmRootCmd
}

const (
FlagDAAuthToken = "da-auth-token"
EnvDAAuthToken = "DA_AUTH_TOKEN"
)

func services(s ...tea_cmd.DockerService) []tea_cmd.DockerService {
return s
}

func StartDA() *cobra.Command {
cmd := &cobra.Command{
Use: "start-da",
Short: "Start the data availability layer client.",
Long: fmt.Sprintf("Start the data availability layer client."),
RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := config.GetConfig(cmd)
if err != nil {
return err
}

// Has the DA_AUTH_TOKEN parameter been set in the config?
isDAAuthTokenSet := len(cfg.DockerEnv[EnvDAAuthToken]) > 0

cfg.Build = true
cfg.Debug = false
cfg.Detach = true
cfg.Timeout = -1
daService := tea_cmd.DockerServiceDA
fmt.Println("starting DA docker service...")
err = tea_cmd.DockerStart(cfg, services(daService))
if err != nil {
fmt.Errorf("error starting %s docker container: %w", daService, err)
}
// TODO: Can this be replaced with a health check in the docker-compose file?
time.Sleep(3 * time.Second)
fmt.Println("started DA service...")

if !isDAAuthTokenSet {
fmt.Println("DA token has not been set in the config file.")
fmt.Println("attempting to get the DA token...")
authTokenLog, daToken, err := getDAToken()
if err != nil {
return err
}
fmt.Println(authTokenLog)
fmt.Println("To skip this check in the future, add the following line to the [evm] section of your config file:")
fmt.Printf("%s=%q\n", EnvDAAuthToken, daToken)
}
return nil
},
}
return cmd
}

func StartEVM() *cobra.Command {
cmd := &cobra.Command{
Use: "start",
Short: "Start the EVM base shard. Use --da-auth-token to pass in an auth token directly.",
Long: "Start the EVM base shard. Requires connection to celestia DA.",
RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := config.GetConfig(cmd)
if err != nil {
return err
}

daToken, err := cmd.Flags().GetString(FlagDAAuthToken)
if err != nil {
return err
}
fmt.Println("start", cfg.DockerEnv[EnvDAAuthToken])
if daToken != "" {
cfg.DockerEnv[EnvDAAuthToken] = daToken
}
fmt.Println("after", cfg.DockerEnv[EnvDAAuthToken])

if cfg.DockerEnv[EnvDAAuthToken] == "" {
return fmt.Errorf("the DA auth token was not found in the config at a[evm].%s, nor set via the"+
"--%s flag. please add the token to the config file or use the flag", EnvDAAuthToken, FlagDAAuthToken)
}

cfg.Build = true
cfg.Debug = false
cfg.Detach = false
cfg.Timeout = 0

err = tea_cmd.DockerStart(cfg, services(tea_cmd.DockerServiceEVM))
if err != nil {
fmt.Errorf("error starting %s docker container: %w", tea_cmd.DockerServiceEVM, err)
}
return nil
},
}
cmd.Flags().String(FlagDAAuthToken, "", "DA Auth Token that allows the rollup to communicate with the Celestia client.")
return cmd
}

func StopAll() *cobra.Command {
cmd := &cobra.Command{
Use: "stop",
Short: "Stop the EVM base shard and DA layer client.",
Long: "Stop the EVM base shard and data availability layer client if they are running.",
RunE: func(cmd *cobra.Command, args []string) error {
return tea_cmd.DockerStop(services(tea_cmd.DockerServiceEVM, tea_cmd.DockerServiceDA))
},
}
return cmd
}

func getDAToken() (authTokenLog, token string, err error) {
// Create a new command
cmd := exec.Command("docker", "logs", "celestia_devnet")
retry := 0
for ; retry < 10; func() {
time.Sleep(2 * time.Second)
retry++
}() {
fmt.Println("attempting to get DA token...")

output, err := cmd.Output()
if err != nil {
fmt.Println("error running command docker logs: ", err)
continue
}

// Find the line containing CELESTIA_NODE_AUTH_TOKEN
lines := bytes.Split(output, []byte("\n"))
for i, line := range lines {
if bytes.Contains(line, []byte("CELESTIA_NODE_AUTH_TOKEN")) {
// Get the next 5 lines after the match
endIndex := i + 6
if endIndex > len(lines) {
endIndex = len(lines)
}
authTokenLines := lines[i:endIndex]
fmt.Println("I have some lines", len(authTokenLines))
for _, X := range authTokenLines {
fmt.Println("->", string(X))
}

// Concatenate the lines to get the final output
authTokenLog = string(bytes.Join(authTokenLines, []byte("\n")))
// The last line is the actual token
token = string(authTokenLines[len(authTokenLines)-1])
break
}
}

// Print the final output
if authTokenLog != "" {
fmt.Println("token found")
return authTokenLog, token, nil
}
fmt.Println("failed... trying again")
}
return "", "", fmt.Errorf("timed out while getting DA token")
}
9 changes: 8 additions & 1 deletion cmd/world/root/root.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package root

import (
"os"

"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"os"
"pkg.world.dev/world-cli/cmd/world/cardinal"
"pkg.world.dev/world-cli/cmd/world/evm"
"pkg.world.dev/world-cli/common/config"
"pkg.world.dev/world-cli/tea/style"
)

Expand All @@ -21,6 +24,10 @@ func init() {

// Register subcommands
rootCmd.AddCommand(cardinal.BaseCmd)

rootCmd.AddCommand(evm.EVMCmds())

config.AddConfigFlag(rootCmd)
}

// rootCmd represents the base command
Expand Down
23 changes: 23 additions & 0 deletions common/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ import (

"github.com/pelletier/go-toml"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
)

const (
WorldCLIConfigFileEnvVariable = "WORLD_CLI_CONFIG_FILE"
WorldCLIConfigFilename = "world.toml"

flagForConfigFile = "config"
)

var (
Expand All @@ -32,6 +35,26 @@ type Config struct {
DockerEnv map[string]string
}

func AddConfigFlag(cmd *cobra.Command) {
cmd.Flags().String(flagForConfigFile, "", "a toml encoded config file")

Check warning on line 39 in common/config/config.go

View check run for this annotation

Codecov / codecov/patch

common/config/config.go#L38-L39

Added lines #L38 - L39 were not covered by tests
}

func GetConfig(cmd *cobra.Command) (cfg Config, err error) {
if !cmd.Flags().Changed(flagForConfigFile) {
// The config flag was not set. Attempt to find the config via environment variables or in the local directory
return LoadConfig("")
}

Check warning on line 46 in common/config/config.go

View check run for this annotation

Codecov / codecov/patch

common/config/config.go#L42-L46

Added lines #L42 - L46 were not covered by tests
// The config flag was explicitly set
configFile, err := cmd.Flags().GetString(flagForConfigFile)
if err != nil {
return cfg, err
}
if configFile == "" {
return cfg, errors.New("config cannot be empty")
}
return LoadConfig(configFile)

Check warning on line 55 in common/config/config.go

View check run for this annotation

Codecov / codecov/patch

common/config/config.go#L48-L55

Added lines #L48 - L55 were not covered by tests
}

func LoadConfig(filename string) (Config, error) {
if filename != "" {
return loadConfigFromFile(filename)
Expand Down
2 changes: 2 additions & 0 deletions common/tea_cmd/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ const (
DockerServiceNakama DockerService = "nakama"
DockerServiceCockroachDB DockerService = "cockroachdb"
DockerServiceRedis DockerService = "redis"
DockerServiceEVM DockerService = "evm"
DockerServiceDA DockerService = "celestia-devnet"
)

func dockerCompose(args ...string) error {
Expand Down

0 comments on commit a585138

Please sign in to comment.