Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 145 additions & 0 deletions cmd/rollapp/da/switch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package da

import (
"encoding/json"
"strconv"
"strings"

"github.com/cosmos/cosmos-sdk/x/params/client/utils"
"github.com/pterm/pterm"
"github.com/spf13/cobra"

initconfig "github.com/dymensionxyz/roller/cmd/config/init"
"github.com/dymensionxyz/roller/cmd/consts"
"github.com/dymensionxyz/roller/data_layer/avail"
"github.com/dymensionxyz/roller/utils/config/tomlconfig"
"github.com/dymensionxyz/roller/utils/filesystem"
"github.com/dymensionxyz/roller/utils/genesis"
"github.com/dymensionxyz/roller/utils/gov"
"github.com/dymensionxyz/roller/utils/rollapp"
"github.com/dymensionxyz/roller/utils/roller"
sequtils "github.com/dymensionxyz/roller/utils/sequencer"
)

func Cmd() *cobra.Command {
cmd := &cobra.Command{
Use: "switch-da",
Short: "Switch to another DA.",
Long: ``,
Args: cobra.MaximumNArgs(0),
Run: func(cmd *cobra.Command, args []string) {
envs := []string{"avail"} // TODO: support more DAs
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

env is not descriptive

env, _ := pterm.DefaultInteractiveSelect.
WithDefaultText("select the DA you want to switch").
WithOptions(envs).
Show()

err := initconfig.AddFlags(cmd)
if err != nil {
pterm.Error.Println("failed to switch DA: ", err)
return
}

home, err := filesystem.ExpandHomePath(
cmd.Flag(initconfig.GlobalFlagNames.Home).Value.String(),
)
if err != nil {
pterm.Error.Println("failed to switch DA: ", err)
return
}

rollappConfig, err := roller.LoadConfig(home)
if err != nil {
pterm.Error.Println("failed to load roller config: ", err)
return
}

switch env {
case "avail":
raResp, err := rollapp.GetMetadataFromChain(rollappConfig.RollappID, rollappConfig.HubData)
if err != nil {
pterm.Error.Println("failed to get metadata from chain: ", err)
return
}

drsVersion, err := genesis.GetDrsVersionFromGenesis(home, raResp)
if err != nil {
pterm.Error.Println("failed to get drs version from genesis: ", err)
return
}

drsVersionInt, err := strconv.ParseInt(drsVersion, 10, 64)
if err != nil {
pterm.Error.Println("failed to get drs version from genesis: ", err)
return
}

if !rollapp.IsDaConfigNewFormat(drsVersionInt, strings.ToLower(raResp.Rollapp.VmType)) {
pterm.Error.Println("required Rollapp DRS version of at least", drsVersionInt)
return
}

dalayer := avail.NewAvail(home)

submited, _ := pterm.DefaultInteractiveConfirm.WithDefaultText("Have you submitted to gov yet?").Show()
if !submited {
// Create Gov
keyName, _ := pterm.DefaultInteractiveTextInput.WithDefaultText("Enter your key name").Show()
keyring, _ := pterm.DefaultInteractiveTextInput.WithDefaultText("Enter your keyring-backend").Show()
title, _ := pterm.DefaultInteractiveTextInput.WithDefaultText("Enter your Proposal Title").Show()
description, _ := pterm.DefaultInteractiveTextInput.WithDefaultText("Enter your Proposal Description").Show()
deposit, _ := pterm.DefaultInteractiveTextInput.WithDefaultText("Enter your Proposal Deposit").Show()
newDAParam := json.RawMessage(`"avail"`)
txHash, err := gov.ParamChangeProposal(home, keyName, keyring,
&utils.ParamChangeProposalJSON{
Title: title,
Description: description,
Changes: utils.ParamChangesJSON{
utils.NewParamChangeJSON("rollappparams", "da", newDAParam),
},
Deposit: deposit + rollappConfig.Denom,
})

if err != nil {
pterm.Error.Println("failed to submit proposal", err)
return
}
pterm.Info.Println("Proposal Tx hash: ", txHash)
}

daConfig := dalayer.GetSequencerDAConfig(consts.NodeType.Sequencer)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetSequencerDAConfig creates new config (at least for celestia), overwriting namespace. we should use another function or refactor it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it only does that with Celestia. Actually I haven't added the ability to switch from da to Celestia yet so can we consider it in future PRs? @srene

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rollappConfig.DA.Backend = "avail"

dymintConfigPath := sequtils.GetDymintFilePath(home)

pterm.Info.Println("updating dymint configuration")

_ = tomlconfig.UpdateFieldInFile(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to include avail da_config + da_layer and also previous, to allow the transition

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain further?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the updated value should be old + new DA, that way the system will know where to transfer from and to where. For example, if the current DA is Celestia and the rollapp is transferred to Avail, then the config should contain both.

	[]string{string("avail", "celestia")},

and

      _ = tomlconfig.UpdateFieldInFile(
	      dymintConfigPath,
	      "da_config",
	      daConfig,
      )

daConfig should contain both, the "current" celestia da config and the future avail da config

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this part still doesn't seem to be implemented @anhductn2001

dymintConfigPath,
"da_layer",
[]string{string("avail")},
)

_ = tomlconfig.UpdateFieldInFile(
dymintConfigPath,
"da_config",
daConfig,
)

if err := roller.WriteConfig(rollappConfig); err != nil {
pterm.Error.Println("failed to write roller config", err)
return
}

pterm.Info.Println("the config update process is complete! Now you need to restart the nodes before the proposal passes.")

default:
pterm.Error.Println("switch does not support da: ", env)
return
}

},
}

return cmd
}
17 changes: 15 additions & 2 deletions cmd/rollapp/drs/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package drs
import (
"os"
"path/filepath"
"strconv"
"strings"

"github.com/pterm/pterm"
Expand Down Expand Up @@ -158,9 +159,21 @@ func UpgradeCmd() *cobra.Command {
rollappConfig.KeyringBackend,
)

drsVersionInt, err := strconv.ParseInt(drsVersion, 10, 64)
if err != nil {
pterm.Error.Println("failed to get drs version from binary: ", err)
return
}

targetDrsInt, err := strconv.ParseInt(drsVersion, 10, 64)
if err != nil {
pterm.Error.Println("failed to convert drs version from arg: ", err)
return
}

if rollapp.IsDAConfigMigrationRequired(
drsVersion,
targetDrs,
drsVersionInt,
targetDrsInt,
strings.ToLower(raResp.Rollapp.VmType),
) {
upgradeDaConfig(sequencer.GetDymintFilePath(home), *damanager)
Expand Down
2 changes: 2 additions & 0 deletions cmd/rollapp/rollapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"github.com/spf13/cobra"

"github.com/dymensionxyz/roller/cmd/rollapp/config"
"github.com/dymensionxyz/roller/cmd/rollapp/da"
"github.com/dymensionxyz/roller/cmd/rollapp/drs"
initrollapp "github.com/dymensionxyz/roller/cmd/rollapp/init"
"github.com/dymensionxyz/roller/cmd/rollapp/keys"
Expand Down Expand Up @@ -36,6 +37,7 @@ func Cmd() *cobra.Command {
cmd.AddCommand(migrate.Cmd())
cmd.AddCommand(drs.Cmd())
cmd.AddCommand(snapshot.Cmd())
cmd.AddCommand(da.Cmd())

sl := []string{"rollapp"}
cmd.AddCommand(
Expand Down
16 changes: 14 additions & 2 deletions cmd/rollapp/setup/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -1070,7 +1070,13 @@ func getDaLayer(home string, raResponse *rollapp.ShowRollappResponse, daType con
return nil
}

if rollapp.IsDaConfigNewFormat(drsVersion, strings.ToLower(raResponse.Rollapp.VmType)) {
drsVersionInt, err := strconv.ParseInt(drsVersion, 10, 64)
if err != nil {
pterm.Error.Println("failed to get drs version from genesis: ", err)
return nil
}

if rollapp.IsDaConfigNewFormat(drsVersionInt, strings.ToLower(raResponse.Rollapp.VmType)) {
return []string{string(daType)}
} else {
return daType
Expand All @@ -1087,7 +1093,13 @@ func getDaConfig(dataLayer datalayer.DataLayer, nodeType string, home string, ra
return nil
}

if rollapp.IsDaConfigNewFormat(drsVersion, strings.ToLower(raResponse.Rollapp.VmType)) {
drsVersionInt, err := strconv.ParseInt(drsVersion, 10, 64)
if err != nil {
pterm.Error.Println("failed to get drs version from genesis: ", err)
return nil
}

if rollapp.IsDaConfigNewFormat(drsVersionInt, strings.ToLower(raResponse.Rollapp.VmType)) {
return []string{daConfig}
} else {
return daConfig
Expand Down
9 changes: 8 additions & 1 deletion data_layer/avail/appid.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,19 @@ import (
func CreateAppID(rpcURL, seedPhrase, rollappID string) (appID uint32, err error) {
api, err := sdk.NewSDK(rpcURL)
if err != nil {
fmt.Printf("cannot create api:%v", err)
return 0, fmt.Errorf("cannot create api: %v", err)
}

// If the appID corresponding to the rollappID already exists, it will be reused.
blockStorage, err := api.Client.StorageAt(prim.None[prim.H256]())
if err != nil {
return 0, err
}

acc, err := sdk.Account.NewKeyPair(seedPhrase)
if err != nil {
return 0, err
}

// Fetch Map Storage
storage := daPallet.StorageAppKeys{}
Expand Down
22 changes: 11 additions & 11 deletions data_layer/avail/avail.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@ func NewAvail(root string) *Avail {
panic(err)
}

daData, exists := consts.DaNetworks[daNetwork]
if !exists {
panic(fmt.Errorf("DA network configuration not found for: %s", daNetwork))
}
availConfig.RpcEndpoint = daData.ApiUrl
availConfig.AccAddress = keyringPair.Address
availConfig.Root = root

pterm.DefaultSection.WithIndentCharacter("🔔").Println("Please fund your Avail addresses below")
pterm.DefaultBasicText.Println(pterm.LightGreen(keyringPair.Address))

Expand All @@ -106,23 +114,15 @@ func NewAvail(root string) *Avail {

insufficientBalances, err := availConfig.CheckDABalance()
if err != nil {
pterm.Error.Println("failed to check balance", err)
panic(pterm.Error.Println("failed to check balance", err))
}

err = keys.PrintInsufficientBalancesIfAny(insufficientBalances)
if err != nil {
pterm.Error.Println("failed to check insufficient balances: ", err)
panic(pterm.Error.Println("failed to check insufficient balances: ", err))
}

daData, exists := consts.DaNetworks[daNetwork]
if !exists {
panic(fmt.Errorf("DA network configuration not found for: %s", daNetwork))
}
availConfig.RpcEndpoint = daData.ApiUrl
availConfig.AccAddress = keyringPair.Address
availConfig.Root = root

availConfig.AppID, err = CreateAppID(rollerData.DA.ApiUrl, availConfig.Mnemonic, rollerData.RollappID)
availConfig.AppID, err = CreateAppID(daData.ApiUrl, availConfig.Mnemonic, rollerData.RollappID)
if err != nil {
panic(err)
}
Expand Down
67 changes: 67 additions & 0 deletions utils/gov/param.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package gov

import (
"crypto/sha256"
"encoding/json"
"fmt"
"os"
"os/exec"
"path/filepath"

paramsutils "github.com/cosmos/cosmos-sdk/x/params/client/utils"
"github.com/dymensionxyz/roller/cmd/consts"
bashutils "github.com/dymensionxyz/roller/utils/bash"
"github.com/pterm/pterm"
)

type CosmosTx struct {
TxHash string `json:"txhash"`
Code int `json:"code"`
RawLog string `json:"raw_log"`
}

// ParamChangeProposal submits a param change proposal to the chain, signed by keyName.
func ParamChangeProposal(home, keyName, keyring string, prop *paramsutils.ParamChangeProposalJSON) (string, error) {
content, err := json.Marshal(prop)
if err != nil {
return "", err
}

hash := sha256.Sum256(content)
proposalFilename := fmt.Sprintf("%x.json", hash)
proposalPath := filepath.Join(home, proposalFilename)

err = os.WriteFile(proposalPath, content, 0o644)
if err != nil {
pterm.Error.Printf("Error writing prop file: %v\n", err)
return "", err
}

cmd := exec.Command(
consts.Executables.RollappEVM,
"tx", "gov", "submit-legacy-proposal",
"param-change",
proposalPath,
"--gas", "auto",
"--from", keyName,
"--keyring-backend", keyring,
"--output", "json",
"-y",
)

out, err := bashutils.ExecCommandWithStdout(cmd)
if err != nil {
return "", err
}

output := CosmosTx{}
err = json.Unmarshal(out.Bytes(), &output)
if err != nil {
return "", err
}
if output.Code != 0 {
return output.TxHash, fmt.Errorf("transaction failed with code %d: %s", output.Code, output.RawLog)
}

return output.TxHash, nil
}
20 changes: 10 additions & 10 deletions utils/rollapp/rollapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import (
)

const (
minEvmDRSNewDAConfig = "6"
minWasmDRSNewDAConfig = "9"
minEvmDRSNewDAConfig = 6
minWasmDRSNewDAConfig = 9
)

func GetHomeDir(home string) string {
Expand Down Expand Up @@ -310,25 +310,25 @@ func Show(raID string, hd consts.HubData) (*ShowRollappResponse, error) {
return &raResponse, nil
}

func IsDaConfigNewFormat(drsVersion string, evmType string) bool {
if drsVersion >= minEvmDRSNewDAConfig && "evm" == evmType ||
drsVersion >= minWasmDRSNewDAConfig && "wasm" == evmType {
func IsDaConfigNewFormat(drsVersion int64, vmType string) bool {
if drsVersion >= minEvmDRSNewDAConfig && "evm" == vmType ||
drsVersion >= minWasmDRSNewDAConfig && "wasm" == vmType {
return true
}
return false
}

func IsDAConfigMigrationRequired(oldDRS string, newDRS string, evmType string) bool {
if oldDRS >= minEvmDRSNewDAConfig && "evm" == evmType {
func IsDAConfigMigrationRequired(oldDRS int64, newDRS int64, vmType string) bool {
if oldDRS >= minEvmDRSNewDAConfig && "evm" == vmType {
return false
}
if oldDRS >= minWasmDRSNewDAConfig && "wasm" == evmType {
if oldDRS >= minWasmDRSNewDAConfig && "wasm" == vmType {
return false
}
if newDRS < minEvmDRSNewDAConfig && "evm" == evmType {
if newDRS < minEvmDRSNewDAConfig && "evm" == vmType {
return false
}
if newDRS < minWasmDRSNewDAConfig && "wasm" == evmType {
if newDRS < minWasmDRSNewDAConfig && "wasm" == vmType {
return false
}
return true
Expand Down
Loading