Skip to content

Commit 1ee761d

Browse files
mergify[bot]zisckytac0turtle
authored andcommitted
feat(x/genutil): add better error messages for genesis validation (backport cosmos#21701) (cosmos#21708)
Co-authored-by: Eric Mokaya <4112301+ziscky@users.noreply.github.com> Co-authored-by: marbar3778 <marbar3778@yahoo.com>
1 parent 78f48ff commit 1ee761d

3 files changed

Lines changed: 74 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
4646
### Improvements
4747

4848
* (x/bank) [#21460](https://github.com/cosmos/cosmos-sdk/pull/21460) Added `Sender` attribute in `MsgMultiSend` event.
49+
* (genutil) [#21701](https://github.com/cosmos/cosmos-sdk/pull/21701) Improved error messages for genesis validation.
4950

5051
### Bug Fixes
5152

x/genutil/client/cli/validate_genesis.go

Lines changed: 22 additions & 4 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

@@ -37,24 +40,39 @@ func ValidateGenesisCmd(mbm module.BasicManager) *cobra.Command {
3740

3841
appGenesis, err := types.AppGenesisFromFile(genesis)
3942
if err != nil {
40-
return err
43+
return enrichUnmarshalError(err)
4144
}
4245

4346
if err := appGenesis.ValidateAndComplete(); err != nil {
4447
return fmt.Errorf("make sure that you have correctly migrated all CometBFT consensus params. Refer the UPGRADING.md (%s): %w", chainUpgradeGuide, err)
4548
}
4649

4750
var genState map[string]json.RawMessage
48-
if err = json.Unmarshal(appGenesis.AppState, &genState); err != nil {
49-
return fmt.Errorf("error unmarshalling genesis doc %s: %s", genesis, err.Error())
51+
if err := json.Unmarshal(appGenesis.AppState, &genState); err != nil {
52+
if strings.Contains(err.Error(), "unexpected end of JSON input") {
53+
return fmt.Errorf("app_state is missing in the genesis file: %s", err.Error())
54+
}
55+
return fmt.Errorf("error unmarshalling genesis doc %s: %w", genesis, err)
5056
}
5157

5258
if err = mbm.ValidateGenesis(cdc, clientCtx.TxConfig, genState); err != nil {
53-
return fmt.Errorf("error validating genesis file %s: %s", genesis, err.Error())
59+
errStr := fmt.Sprintf("error validating genesis file %s: %s", genesis, err.Error())
60+
if errors.Is(err, io.EOF) {
61+
errStr = fmt.Sprintf("%s: section is missing in the app_state", errStr)
62+
}
63+
return fmt.Errorf("%s", errStr)
5464
}
5565

5666
fmt.Fprintf(cmd.OutOrStdout(), "File at %s is a valid genesis file\n", genesis)
5767
return nil
5868
},
5969
}
6070
}
71+
72+
func enrichUnmarshalError(err error) error {
73+
var syntaxErr *json.SyntaxError
74+
if errors.As(err, &syntaxErr) {
75+
return fmt.Errorf("error at offset %d: %s", syntaxErr.Offset, syntaxErr.Error())
76+
}
77+
return err
78+
}

x/genutil/client/cli/validate_genesis_test.go

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
package cli_test
22

33
import (
4+
"encoding/json"
5+
"fmt"
6+
"io"
47
"os"
58
"testing"
69

710
"github.com/stretchr/testify/require"
811

912
"github.com/cosmos/cosmos-sdk/client"
13+
"github.com/cosmos/cosmos-sdk/codec"
1014
"github.com/cosmos/cosmos-sdk/testutil"
1115
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
16+
"github.com/cosmos/cosmos-sdk/types/module"
1217
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
1318
)
1419

@@ -33,14 +38,33 @@ var v037Exported = `{
3338

3439
func TestValidateGenesis(t *testing.T) {
3540
testCases := []struct {
36-
name string
37-
genesis string
38-
expErr bool
41+
name string
42+
genesis string
43+
expErrStr string
44+
basicManager module.BasicManager
3945
}{
46+
{
47+
"invalid json",
48+
`{"app_state": {x,}}`,
49+
"error at offset 16: invalid character",
50+
module.NewBasicManager(),
51+
},
52+
{
53+
"invalid: missing module config in app_state",
54+
func() string {
55+
bz, err := os.ReadFile("../../types/testdata/app_genesis.json")
56+
require.NoError(t, err)
57+
58+
return string(bz)
59+
}(),
60+
"section is missing in the app_state",
61+
module.NewBasicManager(mockModule{}),
62+
},
4063
{
4164
"exported 0.37 genesis file",
4265
v037Exported,
43-
true,
66+
"make sure that you have correctly migrated all CometBFT consensus params",
67+
module.NewBasicManager(),
4468
},
4569
{
4670
"valid 0.50 genesis file",
@@ -50,7 +74,8 @@ func TestValidateGenesis(t *testing.T) {
5074

5175
return string(bz)
5276
}(),
53-
false,
77+
"",
78+
module.NewBasicManager(),
5479
},
5580
}
5681

@@ -59,12 +84,30 @@ func TestValidateGenesis(t *testing.T) {
5984

6085
t.Run(tc.name, func(t *testing.T) {
6186
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")
87+
_, err := clitestutil.ExecTestCLICmd(client.Context{}, cli.ValidateGenesisCmd(tc.basicManager), []string{genesisFile.Name()})
88+
if tc.expErrStr != "" {
89+
require.Contains(t, err.Error(), tc.expErrStr)
6590
} else {
6691
require.NoError(t, err)
6792
}
6893
})
6994
}
7095
}
96+
97+
var _ module.HasGenesisBasics = mockModule{}
98+
99+
type mockModule struct {
100+
module.AppModuleBasic
101+
}
102+
103+
func (m mockModule) Name() string {
104+
return "mock"
105+
}
106+
107+
func (m mockModule) DefaultGenesis(codec.JSONCodec) json.RawMessage {
108+
return json.RawMessage(`{"foo": "bar"}`)
109+
}
110+
111+
func (m mockModule) ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage) error {
112+
return fmt.Errorf("mock section is missing: %w", io.EOF)
113+
}

0 commit comments

Comments
 (0)