Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(lightclient): removed the need for next stateInfo for valiadition #1467

Draft
wants to merge 88 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
c658ec5
initial renames according to adr
mtsitrin Oct 22, 2024
777dc32
reverting states
mtsitrin Oct 22, 2024
b713df3
removed frozen notation. added revision number in rollapp object
mtsitrin Oct 22, 2024
c3a08a5
Merge branch 'main' into mtsitrin/937-rollapp-hard-fork-hub-side
mtsitrin Oct 27, 2024
4d7ca18
cleanup
mtsitrin Oct 27, 2024
fffe076
UT compiles
mtsitrin Oct 27, 2024
e61d2af
fixed state deletion on fraud
mtsitrin Oct 27, 2024
654b069
UT pass
mtsitrin Oct 27, 2024
6782578
fixed StateInfoByHeight UT
mtsitrin Oct 28, 2024
c4d25ac
chainId revision check moved back to create rollapp. as it mess up dy…
mtsitrin Oct 28, 2024
3e06f20
PR comments
mtsitrin Oct 30, 2024
411f4c5
fixed basic sequencer logic to unbond all
mtsitrin Oct 30, 2024
b08a106
feat(hard_fork): part2 (Delyayed ack callback) (#1355)
mtsitrin Oct 31, 2024
617fa63
feat(hard_fork): Lightclient rollback (#1363)
mtsitrin Oct 31, 2024
076136a
feat(hard_fork): DRS and stateUpdate (#1369)
mtsitrin Oct 31, 2024
fe49c1c
feat(hard_fork): rollapp fraud proposal (#1371)
mtsitrin Nov 3, 2024
209f91e
feat(hard_fork): revision start height (#1373)
mtsitrin Nov 3, 2024
8e943b8
cleanup
mtsitrin Nov 3, 2024
31d5d25
Merge branch 'main' into mtsitrin/937-rollapp-hard-fork-hub-side
mtsitrin Nov 3, 2024
9f298af
lightClient doesn't trigger hard fork
mtsitrin Nov 3, 2024
67ec46a
clearing consesnsus state in descending order
mtsitrin Nov 3, 2024
3fda55a
fix UT
mtsitrin Nov 3, 2024
612a673
fraud proposal validates genesis bridge completed
mtsitrin Nov 3, 2024
4078e39
validate revision in header.Header.Version.App
mtsitrin Nov 3, 2024
e57988a
linter
mtsitrin Nov 3, 2024
13a56a5
linter
mtsitrin Nov 3, 2024
e6122d1
feat(hard_fork): delayed ack should create commitment after rolling b…
mtsitrin Nov 3, 2024
ef4afb1
register proposal handler
mtsitrin Nov 4, 2024
d2f8152
updating next proposer on state infos
mtsitrin Nov 4, 2024
d5933ff
feat(hard_fork): update hard fork to support new `x/sequencer` update…
mtsitrin Nov 6, 2024
1ca02de
Merge branch 'main' into mtsitrin/937-rollapp-hard-fork-hub-side
mtsitrin Nov 6, 2024
99e00ac
linter
mtsitrin Nov 6, 2024
10186d4
UT fix
mtsitrin Nov 6, 2024
839b3f3
minor update to fraud proposal
mtsitrin Nov 6, 2024
5a25e6d
delete pendingPacketsByAddress on the delayedAck
mtsitrin Nov 6, 2024
3639156
fixed seqeucner heoght pruning
mtsitrin Nov 6, 2024
c656859
fraud proposal supports future heights
mtsitrin Nov 6, 2024
204de23
fork hook doesn't return error
mtsitrin Nov 6, 2024
e318180
rotation doesn't go through sentinel proposer
mtsitrin Nov 6, 2024
5ec9170
simplified k.UpdateRollappPacketWithStatus interface
mtsitrin Nov 6, 2024
7c40f53
minor
mtsitrin Nov 6, 2024
5a3f9b5
minor log
mtsitrin Nov 6, 2024
6fc604a
Merge branch 'main' into mtsitrin/937-rollapp-hard-fork-hub-side
mtsitrin Nov 7, 2024
6914afb
fixed lightclient when setting canonical channel
mtsitrin Nov 7, 2024
47be8d3
feat(migrations): renamed vulnerable rollapps to obsolete (#1436)
keruch Nov 8, 2024
4f5c5bd
Danwt/mtsitrin 937 rollapp hard fork hub side rewardee (#1441)
danwt Nov 8, 2024
c4b48a7
Danwt/fix upgrade conflicts (#1442)
danwt Nov 8, 2024
5c42bf8
fix frozen
danwt Nov 8, 2024
569ff8f
Merge branch 'main' into mtsitrin/937-rollapp-hard-fork-hub-side
mtsitrin Nov 9, 2024
94f52ec
refactored to use Finalaization queue by rollappId
mtsitrin Nov 9, 2024
40b3557
fixed pruning of finalization queue
mtsitrin Nov 10, 2024
29bd020
cleared unused expected methods
mtsitrin Nov 10, 2024
44eccc4
linter
mtsitrin Nov 10, 2024
f44f36c
more cleanup
mtsitrin Nov 10, 2024
9c43639
comments
mtsitrin Nov 10, 2024
e3570f5
fixed packet commitment and lightclient comments
mtsitrin Nov 10, 2024
9cbc795
return err on HardFork hooks
mtsitrin Nov 10, 2024
44b14e2
not forking on state update with obsolete DRS
mtsitrin Nov 10, 2024
7e51835
linter
mtsitrin Nov 10, 2024
9743b8b
Merge branch 'main' into mtsitrin/937-rollapp-hard-fork-hub-side
mtsitrin Nov 10, 2024
5f6c7f6
renamed fraudHeight
mtsitrin Nov 10, 2024
9a482ba
add error to kickProposer flow
mtsitrin Nov 10, 2024
c25d2bc
fixed UT
mtsitrin Nov 10, 2024
3a876f4
deleteBySender moved to DeletePacket
mtsitrin Nov 10, 2024
5f69b7f
fixed surprise linter
mtsitrin Nov 10, 2024
861a25d
Merge branch 'main' into mtsitrin/937-rollapp-hard-fork-hub-side
mtsitrin Nov 10, 2024
73636ee
DRY pruneSigners code
mtsitrin Nov 11, 2024
93a59c8
feat(sequencer): hardforking when rotating to sentinel (#1455)
mtsitrin Nov 12, 2024
5fceea4
Merge branch 'main' into mtsitrin/937-rollapp-hard-fork-hub-side
mtsitrin Nov 12, 2024
14a5e85
PR comments
mtsitrin Nov 12, 2024
9f8b3ce
AfterRecoveryFromHalt hook cleanup
mtsitrin Nov 12, 2024
d0fb6c8
fixed missing setConsensusMetadata. fixed kicked proposer unbond
mtsitrin Nov 13, 2024
4918834
fixed unbond store
mtsitrin Nov 13, 2024
fb21c59
refactor ValidateUpdatePessimistically to use single state info
mtsitrin Nov 13, 2024
70f4f91
updated expected keeper
mtsitrin Nov 13, 2024
1deed9f
dried out the state update hook
mtsitrin Nov 13, 2024
0e31db9
Merge branch 'main' into 1308-xlightclient-redundent-call-for-findsta…
mtsitrin Nov 14, 2024
e4c3504
removed unused replace
mtsitrin Nov 14, 2024
d2d154f
Merge branch 'main' into 1308-xlightclient-redundent-call-for-findsta…
mtsitrin Nov 17, 2024
358718e
unified canonical and ongoingvalidation
mtsitrin Nov 17, 2024
0088099
fix future height check
mtsitrin Nov 17, 2024
780a46b
DRY canonical setting code
mtsitrin Nov 17, 2024
4859c51
DRY canonical setting code
mtsitrin Nov 17, 2024
b28295a
revert renaming
mtsitrin Nov 17, 2024
4d50d9c
removed canonical setting on update headers
mtsitrin Nov 17, 2024
a72bc23
simplified the StateInfo and LC header validation
mtsitrin Dec 3, 2024
5911b27
fixed tests compile
mtsitrin Dec 3, 2024
490f5be
Merge branch 'main' into 1308-xlightclient-redundent-call-for-findsta…
mtsitrin Dec 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,5 @@ replace (

// broken goleveldb
github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.29
golang.org/x/exp => golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb
)
2 changes: 1 addition & 1 deletion ibctesting/light_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func (s *lightClientSuite) TestSetCanonicalClient_ConsStateMismatch() {
_, err := s.lightclientMsgServer().SetCanonicalClient(s.hubCtx(), setCanonMsg)
s.Require().Error(err)

// Update the rollapp state - this will trigger the check for prospective canonical client
// Update the rollapp state so we could attempt to set the canonical client
msgUpdateState := rollapptypes.NewMsgUpdateState(
s.hubChain().SenderAccount.GetAddress().String(),
rollappChainID(),
Expand Down
10 changes: 10 additions & 0 deletions testutil/keeper/lightclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ type MockIBCCLientKeeper struct {
clientStates map[string]exported.ClientState
}

// IterateConsensusStates implements types.IBCClientKeeperExpected.
func (m *MockIBCCLientKeeper) IterateConsensusStates(ctx sdk.Context, cb func(clientID string, cs ibcclienttypes.ConsensusStateWithHeight) bool) {
panic("unimplemented")
}

// ClientStore implements types.IBCClientKeeperExpected.
func (m *MockIBCCLientKeeper) ClientStore(ctx sdk.Context, clientID string) storetypes.KVStore {
panic("unimplemented")
Expand Down Expand Up @@ -182,6 +187,11 @@ func NewMockSequencerKeeper(sequencers map[string]*sequencertypes.Sequencer) *Mo

type MockRollappKeeper struct{}

// GetLatestStateInfoIndex implements types.RollappKeeperExpected.
func (m *MockRollappKeeper) GetLatestStateInfoIndex(ctx sdk.Context, rollappId string) (rollapptypes.StateInfoIndex, bool) {
panic("unimplemented")
}

func (m *MockRollappKeeper) IsFirstHeightOfLatestFork(ctx sdk.Context, rollappId string, revision, height uint64) bool {
return false
}
Expand Down
78 changes: 21 additions & 57 deletions x/lightclient/ante/ibc_msg_update_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@ import (
ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint"
"github.com/dymensionxyz/gerr-cosmos/gerrc"

"github.com/dymensionxyz/dymension/v3/x/lightclient/types"
rollapptypes "github.com/dymensionxyz/dymension/v3/x/rollapp/types"
sequencertypes "github.com/dymensionxyz/dymension/v3/x/sequencer/types"
)

var (
errIsMisbehaviour = errorsmod.Wrap(gerrc.ErrFailedPrecondition, "misbehavior evidence is disabled for canonical clients")
errNoHeader = errors.New("message does not contain header")
errProposerMismatch = errorsmod.Wrap(gerrc.ErrInvalidArgument, "validator set proposer not equal header proposer field")
)

func (i IBCMessagesDecorator) HandleMsgUpdateClient(ctx sdk.Context, msg *ibcclienttypes.MsgUpdateClient) error {
if !i.k.Enabled() {
return nil
Expand All @@ -32,6 +36,7 @@ func (i IBCMessagesDecorator) HandleMsgUpdateClient(ctx sdk.Context, msg *ibccli
if err != nil {
return errorsmod.Wrap(err, "get header")
}

seq, err := i.getSequencer(ctx, header)
err = errorsmod.Wrap(err, "get sequencer")
if errorsmod.IsOf(err, errProposerMismatch) {
Expand Down Expand Up @@ -70,26 +75,27 @@ func (i IBCMessagesDecorator) HandleMsgUpdateClient(ctx sdk.Context, msg *ibccli
}

h := header.GetHeight().GetRevisionHeight()
stateInfos, err := i.getStateInfos(ctx, rollapp.RollappId, h)
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
err := i.k.SaveSigner(ctx, seq.Address, msg.ClientId, h)
if err != nil {
return errorsmod.Wrap(err, "save signer")
}
return nil
}
if err != nil {
return errorsmod.Wrap(err, "get state infos")
return errorsmod.Wrap(err, "find state info by height")
}

if stateInfos.containingHPlus1 != nil {
// the header is pessimistic: the state update has already been received, so we check the header doesn't mismatch
return errorsmod.Wrap(i.validateUpdatePessimistically(ctx, stateInfos, header.ConsensusState(), h), "validate pessimistic")
err = i.k.ValidateHeaderAgainstStateInfo(ctx, sInfo, header.ConsensusState(), h)
if err != nil {
return errorsmod.Wrap(err, "validate pessimistic")
}

// 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")
return nil
}

var (
errIsMisbehaviour = errorsmod.Wrap(gerrc.ErrFailedPrecondition, "misbehavior evidence is disabled for canonical clients")
errNoHeader = errors.New("message does not contain header")
errProposerMismatch = errorsmod.Wrap(gerrc.ErrInvalidArgument, "validator set proposer not equal header proposer field")
)

func (i IBCMessagesDecorator) getSequencer(ctx sdk.Context, header *ibctm.Header) (sequencertypes.Sequencer, error) {
proposerBySignature := header.ValidatorSet.Proposer.GetAddress()
proposerByData := header.Header.ProposerAddress
Expand All @@ -115,45 +121,3 @@ func getHeader(msg *ibcclienttypes.MsgUpdateClient) (*ibctm.Header, error) {
}
return header, nil
}

// if containingHPlus1 is not nil then containingH also guaranteed to not be nil
type stateInfos struct {
containingH *rollapptypes.StateInfo
containingHPlus1 *rollapptypes.StateInfo
}

// getStateInfos gets state infos for h and h+1
func (i IBCMessagesDecorator) getStateInfos(ctx sdk.Context, rollapp string, h uint64) (stateInfos, error) {
// Check if there are existing block descriptors for the given height of client state
s0, err := i.raK.FindStateInfoByHeight(ctx, rollapp, h)
if errorsmod.IsOf(err, gerrc.ErrNotFound) {
return stateInfos{}, nil
}
if err != nil {
return stateInfos{}, err
}
s1 := s0
if !s1.ContainsHeight(h + 1) {
s1, err = i.raK.FindStateInfoByHeight(ctx, rollapp, h+1)
if errorsmod.IsOf(err, gerrc.ErrNotFound) {
return stateInfos{s0, nil}, nil
}
if err != nil {
return stateInfos{}, err
}
}
return stateInfos{s0, s1}, nil
}

func (i IBCMessagesDecorator) validateUpdatePessimistically(ctx sdk.Context, infos stateInfos, consState *ibctm.ConsensusState, h uint64) error {
bd, _ := infos.containingH.GetBlockDescriptor(h)
seq, err := i.k.SeqK.RealSequencer(ctx, infos.containingHPlus1.Sequencer)
if err != nil {
return errorsmod.Wrap(errors.Join(err, gerrc.ErrInternal), "get sequencer of state info")
}
rollappState := types.RollappState{
BlockDescriptor: bd,
NextBlockSequencer: seq,
}
return errorsmod.Wrap(types.CheckCompatibility(*consState, rollappState), "check compatibility")
}
10 changes: 10 additions & 0 deletions x/lightclient/ante/ibc_msgs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ type MockRollappKeeper struct {
stateInfos map[string]map[uint64]rollapptypes.StateInfo
}

// GetLatestStateInfoIndex implements types.RollappKeeperExpected.
func (m *MockRollappKeeper) GetLatestStateInfoIndex(ctx sdk.Context, rollappId string) (rollapptypes.StateInfoIndex, bool) {
panic("unimplemented")
}

func (m *MockRollappKeeper) IsFirstHeightOfLatestFork(ctx sdk.Context, rollappId string, revision, height uint64) bool {
panic("implement me")
}
Expand Down Expand Up @@ -75,6 +80,11 @@ type MockIBCClientKeeper struct {
clientStates map[string]exported.ClientState
}

// IterateConsensusStates implements types.IBCClientKeeperExpected.
func (m *MockIBCClientKeeper) IterateConsensusStates(ctx sdk.Context, cb func(clientID string, cs ibcclienttypes.ConsensusStateWithHeight) bool) {
panic("unimplemented")
}

// ClientStore implements types.IBCClientKeeperExpected.
func (m *MockIBCClientKeeper) ClientStore(ctx sdk.Context, clientID string) types.KVStore {
panic("unimplemented")
Expand Down
100 changes: 46 additions & 54 deletions x/lightclient/keeper/canonical_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ import (

errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/query"
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/gerr-cosmos/gerrc"
"github.com/dymensionxyz/sdk-utils/utils/uevent"

"github.com/dymensionxyz/dymension/v3/x/lightclient/types"
rollapptypes "github.com/dymensionxyz/dymension/v3/x/rollapp/types"
)

var (
ErrNoMatch = gerrc.ErrFailedPrecondition.Wrap("not at least one cons state matches the rollapp state")
ErrMismatch = gerrc.ErrInvalidArgument.Wrap("consensus state mismatch")
ErrParamsMismatch = gerrc.ErrInvalidArgument.Wrap("params")
)

// intended to be called by relayer, but can be called by anyone
Expand Down Expand Up @@ -39,14 +44,9 @@ func (k *Keeper) TrySetCanonicalClient(ctx sdk.Context, clientID string) error {
return gerrc.ErrAlreadyExists.Wrap("canonical client for rollapp")
}

latestHeight, ok := k.rollappKeeper.GetLatestHeight(ctx, rollappID)
if !ok {
return gerrc.ErrNotFound.Wrap("latest rollapp height")
}

err := k.validClient(ctx, clientID, clientState, rollappID, latestHeight)
err := k.validClient(ctx, clientID, clientState, rollappID)
if err != nil {
return errorsmod.Wrap(err, "unsafe to mark client canonical: check that sequencer has posted a recent state update")
return errorsmod.Wrap(err, "unsafe to mark client canonical")
}

k.SetCanonicalClient(ctx, rollappID, clientID)
Expand Down Expand Up @@ -93,69 +93,43 @@ func (k Keeper) expectedClient() ibctm.ClientState {
return types.DefaultExpectedCanonicalClientParams()
}

var (
ErrNoMatch = gerrc.ErrFailedPrecondition.Wrap("not at least one cons state matches the rollapp state")
ErrMismatch = gerrc.ErrInvalidArgument.Wrap("consensus state mismatch")
ErrParamsMismatch = gerrc.ErrInvalidArgument.Wrap("params")
)

// The canonical client criteria are:
// 1. The client must be a tendermint client.
// 2. The client state must match the expected client params as configured by the module
// 3. All the existing consensus states much match the corresponding height rollapp block descriptors
func (k Keeper) validClient(ctx sdk.Context, clientID string, cs *ibctm.ClientState, rollappId string, maxHeight uint64) error {
log := k.Logger(ctx).With("component", "valid client func", "rollapp", rollappId, "client", clientID)

log.Debug("top of func", "max height", maxHeight, "gas", ctx.GasMeter().GasConsumed())

func (k Keeper) validClient(ctx sdk.Context, clientID string, cs *ibctm.ClientState, rollappId string) error {
expClient := k.expectedClient()

if err := types.IsCanonicalClientParamsValid(cs, &expClient); err != nil {
return errors.Join(err, ErrParamsMismatch)
}

// FIXME: No need to get all consensus states. should iterate over the consensus states
res, err := k.ibcClientKeeper.ConsensusStateHeights(ctx, &ibcclienttypes.QueryConsensusStateHeightsRequest{
ClientId: clientID,
Pagination: &query.PageRequest{Limit: maxHeight},
})
log.Debug("after fetch heights", "max height", maxHeight, "gas", ctx.GasMeter().GasConsumed())
if err != nil {
return errorsmod.Wrap(err, "cons state heights")
sinfo, ok := k.rollappKeeper.GetLatestStateInfoIndex(ctx, rollappId)
if !ok {
return gerrc.ErrNotFound.Wrap("latest state info index")
}

baseHeight := k.GetFirstConsensusStateHeight(ctx, clientID)
atLeastOneMatch := false
for _, consensusHeight := range res.ConsensusStateHeights {
log.Debug("after fetch heights", "cons state height", consensusHeight.RevisionHeight, "gas", ctx.GasMeter().GasConsumed())
h := consensusHeight.GetRevisionHeight()
if maxHeight <= h {
break
for i := sinfo.Index; i > 0; i-- {
sInfo, ok := k.rollappKeeper.GetStateInfo(ctx, rollappId, i)
if !ok {
return errorsmod.Wrap(gerrc.ErrInternal, "get state info")
}
consensusState, _ := k.ibcClientKeeper.GetClientConsensusState(ctx, clientID, consensusHeight)
tmConsensusState, _ := consensusState.(*ibctm.ConsensusState)
stateInfoH, err := k.rollappKeeper.FindStateInfoByHeight(ctx, rollappId, h)
matched, err := k.ValidateStateInfoAgainstConsensusStates(ctx, clientID, &sInfo)
if err != nil {
return errorsmod.Wrapf(err, "find state info by height h: %d", h)
return errors.Join(ErrMismatch, err)
}
stateInfoHplus1, err := k.rollappKeeper.FindStateInfoByHeight(ctx, rollappId, h+1)
if err != nil {
return errorsmod.Wrapf(err, "find state info by height h+1: %d", h+1)
}
bd, _ := stateInfoH.GetBlockDescriptor(h)

nextSeq, err := k.SeqK.RealSequencer(ctx, stateInfoHplus1.Sequencer)
if err != nil {
return errorsmod.Wrap(err, "get sequencer")
if matched {
atLeastOneMatch = true
}
rollappState := types.RollappState{
BlockDescriptor: bd,
NextBlockSequencer: nextSeq,
}
err = types.CheckCompatibility(*tmConsensusState, rollappState)
if err != nil {
return errorsmod.Wrapf(errors.Join(ErrMismatch, err), "check compatibility: height: %d", h)

// break point with the lowest height of the consensus states
if sInfo.StartHeight > baseHeight {
break
}
atLeastOneMatch = true
}

// 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
// for future state updates, which will incur a fraud if they disagree.)
mtsitrin marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -164,3 +138,21 @@ func (k Keeper) validClient(ctx sdk.Context, clientID string, cs *ibctm.ClientSt
}
return nil
}

func (k Keeper) ValidateHeaderAgainstStateInfo(ctx sdk.Context, sInfo *rollapptypes.StateInfo, consState *ibctm.ConsensusState, h uint64) error {
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")
}

rollappState := types.RollappState{
BlockDescriptor: bd,
NextBlockSequencer: nextSeq,
}
return errorsmod.Wrap(types.CheckCompatibility(*consState, rollappState), "check compatibility")
}
25 changes: 25 additions & 0 deletions x/lightclient/keeper/client_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@ import (
ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint"
)

// IterateConsensusStateDescending iterates through all consensus states in descending order
// until cb returns true.
func IterateConsensusStateDescending(clientStore sdk.KVStore, cb func(height exported.Height) (stop bool)) {
iterator := sdk.KVStoreReversePrefixIterator(clientStore, []byte(ibctm.KeyIterateConsensusStatePrefix))
defer iterator.Close() // nolint: errcheck

for ; iterator.Valid(); iterator.Next() {
iterKey := iterator.Key()
height := ibctm.GetHeightFromIterationKey(iterKey)
if cb(height) {
break
}
}
}

// functions here copied from ibc-go/modules/core/02-client/keeper/
// as we need direct access to the client store

Expand Down Expand Up @@ -91,3 +106,13 @@ func deleteIterationKey(clientStore sdk.KVStore, height exported.Height) {
key := ibctm.IterationKey(height)
clientStore.Delete(key)
}

// GetFirstHeight returns the lowest height available for a client.
func (k Keeper) GetFirstConsensusStateHeight(ctx sdk.Context, clientID string) uint64 {
height := clienttypes.Height{}
k.ibcClientKeeper.IterateConsensusStates(ctx, func(clientID string, cs clienttypes.ConsensusStateWithHeight) bool {
height = cs.Height
return true
})
return height.GetRevisionHeight()
}
Loading
Loading