diff --git a/cmd/config/init/flags.go b/cmd/config/init/flags.go index 5ca86f5b..3fca4314 100644 --- a/cmd/config/init/flags.go +++ b/cmd/config/init/flags.go @@ -2,7 +2,9 @@ package initconfig import ( "fmt" + "math/rand" "strings" + "time" "github.com/dymensionxyz/roller/version" @@ -49,13 +51,14 @@ func GetInitConfig(initCmd *cobra.Command, args []string) (config.RollappConfig, if err := RunInteractiveMode(&cfg); err != nil { return cfg, err } - setDecimals(initCmd, &cfg) - return cfg, nil + return formatBaseCfg(cfg, initCmd), nil } rollappId := args[0] denom := args[1] - + if !isAlphanumeric(rollappId) { + return cfg, fmt.Errorf("invalid rollapp id %s. %s", rollappId, validRollappIDMsg) + } hubID := initCmd.Flag(FlagNames.HubID).Value.String() tokenSupply := initCmd.Flag(FlagNames.TokenSupply).Value.String() cfg.RollappID = rollappId @@ -64,8 +67,36 @@ func GetInitConfig(initCmd *cobra.Command, args []string) (config.RollappConfig, cfg.TokenSupply = tokenSupply cfg.DA = config.DAType(strings.ToLower(initCmd.Flag(FlagNames.DAType).Value.String())) cfg.VMType = config.VMType(initCmd.Flag(FlagNames.VMType).Value.String()) + return formatBaseCfg(cfg, initCmd), nil +} + +func formatBaseCfg(cfg config.RollappConfig, initCmd *cobra.Command) config.RollappConfig { setDecimals(initCmd, &cfg) - return cfg, nil + formattedRollappId, err := generateRollappId(cfg) + if err != nil { + return cfg + } + cfg.RollappID = formattedRollappId + return cfg +} + +func generateRollappId(rlpCfg config.RollappConfig) (string, error) { + for { + RandEthId := generateRandEthId() + isUnique, err := isEthIdentifierUnique(RandEthId, rlpCfg) + if err != nil { + return "", err + } + if isUnique { + return fmt.Sprintf("%s_%s-1", rlpCfg.RollappID, RandEthId), nil + } + } +} + +func generateRandEthId() string { + rand.Seed(time.Now().UnixNano()) + randomNumber := rand.Intn(9000000) + 1000000 + return fmt.Sprintf("%d", randomNumber) } func setDecimals(initCmd *cobra.Command, cfg *config.RollappConfig) { diff --git a/cmd/config/init/init.go b/cmd/config/init/init.go index 927a923b..a343d4ce 100644 --- a/cmd/config/init/init.go +++ b/cmd/config/init/init.go @@ -18,7 +18,7 @@ func InitCmd() *cobra.Command { Use: "init | --interactive", Short: "Initialize a RollApp configuration on your local machine.", Long: "Initialize a RollApp configuration on your local machine\n" + requiredFlagsUsage(), - Example: `init mars_9721-1 btc`, + Example: `init mars btc`, PreRunE: func(cmd *cobra.Command, args []string) error { interactive, _ := cmd.Flags().GetBool(FlagNames.Interactive) if interactive { @@ -46,14 +46,13 @@ func InitCmd() *cobra.Command { return initCmd } +const validRollappIDMsg = "A valid RollApp ID should contain only alphanumeric characters, for example, 'mars', 'venus', 'earth', etc." + func requiredFlagsUsage() string { - return ` -A valid RollApp ID should follow the format 'name_uniqueID-revision', where -- 'name' is made up of lowercase English letters -- 'uniqueID' is a number up to the length of 5 digits representing the unique ID EIP155 rollapp ID -- 'revision' is a number up to the length of 5 digits representing the revision number for this rollapp + return fmt.Sprintf(` +%s -A valid denom should consist of 3-6 English alphabet letters, for example, 'btc', 'eth', 'pepe', etc.` +A valid denom should consist of 3-6 English alphabet letters, for example, 'btc', 'eth', 'pepe', etc.`, validRollappIDMsg) } func runInit(cmd *cobra.Command, args []string) error { @@ -73,10 +72,6 @@ func runInit(cmd *cobra.Command, args []string) error { if err != nil { return err } - err = VerifyUniqueRollappID(initConfig.RollappID, initConfig) - if err != nil { - return err - } isRootExist, err := global_utils.DirNotEmpty(initConfig.Home) if err != nil { return err diff --git a/cmd/config/init/interactive.go b/cmd/config/init/interactive.go index 35030ba6..4398fb9e 100644 --- a/cmd/config/init/interactive.go +++ b/cmd/config/init/interactive.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "strings" + "unicode" "github.com/dymensionxyz/roller/config" "github.com/manifoldco/promptui" @@ -50,27 +51,19 @@ func RunInteractiveMode(cfg *config.RollappConfig) error { } promptChainID := promptui.Prompt{ Label: "Enter your RollApp ID", - Default: "myrollapp_1234-1", + Default: "myrollapp", AllowEdit: true, } for { - chainID, err := promptChainID.Run() + rollappID, err := promptChainID.Run() if err != nil { return err } - if cfg.VMType == config.EVM_ROLLAPP { - err = config.ValidateRollAppID(chainID) - if err != nil { - fmt.Println(err) - continue - } - } - err = VerifyUniqueRollappID(chainID, *cfg) - if err != nil { - fmt.Println(err) + if !isAlphanumeric(rollappID) { + fmt.Printf("invalid rollapp id %s. %s\n", rollappID, validRollappIDMsg) continue } - cfg.RollappID = chainID + cfg.RollappID = rollappID break } @@ -112,3 +105,12 @@ func RunInteractiveMode(cfg *config.RollappConfig) error { return nil } + +func isAlphanumeric(s string) bool { + for _, r := range s { + if !unicode.IsLetter(r) && !unicode.IsDigit(r) { + return false + } + } + return true +} diff --git a/cmd/config/init/unique_rollapp_id.go b/cmd/config/init/unique_rollapp_id.go index e7863b82..1f9751f4 100644 --- a/cmd/config/init/unique_rollapp_id.go +++ b/cmd/config/init/unique_rollapp_id.go @@ -2,46 +2,12 @@ package initconfig import ( "encoding/json" - "fmt" "github.com/dymensionxyz/roller/cmd/consts" "github.com/dymensionxyz/roller/cmd/utils" "github.com/dymensionxyz/roller/config" - "net/http" "os/exec" - "strings" ) -// TODO(#150): roller should use RPC for queries instead of REST -func IsRollappIDUnique(rollappID string, initConfig config.RollappConfig) (bool, error) { - if initConfig.VMType == config.SDK_ROLLAPP { - url := initConfig.HubData.API_URL + "/dymensionxyz/dymension/rollapp/rollapp/" + rollappID - - req, err := http.NewRequest("GET", url, nil) - if err != nil { - return false, err - } - - req.Header.Set("accept", "application/json") - - client := &http.Client{} - resp, err := client.Do(req) - if err != nil { - return false, err - } - defer resp.Body.Close() - - if resp.StatusCode == 404 { - return true, nil - } else if resp.StatusCode == 200 { - return false, nil - } else { - return false, fmt.Errorf("unexpected status code: %d", resp.StatusCode) - } - } else { - return verifyUniqueEthIdentifier(rollappID, initConfig) - } -} - type Rollapp struct { ID string `json:"rollappId"` } @@ -50,7 +16,7 @@ type RollappsListResponse struct { Rollapps []Rollapp `json:"rollapp"` } -func verifyUniqueEthIdentifier(rollappID string, rlpCfg config.RollappConfig) (bool, error) { +func isEthIdentifierUnique(ethID string, rlpCfg config.RollappConfig) (bool, error) { commonDymdFlags := utils.GetCommonDymdFlags(rlpCfg) // TODO: Move the filtering by ethereum rollapp ID logic to the hub args := []string{"q", "rollapp", "list", "--limit", "1000000"} @@ -66,30 +32,9 @@ func verifyUniqueEthIdentifier(rollappID string, rlpCfg config.RollappConfig) (b return false, err } for _, rollapp := range rollappsListResponse.Rollapps { - if config.GetEthID(rollapp.ID) == config.GetEthID(rollappID) { + if config.GetEthID(rollapp.ID) == ethID { return false, nil } } return true, nil } - -func VerifyUniqueRollappID(rollappID string, initConfig config.RollappConfig) error { - isUniqueRollapp, err := IsRollappIDUnique(rollappID, initConfig) - if err != nil { - if initConfig.HubData.ID == LocalHubID { - // When using a local hub and the hub is not yet running, we assume the rollapp ID is unique - return nil - } - return err - } - if !isUniqueRollapp { - if initConfig.VMType == config.SDK_ROLLAPP { - return fmt.Errorf("rollapp ID \"%s\" already exists on the hub. Please use a unique ID", rollappID) - } else { - ethID := config.GetEthID(rollappID) - return fmt.Errorf("EIP155 ID \"%s\" already exists on the hub (%s). Please use a unique EIP155 ID", - ethID, strings.Replace(rollappID, ethID, fmt.Sprintf("*%s*", ethID), 1)) - } - } - return nil -} diff --git a/config/chainid.go b/config/chainid.go index ee5ed5f5..6acef211 100644 --- a/config/chainid.go +++ b/config/chainid.go @@ -1,32 +1,9 @@ package config import ( - "fmt" "regexp" ) -var ( - regexChainID = `[a-z]{1,}` - regexEIP155Separator = `_{1}` - regexEIP155 = `[1-9][0-9]*` - regexEpochSeparator = `-{1}` - regexEpoch = `[1-9][0-9]*` - rollappID = regexp.MustCompile(fmt.Sprintf(`^(%s)%s(%s)%s(%s)$`, - regexChainID, - regexEIP155Separator, - regexEIP155, - regexEpochSeparator, - regexEpoch)) -) - -func ValidateRollAppID(id string) error { - if !rollappID.MatchString(id) { - return fmt.Errorf("invalid RollApp ID '%s'. "+ - "Expected format: name_uniqueID-revision (e.g. myrollapp_1234-1)", id) - } - return nil -} - func GetEthID(rollappID string) string { re := regexp.MustCompile(`_(\d+)-`) matches := re.FindStringSubmatch(rollappID) diff --git a/config/config.go b/config/config.go index 78a7d96a..e10c7558 100644 --- a/config/config.go +++ b/config/config.go @@ -55,12 +55,6 @@ func (c RollappConfig) Validate() error { if err != nil { return err } - if c.VMType == EVM_ROLLAPP { - err = ValidateRollAppID(c.RollappID) - if err != nil { - return err - } - } err = IsValidDenom(c.Denom) if err != nil { return err