Skip to content

Commit 9c5cea0

Browse files
authored
feat(x/genutil): add better error messages for genesis validation (#21701)
1 parent 90d81f0 commit 9c5cea0

3 files changed

Lines changed: 60 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i
4646

4747
### Improvements
4848

49+
* (genutil) [#21701](https://github.com/cosmos/cosmos-sdk/pull/21701) Improved error messages for genesis validation.
50+
4951
### Bug Fixes
5052

5153
* (baseapp) [#21256](https://github.com/cosmos/cosmos-sdk/pull/21256) Halt height will not commit the block indicated, meaning that if halt-height is set to 10, only blocks until 9 (included) will be committed. This is to go back to the original behavior before a change was introduced in v0.50.0.

x/genutil/client/cli/validate_genesis.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ package cli
22

33
import (
44
"encoding/json"
5+
"errors"
56
"fmt"
7+
"io"
8+
"strings"
69

710
"github.com/spf13/cobra"
811

@@ -32,7 +35,7 @@ func ValidateGenesisCmd(genMM genesisMM) *cobra.Command {
3235

3336
appGenesis, err := types.AppGenesisFromFile(genesis)
3437
if err != nil {
35-
return err
38+
return enrichUnmarshalError(err)
3639
}
3740

3841
if err := appGenesis.ValidateAndComplete(); err != nil {
@@ -41,12 +44,19 @@ func ValidateGenesisCmd(genMM genesisMM) *cobra.Command {
4144

4245
var genState map[string]json.RawMessage
4346
if err = json.Unmarshal(appGenesis.AppState, &genState); err != nil {
47+
if strings.Contains(err.Error(), "unexpected end of JSON input") {
48+
return fmt.Errorf("app_state is missing in the genesis file: %s", err.Error())
49+
}
4450
return fmt.Errorf("error unmarshalling genesis doc %s: %w", genesis, err)
4551
}
4652

4753
if genMM != nil {
4854
if err = genMM.ValidateGenesis(genState); err != nil {
49-
return fmt.Errorf("error validating genesis file %s: %w", genesis, err)
55+
errStr := fmt.Sprintf("error validating genesis file %s: %s", genesis, err.Error())
56+
if errors.Is(err, io.EOF) {
57+
errStr = fmt.Sprintf("%s: section is missing in the app_state", errStr)
58+
}
59+
return fmt.Errorf("%s", errStr)
5060
}
5161
}
5262

@@ -55,3 +65,11 @@ func ValidateGenesisCmd(genMM genesisMM) *cobra.Command {
5565
},
5666
}
5767
}
68+
69+
func enrichUnmarshalError(err error) error {
70+
var syntaxErr *json.SyntaxError
71+
if errors.As(err, &syntaxErr) {
72+
return fmt.Errorf("error at offset %d: %s", syntaxErr.Offset, syntaxErr.Error())
73+
}
74+
return err
75+
}

x/genutil/client/cli/validate_genesis_test.go

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,16 @@ import (
66

77
"github.com/stretchr/testify/require"
88

9+
appmodulev2 "cosmossdk.io/core/appmodule/v2"
10+
"cosmossdk.io/x/staking"
11+
912
"github.com/cosmos/cosmos-sdk/client"
13+
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
1014
"github.com/cosmos/cosmos-sdk/testutil"
1115
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
16+
"github.com/cosmos/cosmos-sdk/types/module"
17+
testutilmod "github.com/cosmos/cosmos-sdk/types/module/testutil"
18+
"github.com/cosmos/cosmos-sdk/x/genutil"
1219
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
1320
)
1421

@@ -32,15 +39,37 @@ var v037Exported = `{
3239
}`
3340

3441
func TestValidateGenesis(t *testing.T) {
42+
cdc := testutilmod.MakeTestEncodingConfig(codectestutil.CodecOptions{}, genutil.AppModule{}).Codec
3543
testCases := []struct {
36-
name string
37-
genesis string
38-
expErr bool
44+
name string
45+
genesis string
46+
expErrStr string
47+
genMM *module.Manager
3948
}{
49+
{
50+
"invalid json",
51+
`{"app_state": {x,}}`,
52+
"error at offset 16: invalid character",
53+
module.NewManagerFromMap(nil),
54+
},
55+
{
56+
"invalid: missing module config in app_state",
57+
func() string {
58+
bz, err := os.ReadFile("../../types/testdata/app_genesis.json")
59+
require.NoError(t, err)
60+
61+
return string(bz)
62+
}(),
63+
"section is missing in the app_state",
64+
module.NewManagerFromMap(map[string]appmodulev2.AppModule{
65+
"custommod": staking.NewAppModule(cdc, nil, nil, nil),
66+
}),
67+
},
4068
{
4169
"exported 0.37 genesis file",
4270
v037Exported,
43-
true,
71+
"make sure that you have correctly migrated all CometBFT consensus params",
72+
module.NewManagerFromMap(nil),
4473
},
4574
{
4675
"valid 0.50 genesis file",
@@ -50,7 +79,8 @@ func TestValidateGenesis(t *testing.T) {
5079

5180
return string(bz)
5281
}(),
53-
false,
82+
"",
83+
module.NewManagerFromMap(nil),
5484
},
5585
}
5686

@@ -59,9 +89,9 @@ func TestValidateGenesis(t *testing.T) {
5989

6090
t.Run(tc.name, func(t *testing.T) {
6191
genesisFile := testutil.WriteToNewTempFile(t, tc.genesis)
62-
_, err := clitestutil.ExecTestCLICmd(client.Context{}, cli.ValidateGenesisCmd(nil), []string{genesisFile.Name()})
63-
if tc.expErr {
64-
require.Contains(t, err.Error(), "make sure that you have correctly migrated all CometBFT consensus params")
92+
_, err := clitestutil.ExecTestCLICmd(client.Context{}, cli.ValidateGenesisCmd(tc.genMM), []string{genesisFile.Name()})
93+
if tc.expErrStr != "" {
94+
require.Contains(t, err.Error(), tc.expErrStr)
6595
} else {
6696
require.NoError(t, err)
6797
}

0 commit comments

Comments
 (0)