github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/core/04-channel/keeper/keeper.go (about)

     1  package keeper
     2  
     3  import (
     4  	"strconv"
     5  	"strings"
     6  
     7  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec"
     8  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     9  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
    10  	capabilitykeeper "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/capability/keeper"
    11  	capabilitytypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/capability/types"
    12  	clienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types"
    13  	connectiontypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/03-connection/types"
    14  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/types"
    15  	porttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/05-port/types"
    16  	host "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/24-host"
    17  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/common"
    18  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/exported"
    19  	"github.com/fibonacci-chain/fbc/libs/tendermint/libs/log"
    20  	db "github.com/fibonacci-chain/fbc/libs/tm-db"
    21  )
    22  
    23  // Keeper defines the IBC channel keeper
    24  type Keeper struct {
    25  	// implements gRPC QueryServer interface
    26  	types.QueryServer
    27  
    28  	storeKey         sdk.StoreKey
    29  	cdc              *codec.CodecProxy
    30  	clientKeeper     types.ClientKeeper
    31  	connectionKeeper types.ConnectionKeeper
    32  	portKeeper       types.PortKeeper
    33  	scopedKeeper     *capabilitykeeper.ScopedKeeper
    34  }
    35  
    36  // NewKeeper creates a new IBC channel Keeper instance
    37  func NewKeeper(
    38  	cdc *codec.CodecProxy, key sdk.StoreKey,
    39  	clientKeeper types.ClientKeeper, connectionKeeper types.ConnectionKeeper,
    40  	portKeeper types.PortKeeper, scopedKeeper *capabilitykeeper.ScopedKeeper,
    41  ) Keeper {
    42  	return Keeper{
    43  		storeKey:         key,
    44  		cdc:              cdc,
    45  		clientKeeper:     clientKeeper,
    46  		connectionKeeper: connectionKeeper,
    47  		portKeeper:       portKeeper,
    48  		scopedKeeper:     scopedKeeper,
    49  	}
    50  }
    51  
    52  // Logger returns a module-specific logger.
    53  func (k Keeper) Logger(ctx sdk.Context) log.Logger {
    54  	return ctx.Logger().With("module", "x/"+host.ModuleName+"/"+types.SubModuleName)
    55  }
    56  
    57  // GenerateChannelIdentifier returns the next channel identifier.
    58  func (k Keeper) GenerateChannelIdentifier(ctx sdk.Context) string {
    59  	nextChannelSeq := k.GetNextChannelSequence(ctx)
    60  	channelID := types.FormatChannelIdentifier(nextChannelSeq)
    61  
    62  	nextChannelSeq++
    63  	k.SetNextChannelSequence(ctx, nextChannelSeq)
    64  	return channelID
    65  }
    66  
    67  // GetChannel returns a channel with a particular identifier binded to a specific port
    68  func (k Keeper) GetChannel(ctx sdk.Context, portID, channelID string) (types.Channel, bool) {
    69  	store := ctx.KVStore(k.storeKey)
    70  	bz := store.Get(host.ChannelKey(portID, channelID))
    71  	if bz == nil {
    72  		return types.Channel{}, false
    73  	}
    74  
    75  	ret := common.MustUnmarshalChannel(k.cdc, bz)
    76  	return *ret, true
    77  }
    78  
    79  // SetChannel sets a channel to the store
    80  func (k Keeper) SetChannel(ctx sdk.Context, portID, channelID string, channel types.Channel) {
    81  	store := ctx.KVStore(k.storeKey)
    82  
    83  	bz := common.MustMarshalChannel(k.cdc, &channel)
    84  	store.Set(host.ChannelKey(portID, channelID), bz)
    85  }
    86  
    87  // GetAppVersion gets the version for the specified channel.
    88  func (k Keeper) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) {
    89  	channel, found := k.GetChannel(ctx, portID, channelID)
    90  	if !found {
    91  		return "", false
    92  	}
    93  
    94  	return channel.Version, true
    95  }
    96  
    97  // GetNextChannelSequence gets the next channel sequence from the store.
    98  func (k Keeper) GetNextChannelSequence(ctx sdk.Context) uint64 {
    99  	store := ctx.KVStore(k.storeKey)
   100  	bz := store.Get([]byte(types.KeyNextChannelSequence))
   101  	if bz == nil {
   102  		panic("next channel sequence is nil")
   103  	}
   104  
   105  	return sdk.BigEndianToUint64(bz)
   106  }
   107  
   108  // SetNextChannelSequence sets the next channel sequence to the store.
   109  func (k Keeper) SetNextChannelSequence(ctx sdk.Context, sequence uint64) {
   110  	store := ctx.KVStore(k.storeKey)
   111  	bz := sdk.Uint64ToBigEndian(sequence)
   112  	store.Set([]byte(types.KeyNextChannelSequence), bz)
   113  }
   114  
   115  // GetNextSequenceSend gets a channel's next send sequence from the store
   116  func (k Keeper) GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool) {
   117  	store := ctx.KVStore(k.storeKey)
   118  	bz := store.Get(host.NextSequenceSendKey(portID, channelID))
   119  	if bz == nil {
   120  		return 0, false
   121  	}
   122  
   123  	return sdk.BigEndianToUint64(bz), true
   124  }
   125  
   126  // SetNextSequenceSend sets a channel's next send sequence to the store
   127  func (k Keeper) SetNextSequenceSend(ctx sdk.Context, portID, channelID string, sequence uint64) {
   128  	store := ctx.KVStore(k.storeKey)
   129  	bz := sdk.Uint64ToBigEndian(sequence)
   130  	store.Set(host.NextSequenceSendKey(portID, channelID), bz)
   131  }
   132  
   133  // GetNextSequenceRecv gets a channel's next receive sequence from the store
   134  func (k Keeper) GetNextSequenceRecv(ctx sdk.Context, portID, channelID string) (uint64, bool) {
   135  	store := ctx.KVStore(k.storeKey)
   136  	bz := store.Get(host.NextSequenceRecvKey(portID, channelID))
   137  	if bz == nil {
   138  		return 0, false
   139  	}
   140  
   141  	return sdk.BigEndianToUint64(bz), true
   142  }
   143  
   144  // SetNextSequenceRecv sets a channel's next receive sequence to the store
   145  func (k Keeper) SetNextSequenceRecv(ctx sdk.Context, portID, channelID string, sequence uint64) {
   146  	store := ctx.KVStore(k.storeKey)
   147  	bz := sdk.Uint64ToBigEndian(sequence)
   148  	store.Set(host.NextSequenceRecvKey(portID, channelID), bz)
   149  }
   150  
   151  // GetNextSequenceAck gets a channel's next ack sequence from the store
   152  func (k Keeper) GetNextSequenceAck(ctx sdk.Context, portID, channelID string) (uint64, bool) {
   153  	store := ctx.KVStore(k.storeKey)
   154  	bz := store.Get(host.NextSequenceAckKey(portID, channelID))
   155  	if bz == nil {
   156  		return 0, false
   157  	}
   158  
   159  	return sdk.BigEndianToUint64(bz), true
   160  }
   161  
   162  // SetNextSequenceAck sets a channel's next ack sequence to the store
   163  func (k Keeper) SetNextSequenceAck(ctx sdk.Context, portID, channelID string, sequence uint64) {
   164  	store := ctx.KVStore(k.storeKey)
   165  	bz := sdk.Uint64ToBigEndian(sequence)
   166  	store.Set(host.NextSequenceAckKey(portID, channelID), bz)
   167  }
   168  
   169  // GetPacketReceipt gets a packet receipt from the store
   170  func (k Keeper) GetPacketReceipt(ctx sdk.Context, portID, channelID string, sequence uint64) (string, bool) {
   171  	store := ctx.KVStore(k.storeKey)
   172  	bz := store.Get(host.PacketReceiptKey(portID, channelID, sequence))
   173  	if bz == nil {
   174  		return "", false
   175  	}
   176  
   177  	return string(bz), true
   178  }
   179  
   180  // SetPacketReceipt sets an empty packet receipt to the store
   181  func (k Keeper) SetPacketReceipt(ctx sdk.Context, portID, channelID string, sequence uint64) {
   182  	store := ctx.KVStore(k.storeKey)
   183  	store.Set(host.PacketReceiptKey(portID, channelID, sequence), []byte{byte(1)})
   184  }
   185  
   186  // GetPacketCommitment gets the packet commitment hash from the store
   187  func (k Keeper) GetPacketCommitment(ctx sdk.Context, portID, channelID string, sequence uint64) []byte {
   188  	store := ctx.KVStore(k.storeKey)
   189  	bz := store.Get(host.PacketCommitmentKey(portID, channelID, sequence))
   190  	return bz
   191  }
   192  
   193  // HasPacketCommitment returns true if the packet commitment exists
   194  func (k Keeper) HasPacketCommitment(ctx sdk.Context, portID, channelID string, sequence uint64) bool {
   195  	store := ctx.KVStore(k.storeKey)
   196  	return store.Has(host.PacketCommitmentKey(portID, channelID, sequence))
   197  }
   198  
   199  // SetPacketCommitment sets the packet commitment hash to the store
   200  func (k Keeper) SetPacketCommitment(ctx sdk.Context, portID, channelID string, sequence uint64, commitmentHash []byte) {
   201  	store := ctx.KVStore(k.storeKey)
   202  	store.Set(host.PacketCommitmentKey(portID, channelID, sequence), commitmentHash)
   203  }
   204  
   205  func (k Keeper) deletePacketCommitment(ctx sdk.Context, portID, channelID string, sequence uint64) {
   206  	store := ctx.KVStore(k.storeKey)
   207  	store.Delete(host.PacketCommitmentKey(portID, channelID, sequence))
   208  }
   209  
   210  // SetPacketAcknowledgement sets the packet ack hash to the store
   211  func (k Keeper) SetPacketAcknowledgement(ctx sdk.Context, portID, channelID string, sequence uint64, ackHash []byte) {
   212  	store := ctx.KVStore(k.storeKey)
   213  	store.Set(host.PacketAcknowledgementKey(portID, channelID, sequence), ackHash)
   214  }
   215  
   216  // GetPacketAcknowledgement gets the packet ack hash from the store
   217  func (k Keeper) GetPacketAcknowledgement(ctx sdk.Context, portID, channelID string, sequence uint64) ([]byte, bool) {
   218  	store := ctx.KVStore(k.storeKey)
   219  	bz := store.Get(host.PacketAcknowledgementKey(portID, channelID, sequence))
   220  	if bz == nil {
   221  		return nil, false
   222  	}
   223  	return bz, true
   224  }
   225  
   226  // HasPacketAcknowledgement check if the packet ack hash is already on the store
   227  func (k Keeper) HasPacketAcknowledgement(ctx sdk.Context, portID, channelID string, sequence uint64) bool {
   228  	store := ctx.KVStore(k.storeKey)
   229  	return store.Has(host.PacketAcknowledgementKey(portID, channelID, sequence))
   230  }
   231  
   232  // IteratePacketSequence provides an iterator over all send, receive or ack sequences.
   233  // For each sequence, cb will be called. If the cb returns true, the iterator
   234  // will close and stop.
   235  func (k Keeper) IteratePacketSequence(ctx sdk.Context, iterator db.Iterator, cb func(portID, channelID string, sequence uint64) bool) {
   236  	defer iterator.Close()
   237  	for ; iterator.Valid(); iterator.Next() {
   238  		portID, channelID, err := host.ParseChannelPath(string(iterator.Key()))
   239  		if err != nil {
   240  			// return if the key is not a channel key
   241  			return
   242  		}
   243  
   244  		sequence := sdk.BigEndianToUint64(iterator.Value())
   245  
   246  		if cb(portID, channelID, sequence) {
   247  			break
   248  		}
   249  	}
   250  }
   251  
   252  // GetAllPacketSendSeqs returns all stored next send sequences.
   253  func (k Keeper) GetAllPacketSendSeqs(ctx sdk.Context) (seqs []types.PacketSequence) {
   254  	store := ctx.KVStore(k.storeKey)
   255  	iterator := sdk.KVStorePrefixIterator(store, []byte(host.KeyNextSeqSendPrefix))
   256  	k.IteratePacketSequence(ctx, iterator, func(portID, channelID string, nextSendSeq uint64) bool {
   257  		ps := types.NewPacketSequence(portID, channelID, nextSendSeq)
   258  		seqs = append(seqs, ps)
   259  		return false
   260  	})
   261  	return seqs
   262  }
   263  
   264  // GetAllPacketRecvSeqs returns all stored next recv sequences.
   265  func (k Keeper) GetAllPacketRecvSeqs(ctx sdk.Context) (seqs []types.PacketSequence) {
   266  	store := ctx.KVStore(k.storeKey)
   267  	iterator := sdk.KVStorePrefixIterator(store, []byte(host.KeyNextSeqRecvPrefix))
   268  	k.IteratePacketSequence(ctx, iterator, func(portID, channelID string, nextRecvSeq uint64) bool {
   269  		ps := types.NewPacketSequence(portID, channelID, nextRecvSeq)
   270  		seqs = append(seqs, ps)
   271  		return false
   272  	})
   273  	return seqs
   274  }
   275  
   276  // GetAllPacketAckSeqs returns all stored next acknowledgements sequences.
   277  func (k Keeper) GetAllPacketAckSeqs(ctx sdk.Context) (seqs []types.PacketSequence) {
   278  	store := ctx.KVStore(k.storeKey)
   279  	iterator := sdk.KVStorePrefixIterator(store, []byte(host.KeyNextSeqAckPrefix))
   280  	k.IteratePacketSequence(ctx, iterator, func(portID, channelID string, nextAckSeq uint64) bool {
   281  		ps := types.NewPacketSequence(portID, channelID, nextAckSeq)
   282  		seqs = append(seqs, ps)
   283  		return false
   284  	})
   285  	return seqs
   286  }
   287  
   288  // IteratePacketCommitment provides an iterator over all PacketCommitment objects. For each
   289  // packet commitment, cb will be called. If the cb returns true, the iterator will close
   290  // and stop.
   291  func (k Keeper) IteratePacketCommitment(ctx sdk.Context, cb func(portID, channelID string, sequence uint64, hash []byte) bool) {
   292  	store := ctx.KVStore(k.storeKey)
   293  	iterator := sdk.KVStorePrefixIterator(store, []byte(host.KeyPacketCommitmentPrefix))
   294  	k.iterateHashes(ctx, iterator, cb)
   295  }
   296  
   297  // GetAllPacketCommitments returns all stored PacketCommitments objects.
   298  func (k Keeper) GetAllPacketCommitments(ctx sdk.Context) (commitments []types.PacketState) {
   299  	k.IteratePacketCommitment(ctx, func(portID, channelID string, sequence uint64, hash []byte) bool {
   300  		pc := types.NewPacketState(portID, channelID, sequence, hash)
   301  		commitments = append(commitments, pc)
   302  		return false
   303  	})
   304  	return commitments
   305  }
   306  
   307  // IteratePacketCommitmentAtChannel provides an iterator over all PacketCommmitment objects
   308  // at a specified channel. For each packet commitment, cb will be called. If the cb returns
   309  // true, the iterator will close and stop.
   310  func (k Keeper) IteratePacketCommitmentAtChannel(ctx sdk.Context, portID, channelID string, cb func(_, _ string, sequence uint64, hash []byte) bool) {
   311  	store := ctx.KVStore(k.storeKey)
   312  	iterator := sdk.KVStorePrefixIterator(store, []byte(host.PacketCommitmentPrefixPath(portID, channelID)))
   313  	k.iterateHashes(ctx, iterator, cb)
   314  }
   315  
   316  // GetAllPacketCommitmentsAtChannel returns all stored PacketCommitments objects for a specified
   317  // port ID and channel ID.
   318  func (k Keeper) GetAllPacketCommitmentsAtChannel(ctx sdk.Context, portID, channelID string) (commitments []types.PacketState) {
   319  	k.IteratePacketCommitmentAtChannel(ctx, portID, channelID, func(_, _ string, sequence uint64, hash []byte) bool {
   320  		pc := types.NewPacketState(portID, channelID, sequence, hash)
   321  		commitments = append(commitments, pc)
   322  		return false
   323  	})
   324  	return commitments
   325  }
   326  
   327  // IteratePacketReceipt provides an iterator over all PacketReceipt objects. For each
   328  // receipt, cb will be called. If the cb returns true, the iterator will close
   329  // and stop.
   330  func (k Keeper) IteratePacketReceipt(ctx sdk.Context, cb func(portID, channelID string, sequence uint64, receipt []byte) bool) {
   331  	store := ctx.KVStore(k.storeKey)
   332  	iterator := sdk.KVStorePrefixIterator(store, []byte(host.KeyPacketReceiptPrefix))
   333  	k.iterateHashes(ctx, iterator, cb)
   334  }
   335  
   336  // GetAllPacketReceipts returns all stored PacketReceipt objects.
   337  func (k Keeper) GetAllPacketReceipts(ctx sdk.Context) (receipts []types.PacketState) {
   338  	k.IteratePacketReceipt(ctx, func(portID, channelID string, sequence uint64, receipt []byte) bool {
   339  		packetReceipt := types.NewPacketState(portID, channelID, sequence, receipt)
   340  		receipts = append(receipts, packetReceipt)
   341  		return false
   342  	})
   343  	return receipts
   344  }
   345  
   346  // IteratePacketAcknowledgement provides an iterator over all PacketAcknowledgement objects. For each
   347  // aknowledgement, cb will be called. If the cb returns true, the iterator will close
   348  // and stop.
   349  func (k Keeper) IteratePacketAcknowledgement(ctx sdk.Context, cb func(portID, channelID string, sequence uint64, hash []byte) bool) {
   350  	store := ctx.KVStore(k.storeKey)
   351  	iterator := sdk.KVStorePrefixIterator(store, []byte(host.KeyPacketAckPrefix))
   352  	k.iterateHashes(ctx, iterator, cb)
   353  }
   354  
   355  // GetAllPacketAcks returns all stored PacketAcknowledgements objects.
   356  func (k Keeper) GetAllPacketAcks(ctx sdk.Context) (acks []types.PacketState) {
   357  	k.IteratePacketAcknowledgement(ctx, func(portID, channelID string, sequence uint64, ack []byte) bool {
   358  		packetAck := types.NewPacketState(portID, channelID, sequence, ack)
   359  		acks = append(acks, packetAck)
   360  		return false
   361  	})
   362  	return acks
   363  }
   364  
   365  // IterateChannels provides an iterator over all Channel objects. For each
   366  // Channel, cb will be called. If the cb returns true, the iterator will close
   367  // and stop.
   368  func (k Keeper) IterateChannels(ctx sdk.Context, cb func(types.IdentifiedChannel) bool) {
   369  	store := ctx.KVStore(k.storeKey)
   370  	iterator := sdk.KVStorePrefixIterator(store, []byte(host.KeyChannelEndPrefix))
   371  
   372  	defer iterator.Close()
   373  	for ; iterator.Valid(); iterator.Next() {
   374  		var channel types.Channel
   375  		channel = *common.MustUnmarshalChannel(k.cdc, iterator.Value())
   376  
   377  		portID, channelID := host.MustParseChannelPath(string(iterator.Key()))
   378  		identifiedChannel := types.NewIdentifiedChannel(portID, channelID, channel)
   379  		if cb(identifiedChannel) {
   380  			break
   381  		}
   382  	}
   383  }
   384  
   385  // GetAllChannels returns all stored Channel objects.
   386  func (k Keeper) GetAllChannels(ctx sdk.Context) (channels []types.IdentifiedChannel) {
   387  	k.IterateChannels(ctx, func(channel types.IdentifiedChannel) bool {
   388  		channels = append(channels, channel)
   389  		return false
   390  	})
   391  	return channels
   392  }
   393  
   394  // GetChannelClientState returns the associated client state with its ID, from a port and channel identifier.
   395  func (k Keeper) GetChannelClientState(ctx sdk.Context, portID, channelID string) (string, exported.ClientState, error) {
   396  	channel, found := k.GetChannel(ctx, portID, channelID)
   397  	if !found {
   398  		return "", nil, sdkerrors.Wrapf(types.ErrChannelNotFound, "port-id: %s, channel-id: %s", portID, channelID)
   399  	}
   400  
   401  	connection, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0])
   402  	if !found {
   403  		return "", nil, sdkerrors.Wrapf(connectiontypes.ErrConnectionNotFound, "connection-id: %s", channel.ConnectionHops[0])
   404  	}
   405  
   406  	clientState, found := k.clientKeeper.GetClientState(ctx, connection.ClientId)
   407  	if !found {
   408  		return "", nil, sdkerrors.Wrapf(clienttypes.ErrClientNotFound, "client-id: %s", connection.ClientId)
   409  	}
   410  
   411  	return connection.ClientId, clientState, nil
   412  }
   413  
   414  // GetConnection wraps the connection keeper's GetConnection function.
   415  func (k Keeper) GetConnection(ctx sdk.Context, connectionID string) (exported.ConnectionI, error) {
   416  	connection, found := k.connectionKeeper.GetConnection(ctx, connectionID)
   417  	if !found {
   418  		return nil, sdkerrors.Wrapf(connectiontypes.ErrConnectionNotFound, "connection-id: %s", connectionID)
   419  	}
   420  
   421  	return connection, nil
   422  }
   423  
   424  // GetChannelConnection returns the connection ID and state associated with the given port and channel identifier.
   425  func (k Keeper) GetChannelConnection(ctx sdk.Context, portID, channelID string) (string, exported.ConnectionI, error) {
   426  	channel, found := k.GetChannel(ctx, portID, channelID)
   427  	if !found {
   428  		return "", nil, sdkerrors.Wrapf(types.ErrChannelNotFound, "port-id: %s, channel-id: %s", portID, channelID)
   429  	}
   430  
   431  	connectionID := channel.ConnectionHops[0]
   432  
   433  	connection, found := k.connectionKeeper.GetConnection(ctx, connectionID)
   434  	if !found {
   435  		return "", nil, sdkerrors.Wrapf(connectiontypes.ErrConnectionNotFound, "connection-id: %s", connectionID)
   436  	}
   437  
   438  	return connectionID, connection, nil
   439  }
   440  
   441  // LookupModuleByChannel will return the IBCModule along with the capability associated with a given channel defined by its portID and channelID
   442  func (k Keeper) LookupModuleByChannel(ctx sdk.Context, portID, channelID string) (string, *capabilitytypes.Capability, error) {
   443  	modules, cap, err := k.scopedKeeper.LookupModules(ctx, host.ChannelCapabilityPath(portID, channelID))
   444  	if err != nil {
   445  		return "", nil, err
   446  	}
   447  
   448  	return porttypes.GetModuleOwner(modules), cap, nil
   449  }
   450  
   451  // common functionality for IteratePacketCommitment and IteratePacketAcknowledgement
   452  func (k Keeper) iterateHashes(_ sdk.Context, iterator db.Iterator, cb func(portID, channelID string, sequence uint64, hash []byte) bool) {
   453  	defer iterator.Close()
   454  
   455  	for ; iterator.Valid(); iterator.Next() {
   456  		keySplit := strings.Split(string(iterator.Key()), "/")
   457  		portID := keySplit[2]
   458  		channelID := keySplit[4]
   459  
   460  		sequence, err := strconv.ParseUint(keySplit[len(keySplit)-1], 10, 64)
   461  		if err != nil {
   462  			panic(err)
   463  		}
   464  
   465  		if cb(portID, channelID, sequence, iterator.Value()) {
   466  			break
   467  		}
   468  	}
   469  }