diff --git a/rollkit/CHANGELOG.md b/rollkit/CHANGELOG.md index 0a5ed21c..1aa8aea0 100644 --- a/rollkit/CHANGELOG.md +++ b/rollkit/CHANGELOG.md @@ -2,7 +2,11 @@ ## Unreleased +## [`v0.3.0`](https://github.com/ignite/apps/releases/tag/rollkit/v0.3.0) + * [#112](https://github.com/ignite/apps/pull/112) Use default command instead cobra commands. +* [#192](https://github.com/ignite/apps/pull/192) Upgrade Rollkit to `v1.x` and use [`go-execution-abci`](https://github.com/rollkit/go-execution-abci) instead of [`cosmos-sdk-starter`](https://github.com/rollkit/cosmos-sdk-starter). + * Note, if you already have rollkit installed, you need to redo the wiring manually. ## [`v0.2.1`](https://github.com/ignite/apps/releases/tag/rollkit/v0.2.1) diff --git a/rollkit/README.md b/rollkit/README.md index b401913b..41d21d88 100644 --- a/rollkit/README.md +++ b/rollkit/README.md @@ -4,20 +4,35 @@ This Ignite App is aimed to extend [Ignite CLI](https://github.com/ignite/cli) a ## Prerequisites -* Ignite CLI version v28.4.0 or greater. +* Ignite CLI version v28.9.0 or greater. * Knowledge of blockchain development (Cosmos SDK). ## Usage ```sh -ignite s chain gm --address-prefix gm --minimal +ignite s chain gm --address-prefix gm --minimal --no-module cd gm -ignite app install -g github.com/ignite/apps/rollkit@rollkit/v0.2.1 +ignite app install -g github.com/ignite/apps/rollkit@latest ignite rollkit add -ignite chain build +ignite chain build --skip-proto ignite rollkit init ``` +Then start `local-da` or use Celestia mainnet as data availability layer. + +```sh +# go install github.com/rollkit/rollkit/da/cmd/local-da@latest +git clone github.com/rollkit/rollkit --depth 1 +cd rollkit/da/cmd/local-da +go run . +``` + +Finally, run the rollup node: + +```sh +gmd start --rollkit.node.aggregator +``` + Learn more about Rollkit and Ignite in their respective documentation: * diff --git a/rollkit/cmd/add.go b/rollkit/cmd/add.go index 3b41661a..ff71072e 100644 --- a/rollkit/cmd/add.go +++ b/rollkit/cmd/add.go @@ -59,11 +59,13 @@ func AddHandler(ctx context.Context, cmd *plugin.ExecutedCommand) error { // finish finalize the scaffolded code (formating, dependencies). func finish(ctx context.Context, session *cliui.Session, path string) error { + session.StopSpinner() session.StartSpinner("go mod tidy...") if err := gocmd.ModTidy(ctx, path); err != nil { return err } + session.StopSpinner() session.StartSpinner("Formatting code...") if err := gocmd.Fmt(ctx, path); err != nil { return err diff --git a/rollkit/cmd/init.go b/rollkit/cmd/init.go index b91843b1..301090b6 100644 --- a/rollkit/cmd/init.go +++ b/rollkit/cmd/init.go @@ -13,6 +13,7 @@ import ( cmttypes "github.com/cometbft/cometbft/types" sdk "github.com/cosmos/cosmos-sdk/types" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + configchain "github.com/ignite/cli/v28/ignite/config/chain" "github.com/ignite/cli/v28/ignite/pkg/cliui" "github.com/ignite/cli/v28/ignite/pkg/cliui/colors" diff --git a/rollkit/go.mod b/rollkit/go.mod index 37855649..2db1c487 100644 --- a/rollkit/go.mod +++ b/rollkit/go.mod @@ -9,7 +9,7 @@ require ( github.com/gobuffalo/genny/v2 v2.1.0 github.com/gobuffalo/plush/v4 v4.1.19 github.com/hashicorp/go-plugin v1.6.1 - github.com/ignite/cli/v28 v28.8.2 + github.com/ignite/cli/v28 v28.10.0 github.com/stretchr/testify v1.10.0 ) diff --git a/rollkit/go.sum b/rollkit/go.sum index 71c98daf..4207d1d3 100644 --- a/rollkit/go.sum +++ b/rollkit/go.sum @@ -509,8 +509,8 @@ github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmK github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ignite/cli/v28 v28.8.2 h1:35wFZkK9Bs8+GHMat2X37WBYCpbx8kX1DmYQIc7momQ= -github.com/ignite/cli/v28 v28.8.2/go.mod h1:NQdeVKo3JywfXn2gPwDowWgw0tJdp1bVbKh/L5Dt9/Q= +github.com/ignite/cli/v28 v28.10.0 h1:/qhdqhYbNEYuZeslU5DILksNDfWw5FGZQpn0zQq3SY0= +github.com/ignite/cli/v28 v28.10.0/go.mod h1:T2GMEMO2izmLg9PDdsrJ8u0YwZmBXy1Xnbg0W917HPQ= github.com/ignite/web v0.6.1 h1:kHG+T7NnR8cCPjAGxEFQD+njVYM08toeG57iYRXzpwo= github.com/ignite/web v0.6.1/go.mod h1:WZWBaBYF8RazN7dE462BLpvXDY8ScacxcJ07BKwX/jY= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= diff --git a/rollkit/integration/app_test.go b/rollkit/integration/app_test.go index 59c47caa..35f541bc 100644 --- a/rollkit/integration/app_test.go +++ b/rollkit/integration/app_test.go @@ -67,7 +67,7 @@ func TestRollkit(t *testing.T) { )), )) - if !strings.Contains(buf.String(), "--rollkit.da_") { + if !strings.Contains(buf.String(), "--rollkit.da") { t.Errorf("rollkitd doesn't contain --rollkit flags: %s", buf.String()) } diff --git a/rollkit/template/constants.go b/rollkit/template/constants.go new file mode 100644 index 00000000..1e942172 --- /dev/null +++ b/rollkit/template/constants.go @@ -0,0 +1,16 @@ +package template + +const ( + ServerAddCommandsWithStartCmdOptions = "server.AddCommandsWithStartCmdOptions" + + RollkitV0XStartHandler = "rollserv.StartHandler" + RollkitV1XStartHandler = "abciserver.StartHandler" +) + +const ( + GoExecPackage = "github.com/rollkit/go-execution-abci" + GoExecVersion = "v0.2.1-0.20250507114132-4abb42ac7c60" // TODO(@julienrbrt): use tag when available + + RollkitPackage = "github.com/rollkit/rollkit" + RollkitVersion = "v0.14.2-0.20250506085607-c574d7c79224" // TODO(@julienrbrt): use tag when available +) diff --git a/rollkit/template/rollkit.go b/rollkit/template/rollkit.go index 91f8d9e5..d92e189e 100644 --- a/rollkit/template/rollkit.go +++ b/rollkit/template/rollkit.go @@ -1,6 +1,7 @@ package template import ( + "os" "path/filepath" "strings" @@ -9,6 +10,7 @@ import ( "github.com/ignite/cli/v28/ignite/pkg/cosmosver" "github.com/ignite/cli/v28/ignite/pkg/errors" + "github.com/ignite/cli/v28/ignite/pkg/gomodule" "github.com/ignite/cli/v28/ignite/pkg/xast" "github.com/ignite/cli/v28/ignite/pkg/xgenny" "github.com/ignite/cli/v28/ignite/services/chain" @@ -27,13 +29,20 @@ func NewRollKitGenerator(chain *chain.Chain) (*genny.Generator, error) { return nil, err } - g.RunFn(commandsModify(chain.AppPath(), binaryName, chain.Version)) + appPath := chain.AppPath() + + if err := updateDependencies(appPath); err != nil { + return nil, errors.Errorf("failed to update go.mod: %w", err) + } + + g.RunFn(commandsStartModify(appPath, binaryName, chain.Version)) + g.RunFn(commandsGenesisModify(appPath, binaryName)) return g, nil } -// commandsModify modifies the application start to use rollkit. -func commandsModify(appPath, binaryName string, version cosmosver.Version) genny.RunFn { +// commandsStartModify modifies the application start to use rollkit. +func commandsStartModify(appPath, binaryName string, version cosmosver.Version) genny.RunFn { return func(r *genny.Runner) error { cmdPath := filepath.Join(appPath, "cmd", binaryName, "cmd/commands.go") f, err := r.Disk.Find(cmdPath) @@ -41,8 +50,12 @@ func commandsModify(appPath, binaryName string, version cosmosver.Version) genny return err } - if strings.Contains(f.String(), "rollserv.StartHandler[servertypes.Application]") { - return errors.New("rollkit is already installed") + if strings.Contains(f.String(), RollkitV0XStartHandler) { + return errors.New("rollkit v0.x is already installed. Please remove it before installing rollkit v1.x") + } + + if strings.Contains(f.String(), RollkitV1XStartHandler) { + return errors.New("rollkit is already installed.") } if version.LT(cosmosver.StargateFiftyVersion) { @@ -51,41 +64,112 @@ func commandsModify(appPath, binaryName string, version cosmosver.Version) genny content, err := xast.AppendImports( f.String(), - xast.WithLastNamedImport("rollserv", "github.com/rollkit/cosmos-sdk-starter/server"), - xast.WithLastNamedImport("rollconf", "github.com/rollkit/rollkit/config"), + xast.WithLastNamedImport("abciserver", "github.com/rollkit/go-execution-abci/server"), ) if err != nil { return err } - // TODO(@julienrbrt) eventually use ast for simply replacing AddCommands or AddCommandsWithStartCmdOptions - const ( - defaultv050ServerOptions = "server.AddCommands(rootCmd, app.DefaultNodeHome, newApp, appExport, addModuleInitFlags)" - secondv050DefaultServerOptions = `server.AddCommandsWithStartCmdOptions(rootCmd, app.DefaultNodeHome, newApp, appExport, server.StartCmdOptions{ - AddFlags: func(startCmd *cobra.Command) { - addModuleInitFlags(startCmd) + // replace potential legacy boilerplate present in an ignite v28 chain. + content = replaceLegacyAddCommands(content) + + // modify the add commands arguments using xast. + content, err = xast.ModifyCaller(content, ServerAddCommandsWithStartCmdOptions, func(args []string) ([]string, error) { + return []string{ + "rootCmd", + "app.DefaultNodeHome", + "newApp", + "appExport", + `server.StartCmdOptions{ + AddFlags: func(cmd *cobra.Command) { + abciserver.AddFlags(cmd) }, - })` - thirdv050DefaultServerOptions = "server.AddCommandsWithStartCmdOptions(rootCmd, app.DefaultNodeHome, newApp, appExport, server.StartCmdOptions{})" - - rollkitServerOptions = `server.AddCommandsWithStartCmdOptions( - rootCmd, - app.DefaultNodeHome, - newApp, appExport, - server.StartCmdOptions{ - AddFlags: func(cmd *cobra.Command) { - rollconf.AddFlags(cmd) - addModuleInitFlags(cmd) - }, - StartCommandHandler: rollserv.StartHandler[servertypes.Application], - })` + StartCommandHandler: abciserver.StartHandler(), + }`, + }, nil + }) + + return r.File(genny.NewFileS(cmdPath, content)) + } +} + +// commandsGenesisModify modifies the application genesis command to use rollkit. +func commandsGenesisModify(appPath, binaryName string) genny.RunFn { + return func(r *genny.Runner) error { + cmdPath := filepath.Join(appPath, "cmd", binaryName, "cmd/commands.go") + f, err := r.Disk.Find(cmdPath) + if err != nil { + return err + } + + content, err := xast.AppendImports( + f.String(), + xast.WithLastNamedImport("rollconf", "github.com/rollkit/rollkit/pkg/config"), + xast.WithLastNamedImport("abciserver", "github.com/rollkit/go-execution-abci/server"), + ) + if err != nil { + return err + } + + // use ast to modify the function that initializes genesisCmd + content, err = xast.ModifyFunction(content, "initRootCmd", + xast.AppendFuncAtLine(` + genesisCmd := genutilcli.InitCmd(basicManager, app.DefaultNodeHome) + rollconf.AddFlags(genesisCmd) + genesisCmdRunE := genesisCmd.RunE + genesisCmd.RunE = func(cmd *cobra.Command, args []string) error { + if err := genesisCmdRunE(cmd, args); err != nil { + return err + } + return abciserver.InitRunE(cmd, args) + } + `, + 0), ) + if err != nil { + return err + } + + // modify the add commands arguments using xast. + content, err = xast.ModifyCaller(content, "rootCmd.AddCommand", func(args []string) ([]string, error) { + if strings.Contains(args[0], "InitCmd") { + args[0] = "genesisCmd" + } - // try all 3 possible default server options - content = strings.ReplaceAll(content, defaultv050ServerOptions, rollkitServerOptions) - content = strings.ReplaceAll(content, secondv050DefaultServerOptions, rollkitServerOptions) - content = strings.ReplaceAll(content, thirdv050DefaultServerOptions, rollkitServerOptions) + return args, nil + }) return r.File(genny.NewFileS(cmdPath, content)) } } + +// updateDependencies makes sure the correct dependencies are added to the go.mod files. +// go-execution-abci expects rollkit v1.0 to be used. +func updateDependencies(appPath string) error { + gomod, err := gomodule.ParseAt(appPath) + if err != nil { + return errors.Errorf("failed to parse go.mod: %w", err) + } + + gomod.AddNewRequire(GoExecPackage, GoExecVersion, false) + gomod.AddNewRequire(RollkitPackage, RollkitVersion, false) + + // temporarily add a replace for rollkit + // it can be removed once we have a tag + gomod.AddReplace(RollkitPackage, "", RollkitPackage, RollkitVersion) + gomod.AddReplace(GoExecPackage, "", GoExecPackage, GoExecVersion) + + // save go.mod + data, err := gomod.Format() + if err != nil { + return errors.Errorf("failed to format go.mod: %w", err) + } + + return os.WriteFile(filepath.Join(appPath, "go.mod"), data, 0o644) +} + +// replaceLegacyAddCommands replaces the legacy `AddCommands` with a temporary `AddCommandsWithStartCmdOptions` boilerplate. +// Atfterwards, we let the same xast function replace the `AddCommandsWithStartCmdOptions` argument. +func replaceLegacyAddCommands(content string) string { + return strings.Replace(content, "server.AddCommands(", ServerAddCommandsWithStartCmdOptions+"(", 1) +}