-
Notifications
You must be signed in to change notification settings - Fork 170
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
432 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package cmd | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"github.com/babylonchain/babylon/x/checkpointing/types" | ||
"github.com/cosmos/cosmos-sdk/client" | ||
"github.com/cosmos/cosmos-sdk/server" | ||
"github.com/cosmos/cosmos-sdk/types/module" | ||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" | ||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" | ||
"github.com/spf13/cobra" | ||
tmtypes "github.com/tendermint/tendermint/types" | ||
) | ||
|
||
const chainUpgradeGuide = "https://github.com/cosmos/cosmos-sdk/blob/main/UPGRADING.md" | ||
|
||
// ValidateGenesisCmd takes a genesis file, and makes sure that it is valid. | ||
// 1. genesis state of each module should be valid according to each module's | ||
// validation rule | ||
// 2. each genesis BLS key or gentx should have a corresponding gentx or genesis | ||
// BLS key | ||
// modified based on "github.com/cosmos/cosmos-sdk/x/genutil/client/cli/validate_genesis.go" | ||
func ValidateGenesisCmd(mbm module.BasicManager) *cobra.Command { | ||
return &cobra.Command{ | ||
Use: "validate-genesis [file]", | ||
Args: cobra.RangeArgs(0, 1), | ||
Short: "validates the genesis file at the default location or at the location passed as an arg", | ||
RunE: func(cmd *cobra.Command, args []string) (err error) { | ||
serverCtx := server.GetServerContextFromCmd(cmd) | ||
clientCtx := client.GetClientContextFromCmd(cmd) | ||
|
||
cdc := clientCtx.Codec | ||
|
||
// Load default if passed no args, otherwise load passed file | ||
var genesis string | ||
if len(args) == 0 { | ||
genesis = serverCtx.Config.GenesisFile() | ||
} else { | ||
genesis = args[0] | ||
} | ||
|
||
genDoc, err := validateGenDoc(genesis) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
var genState map[string]json.RawMessage | ||
if err = json.Unmarshal(genDoc.AppState, &genState); err != nil { | ||
return fmt.Errorf("error unmarshalling genesis doc %s: %s", genesis, err.Error()) | ||
} | ||
|
||
if err = mbm.ValidateGenesis(cdc, clientCtx.TxConfig, genState); err != nil { | ||
return fmt.Errorf("error validating genesis file %s: %s", genesis, err.Error()) | ||
} | ||
|
||
if err = CheckCorrespondence(clientCtx, genState); err != nil { | ||
return fmt.Errorf("error validating genesis file correspondence %s: %s", genesis, err.Error()) | ||
} | ||
|
||
fmt.Printf("File at %s is a valid genesis file\n", genesis) | ||
return nil | ||
}, | ||
} | ||
} | ||
|
||
// validateGenDoc reads a genesis file and validates that it is a correct | ||
// Tendermint GenesisDoc. This function does not do any cosmos-related | ||
// validation. | ||
func validateGenDoc(importGenesisFile string) (*tmtypes.GenesisDoc, error) { | ||
genDoc, err := tmtypes.GenesisDocFromFile(importGenesisFile) | ||
if err != nil { | ||
return nil, fmt.Errorf("%s. Make sure that"+ | ||
" you have correctly migrated all Tendermint consensus params, please see the"+ | ||
" chain migration guide at %s for more info", | ||
err.Error(), chainUpgradeGuide, | ||
) | ||
} | ||
|
||
return genDoc, nil | ||
} | ||
|
||
// CheckCorrespondence checks that each genesis tx/BLS key should have one | ||
// corresponding BLS key/genesis tx | ||
func CheckCorrespondence(ctx client.Context, genesis map[string]json.RawMessage) error { | ||
checkpointingGenState := types.GetGenesisStateFromAppState(ctx.Codec, genesis) | ||
gks := checkpointingGenState.GetGenesisKeys() | ||
genTxState := genutiltypes.GetGenesisStateFromAppState(ctx.Codec, genesis) | ||
addresses := make(map[string]struct{}, 0) | ||
for _, gk := range gks { | ||
addresses[gk.ValidatorAddress] = struct{}{} | ||
} | ||
if len(addresses) != len(gks) { | ||
return errors.New("duplicate genesis BLS keys") | ||
} | ||
if len(addresses) != len(genTxState.GenTxs) { | ||
return errors.New("genesis txs and genesis BLS keys do not match") | ||
} | ||
|
||
for _, genTx := range genTxState.GenTxs { | ||
tx, err := genutiltypes.ValidateAndGetGenTx(genTx, ctx.TxConfig.TxJSONDecoder()) | ||
if err != nil { | ||
return err | ||
} | ||
msgs := tx.GetMsgs() | ||
if len(msgs) == 0 { | ||
return errors.New("invalid genesis transaction") | ||
} | ||
msgCreateValidator := msgs[0].(*stakingtypes.MsgCreateValidator) | ||
if _, exists := addresses[msgCreateValidator.ValidatorAddress]; !exists { | ||
return errors.New("genesis txs and genesis BLS keys do not match") | ||
} | ||
} | ||
|
||
return nil | ||
} |
Oops, something went wrong.