From f88d9ab5862b4e5fcbc1f1adec30132e7d12facf Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Mon, 11 May 2020 11:46:00 -0400 Subject: [PATCH] x/ibc: create localhost client on InitGenesis (#6170) closes: #6159 --- x/ibc/02-client/abci_test.go | 27 ++++++++++++--------------- x/ibc/02-client/genesis.go | 25 +++++++++++++++++++++++++ x/ibc/02-client/handler.go | 2 -- x/ibc/02-client/keeper/client.go | 20 +++++++++++++------- x/ibc/02-client/keeper/client_test.go | 3 --- x/ibc/02-client/keeper/keeper_test.go | 5 +++++ x/ibc/02-client/types/genesis.go | 5 ++++- x/ibc/02-client/types/genesis_test.go | 4 ++++ x/ibc/09-localhost/client/cli/tx.go | 7 +++---- x/ibc/client/cli/cli.go | 4 ++-- x/ibc/genesis.go | 2 +- x/ibc/genesis_test.go | 2 ++ x/ibc/module.go | 5 ++++- 13 files changed, 75 insertions(+), 36 deletions(-) diff --git a/x/ibc/02-client/abci_test.go b/x/ibc/02-client/abci_test.go index 0654a9b332..e61cc2f368 100644 --- a/x/ibc/02-client/abci_test.go +++ b/x/ibc/02-client/abci_test.go @@ -11,7 +11,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" - localhosttypes "github.com/cosmos/cosmos-sdk/x/ibc/09-localhost/types" ) type ClientTestSuite struct { @@ -27,7 +26,7 @@ func (suite *ClientTestSuite) SetupTest() { suite.app = simapp.Setup(isCheckTx) suite.cdc = suite.app.Codec() - suite.ctx = suite.app.BaseApp.NewContext(isCheckTx, abci.Header{Height: 1, ChainID: "localhost_chain"}) + suite.ctx = suite.app.BaseApp.NewContext(isCheckTx, abci.Header{Height: 0, ChainID: "localhost_chain"}) } @@ -36,25 +35,23 @@ func TestClientTestSuite(t *testing.T) { } func (suite *ClientTestSuite) TestBeginBlocker() { - localHostClient := localhosttypes.NewClientState( - suite.app.IBCKeeper.ClientKeeper.ClientStore(suite.ctx, exported.ClientTypeLocalHost), - suite.ctx.ChainID(), - suite.ctx.BlockHeight(), - ) - _, err := suite.app.IBCKeeper.ClientKeeper.CreateClient(suite.ctx, localHostClient, nil) - suite.Require().NoError(err) + prevHeight := suite.ctx.BlockHeight() - // increase height - suite.ctx = suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + 1) + localHostClient, found := suite.app.IBCKeeper.ClientKeeper.GetClientState(suite.ctx, exported.ClientTypeLocalHost) + suite.Require().True(found) + suite.Require().Equal(prevHeight, int64(localHostClient.GetLatestHeight())) - var prevHeight uint64 for i := 0; i < 10; i++ { - prevHeight = localHostClient.GetLatestHeight() + // increment height + suite.ctx = suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + 1) + suite.Require().NotPanics(func() { client.BeginBlocker(suite.ctx, suite.app.IBCKeeper.ClientKeeper) }, "BeginBlocker shouldn't panic") - localHostClient, found := suite.app.IBCKeeper.ClientKeeper.GetClientState(suite.ctx, localHostClient.GetID()) + + localHostClient, found = suite.app.IBCKeeper.ClientKeeper.GetClientState(suite.ctx, exported.ClientTypeLocalHost) suite.Require().True(found) - suite.Require().Equal(prevHeight+1, localHostClient.GetLatestHeight()) + suite.Require().Equal(prevHeight+1, int64(localHostClient.GetLatestHeight())) + prevHeight = int64(localHostClient.GetLatestHeight()) } } diff --git a/x/ibc/02-client/genesis.go b/x/ibc/02-client/genesis.go index b16c2e9372..4188a316a7 100644 --- a/x/ibc/02-client/genesis.go +++ b/x/ibc/02-client/genesis.go @@ -2,6 +2,8 @@ package client import ( sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" + localhosttypes "github.com/cosmos/cosmos-sdk/x/ibc/09-localhost/types" ) // InitGenesis initializes the ibc client submodule's state from a provided genesis @@ -16,6 +18,28 @@ func InitGenesis(ctx sdk.Context, k Keeper, gs GenesisState) { k.SetClientConsensusState(ctx, cs.ClientID, consState.GetHeight(), consState) } } + + if !gs.CreateLocalhost { + return + } + + // NOTE: return if the localhost client was already imported. The chain-id and + // block height will be overwriten to the correct values during BeginBlock. + if _, found := k.GetClientState(ctx, exported.ClientTypeLocalHost); found { + return + } + + // client id is always "localhost" + clientState := localhosttypes.NewClientState( + k.ClientStore(ctx, exported.ClientTypeLocalHost), + ctx.ChainID(), + ctx.BlockHeight(), + ) + + _, err := k.CreateClient(ctx, clientState, nil) + if err != nil { + panic(err) + } } // ExportGenesis returns the ibc client submodule's exported genesis. @@ -23,5 +47,6 @@ func ExportGenesis(ctx sdk.Context, k Keeper) GenesisState { return GenesisState{ Clients: k.GetAllClients(ctx), ClientsConsensus: k.GetAllConsensusStates(ctx), + CreateLocalhost: true, } } diff --git a/x/ibc/02-client/handler.go b/x/ibc/02-client/handler.go index 00029f18c2..f70cbe7883 100644 --- a/x/ibc/02-client/handler.go +++ b/x/ibc/02-client/handler.go @@ -18,8 +18,6 @@ func HandleMsgCreateClient(ctx sdk.Context, k Keeper, msg exported.MsgCreateClie var clientState exported.ClientState switch clientType { - case 0: - return nil, sdkerrors.Wrap(ErrInvalidClientType, msg.GetClientType()) case exported.Tendermint: tmMsg, ok := msg.(ibctmtypes.MsgCreateClient) if !ok { diff --git a/x/ibc/02-client/keeper/client.go b/x/ibc/02-client/keeper/client.go index e8a12cc6da..ebb5a71018 100644 --- a/x/ibc/02-client/keeper/client.go +++ b/x/ibc/02-client/keeper/client.go @@ -89,7 +89,7 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.H // override client state and update the block height clientState = localhosttypes.NewClientState( k.ClientStore(ctx, clientState.GetID()), - clientState.GetChainID(), + ctx.ChainID(), // use the chain ID from context since the client is from the running chain (i.e self). ctx.BlockHeight(), ) default: @@ -110,17 +110,23 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.H k.Logger(ctx).Info(fmt.Sprintf("client %s updated to height %d", clientID, clientState.GetLatestHeight())) // Emit events in keeper so antehandler emits them as well - ctx.EventManager().EmitEvents(sdk.Events{ + ctx.EventManager().EmitEvent( sdk.NewEvent( types.EventTypeUpdateClient, sdk.NewAttribute(types.AttributeKeyClientID, clientID), sdk.NewAttribute(types.AttributeKeyClientType, clientType.String()), ), - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), - ), - }) + ) + + // localhost client is not updated though messages + if clientType != exported.Localhost { + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + ), + ) + } return clientState, nil } diff --git a/x/ibc/02-client/keeper/client_test.go b/x/ibc/02-client/keeper/client_test.go index b04a51f9ed..d97d26321e 100644 --- a/x/ibc/02-client/keeper/client_test.go +++ b/x/ibc/02-client/keeper/client_test.go @@ -184,9 +184,6 @@ func (suite *KeeperTestSuite) TestUpdateClientLocalhost() { suite.ctx.BlockHeight(), ) - localhostClient, err := suite.keeper.CreateClient(suite.ctx, localhostClient, nil) - suite.Require().NoError(err, err) - suite.ctx = suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + 1) updatedClientState, err := suite.keeper.UpdateClient(suite.ctx, exported.ClientTypeLocalHost, nil) diff --git a/x/ibc/02-client/keeper/keeper_test.go b/x/ibc/02-client/keeper/keeper_test.go index 4b5104b32f..deb7b45b5c 100644 --- a/x/ibc/02-client/keeper/keeper_test.go +++ b/x/ibc/02-client/keeper/keeper_test.go @@ -129,6 +129,11 @@ func (suite KeeperTestSuite) TestGetAllClients() { suite.keeper.SetClientState(suite.ctx, expClients[i]) } + // add localhost client + localHostClient, found := suite.keeper.GetClientState(suite.ctx, exported.ClientTypeLocalHost) + suite.Require().True(found) + expClients = append(expClients, localHostClient) + clients := suite.keeper.GetAllClients(suite.ctx) suite.Require().Len(clients, len(expClients)) suite.Require().Equal(expClients, clients) diff --git a/x/ibc/02-client/types/genesis.go b/x/ibc/02-client/types/genesis.go index aa41ee5fcd..43c3a1af50 100644 --- a/x/ibc/02-client/types/genesis.go +++ b/x/ibc/02-client/types/genesis.go @@ -25,15 +25,17 @@ func NewClientConsensusStates(id string, states []exported.ConsensusState) Clien type GenesisState struct { Clients []exported.ClientState `json:"clients" yaml:"clients"` ClientsConsensus []ClientConsensusStates `json:"clients_consensus" yaml:"clients_consensus"` + CreateLocalhost bool `json:"create_localhost" yaml:"create_localhost"` } // NewGenesisState creates a GenesisState instance. func NewGenesisState( - clients []exported.ClientState, clientsConsensus []ClientConsensusStates, + clients []exported.ClientState, clientsConsensus []ClientConsensusStates, createLocalhost bool, ) GenesisState { return GenesisState{ Clients: clients, ClientsConsensus: clientsConsensus, + CreateLocalhost: createLocalhost, } } @@ -42,6 +44,7 @@ func DefaultGenesisState() GenesisState { return GenesisState{ Clients: []exported.ClientState{}, ClientsConsensus: []ClientConsensusStates{}, + CreateLocalhost: true, } } diff --git a/x/ibc/02-client/types/genesis_test.go b/x/ibc/02-client/types/genesis_test.go index ebc65ca44a..d006e0a3ab 100644 --- a/x/ibc/02-client/types/genesis_test.go +++ b/x/ibc/02-client/types/genesis_test.go @@ -67,6 +67,7 @@ func TestValidateGenesis(t *testing.T) { }, }, }, + true, ), expPass: true, }, @@ -78,6 +79,7 @@ func TestValidateGenesis(t *testing.T) { localhosttypes.NewClientState(store, "chaindID", 0), }, nil, + true, ), expPass: false, }, @@ -98,6 +100,7 @@ func TestValidateGenesis(t *testing.T) { }, }, }, + true, ), expPass: false, }, @@ -118,6 +121,7 @@ func TestValidateGenesis(t *testing.T) { }, ), }, + true, ), expPass: false, }, diff --git a/x/ibc/09-localhost/client/cli/tx.go b/x/ibc/09-localhost/client/cli/tx.go index 83f776a98f..68bc633f11 100644 --- a/x/ibc/09-localhost/client/cli/tx.go +++ b/x/ibc/09-localhost/client/cli/tx.go @@ -23,10 +23,9 @@ func GetCmdCreateClient(cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "create new localhost client", - Long: strings.TrimSpace(fmt.Sprintf(`create new localhost (loopback) client: - -Example: -$ %s tx ibc client localhost create --from node0 --home ../node0/cli --chain-id $CID + Long: strings.TrimSpace(fmt.Sprintf(`create new localhost (loopback) client: +Example: +$ %s tx ibc client localhost create --from node0 --home ../node0/cli --chain-id $CID `, version.ClientName), ), Args: cobra.ExactArgs(0), diff --git a/x/ibc/client/cli/cli.go b/x/ibc/client/cli/cli.go index 0ba304e8fe..dc0f52eaac 100644 --- a/x/ibc/client/cli/cli.go +++ b/x/ibc/client/cli/cli.go @@ -10,7 +10,7 @@ import ( connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" tmclient "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/client/cli" - localhostclient "github.com/cosmos/cosmos-sdk/x/ibc/09-localhost/client/cli" + localhost "github.com/cosmos/cosmos-sdk/x/ibc/09-localhost" "github.com/cosmos/cosmos-sdk/x/ibc/types" ) @@ -26,7 +26,7 @@ func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { ibcTxCmd.AddCommand(flags.PostCommands( tmclient.GetTxCmd(cdc, storeKey), - localhostclient.GetTxCmd(cdc, storeKey), + localhost.GetTxCmd(cdc, storeKey), connection.GetTxCmd(cdc, storeKey), channel.GetTxCmd(cdc, storeKey), )...) diff --git a/x/ibc/genesis.go b/x/ibc/genesis.go index 673af88569..34dc368d04 100644 --- a/x/ibc/genesis.go +++ b/x/ibc/genesis.go @@ -39,7 +39,7 @@ func (gs GenesisState) Validate() error { // InitGenesis initializes the ibc state from a provided genesis // state. -func InitGenesis(ctx sdk.Context, k Keeper, gs GenesisState) { +func InitGenesis(ctx sdk.Context, k Keeper, createLocalhost bool, gs GenesisState) { client.InitGenesis(ctx, k.ClientKeeper, gs.ClientGenesis) connection.InitGenesis(ctx, k.ConnectionKeeper, gs.ConnectionGenesis) channel.InitGenesis(ctx, k.ChannelKeeper, gs.ChannelGenesis) diff --git a/x/ibc/genesis_test.go b/x/ibc/genesis_test.go index 1d9ada5b32..70dd7daa1f 100644 --- a/x/ibc/genesis_test.go +++ b/x/ibc/genesis_test.go @@ -41,6 +41,7 @@ func (suite *IBCTestSuite) TestValidateGenesis() { }, ), }, + true, ), ConnectionGenesis: connection.NewGenesisState( []connection.End{ @@ -84,6 +85,7 @@ func (suite *IBCTestSuite) TestValidateGenesis() { localhosttypes.NewClientState(suite.store, "chaindID", 0), }, nil, + false, ), ConnectionGenesis: connection.DefaultGenesisState(), }, diff --git a/x/ibc/module.go b/x/ibc/module.go index c3d829c249..7af27b9bb5 100644 --- a/x/ibc/module.go +++ b/x/ibc/module.go @@ -92,6 +92,9 @@ func (AppModuleBasic) RegisterInterfaceTypes(registry cdctypes.InterfaceRegistry type AppModule struct { AppModuleBasic keeper *Keeper + + // create localhost by default + createLocalhost bool } // NewAppModule creates a new AppModule object @@ -139,7 +142,7 @@ func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONMarshaler, bz jso if err != nil { panic(fmt.Sprintf("failed to unmarshal %s genesis state: %s", ModuleName, err)) } - InitGenesis(ctx, *am.keeper, gs) + InitGenesis(ctx, *am.keeper, am.createLocalhost, gs) return []abci.ValidatorUpdate{} }