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 }