Some checks failed
CodeQL / Analyze (push) Waiting to run
golangci-lint / lint (push) Waiting to run
Tests / Code Coverage / build (amd64) (push) Waiting to run
Tests / Code Coverage / build (arm64) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[additional-args:-tags="test_e2e" name:e2e path:./e2e]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:08-wasm path:./modules/light-clients/08-wasm]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:ibc-go path:.]) (push) Waiting to run
Docker Build & Push Simapp (main) / docker-build (push) Has been cancelled
240 lines
9.4 KiB
Go
240 lines
9.4 KiB
Go
package tendermint
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
errorsmod "cosmossdk.io/errors"
|
|
|
|
"git.cw.tr/mukan-network/mukan-sdk/codec"
|
|
sdk "git.cw.tr/mukan-network/mukan-sdk/types"
|
|
|
|
clienttypes "git.cw.tr/mukan-network/mukan-ibc/modules/core/02-client/types"
|
|
ibcerrors "git.cw.tr/mukan-network/mukan-ibc/modules/core/errors"
|
|
"git.cw.tr/mukan-network/mukan-ibc/modules/core/exported"
|
|
)
|
|
|
|
var _ exported.LightClientModule = (*LightClientModule)(nil)
|
|
|
|
// LightClientModule implements the core IBC api.LightClientModule interface.
|
|
type LightClientModule struct {
|
|
cdc codec.BinaryCodec
|
|
storeProvider clienttypes.StoreProvider
|
|
}
|
|
|
|
// NewLightClientModule creates and returns a new 07-tendermint LightClientModule.
|
|
func NewLightClientModule(cdc codec.BinaryCodec, storeProvider clienttypes.StoreProvider) LightClientModule {
|
|
return LightClientModule{
|
|
cdc: cdc,
|
|
storeProvider: storeProvider,
|
|
}
|
|
}
|
|
|
|
// Initialize unmarshals the provided client and consensus states and performs basic validation. It calls into the
|
|
// clientState.initialize method.
|
|
func (l LightClientModule) Initialize(ctx sdk.Context, clientID string, clientStateBz, consensusStateBz []byte) error {
|
|
var clientState ClientState
|
|
if err := l.cdc.Unmarshal(clientStateBz, &clientState); err != nil {
|
|
return fmt.Errorf("failed to unmarshal client state bytes into client state: %w", err)
|
|
}
|
|
|
|
if err := clientState.Validate(); err != nil {
|
|
return err
|
|
}
|
|
|
|
var consensusState ConsensusState
|
|
if err := l.cdc.Unmarshal(consensusStateBz, &consensusState); err != nil {
|
|
return fmt.Errorf("failed to unmarshal consensus state bytes into consensus state: %w", err)
|
|
}
|
|
|
|
if err := consensusState.ValidateBasic(); err != nil {
|
|
return err
|
|
}
|
|
|
|
clientStore := l.storeProvider.ClientStore(ctx, clientID)
|
|
|
|
return clientState.initialize(ctx, l.cdc, clientStore, &consensusState)
|
|
}
|
|
|
|
// VerifyClientMessage obtains the client state associated with the client identifier and calls into the clientState.VerifyClientMessage method.
|
|
func (l LightClientModule) VerifyClientMessage(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) error {
|
|
clientStore := l.storeProvider.ClientStore(ctx, clientID)
|
|
clientState, found := getClientState(clientStore, l.cdc)
|
|
if !found {
|
|
return errorsmod.Wrap(clienttypes.ErrClientNotFound, clientID)
|
|
}
|
|
|
|
return clientState.VerifyClientMessage(ctx, l.cdc, clientStore, clientMsg)
|
|
}
|
|
|
|
// CheckForMisbehaviour obtains the client state associated with the client identifier and calls into the clientState.CheckForMisbehaviour method.
|
|
func (l LightClientModule) CheckForMisbehaviour(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) bool {
|
|
clientStore := l.storeProvider.ClientStore(ctx, clientID)
|
|
clientState, found := getClientState(clientStore, l.cdc)
|
|
if !found {
|
|
panic(errorsmod.Wrap(clienttypes.ErrClientNotFound, clientID))
|
|
}
|
|
|
|
return clientState.CheckForMisbehaviour(ctx, l.cdc, clientStore, clientMsg)
|
|
}
|
|
|
|
// UpdateStateOnMisbehaviour obtains the client state associated with the client identifier and calls into the clientState.UpdateStateOnMisbehaviour method.
|
|
func (l LightClientModule) UpdateStateOnMisbehaviour(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) {
|
|
clientStore := l.storeProvider.ClientStore(ctx, clientID)
|
|
clientState, found := getClientState(clientStore, l.cdc)
|
|
if !found {
|
|
panic(errorsmod.Wrap(clienttypes.ErrClientNotFound, clientID))
|
|
}
|
|
|
|
clientState.UpdateStateOnMisbehaviour(ctx, l.cdc, clientStore, clientMsg)
|
|
}
|
|
|
|
// UpdateState obtains the client state associated with the client identifier and calls into the clientState.UpdateState method.
|
|
func (l LightClientModule) UpdateState(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) []exported.Height {
|
|
clientStore := l.storeProvider.ClientStore(ctx, clientID)
|
|
clientState, found := getClientState(clientStore, l.cdc)
|
|
if !found {
|
|
panic(errorsmod.Wrap(clienttypes.ErrClientNotFound, clientID))
|
|
}
|
|
|
|
return clientState.UpdateState(ctx, l.cdc, clientStore, clientMsg)
|
|
}
|
|
|
|
// VerifyMembership obtains the client state associated with the client identifier and calls into the clientState.verifyMembership method.
|
|
func (l LightClientModule) VerifyMembership(
|
|
ctx sdk.Context,
|
|
clientID string,
|
|
height exported.Height,
|
|
delayTimePeriod uint64,
|
|
delayBlockPeriod uint64,
|
|
proof []byte,
|
|
path exported.Path,
|
|
value []byte,
|
|
) error {
|
|
clientStore := l.storeProvider.ClientStore(ctx, clientID)
|
|
clientState, found := getClientState(clientStore, l.cdc)
|
|
if !found {
|
|
return errorsmod.Wrap(clienttypes.ErrClientNotFound, clientID)
|
|
}
|
|
|
|
return clientState.verifyMembership(ctx, clientStore, l.cdc, height, delayTimePeriod, delayBlockPeriod, proof, path, value)
|
|
}
|
|
|
|
// VerifyNonMembership obtains the client state associated with the client identifier and calls into the clientState.verifyNonMembership method.
|
|
func (l LightClientModule) VerifyNonMembership(
|
|
ctx sdk.Context,
|
|
clientID string,
|
|
height exported.Height,
|
|
delayTimePeriod uint64,
|
|
delayBlockPeriod uint64,
|
|
proof []byte,
|
|
path exported.Path,
|
|
) error {
|
|
clientStore := l.storeProvider.ClientStore(ctx, clientID)
|
|
clientState, found := getClientState(clientStore, l.cdc)
|
|
if !found {
|
|
return errorsmod.Wrap(clienttypes.ErrClientNotFound, clientID)
|
|
}
|
|
|
|
return clientState.verifyNonMembership(ctx, clientStore, l.cdc, height, delayTimePeriod, delayBlockPeriod, proof, path)
|
|
}
|
|
|
|
// Status obtains the client state associated with the client identifier and calls into the clientState.status method.
|
|
func (l LightClientModule) Status(ctx sdk.Context, clientID string) exported.Status {
|
|
clientStore := l.storeProvider.ClientStore(ctx, clientID)
|
|
clientState, found := getClientState(clientStore, l.cdc)
|
|
if !found {
|
|
return exported.Unknown
|
|
}
|
|
|
|
return clientState.status(ctx, clientStore, l.cdc)
|
|
}
|
|
|
|
// LatestHeight returns the latest height for the client state for the given client identifier.
|
|
// If no client is present for the provided client identifier a zero value height is returned.
|
|
func (l LightClientModule) LatestHeight(ctx sdk.Context, clientID string) exported.Height {
|
|
clientStore := l.storeProvider.ClientStore(ctx, clientID)
|
|
clientState, found := getClientState(clientStore, l.cdc)
|
|
if !found {
|
|
return clienttypes.ZeroHeight()
|
|
}
|
|
|
|
return clientState.LatestHeight
|
|
}
|
|
|
|
// TimestampAtHeight obtains the client state associated with the client identifier and calls into the clientState.getTimestampAtHeight method.
|
|
func (l LightClientModule) TimestampAtHeight(
|
|
ctx sdk.Context,
|
|
clientID string,
|
|
height exported.Height,
|
|
) (uint64, error) {
|
|
clientStore := l.storeProvider.ClientStore(ctx, clientID)
|
|
clientState, found := getClientState(clientStore, l.cdc)
|
|
if !found {
|
|
return 0, errorsmod.Wrap(clienttypes.ErrClientNotFound, clientID)
|
|
}
|
|
|
|
return clientState.getTimestampAtHeight(clientStore, l.cdc, height)
|
|
}
|
|
|
|
// RecoverClient asserts that the substitute client is a tendermint client. It obtains the client state associated with the
|
|
// subject client and calls into the subjectClientState.CheckSubstituteAndUpdateState method.
|
|
func (l LightClientModule) RecoverClient(ctx sdk.Context, clientID, substituteClientID string) error {
|
|
substituteClientType, _, err := clienttypes.ParseClientIdentifier(substituteClientID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if substituteClientType != exported.Tendermint {
|
|
return errorsmod.Wrapf(clienttypes.ErrInvalidClientType, "expected: %s, got: %s", exported.Tendermint, substituteClientType)
|
|
}
|
|
|
|
clientStore := l.storeProvider.ClientStore(ctx, clientID)
|
|
clientState, found := getClientState(clientStore, l.cdc)
|
|
if !found {
|
|
return errorsmod.Wrap(clienttypes.ErrClientNotFound, clientID)
|
|
}
|
|
|
|
substituteClientStore := l.storeProvider.ClientStore(ctx, substituteClientID)
|
|
substituteClient, found := getClientState(substituteClientStore, l.cdc)
|
|
if !found {
|
|
return errorsmod.Wrap(clienttypes.ErrClientNotFound, substituteClientID)
|
|
}
|
|
|
|
return clientState.CheckSubstituteAndUpdateState(ctx, l.cdc, clientStore, substituteClientStore, substituteClient)
|
|
}
|
|
|
|
// VerifyUpgradeAndUpdateState obtains the client state associated with the client identifier and calls into the clientState.VerifyUpgradeAndUpdateState method.
|
|
// The new client and consensus states will be unmarshaled and an error is returned if the new client state is not at a height greater
|
|
// than the existing client.
|
|
func (l LightClientModule) VerifyUpgradeAndUpdateState(
|
|
ctx sdk.Context,
|
|
clientID string,
|
|
newClient []byte,
|
|
newConsState []byte,
|
|
upgradeClientProof,
|
|
upgradeConsensusStateProof []byte,
|
|
) error {
|
|
var newClientState ClientState
|
|
if err := l.cdc.Unmarshal(newClient, &newClientState); err != nil {
|
|
return errorsmod.Wrap(clienttypes.ErrInvalidClient, err.Error())
|
|
}
|
|
|
|
var newConsensusState ConsensusState
|
|
if err := l.cdc.Unmarshal(newConsState, &newConsensusState); err != nil {
|
|
return errorsmod.Wrap(clienttypes.ErrInvalidConsensus, err.Error())
|
|
}
|
|
|
|
clientStore := l.storeProvider.ClientStore(ctx, clientID)
|
|
clientState, found := getClientState(clientStore, l.cdc)
|
|
if !found {
|
|
return errorsmod.Wrap(clienttypes.ErrClientNotFound, clientID)
|
|
}
|
|
|
|
// last height of current counterparty chain must be client's latest height
|
|
lastHeight := clientState.LatestHeight
|
|
if !newClientState.LatestHeight.GT(lastHeight) {
|
|
return errorsmod.Wrapf(ibcerrors.ErrInvalidHeight, "upgraded client height %s must be at greater than current client height %s", newClientState.LatestHeight, lastHeight)
|
|
}
|
|
|
|
return clientState.VerifyUpgradeAndUpdateState(ctx, l.cdc, clientStore, &newClientState, &newConsensusState, upgradeClientProof, upgradeConsensusStateProof)
|
|
}
|