diff --git a/chain/cosmos/chain_node.go b/chain/cosmos/chain_node.go index 623f37c77..cbe1d9fda 100644 --- a/chain/cosmos/chain_node.go +++ b/chain/cosmos/chain_node.go @@ -1043,10 +1043,32 @@ func (tn *ChainNode) ExportState(ctx context.Context, height int64) (string, err tn.lock.Lock() defer tn.lock.Unlock() - stdout, stderr, err := tn.ExecBin(ctx, "export", "--height", fmt.Sprint(height)) + var ( + doc = "state_export.json" + docPath = path.Join(tn.HomeDir(), doc) + + isNewGenesis = tn.Chain.Config().UsingNewGenesisCommand + + command = []string{"export", "--height", fmt.Sprint(height), "--home", tn.HomeDir()} + ) + + if isNewGenesis { + command = append(command, "--output-document", docPath) + } + + stdout, stderr, err := tn.ExecBin(ctx, command...) if err != nil { return "", err } + + if isNewGenesis { + content, err := tn.ReadFile(ctx, doc) + if err != nil { + return "", err + } + return string(content), nil + } + // output comes to stderr on older versions return string(stdout) + string(stderr), nil } diff --git a/examples/cosmos/chain_export_test.go b/examples/cosmos/chain_export_test.go new file mode 100644 index 000000000..200cff2eb --- /dev/null +++ b/examples/cosmos/chain_export_test.go @@ -0,0 +1,116 @@ +package cosmos_test + +import ( + "context" + "testing" + "time" + + "github.com/strangelove-ventures/interchaintest/v8" + "github.com/strangelove-ventures/interchaintest/v8/chain/cosmos" + "github.com/strangelove-ventures/interchaintest/v8/ibc" + "github.com/strangelove-ventures/interchaintest/v8/testutil" + "github.com/stretchr/testify/require" + "go.uber.org/zap" + "go.uber.org/zap/zaptest" +) + +func TestJunoStateExport(t *testing.T) { + // SDK v45 + CosmosChainStateExportTest(t, "juno", "v15.0.0", false) + // SDK v47 + CosmosChainStateExportTest(t, "juno", "v16.0.0", true) +} + +func CosmosChainStateExportTest(t *testing.T, name, version string, useNewGenesisCmd bool) { + if testing.Short() { + t.Skip("skipping in short mode") + } + + numVals := 1 + numFullNodes := 0 + + cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{ + { + Name: name, + ChainName: name, + Version: version, + ChainConfig: ibc.ChainConfig{ + Denom: "ujuno", + UsingNewGenesisCommand: useNewGenesisCmd, + }, + NumValidators: &numVals, + NumFullNodes: &numFullNodes, + }, + }) + + chains, err := cf.Chains(t.Name()) + require.NoError(t, err) + + chain := chains[0].(*cosmos.CosmosChain) + + ic := interchaintest.NewInterchain(). + AddChain(chain) + + ctx := context.Background() + client, network := interchaintest.DockerSetup(t) + + require.NoError(t, ic.Build(ctx, nil, interchaintest.InterchainBuildOptions{ + TestName: t.Name(), + Client: client, + NetworkID: network, + SkipPathCreation: true, + })) + t.Cleanup(func() { + _ = ic.Close() + }) + + HaltChainAndExportGenesis(ctx, t, chain, nil, 3) +} + +func HaltChainAndExportGenesis(ctx context.Context, t *testing.T, chain *cosmos.CosmosChain, relayer ibc.Relayer, haltHeight int64) { + timeoutCtx, timeoutCtxCancel := context.WithTimeout(ctx, time.Minute*2) + defer timeoutCtxCancel() + + err := testutil.WaitForBlocks(timeoutCtx, int(haltHeight), chain) + require.NoError(t, err, "chain did not halt at halt height") + + err = chain.StopAllNodes(ctx) + require.NoError(t, err, "error stopping node(s)") + + state, err := chain.ExportState(ctx, int64(haltHeight)) + require.NoError(t, err, "error exporting state") + + appToml := make(testutil.Toml) + + for _, node := range chain.Nodes() { + err := node.OverwriteGenesisFile(ctx, []byte(state)) + require.NoError(t, err) + } + + for _, node := range chain.Nodes() { + err := testutil.ModifyTomlConfigFile( + ctx, + zap.NewExample(), + node.DockerClient, + node.TestName, + node.VolumeName, + "config/app.toml", + appToml, + ) + require.NoError(t, err) + } + + err = chain.StartAllNodes(ctx) + require.NoError(t, err, "error starting node(s)") + + timeoutCtx, timeoutCtxCancel = context.WithTimeout(ctx, time.Minute*2) + defer timeoutCtxCancel() + + err = testutil.WaitForBlocks(timeoutCtx, int(5), chain) + require.NoError(t, err, "chain did not produce blocks after halt") + + height, err := chain.Height(ctx) + require.NoError(t, err, "error getting height after halt") + + require.Greater(t, int64(height), haltHeight, "height did not increment after halt") +}