diff --git a/x/lightclient/ante/ibc_msg_update_client.go b/x/lightclient/ante/ibc_msg_update_client.go index cf3412fd7..de6cd9aaf 100644 --- a/x/lightclient/ante/ibc_msg_update_client.go +++ b/x/lightclient/ante/ibc_msg_update_client.go @@ -75,7 +75,6 @@ func (i IBCMessagesDecorator) HandleMsgUpdateClient(ctx sdk.Context, msg *ibccli h := header.GetHeight().GetRevisionHeight() sInfo, err := i.raK.FindStateInfoByHeight(ctx, rollapp.RollappId, h) if errorsmod.IsOf(err, gerrc.ErrNotFound) { - // the header is optimistic: the state update has not yet been received, so we save optimistically return errorsmod.Wrap(i.k.SaveSigner(ctx, seq.Address, msg.ClientId, h), "save updater") } diff --git a/x/lightclient/keeper/canonical_client.go b/x/lightclient/keeper/canonical_client.go index 161f98da6..39bb2a3fd 100644 --- a/x/lightclient/keeper/canonical_client.go +++ b/x/lightclient/keeper/canonical_client.go @@ -102,7 +102,7 @@ func (k Keeper) validClient(ctx sdk.Context, clientID string, cs exported.Client // iterate until we pass the fraud height if h.GetRevisionHeight() < minHeight { - return true + return true // break } consensusState, ok := k.ibcClientKeeper.GetClientConsensusState(ctx, clientID, h) @@ -114,21 +114,14 @@ func (k Keeper) validClient(ctx sdk.Context, clientID string, cs exported.Client return false } - var stateInfo *rollapptypes.StateInfo - stateInfo, err = k.rollappKeeper.FindStateInfoByHeight(ctx, rollappId, h.GetRevisionHeight()) - if err != nil { - err = errorsmod.Wrapf(err, "find state info by height h: %d", h.GetRevisionHeight()) - return true - } - - err = k.ValidateUpdatePessimistically(ctx, stateInfo, tmConsensusState, h.GetRevisionHeight()) + err = k.ValidateUpdatePessimistically(ctx, sInfo, tmConsensusState, h.GetRevisionHeight()) if err != nil { err = errorsmod.Wrapf(err, "validate pessimistic h: %d", h.GetRevisionHeight()) - return true + return true // break } atLeastOneMatch = true - return false + return true // break }) // Need to be sure that at least one consensus state agrees with a state update // (There are also no disagreeing consensus states. There may be some consensus states @@ -144,7 +137,10 @@ func (k Keeper) validClient(ctx sdk.Context, clientID string, cs exported.Client } func (k Keeper) ValidateUpdatePessimistically(ctx sdk.Context, sInfo *rollapptypes.StateInfo, consState *ibctm.ConsensusState, h uint64) error { - bd, _ := sInfo.GetBlockDescriptor(h) + bd, ok := sInfo.GetBlockDescriptor(h) + if !ok { + return errorsmod.Wrapf(gerrc.ErrInternal, "no block descriptor found for height %d", h) + } nextSeq, err := k.SeqK.RealSequencer(ctx, sInfo.NextSequencerForHeight(h)) if err != nil { return errorsmod.Wrap(errors.Join(err, gerrc.ErrInternal), "get sequencer of state info") diff --git a/x/lightclient/keeper/hook_listener.go b/x/lightclient/keeper/hook_listener.go index fb858ba0d..9bf7444cc 100644 --- a/x/lightclient/keeper/hook_listener.go +++ b/x/lightclient/keeper/hook_listener.go @@ -1,15 +1,10 @@ package keeper import ( - "errors" - errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" ibcclienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" - "github.com/dymensionxyz/dymension/v3/x/lightclient/types" - sequencertypes "github.com/dymensionxyz/dymension/v3/x/sequencer/types" - "github.com/dymensionxyz/gerr-cosmos/gerrc" rollapptypes "github.com/dymensionxyz/dymension/v3/x/rollapp/types" ) @@ -44,6 +39,9 @@ func (hook rollappHook) AfterUpdateState( client, ok = hook.k.FindMatchingClient(ctx, stateInfo) if ok { hook.k.SetCanonicalClient(ctx, rollappId, client) + if err := hook.k.PruneSignersBelow(ctx, client, stateInfo.GetLatestHeight()+1); err != nil { + return errorsmod.Wrap(err, "prune signers") + } } return nil } @@ -57,24 +55,13 @@ func (hook rollappHook) AfterUpdateState( return nil } - // TODO: check hard fork in progress here - - seq, err := hook.k.SeqK.RealSequencer(ctx, stateInfo.Sequencer) - if err != nil { - return errorsmod.Wrap(errors.Join(gerrc.ErrInternal, err), "get sequencer for state info") - } - - // [hStart-1..,hEnd) is correct because we compare against a next validators hash - for h := stateInfo.GetStartHeight() - 1; h < stateInfo.GetLatestHeight(); h++ { - if err := hook.validateOptimisticUpdate(ctx, rollappId, client, seq, stateInfo, h); err != nil { - return errorsmod.Wrap(err, "validate optimistic update") - } + if err := hook.validateOptimisticUpdate(ctx, client, stateInfo); err != nil { + return errorsmod.Wrap(err, "validate optimistic update") } - // we now verified everything up to and including stateInfo.GetLatestHeight()-1 - // so we should prune everything up to stateInfo.GetLatestHeight()-1 + // we now verified everything up to and including stateInfo.GetLatestHeight() // this removes the unbonding condition for the sequencers - if err := hook.k.PruneSignersBelow(ctx, client, stateInfo.GetLatestHeight()); err != nil { + if err := hook.k.PruneSignersBelow(ctx, client, stateInfo.GetLatestHeight()+1); err != nil { return errorsmod.Wrap(err, "prune signers") } @@ -83,52 +70,25 @@ func (hook rollappHook) AfterUpdateState( func (hook rollappHook) validateOptimisticUpdate( ctx sdk.Context, - rollapp string, client string, - nextSequencer sequencertypes.Sequencer, - cache *rollapptypes.StateInfo, // a place to look up the BD for a height - h uint64, + stateInfo *rollapptypes.StateInfo, // a place to look up the BD for a height ) error { - got, ok := hook.getConsensusState(ctx, client, h) - if !ok { - // done, nothing to validate - return nil - } - expectBD, err := hook.getBlockDescriptor(ctx, rollapp, cache, h) - if err != nil { - return err - } - expect := types.RollappState{ - BlockDescriptor: expectBD, - NextBlockSequencer: nextSequencer, - } + for h := stateInfo.GetStartHeight(); h <= stateInfo.GetLatestHeight(); h++ { + got, ok := hook.getConsensusState(ctx, client, h) + if !ok { + continue + } - err = types.CheckCompatibility(*got, expect) - if err != nil { - return errors.Join(gerrc.ErrFault, err) + err := hook.k.ValidateUpdatePessimistically(ctx, stateInfo, got, h) + if err != nil { + return errorsmod.Wrapf(err, "validate pessimistic h: %d", h) + } } // everything is fine return nil } -func (hook rollappHook) getBlockDescriptor(ctx sdk.Context, - rollapp string, - cache *rollapptypes.StateInfo, - h uint64, -) (rollapptypes.BlockDescriptor, error) { - stateInfo := cache - if !stateInfo.ContainsHeight(h) { - var err error - stateInfo, err = hook.k.rollappKeeper.FindStateInfoByHeight(ctx, rollapp, h) - if err != nil { - return rollapptypes.BlockDescriptor{}, errors.Join(err, gerrc.ErrInternal) - } - } - bd, _ := stateInfo.GetBlockDescriptor(h) - return bd, nil -} - func (hook rollappHook) getConsensusState(ctx sdk.Context, client string, h uint64,