diff --git a/modules/light-clients/06-solomachine/light_client_module.go b/modules/light-clients/06-solomachine/light_client_module.go index 86f75267d9e..ca2a812aa3a 100644 --- a/modules/light-clients/06-solomachine/light_client_module.go +++ b/modules/light-clients/06-solomachine/light_client_module.go @@ -12,7 +12,7 @@ import ( var _ exported.LightClientModule = (*LightClientModule)(nil) -// LightClientModule implements the core IBC api.LightClientModule interface? +// LightClientModule implements the core IBC api.LightClientModule interface type LightClientModule struct { cdc codec.BinaryCodec storeProvider exported.ClientStoreProvider @@ -25,6 +25,9 @@ func NewLightClientModule(cdc codec.BinaryCodec) LightClientModule { } } +// RegisterStoreProvider is called by core IBC when a LightClientModule is added to the router. +// It allows the LightClientModule to set a ClientStoreProvider which supplies isolated prefix client stores +// to IBC light client instances. func (lcm *LightClientModule) RegisterStoreProvider(storeProvider exported.ClientStoreProvider) { lcm.storeProvider = storeProvider } @@ -86,7 +89,7 @@ func (lcm LightClientModule) CheckForMisbehaviour(ctx sdk.Context, clientID stri return clientState.CheckForMisbehaviour(ctx, lcm.cdc, clientStore, clientMsg) } -// UpdateStateOnMisbehaviour should perform appropriate state changes on a client state given that misbehaviour has been detected and verified +// UpdateStateOnMisbehaviour should perform appropriate state changes on a client state given that misbehaviour has been detected and verified. // // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 08-solomachine-{n}. func (lcm LightClientModule) UpdateStateOnMisbehaviour(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) { @@ -217,14 +220,7 @@ func (lcm LightClientModule) RecoverClient(ctx sdk.Context, clientID, substitute return clientState.CheckSubstituteAndUpdateState(ctx, lcm.cdc, clientStore, substituteClientStore, substituteClient) } -// // Upgrade functions -// // NOTE: proof heights are not included as upgrade to a new revision is expected to pass only on the last -// // height committed by the current revision. Clients are responsible for ensuring that the planned last -// // height of the current revision is somehow encoded in the proof verification process. -// // This is to ensure that no premature upgrades occur, since upgrade plans committed to by the counterparty -// // may be cancelled or modified before the last planned height. -// // If the upgrade is verified, the upgraded client and consensus states must be set in the client store. -// // Deprecated: will be removed as performs internal functionality +// VerifyUpgradeAndUpdateState returns an error since solomachine client does not support upgrades // // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 08-solomachine-{n}. func (LightClientModule) VerifyUpgradeAndUpdateState(ctx sdk.Context, clientID string, newClient []byte, newConsState []byte, upgradeClientProof, upgradeConsensusStateProof []byte) error { diff --git a/modules/light-clients/07-tendermint/light_client_module.go b/modules/light-clients/07-tendermint/light_client_module.go index 12391a10b1f..123d2b7d414 100644 --- a/modules/light-clients/07-tendermint/light_client_module.go +++ b/modules/light-clients/07-tendermint/light_client_module.go @@ -13,17 +13,22 @@ import ( var _ exported.LightClientModule = (*LightClientModule)(nil) +// LightClientModule implements the core IBC api.LightClientModule interface. type LightClientModule struct { keeper keeper.Keeper storeProvider exported.ClientStoreProvider } +// NewLightClientModule creates and returns a new 08-wasm LightClientModule. func NewLightClientModule(cdc codec.BinaryCodec, authority string) LightClientModule { return LightClientModule{ keeper: keeper.NewKeeper(cdc, authority), } } +// RegisterStoreProvider is called by core IBC when a LightClientModule is added to the router. +// It allows the LightClientModule to set a ClientStoreProvider which supplies isolated prefix client stores +// to IBC light client instances. func (lcm *LightClientModule) RegisterStoreProvider(storeProvider exported.ClientStoreProvider) { lcm.storeProvider = storeProvider } @@ -56,6 +61,11 @@ func (lcm LightClientModule) Initialize(ctx sdk.Context, clientID string, client return clientState.Initialize(ctx, lcm.keeper.Codec(), clientStore, &consensusState) } +// VerifyClientMessage must verify a ClientMessage. A ClientMessage could be a Header, Misbehaviour, or batch update. +// It must handle each type of ClientMessage appropriately. Calls to CheckForMisbehaviour, UpdateState, and UpdateStateOnMisbehaviour +// will assume that the content of the ClientMessage has been verified and can be trusted. An error should be returned +// if the ClientMessage fails to verify. +// // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 07-tendermint-{n}. func (lcm LightClientModule) VerifyClientMessage(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) error { clientStore := lcm.storeProvider.ClientStore(ctx, clientID) @@ -69,6 +79,9 @@ func (lcm LightClientModule) VerifyClientMessage(ctx sdk.Context, clientID strin return clientState.VerifyClientMessage(ctx, cdc, clientStore, clientMsg) } +// CheckForMisbehaviour checks for evidence of a misbehaviour in Header or Misbehaviour type. It assumes the ClientMessage +// has already been verified. +// // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 07-tendermint-{n}. func (lcm LightClientModule) CheckForMisbehaviour(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) bool { clientStore := lcm.storeProvider.ClientStore(ctx, clientID) @@ -82,6 +95,8 @@ func (lcm LightClientModule) CheckForMisbehaviour(ctx sdk.Context, clientID stri return clientState.CheckForMisbehaviour(ctx, cdc, clientStore, clientMsg) } +// UpdateStateOnMisbehaviour should perform appropriate state changes on a client state given that misbehaviour has been detected and verified. +// // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 07-tendermint-{n}. func (lcm LightClientModule) UpdateStateOnMisbehaviour(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) { clientStore := lcm.storeProvider.ClientStore(ctx, clientID) @@ -95,6 +110,9 @@ func (lcm LightClientModule) UpdateStateOnMisbehaviour(ctx sdk.Context, clientID clientState.UpdateStateOnMisbehaviour(ctx, cdc, clientStore, clientMsg) } +// UpdateState updates and stores as necessary any associated information for an IBC client, such as the ClientState and corresponding ConsensusState. +// Upon successful update, a list of consensus heights is returned. It assumes the ClientMessage has already been verified. +// // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 07-tendermint-{n}. func (lcm LightClientModule) UpdateState(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) []exported.Height { clientStore := lcm.storeProvider.ClientStore(ctx, clientID) @@ -108,6 +126,9 @@ func (lcm LightClientModule) UpdateState(ctx sdk.Context, clientID string, clien return clientState.UpdateState(ctx, cdc, clientStore, clientMsg) } +// VerifyMembership is a generic proof verification method which verifies a proof of the existence of a value at a given CommitmentPath at the specified height. +// The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24). +// // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 07-tendermint-{n}. func (lcm LightClientModule) VerifyMembership( ctx sdk.Context, @@ -130,6 +151,9 @@ func (lcm LightClientModule) VerifyMembership( return clientState.VerifyMembership(ctx, clientStore, cdc, height, delayTimePeriod, delayBlockPeriod, proof, path, value) } +// VerifyNonMembership is a generic proof verification method which verifies the absence of a given CommitmentPath at a specified height. +// The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24). +// // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 07-tendermint-{n}. func (lcm LightClientModule) VerifyNonMembership( ctx sdk.Context, @@ -151,6 +175,8 @@ func (lcm LightClientModule) VerifyNonMembership( return clientState.VerifyNonMembership(ctx, clientStore, cdc, height, delayTimePeriod, delayBlockPeriod, proof, path) } +// Status must return the status of the client. Only Active clients are allowed to process packets. +// // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 07-tendermint-{n}. func (lcm LightClientModule) Status(ctx sdk.Context, clientID string) exported.Status { clientStore := lcm.storeProvider.ClientStore(ctx, clientID) @@ -164,6 +190,8 @@ func (lcm LightClientModule) Status(ctx sdk.Context, clientID string) exported.S return clientState.Status(ctx, clientStore, cdc) } +// TimestampAtHeight must return the timestamp for the consensus state associated with the provided height. +// // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 07-tendermint-{n}. func (lcm LightClientModule) TimestampAtHeight( ctx sdk.Context, @@ -181,6 +209,9 @@ func (lcm LightClientModule) TimestampAtHeight( return clientState.GetTimestampAtHeight(ctx, clientStore, cdc, height) } +// RecoverClient must verify that the provided substitute may be used to update the subject client. +// The light client must set the updated client and consensus states within the clientStore for the subject client. +// // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 07-tendermint-{n}. func (lcm LightClientModule) RecoverClient(ctx sdk.Context, clientID, substituteClientID string) error { substituteClientType, _, err := clienttypes.ParseClientIdentifier(substituteClientID) @@ -213,6 +244,9 @@ func (lcm LightClientModule) RecoverClient(ctx sdk.Context, clientID, substitute return clientState.CheckSubstituteAndUpdateState(ctx, cdc, clientStore, substituteClientStore, substituteClient) } +// VerifyUpgradeAndUpdateState, on a successful verification expects the contract to update +// the new client state, consensus state, and any other client metadata. +// // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 07-tendermint-{n}. func (lcm LightClientModule) VerifyUpgradeAndUpdateState( ctx sdk.Context, diff --git a/modules/light-clients/08-wasm/light_client_module.go b/modules/light-clients/08-wasm/light_client_module.go index bf3e69bfc9d..7f0b5284636 100644 --- a/modules/light-clients/08-wasm/light_client_module.go +++ b/modules/light-clients/08-wasm/light_client_module.go @@ -13,7 +13,7 @@ import ( var _ exported.LightClientModule = (*LightClientModule)(nil) -// LightClientModule implements the core IBC api.LightClientModule interface? +// LightClientModule implements the core IBC api.LightClientModule interface. type LightClientModule struct { keeper wasmkeeper.Keeper storeProvider exported.ClientStoreProvider @@ -26,6 +26,9 @@ func NewLightClientModule(keeper wasmkeeper.Keeper) LightClientModule { } } +// RegisterStoreProvider is called by core IBC when a LightClientModule is added to the router. +// It allows the LightClientModule to set a ClientStoreProvider which supplies isolated prefix client stores +// to IBC light client instances. func (lcm *LightClientModule) RegisterStoreProvider(storeProvider exported.ClientStoreProvider) { lcm.storeProvider = storeProvider } @@ -77,7 +80,7 @@ func (lcm LightClientModule) VerifyClientMessage(ctx sdk.Context, clientID strin return clientState.VerifyClientMessage(ctx, lcm.keeper.Codec(), clientStore, clientMsg) } -// Checks for evidence of a misbehaviour in Header or Misbehaviour type. It assumes the ClientMessage +// CheckForMisbehaviour checks for evidence of a misbehaviour in Header or Misbehaviour type. It assumes the ClientMessage // has already been verified. // // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 08-wasm-{n}. @@ -93,7 +96,7 @@ func (lcm LightClientModule) CheckForMisbehaviour(ctx sdk.Context, clientID stri return clientState.CheckForMisbehaviour(ctx, cdc, clientStore, clientMsg) } -// UpdateStateOnMisbehaviour should perform appropriate state changes on a client state given that misbehaviour has been detected and verified +// UpdateStateOnMisbehaviour should perform appropriate state changes on a client state given that misbehaviour has been detected and verified. // // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 08-wasm-{n}. func (lcm LightClientModule) UpdateStateOnMisbehaviour(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) { @@ -238,14 +241,8 @@ func (lcm LightClientModule) RecoverClient(ctx sdk.Context, clientID, substitute return clientState.CheckSubstituteAndUpdateState(ctx, cdc, clientStore, substituteClientStore, substituteClient) } -// // Upgrade functions -// // NOTE: proof heights are not included as upgrade to a new revision is expected to pass only on the last -// // height committed by the current revision. Clients are responsible for ensuring that the planned last -// // height of the current revision is somehow encoded in the proof verification process. -// // This is to ensure that no premature upgrades occur, since upgrade plans committed to by the counterparty -// // may be cancelled or modified before the last planned height. -// // If the upgrade is verified, the upgraded client and consensus states must be set in the client store. -// // DEPRECATED: will be removed as performs internal functionality +// VerifyUpgradeAndUpdateState, on a successful verification expects the contract to update +// the new client state, consensus state, and any other client metadata. // // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 08-wasm-{n}. func (LightClientModule) VerifyUpgradeAndUpdateState(ctx sdk.Context, clientID string, newClient []byte, newConsState []byte, upgradeClientProof, upgradeConsensusStateProof []byte) error { diff --git a/modules/light-clients/09-localhost/light_client_module.go b/modules/light-clients/09-localhost/light_client_module.go index 3711edb8a1b..076218134b1 100644 --- a/modules/light-clients/09-localhost/light_client_module.go +++ b/modules/light-clients/09-localhost/light_client_module.go @@ -14,12 +14,14 @@ import ( var _ exported.LightClientModule = (*LightClientModule)(nil) +// LightClientModule implements the core IBC api.LightClientModule interface. type LightClientModule struct { cdc codec.BinaryCodec key storetypes.StoreKey storeProvider exported.ClientStoreProvider } +// NewLightClientModule creates and returns a new 09-localhost LightClientModule. func NewLightClientModule(cdc codec.BinaryCodec, key storetypes.StoreKey) *LightClientModule { return &LightClientModule{ cdc: cdc, @@ -27,12 +29,17 @@ func NewLightClientModule(cdc codec.BinaryCodec, key storetypes.StoreKey) *Light } } +// RegisterStoreProvider is called by core IBC when a LightClientModule is added to the router. +// It allows the LightClientModule to set a ClientStoreProvider which supplies isolated prefix client stores +// to IBC light client instances. func (lcm *LightClientModule) RegisterStoreProvider(storeProvider exported.ClientStoreProvider) { lcm.storeProvider = storeProvider } +// Initialize ensures that initial consensus state for localhost is nil. +// // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 09-localhost-{n}. -func (lcm LightClientModule) Initialize(ctx sdk.Context, clientID string, clientStateBz, consensusStateBz []byte) error { +func (lcm LightClientModule) Initialize(ctx sdk.Context, clientID string, _, consensusStateBz []byte) error { if len(consensusStateBz) != 0 { return errorsmod.Wrap(clienttypes.ErrInvalidConsensus, "initial consensus state for localhost must be nil.") } @@ -46,27 +53,26 @@ func (lcm LightClientModule) Initialize(ctx sdk.Context, clientID string, client return nil } +// VerifyClientMessage is unsupported by the 09-localhost client type and returns an error. +// // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 09-localhost-{n}. -func (lcm LightClientModule) VerifyClientMessage(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) error { - clientStore := lcm.storeProvider.ClientStore(ctx, clientID) - cdc := lcm.cdc - - clientState, found := getClientState(clientStore, cdc) - if !found { - return errorsmod.Wrap(clienttypes.ErrClientNotFound, clientID) - } - - return clientState.VerifyClientMessage(ctx, cdc, clientStore, clientMsg) +func (LightClientModule) VerifyClientMessage(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) error { + return errorsmod.Wrap(clienttypes.ErrUpdateClientFailed, "client message verification is unsupported by the localhost client") } +// CheckForMisbehaviour is unsupported by the 09-localhost client type and performs a no-op, returning false. func (LightClientModule) CheckForMisbehaviour(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) bool { return false } +// UpdateStateOnMisbehaviour is unsupported by the 09-localhost client type and performs a no-op. func (LightClientModule) UpdateStateOnMisbehaviour(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) { // no-op } +// UpdateState updates and stores as necessary any associated information for an IBC client, such as the ClientState and corresponding ConsensusState. +// Upon successful update, a list of consensus heights is returned. It assumes the ClientMessage has already been verified. +// // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 09-localhost-{n}. func (lcm LightClientModule) UpdateState(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) []exported.Height { clientStore := lcm.storeProvider.ClientStore(ctx, clientID) @@ -80,6 +86,10 @@ func (lcm LightClientModule) UpdateState(ctx sdk.Context, clientID string, clien return clientState.UpdateState(ctx, cdc, clientStore, clientMsg) } +// VerifyMembership is a generic proof verification method which verifies the existence of a given key and value within the IBC store. +// The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24). +// The caller must provide the full IBC store. +// // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 09-localhost-{n}. func (lcm LightClientModule) VerifyMembership( ctx sdk.Context, @@ -103,6 +113,10 @@ func (lcm LightClientModule) VerifyMembership( return clientState.VerifyMembership(ctx, ibcStore, cdc, height, delayTimePeriod, delayBlockPeriod, proof, path, value) } +// VerifyNonMembership is a generic proof verification method which verifies the absence of a given CommitmentPath within the IBC store. +// The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24). +// The caller must provide the full IBC store. +// // CONTRACT: clientID is validated in 02-client router, thus clientID is assumed here to have the format 09-localhost-{n}. func (lcm LightClientModule) VerifyNonMembership( ctx sdk.Context, @@ -130,6 +144,8 @@ func (LightClientModule) Status(ctx sdk.Context, clientID string) exported.Statu return exported.Active } +// TimestampAtHeight returns the current block time retrieved from the application context. The localhost client does not store consensus states and thus +// cannot provide a timestamp for the provided height. func (LightClientModule) TimestampAtHeight( ctx sdk.Context, clientID string, @@ -138,10 +154,12 @@ func (LightClientModule) TimestampAtHeight( return uint64(ctx.BlockTime().UnixNano()), nil } -func (LightClientModule) RecoverClient(ctx sdk.Context, clientID, substituteClientID string) error { +// RecoverClient returns an error. The localhost cannot be modified by proposals. +func (LightClientModule) RecoverClient(_ sdk.Context, _, _ string) error { return errorsmod.Wrap(clienttypes.ErrUpdateClientFailed, "cannot update localhost client with a proposal") } +// VerifyUpgradeAndUpdateState returns an error since localhost cannot be upgraded. func (LightClientModule) VerifyUpgradeAndUpdateState( ctx sdk.Context, clientID string,