From c9ec0ff0870fd2a3220869b7b94a412a29ec8017 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Thu, 14 May 2020 18:47:11 -0400 Subject: [PATCH] x/ibc: default genesis state for sims (#6158) * x/ibc: default genesis state for sims * add ibc and transfer module to simulations * minor update * remove TODO * add validation to transfer genesis * fix transfer init genesis * address @alexanderbez comments --- simapp/app.go | 2 + simapp/sim_test.go | 4 ++ x/ibc/02-client/simulation/genesis.go | 13 +++++ x/ibc/02-client/types/genesis.go | 2 +- x/ibc/03-connection/simulation/genesis.go | 13 +++++ x/ibc/03-connection/types/connection.go | 8 +-- x/ibc/03-connection/types/genesis.go | 4 +- x/ibc/03-connection/types/msgs.go | 12 ++--- x/ibc/04-channel/simulation/genesis.go | 13 +++++ x/ibc/04-channel/types/channel.go | 10 ++-- x/ibc/04-channel/types/genesis.go | 4 +- x/ibc/04-channel/types/msgs.go | 24 ++++----- x/ibc/04-channel/types/packet.go | 8 +-- x/ibc/05-port/keeper/keeper.go | 4 +- x/ibc/07-tendermint/types/client_state.go | 2 +- x/ibc/07-tendermint/types/evidence.go | 2 +- x/ibc/07-tendermint/types/msgs.go | 4 +- x/ibc/09-localhost/types/client_state.go | 2 +- x/ibc/20-transfer/genesis.go | 6 +-- x/ibc/20-transfer/keeper/keeper.go | 12 +++-- x/ibc/20-transfer/module.go | 45 +++++++++++++++-- x/ibc/20-transfer/simulation/genesis.go | 31 ++++++++++++ x/ibc/20-transfer/types/genesis.go | 15 +++++- x/ibc/20-transfer/types/genesis_test.go | 47 ++++++++++++++++++ x/ibc/20-transfer/types/keys.go | 8 +-- x/ibc/20-transfer/types/msgs.go | 4 +- x/ibc/23-commitment/types/merkle.go | 2 +- x/ibc/24-host/validate.go | 23 +++++---- x/ibc/module.go | 39 +++++++++++++-- x/ibc/simulation/genesis.go | 60 +++++++++++++++++++++++ 30 files changed, 344 insertions(+), 79 deletions(-) create mode 100644 x/ibc/02-client/simulation/genesis.go create mode 100644 x/ibc/03-connection/simulation/genesis.go create mode 100644 x/ibc/04-channel/simulation/genesis.go create mode 100644 x/ibc/20-transfer/simulation/genesis.go create mode 100644 x/ibc/20-transfer/types/genesis_test.go create mode 100644 x/ibc/simulation/genesis.go diff --git a/simapp/app.go b/simapp/app.go index 20bdcd1be0..793afdff4e 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -320,6 +320,8 @@ func NewSimApp( slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), params.NewAppModule(app.ParamsKeeper), evidence.NewAppModule(app.EvidenceKeeper), + ibc.NewAppModule(app.IBCKeeper), + transferModule, ) app.sm.RegisterStoreDecoders() diff --git a/simapp/sim_test.go b/simapp/sim_test.go index ef441193b6..1e75bec34a 100644 --- a/simapp/sim_test.go +++ b/simapp/sim_test.go @@ -23,6 +23,8 @@ import ( distr "github.com/cosmos/cosmos-sdk/x/distribution" "github.com/cosmos/cosmos-sdk/x/evidence" "github.com/cosmos/cosmos-sdk/x/gov" + "github.com/cosmos/cosmos-sdk/x/ibc" + transfer "github.com/cosmos/cosmos-sdk/x/ibc/20-transfer" "github.com/cosmos/cosmos-sdk/x/mint" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" "github.com/cosmos/cosmos-sdk/x/simulation" @@ -160,6 +162,8 @@ func TestAppImportExport(t *testing.T) { {app.keys[gov.StoreKey], newApp.keys[gov.StoreKey], [][]byte{}}, {app.keys[evidence.StoreKey], newApp.keys[evidence.StoreKey], [][]byte{}}, {app.keys[capability.StoreKey], newApp.keys[capability.StoreKey], [][]byte{}}, + {app.keys[ibc.StoreKey], newApp.keys[ibc.StoreKey], [][]byte{}}, + {app.keys[transfer.StoreKey], newApp.keys[transfer.StoreKey], [][]byte{}}, } for _, skp := range storeKeysPrefixes { diff --git a/x/ibc/02-client/simulation/genesis.go b/x/ibc/02-client/simulation/genesis.go new file mode 100644 index 0000000000..314faab8c1 --- /dev/null +++ b/x/ibc/02-client/simulation/genesis.go @@ -0,0 +1,13 @@ +package simulation + +import ( + "math/rand" + + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" +) + +// GenClientGenesis returns the default client genesis state. +func GenClientGenesis(_ *rand.Rand, _ []simtypes.Account) types.GenesisState { + return types.DefaultGenesisState() +} diff --git a/x/ibc/02-client/types/genesis.go b/x/ibc/02-client/types/genesis.go index 43c3a1af50..38343a8cf6 100644 --- a/x/ibc/02-client/types/genesis.go +++ b/x/ibc/02-client/types/genesis.go @@ -58,7 +58,7 @@ func (gs GenesisState) Validate() error { } for i, cs := range gs.ClientsConsensus { - if err := host.DefaultClientIdentifierValidator(cs.ClientID); err != nil { + if err := host.ClientIdentifierValidator(cs.ClientID); err != nil { return fmt.Errorf("invalid client consensus state %d: %w", i, err) } for _, consensusState := range cs.ConsensusStates { diff --git a/x/ibc/03-connection/simulation/genesis.go b/x/ibc/03-connection/simulation/genesis.go new file mode 100644 index 0000000000..1d49ba57a0 --- /dev/null +++ b/x/ibc/03-connection/simulation/genesis.go @@ -0,0 +1,13 @@ +package simulation + +import ( + "math/rand" + + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types" +) + +// GenConnectionGenesis returns the default connection genesis state. +func GenConnectionGenesis(_ *rand.Rand, _ []simtypes.Account) types.GenesisState { + return types.DefaultGenesisState() +} diff --git a/x/ibc/03-connection/types/connection.go b/x/ibc/03-connection/types/connection.go index 3d88538681..66d9c01548 100644 --- a/x/ibc/03-connection/types/connection.go +++ b/x/ibc/03-connection/types/connection.go @@ -52,10 +52,10 @@ func (c ConnectionEnd) GetVersions() []string { // NOTE: the protocol supports that the connection and client IDs match the // counterparty's. func (c ConnectionEnd) ValidateBasic() error { - if err := host.DefaultConnectionIdentifierValidator(c.ID); err != nil { + if err := host.ConnectionIdentifierValidator(c.ID); err != nil { return sdkerrors.Wrapf(err, "invalid connection ID: %s", c.ID) } - if err := host.DefaultClientIdentifierValidator(c.ClientID); err != nil { + if err := host.ClientIdentifierValidator(c.ClientID); err != nil { return sdkerrors.Wrapf(err, "invalid client ID: %s", c.ClientID) } if len(c.Versions) == 0 { @@ -97,7 +97,7 @@ func (c Counterparty) GetPrefix() commitmentexported.Prefix { // ValidateBasic performs a basic validation check of the identifiers and prefix func (c Counterparty) ValidateBasic() error { - if err := host.DefaultConnectionIdentifierValidator(c.ConnectionID); err != nil { + if err := host.ConnectionIdentifierValidator(c.ConnectionID); err != nil { return sdkerrors.Wrap(err, sdkerrors.Wrapf( ErrInvalidCounterparty, @@ -105,7 +105,7 @@ func (c Counterparty) ValidateBasic() error { ).Error(), ) } - if err := host.DefaultClientIdentifierValidator(c.ClientID); err != nil { + if err := host.ClientIdentifierValidator(c.ClientID); err != nil { return sdkerrors.Wrap(err, sdkerrors.Wrapf( ErrInvalidCounterparty, diff --git a/x/ibc/03-connection/types/genesis.go b/x/ibc/03-connection/types/genesis.go index 8bc9a615d3..bec90f6949 100644 --- a/x/ibc/03-connection/types/genesis.go +++ b/x/ibc/03-connection/types/genesis.go @@ -54,11 +54,11 @@ func (gs GenesisState) Validate() error { } for i, conPaths := range gs.ClientConnectionPaths { - if err := host.DefaultClientIdentifierValidator(conPaths.ClientID); err != nil { + if err := host.ClientIdentifierValidator(conPaths.ClientID); err != nil { return fmt.Errorf("invalid client connection path %d: %w", i, err) } for _, path := range conPaths.Paths { - if err := host.DefaultPathValidator(path); err != nil { + if err := host.PathValidator(path); err != nil { return fmt.Errorf("invalid client connection path %d: %w", i, err) } } diff --git a/x/ibc/03-connection/types/msgs.go b/x/ibc/03-connection/types/msgs.go index 305496207d..f459abd6c9 100644 --- a/x/ibc/03-connection/types/msgs.go +++ b/x/ibc/03-connection/types/msgs.go @@ -38,10 +38,10 @@ func (msg MsgConnectionOpenInit) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgConnectionOpenInit) ValidateBasic() error { - if err := host.DefaultConnectionIdentifierValidator(msg.ConnectionID); err != nil { + if err := host.ConnectionIdentifierValidator(msg.ConnectionID); err != nil { return sdkerrors.Wrapf(err, "invalid connection ID: %s", msg.ConnectionID) } - if err := host.DefaultClientIdentifierValidator(msg.ClientID); err != nil { + if err := host.ClientIdentifierValidator(msg.ClientID); err != nil { return sdkerrors.Wrapf(err, "invalid client ID: %s", msg.ClientID) } if msg.Signer.Empty() { @@ -95,10 +95,10 @@ func (msg MsgConnectionOpenTry) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgConnectionOpenTry) ValidateBasic() error { - if err := host.DefaultConnectionIdentifierValidator(msg.ConnectionID); err != nil { + if err := host.ConnectionIdentifierValidator(msg.ConnectionID); err != nil { return sdkerrors.Wrapf(err, "invalid connection ID: %s", msg.ConnectionID) } - if err := host.DefaultClientIdentifierValidator(msg.ClientID); err != nil { + if err := host.ClientIdentifierValidator(msg.ClientID); err != nil { return sdkerrors.Wrapf(err, "invalid client ID: %s", msg.ClientID) } if len(msg.CounterpartyVersions) == 0 { @@ -171,7 +171,7 @@ func (msg MsgConnectionOpenAck) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgConnectionOpenAck) ValidateBasic() error { - if err := host.DefaultConnectionIdentifierValidator(msg.ConnectionID); err != nil { + if err := host.ConnectionIdentifierValidator(msg.ConnectionID); err != nil { return sdkerrors.Wrap(err, "invalid connection ID") } if strings.TrimSpace(msg.Version) == "" { @@ -235,7 +235,7 @@ func (msg MsgConnectionOpenConfirm) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgConnectionOpenConfirm) ValidateBasic() error { - if err := host.DefaultConnectionIdentifierValidator(msg.ConnectionID); err != nil { + if err := host.ConnectionIdentifierValidator(msg.ConnectionID); err != nil { return sdkerrors.Wrap(err, "invalid connection ID") } if msg.ProofAck.IsEmpty() { diff --git a/x/ibc/04-channel/simulation/genesis.go b/x/ibc/04-channel/simulation/genesis.go new file mode 100644 index 0000000000..42808ed39d --- /dev/null +++ b/x/ibc/04-channel/simulation/genesis.go @@ -0,0 +1,13 @@ +package simulation + +import ( + "math/rand" + + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types" +) + +// GenChannelGenesis returns the default channel genesis state. +func GenChannelGenesis(_ *rand.Rand, _ []simtypes.Account) types.GenesisState { + return types.DefaultGenesisState() +} diff --git a/x/ibc/04-channel/types/channel.go b/x/ibc/04-channel/types/channel.go index 6f99a296ef..3032ef9870 100644 --- a/x/ibc/04-channel/types/channel.go +++ b/x/ibc/04-channel/types/channel.go @@ -66,7 +66,7 @@ func (ch Channel) ValidateBasic() error { sdkerrors.Wrap(ErrTooManyConnectionHops, "IBC v1.0 only supports one connection hop").Error(), ) } - if err := host.DefaultConnectionIdentifierValidator(ch.ConnectionHops[0]); err != nil { + if err := host.ConnectionIdentifierValidator(ch.ConnectionHops[0]); err != nil { return sdkerrors.Wrap( ErrInvalidChannel, sdkerrors.Wrap(err, "invalid connection hop ID").Error(), @@ -101,13 +101,13 @@ func (c Counterparty) GetChannelID() string { // ValidateBasic performs a basic validation check of the identifiers func (c Counterparty) ValidateBasic() error { - if err := host.DefaultPortIdentifierValidator(c.PortID); err != nil { + if err := host.PortIdentifierValidator(c.PortID); err != nil { return sdkerrors.Wrap( ErrInvalidCounterparty, sdkerrors.Wrap(err, "invalid counterparty connection ID").Error(), ) } - if err := host.DefaultChannelIdentifierValidator(c.ChannelID); err != nil { + if err := host.ChannelIdentifierValidator(c.ChannelID); err != nil { return sdkerrors.Wrap( ErrInvalidCounterparty, sdkerrors.Wrap(err, "invalid counterparty client ID").Error(), @@ -143,10 +143,10 @@ func NewIdentifiedChannel(portID, channelID string, ch Channel) IdentifiedChanne // ValidateBasic performs a basic validation of the identifiers and channel fields. func (ic IdentifiedChannel) ValidateBasic() error { - if err := host.DefaultChannelIdentifierValidator(ic.ID); err != nil { + if err := host.ChannelIdentifierValidator(ic.ID); err != nil { return sdkerrors.Wrap(ErrInvalidChannel, err.Error()) } - if err := host.DefaultPortIdentifierValidator(ic.PortID); err != nil { + if err := host.PortIdentifierValidator(ic.PortID); err != nil { return sdkerrors.Wrap(ErrInvalidChannel, err.Error()) } channel := NewChannel(ic.State, ic.Ordering, ic.Counterparty, ic.ConnectionHops, ic.Version) diff --git a/x/ibc/04-channel/types/genesis.go b/x/ibc/04-channel/types/genesis.go index 8e426a06ac..15fb092b8a 100644 --- a/x/ibc/04-channel/types/genesis.go +++ b/x/ibc/04-channel/types/genesis.go @@ -129,10 +129,10 @@ func (gs GenesisState) Validate() error { } func validateGenFields(portID, channelID string, sequence uint64) error { - if err := host.DefaultPortIdentifierValidator(portID); err != nil { + if err := host.PortIdentifierValidator(portID); err != nil { return err } - if err := host.DefaultChannelIdentifierValidator(channelID); err != nil { + if err := host.ChannelIdentifierValidator(channelID); err != nil { return err } if sequence == 0 { diff --git a/x/ibc/04-channel/types/msgs.go b/x/ibc/04-channel/types/msgs.go index 93b5dd83a2..1c3c617acb 100644 --- a/x/ibc/04-channel/types/msgs.go +++ b/x/ibc/04-channel/types/msgs.go @@ -39,10 +39,10 @@ func (msg MsgChannelOpenInit) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgChannelOpenInit) ValidateBasic() error { - if err := host.DefaultPortIdentifierValidator(msg.PortID); err != nil { + if err := host.PortIdentifierValidator(msg.PortID); err != nil { return sdkerrors.Wrap(err, "invalid port ID") } - if err := host.DefaultChannelIdentifierValidator(msg.ChannelID); err != nil { + if err := host.ChannelIdentifierValidator(msg.ChannelID); err != nil { return sdkerrors.Wrap(err, "invalid channel ID") } // Signer can be empty @@ -92,10 +92,10 @@ func (msg MsgChannelOpenTry) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgChannelOpenTry) ValidateBasic() error { - if err := host.DefaultPortIdentifierValidator(msg.PortID); err != nil { + if err := host.PortIdentifierValidator(msg.PortID); err != nil { return sdkerrors.Wrap(err, "invalid port ID") } - if err := host.DefaultChannelIdentifierValidator(msg.ChannelID); err != nil { + if err := host.ChannelIdentifierValidator(msg.ChannelID); err != nil { return sdkerrors.Wrap(err, "invalid channel ID") } if strings.TrimSpace(msg.CounterpartyVersion) == "" { @@ -153,10 +153,10 @@ func (msg MsgChannelOpenAck) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgChannelOpenAck) ValidateBasic() error { - if err := host.DefaultPortIdentifierValidator(msg.PortID); err != nil { + if err := host.PortIdentifierValidator(msg.PortID); err != nil { return sdkerrors.Wrap(err, "invalid port ID") } - if err := host.DefaultChannelIdentifierValidator(msg.ChannelID); err != nil { + if err := host.ChannelIdentifierValidator(msg.ChannelID); err != nil { return sdkerrors.Wrap(err, "invalid channel ID") } if strings.TrimSpace(msg.CounterpartyVersion) == "" { @@ -213,10 +213,10 @@ func (msg MsgChannelOpenConfirm) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgChannelOpenConfirm) ValidateBasic() error { - if err := host.DefaultPortIdentifierValidator(msg.PortID); err != nil { + if err := host.PortIdentifierValidator(msg.PortID); err != nil { return sdkerrors.Wrap(err, "invalid port ID") } - if err := host.DefaultChannelIdentifierValidator(msg.ChannelID); err != nil { + if err := host.ChannelIdentifierValidator(msg.ChannelID); err != nil { return sdkerrors.Wrap(err, "invalid channel ID") } if msg.ProofAck.IsEmpty() { @@ -267,10 +267,10 @@ func (msg MsgChannelCloseInit) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgChannelCloseInit) ValidateBasic() error { - if err := host.DefaultPortIdentifierValidator(msg.PortID); err != nil { + if err := host.PortIdentifierValidator(msg.PortID); err != nil { return sdkerrors.Wrap(err, "invalid port ID") } - if err := host.DefaultChannelIdentifierValidator(msg.ChannelID); err != nil { + if err := host.ChannelIdentifierValidator(msg.ChannelID); err != nil { return sdkerrors.Wrap(err, "invalid channel ID") } // Signer can be empty @@ -315,10 +315,10 @@ func (msg MsgChannelCloseConfirm) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgChannelCloseConfirm) ValidateBasic() error { - if err := host.DefaultPortIdentifierValidator(msg.PortID); err != nil { + if err := host.PortIdentifierValidator(msg.PortID); err != nil { return sdkerrors.Wrap(err, "invalid port ID") } - if err := host.DefaultChannelIdentifierValidator(msg.ChannelID); err != nil { + if err := host.ChannelIdentifierValidator(msg.ChannelID); err != nil { return sdkerrors.Wrap(err, "invalid channel ID") } if msg.ProofInit.IsEmpty() { diff --git a/x/ibc/04-channel/types/packet.go b/x/ibc/04-channel/types/packet.go index 626ffae89f..d271b98567 100644 --- a/x/ibc/04-channel/types/packet.go +++ b/x/ibc/04-channel/types/packet.go @@ -71,25 +71,25 @@ func (p Packet) GetTimeoutTimestamp() uint64 { return p.TimeoutTimestamp } // ValidateBasic implements PacketI interface func (p Packet) ValidateBasic() error { - if err := host.DefaultPortIdentifierValidator(p.SourcePort); err != nil { + if err := host.PortIdentifierValidator(p.SourcePort); err != nil { return sdkerrors.Wrapf( ErrInvalidPacket, sdkerrors.Wrapf(err, "invalid source port ID: %s", p.SourcePort).Error(), ) } - if err := host.DefaultPortIdentifierValidator(p.DestinationPort); err != nil { + if err := host.PortIdentifierValidator(p.DestinationPort); err != nil { return sdkerrors.Wrapf( ErrInvalidPacket, sdkerrors.Wrapf(err, "invalid destination port ID: %s", p.DestinationPort).Error(), ) } - if err := host.DefaultChannelIdentifierValidator(p.SourceChannel); err != nil { + if err := host.ChannelIdentifierValidator(p.SourceChannel); err != nil { return sdkerrors.Wrapf( ErrInvalidPacket, sdkerrors.Wrapf(err, "invalid source channel ID: %s", p.SourceChannel).Error(), ) } - if err := host.DefaultChannelIdentifierValidator(p.DestinationChannel); err != nil { + if err := host.ChannelIdentifierValidator(p.DestinationChannel); err != nil { return sdkerrors.Wrapf( ErrInvalidPacket, sdkerrors.Wrapf(err, "invalid destination channel ID: %s", p.DestinationChannel).Error(), diff --git a/x/ibc/05-port/keeper/keeper.go b/x/ibc/05-port/keeper/keeper.go index aa64e6e1c1..4d052ebc10 100644 --- a/x/ibc/05-port/keeper/keeper.go +++ b/x/ibc/05-port/keeper/keeper.go @@ -39,7 +39,7 @@ func (k Keeper) isBound(ctx sdk.Context, portID string) bool { // The capability must then be passed to a module which will need to pass // it as an extra parameter when calling functions on the IBC module. func (k *Keeper) BindPort(ctx sdk.Context, portID string) *capability.Capability { - if err := host.DefaultPortIdentifierValidator(portID); err != nil { + if err := host.PortIdentifierValidator(portID); err != nil { panic(err.Error()) } @@ -61,7 +61,7 @@ func (k *Keeper) BindPort(ctx sdk.Context, portID string) *capability.Capability // generated and bound to the port (provided as a parameter) which the capability // is being authenticated against. func (k Keeper) Authenticate(ctx sdk.Context, key *capability.Capability, portID string) bool { - if err := host.DefaultPortIdentifierValidator(portID); err != nil { + if err := host.PortIdentifierValidator(portID); err != nil { panic(err.Error()) } diff --git a/x/ibc/07-tendermint/types/client_state.go b/x/ibc/07-tendermint/types/client_state.go index 0807208930..7bcb6129e2 100644 --- a/x/ibc/07-tendermint/types/client_state.go +++ b/x/ibc/07-tendermint/types/client_state.go @@ -127,7 +127,7 @@ func (cs ClientState) IsFrozen() bool { // Validate performs a basic validation of the client state fields. func (cs ClientState) Validate() error { - if err := host.DefaultClientIdentifierValidator(cs.ID); err != nil { + if err := host.ClientIdentifierValidator(cs.ID); err != nil { return err } if err := lite.ValidateTrustLevel(cs.TrustLevel); err != nil { diff --git a/x/ibc/07-tendermint/types/evidence.go b/x/ibc/07-tendermint/types/evidence.go index d161c10ed5..ebfe518794 100644 --- a/x/ibc/07-tendermint/types/evidence.go +++ b/x/ibc/07-tendermint/types/evidence.go @@ -75,7 +75,7 @@ func (ev Evidence) GetHeight() int64 { // ValidateBasic implements Evidence interface func (ev Evidence) ValidateBasic() error { - if err := host.DefaultClientIdentifierValidator(ev.ClientID); err != nil { + if err := host.ClientIdentifierValidator(ev.ClientID); err != nil { return sdkerrors.Wrap(clienttypes.ErrInvalidEvidence, err.Error()) } diff --git a/x/ibc/07-tendermint/types/msgs.go b/x/ibc/07-tendermint/types/msgs.go index b4f8005fd6..3fcc15e1b6 100644 --- a/x/ibc/07-tendermint/types/msgs.go +++ b/x/ibc/07-tendermint/types/msgs.go @@ -87,7 +87,7 @@ func (msg MsgCreateClient) ValidateBasic() error { if err := msg.Header.ValidateBasic(msg.Header.ChainID); err != nil { return sdkerrors.Wrapf(ErrInvalidHeader, "header failed validatebasic with its own chain-id: %v", err) } - return host.DefaultClientIdentifierValidator(msg.ClientID) + return host.ClientIdentifierValidator(msg.ClientID) } // GetSignBytes implements sdk.Msg @@ -153,7 +153,7 @@ func (msg MsgUpdateClient) ValidateBasic() error { if msg.Signer.Empty() { return sdkerrors.ErrInvalidAddress } - return host.DefaultClientIdentifierValidator(msg.ClientID) + return host.ClientIdentifierValidator(msg.ClientID) } // GetSignBytes implements sdk.Msg diff --git a/x/ibc/09-localhost/types/client_state.go b/x/ibc/09-localhost/types/client_state.go index 665761a4a1..61d7bcd299 100644 --- a/x/ibc/09-localhost/types/client_state.go +++ b/x/ibc/09-localhost/types/client_state.go @@ -72,7 +72,7 @@ func (cs ClientState) Validate() error { if cs.Height <= 0 { return fmt.Errorf("height must be positive: %d", cs.Height) } - return host.DefaultClientIdentifierValidator(cs.ID) + return host.ClientIdentifierValidator(cs.ID) } // VerifyClientConsensusState verifies a proof of the consensus diff --git a/x/ibc/20-transfer/genesis.go b/x/ibc/20-transfer/genesis.go index 659a9428f5..f88dac5310 100644 --- a/x/ibc/20-transfer/genesis.go +++ b/x/ibc/20-transfer/genesis.go @@ -9,6 +9,8 @@ import ( // InitGenesis binds to portid from genesis state func InitGenesis(ctx sdk.Context, keeper Keeper, state types.GenesisState) { + keeper.SetPort(ctx, state.PortID) + // Only try to bind to port if it is not already bound, since we may already own // port capability from capability InitGenesis if !keeper.IsBound(ctx, state.PortID) { @@ -29,9 +31,7 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, state types.GenesisState) { // ExportGenesis exports transfer module's portID into its geneis state func ExportGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState { - portID := keeper.GetPort(ctx) - return types.GenesisState{ - PortID: portID, + PortID: keeper.GetPort(ctx), } } diff --git a/x/ibc/20-transfer/keeper/keeper.go b/x/ibc/20-transfer/keeper/keeper.go index 2e5badd0c4..da0f400f07 100644 --- a/x/ibc/20-transfer/keeper/keeper.go +++ b/x/ibc/20-transfer/keeper/keeper.go @@ -102,10 +102,6 @@ func (k Keeper) IsBound(ctx sdk.Context, portID string) bool { // BindPort defines a wrapper function for the ort Keeper's function in // order to expose it to module's InitGenesis function func (k Keeper) BindPort(ctx sdk.Context, portID string) error { - // Set the portID into our store so we can retrieve it later - store := ctx.KVStore(k.storeKey) - store.Set([]byte(types.PortKey), []byte(portID)) - cap := k.portKeeper.BindPort(ctx, portID) return k.ClaimCapability(ctx, cap, host.PortPath(portID)) } @@ -113,7 +109,13 @@ func (k Keeper) BindPort(ctx sdk.Context, portID string) error { // GetPort returns the portID for the transfer module. Used in ExportGenesis func (k Keeper) GetPort(ctx sdk.Context) string { store := ctx.KVStore(k.storeKey) - return string(store.Get([]byte(types.PortKey))) + return string(store.Get(types.PortKey)) +} + +// SetPort sets the portID for the transfer module. Used in InitGenesis +func (k Keeper) SetPort(ctx sdk.Context, portID string) { + store := ctx.KVStore(k.storeKey) + store.Set(types.PortKey, []byte(portID)) } // ClaimCapability allows the transfer module that can claim a capability that IBC module diff --git a/x/ibc/20-transfer/module.go b/x/ibc/20-transfer/module.go index 27806bbd09..b1ab11fb5b 100644 --- a/x/ibc/20-transfer/module.go +++ b/x/ibc/20-transfer/module.go @@ -3,6 +3,7 @@ package transfer import ( "encoding/json" "fmt" + "math/rand" "github.com/gorilla/mux" "github.com/spf13/cobra" @@ -15,6 +16,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/capability" channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types" @@ -22,6 +24,7 @@ import ( porttypes "github.com/cosmos/cosmos-sdk/x/ibc/05-port/types" "github.com/cosmos/cosmos-sdk/x/ibc/20-transfer/client/cli" "github.com/cosmos/cosmos-sdk/x/ibc/20-transfer/client/rest" + "github.com/cosmos/cosmos-sdk/x/ibc/20-transfer/simulation" "github.com/cosmos/cosmos-sdk/x/ibc/20-transfer/types" host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" ) @@ -48,12 +51,17 @@ func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) { // DefaultGenesis returns default genesis state as raw bytes for the ibc // transfer module. func (AppModuleBasic) DefaultGenesis(cdc codec.JSONMarshaler) json.RawMessage { - return cdc.MustMarshalJSON(types.DefaultGenesis()) + return cdc.MustMarshalJSON(types.DefaultGenesisState()) } // ValidateGenesis performs genesis state validation for the ibc transfer module. -func (AppModuleBasic) ValidateGenesis(_ codec.JSONMarshaler, _ json.RawMessage) error { - return nil +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONMarshaler, bz json.RawMessage) error { + var gs types.GenesisState + if err := cdc.UnmarshalJSON(bz, &gs); err != nil { + return fmt.Errorf("failed to unmarshal %s genesis state: %w", ModuleName, err) + } + + return gs.Validate() } // RegisterRESTRoutes implements AppModuleBasic interface @@ -132,7 +140,6 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json // BeginBlock implements the AppModule interface func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { - } // EndBlock implements the AppModule interface @@ -140,6 +147,36 @@ func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.V return []abci.ValidatorUpdate{} } +//____________________________________________________________________________ + +// AppModuleSimulation functions + +// GenerateGenesisState creates a randomized GenState of the transfer module. +func (AppModule) GenerateGenesisState(simState *module.SimulationState) { + simulation.RandomizedGenState(simState) +} + +// ProposalContents doesn't return any content functions for governance proposals. +func (AppModule) ProposalContents(_ module.SimulationState) []simtypes.WeightedProposalContent { + return nil +} + +// RandomizedParams returns nil. +func (AppModule) RandomizedParams(_ *rand.Rand) []simtypes.ParamChange { + return nil +} + +// RegisterStoreDecoder registers a decoder for transfer module's types +func (am AppModule) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) { +} + +// WeightedOperations returns the all the transfer module operations with their respective weights. +func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation { + return nil +} + +//____________________________________________________________________________ + // Implement IBCModule callbacks func (am AppModule) OnChanOpenInit( ctx sdk.Context, diff --git a/x/ibc/20-transfer/simulation/genesis.go b/x/ibc/20-transfer/simulation/genesis.go new file mode 100644 index 0000000000..e0066c456f --- /dev/null +++ b/x/ibc/20-transfer/simulation/genesis.go @@ -0,0 +1,31 @@ +package simulation + +import ( + "fmt" + "math/rand" + "strings" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/ibc/20-transfer/types" +) + +// Simulation parameter constants +const port = "port_id" + +// RandomizedGenState generates a random GenesisState for transfer. +func RandomizedGenState(simState *module.SimulationState) { + var portID string + simState.AppParams.GetOrGenerate( + simState.Cdc, port, &portID, simState.Rand, + func(r *rand.Rand) { portID = strings.ToLower(simtypes.RandStringOfLength(r, 20)) }, + ) + + transferGenesis := types.GenesisState{ + PortID: portID, + } + + fmt.Printf("Selected randomly generated %s parameters:\n%s\n", types.ModuleName, codec.MustMarshalJSONIndent(simState.Cdc, transferGenesis)) + simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(transferGenesis) +} diff --git a/x/ibc/20-transfer/types/genesis.go b/x/ibc/20-transfer/types/genesis.go index 1c81073f09..26f7b2f791 100644 --- a/x/ibc/20-transfer/types/genesis.go +++ b/x/ibc/20-transfer/types/genesis.go @@ -1,13 +1,24 @@ package types +import ( + host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" +) + // GenesisState is currently only used to ensure that the InitGenesis gets run // by the module manager type GenesisState struct { - PortID string `json:"portid" yaml:"portid"` + PortID string `json:"port_id" yaml:"port_id"` } -func DefaultGenesis() GenesisState { +// DefaultGenesisState returns a GenesisState with "transfer" as the default PortID. +func DefaultGenesisState() GenesisState { return GenesisState{ PortID: PortID, } } + +// Validate performs basic genesis state validation returning an error upon any +// failure. +func (gs GenesisState) Validate() error { + return host.PortIdentifierValidator(gs.PortID) +} diff --git a/x/ibc/20-transfer/types/genesis_test.go b/x/ibc/20-transfer/types/genesis_test.go new file mode 100644 index 0000000000..58a7e86a95 --- /dev/null +++ b/x/ibc/20-transfer/types/genesis_test.go @@ -0,0 +1,47 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/x/ibc/20-transfer/types" +) + +func TestValidateGenesis(t *testing.T) { + testCases := []struct { + name string + genState types.GenesisState + expPass bool + }{ + { + name: "default", + genState: types.DefaultGenesisState(), + expPass: true, + }, + { + "valid genesis", + types.GenesisState{ + PortID: "portidone", + }, + true, + }, + { + "invalid client", + types.GenesisState{ + PortID: "INVALIDPORT", + }, + false, + }, + } + + for _, tc := range testCases { + tc := tc + err := tc.genState.Validate() + if tc.expPass { + require.NoError(t, err, tc.name) + } else { + require.Error(t, err, tc.name) + } + } +} diff --git a/x/ibc/20-transfer/types/keys.go b/x/ibc/20-transfer/types/keys.go index 1c74d3603b..dfecdf1372 100644 --- a/x/ibc/20-transfer/types/keys.go +++ b/x/ibc/20-transfer/types/keys.go @@ -17,7 +17,7 @@ const ( // module supports Version = "ics20-1" - // Default PortID that transfer module binds to + // PortID is the default port id that transfer module binds to PortID = "transfer" // StoreKey is the store key string for IBC transfer @@ -26,13 +26,13 @@ const ( // RouterKey is the message route for IBC transfer RouterKey = ModuleName - // Key to store portID in our store - PortKey = "portID" - // QuerierRoute is the querier route for IBC transfer QuerierRoute = ModuleName ) +// PortKey defines the key to store the port ID in store +var PortKey = []byte{0x01} + // GetEscrowAddress returns the escrow address for the specified channel // // CONTRACT: this assumes that there's only one bank bridge module that owns the diff --git a/x/ibc/20-transfer/types/msgs.go b/x/ibc/20-transfer/types/msgs.go index 5dc814d59d..6b0eb8c924 100644 --- a/x/ibc/20-transfer/types/msgs.go +++ b/x/ibc/20-transfer/types/msgs.go @@ -37,10 +37,10 @@ func (MsgTransfer) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgTransfer) ValidateBasic() error { - if err := host.DefaultPortIdentifierValidator(msg.SourcePort); err != nil { + if err := host.PortIdentifierValidator(msg.SourcePort); err != nil { return sdkerrors.Wrap(err, "invalid source port ID") } - if err := host.DefaultChannelIdentifierValidator(msg.SourceChannel); err != nil { + if err := host.ChannelIdentifierValidator(msg.SourceChannel); err != nil { return sdkerrors.Wrap(err, "invalid source channel ID") } if !msg.Amount.IsAllPositive() { diff --git a/x/ibc/23-commitment/types/merkle.go b/x/ibc/23-commitment/types/merkle.go index 5da657892e..4f54c2341b 100644 --- a/x/ibc/23-commitment/types/merkle.go +++ b/x/ibc/23-commitment/types/merkle.go @@ -109,7 +109,7 @@ func (mp MerklePath) IsEmpty() bool { // CONTRACT: provided path string MUST be a well formated path. See ICS24 for // reference. func ApplyPrefix(prefix exported.Prefix, path string) (MerklePath, error) { - err := host.DefaultPathValidator(path) + err := host.PathValidator(path) if err != nil { return MerklePath{}, err } diff --git a/x/ibc/24-host/validate.go b/x/ibc/24-host/validate.go index cda6f45450..1d8fe56919 100644 --- a/x/ibc/24-host/validate.go +++ b/x/ibc/24-host/validate.go @@ -32,31 +32,31 @@ func defaultIdentifierValidator(id string, min, max int) error { //nolint:unpara return nil } -// DefaultClientIdentifierValidator is the default validator function for Client identifiers +// ClientIdentifierValidator is the default validator function for Client identifiers. // A valid Identifier must be between 9-20 characters and only contain lowercase // alphabetic characters, -func DefaultClientIdentifierValidator(id string) error { +func ClientIdentifierValidator(id string) error { return defaultIdentifierValidator(id, 9, 20) } -// DefaultConnectionIdentifierValidator is the default validator function for Connection identifiers +// ConnectionIdentifierValidator is the default validator function for Connection identifiers. // A valid Identifier must be between 10-20 characters and only contain lowercase // alphabetic characters, -func DefaultConnectionIdentifierValidator(id string) error { +func ConnectionIdentifierValidator(id string) error { return defaultIdentifierValidator(id, 10, 20) } -// DefaultChannelIdentifierValidator is the default validator function for Channel identifiers +// ChannelIdentifierValidator is the default validator function for Channel identifiers. // A valid Identifier must be between 10-20 characters and only contain lowercase // alphabetic characters, -func DefaultChannelIdentifierValidator(id string) error { +func ChannelIdentifierValidator(id string) error { return defaultIdentifierValidator(id, 10, 20) } -// DefaultPortIdentifierValidator is the default validator function for Port identifiers +// PortIdentifierValidator is the default validator function for Port identifiers. // A valid Identifier must be between 2-20 characters and only contain lowercase // alphabetic characters, -func DefaultPortIdentifierValidator(id string) error { +func PortIdentifierValidator(id string) error { return defaultIdentifierValidator(id, 2, 20) } @@ -77,10 +77,9 @@ func NewPathValidator(idValidator ValidateFn) ValidateFn { } } -// DefaultPathValidator takes in path string and validates -// with default identifier rules. This is optimized by simply -// checking that all path elements are alphanumeric -func DefaultPathValidator(path string) error { +// PathValidator takes in path string and validateswith def ault identifier rules. +// This is optimized by simply checking that all path elements are alphanumeric. +func PathValidator(path string) error { pathArr := strings.Split(path, "/") if pathArr[0] == path { return sdkerrors.Wrapf(ErrInvalidPath, "path %s doesn't contain any separator '/'", path) diff --git a/x/ibc/module.go b/x/ibc/module.go index 71cb32f42a..84bea0207b 100644 --- a/x/ibc/module.go +++ b/x/ibc/module.go @@ -3,6 +3,7 @@ package ibc import ( "encoding/json" "fmt" + "math/rand" "github.com/gorilla/mux" "github.com/spf13/cobra" @@ -14,16 +15,18 @@ import ( cdctypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" "github.com/cosmos/cosmos-sdk/x/ibc/client/cli" "github.com/cosmos/cosmos-sdk/x/ibc/client/rest" + "github.com/cosmos/cosmos-sdk/x/ibc/simulation" ) -// TODO: AppModuleSimulation var ( - _ module.AppModule = AppModule{} - _ module.AppModuleBasic = AppModuleBasic{} + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} + _ module.AppModuleSimulation = AppModule{} ) // AppModuleBasic defines the basic application module used by the ibc module. @@ -151,3 +154,33 @@ func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate { return []abci.ValidatorUpdate{} } + +//____________________________________________________________________________ + +// AppModuleSimulation functions + +// GenerateGenesisState creates a randomized GenState of the ibc module. +func (AppModule) GenerateGenesisState(simState *module.SimulationState) { + simulation.RandomizedGenState(simState) +} + +// ProposalContents doesn't return any content functions for governance proposals. +func (AppModule) ProposalContents(_ module.SimulationState) []simtypes.WeightedProposalContent { + return nil +} + +// RandomizedParams returns nil since IBC doesn't register parameter changes. +func (AppModule) RandomizedParams(_ *rand.Rand) []simtypes.ParamChange { + return nil +} + +// RegisterStoreDecoder registers a decoder for ibc module's types +func (am AppModule) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) { + // TODO: in a following PR + // sdr[StoreKey] = simulation.NewDecodeStore(am.cdc) +} + +// WeightedOperations returns the all the ibc module operations with their respective weights. +func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation { + return nil +} diff --git a/x/ibc/simulation/genesis.go b/x/ibc/simulation/genesis.go new file mode 100644 index 0000000000..2b5baff9bb --- /dev/null +++ b/x/ibc/simulation/genesis.go @@ -0,0 +1,60 @@ +package simulation + +// DONTCOVER + +import ( + "fmt" + "math/rand" + + "github.com/cosmos/cosmos-sdk/codec" + + "github.com/cosmos/cosmos-sdk/types/module" + clientsims "github.com/cosmos/cosmos-sdk/x/ibc/02-client/simulation" + clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" + connectionsims "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/simulation" + connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types" + channelsims "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/simulation" + channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types" + host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" + "github.com/cosmos/cosmos-sdk/x/ibc/types" +) + +// Simulation parameter constants +const ( + clientGenesis = "client_genesis" + connectionGenesis = "connection_genesis" + channelGenesis = "channel_genesis" +) + +// RandomizedGenState generates a random GenesisState for evidence +func RandomizedGenState(simState *module.SimulationState) { + var ( + clientGenesisState clienttypes.GenesisState + connectionGenesisState connectiontypes.GenesisState + channelGenesisState channeltypes.GenesisState + ) + + simState.AppParams.GetOrGenerate( + simState.Cdc, clientGenesis, &clientGenesisState, simState.Rand, + func(r *rand.Rand) { clientGenesisState = clientsims.GenClientGenesis(r, simState.Accounts) }, + ) + + simState.AppParams.GetOrGenerate( + simState.Cdc, connectionGenesis, &connectionGenesisState, simState.Rand, + func(r *rand.Rand) { connectionGenesisState = connectionsims.GenConnectionGenesis(r, simState.Accounts) }, + ) + + simState.AppParams.GetOrGenerate( + simState.Cdc, channelGenesis, &channelGenesisState, simState.Rand, + func(r *rand.Rand) { channelGenesisState = channelsims.GenChannelGenesis(r, simState.Accounts) }, + ) + + ibcGenesis := types.GenesisState{ + ClientGenesis: clientGenesisState, + ConnectionGenesis: connectionGenesisState, + ChannelGenesis: channelGenesisState, + } + + fmt.Printf("Selected randomly generated %s parameters:\n%s\n", host.ModuleName, codec.MustMarshalJSONIndent(simState.Cdc, ibcGenesis)) + simState.GenState[host.ModuleName] = simState.Cdc.MustMarshalJSON(ibcGenesis) +}