x/ibc: create localhost client on InitGenesis (#6170)

closes: #6159
This commit is contained in:
Federico Kunze 2020-05-11 11:46:00 -04:00 committed by GitHub
parent f37308778a
commit f88d9ab586
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 75 additions and 36 deletions

View File

@ -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())
}
}

View File

@ -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,
}
}

View File

@ -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 {

View File

@ -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
}

View File

@ -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)

View File

@ -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)

View File

@ -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,
}
}

View File

@ -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,
},

View File

@ -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/<app>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/<app>cli --chain-id $CID
`, version.ClientName),
),
Args: cobra.ExactArgs(0),

View File

@ -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),
)...)

View File

@ -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)

View File

@ -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(),
},

View File

@ -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{}
}