github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/core/03-connection/keeper/keeper.go (about) 1 package keeper 2 3 import ( 4 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec" 5 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 6 sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors" 7 8 paramtypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/params/subspace" 9 clienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types" 10 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/03-connection/types" 11 commitmenttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/23-commitment/types" 12 host "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/24-host" 13 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/common" 14 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/exported" 15 "github.com/fibonacci-chain/fbc/libs/tendermint/libs/log" 16 ) 17 18 // Keeper defines the IBC connection keeper 19 type Keeper struct { 20 // implements gRPC QueryServer interface 21 types.QueryServer 22 23 storeKey sdk.StoreKey 24 paramSpace paramtypes.Subspace 25 cdc *codec.CodecProxy 26 clientKeeper types.ClientKeeper 27 } 28 29 // NewKeeper creates a new IBC connection Keeper instance 30 func NewKeeper(cdc *codec.CodecProxy, key sdk.StoreKey, paramSpace paramtypes.Subspace, ck types.ClientKeeper) Keeper { 31 return Keeper{ 32 storeKey: key, 33 cdc: cdc, 34 paramSpace: paramSpace, 35 clientKeeper: ck, 36 } 37 } 38 39 // Logger returns a module-specific logger. 40 func (k Keeper) Logger(ctx sdk.Context) log.Logger { 41 return ctx.Logger().With("module", "x/"+host.ModuleName+"/"+types.SubModuleName) 42 } 43 44 // GetCommitmentPrefix returns the IBC connection store prefix as a commitment 45 // Prefix 46 func (k Keeper) GetCommitmentPrefix() exported.Prefix { 47 return commitmenttypes.NewMerklePrefix([]byte(k.storeKey.Name())) 48 } 49 50 // GenerateConnectionIdentifier returns the next connection identifier. 51 func (k Keeper) GenerateConnectionIdentifier(ctx sdk.Context) string { 52 nextConnSeq := k.GetNextConnectionSequence(ctx) 53 connectionID := types.FormatConnectionIdentifier(nextConnSeq) 54 55 nextConnSeq++ 56 k.SetNextConnectionSequence(ctx, nextConnSeq) 57 return connectionID 58 } 59 60 // GetConnection returns a connection with a particular identifier 61 func (k Keeper) GetConnection(ctx sdk.Context, connectionID string) (types.ConnectionEnd, bool) { 62 store := ctx.KVStore(k.storeKey) 63 bz := store.Get(host.ConnectionKey(connectionID)) 64 if bz == nil { 65 return types.ConnectionEnd{}, false 66 } 67 68 var connection types.ConnectionEnd 69 connection = *common.MustUnmarshalConnection(k.cdc, bz) 70 k.Logger(ctx).Info("acquire connection", "id", connectionID, "state", connection.State) 71 return connection, true 72 } 73 74 // SetConnection sets a connection to the store 75 func (k Keeper) SetConnection(ctx sdk.Context, connectionID string, connection types.ConnectionEnd) { 76 store := ctx.KVStore(k.storeKey) 77 bz := common.MustMarshalConnection(k.cdc, &connection) 78 store.Set(host.ConnectionKey(connectionID), bz) 79 k.Logger(ctx).Info("write connection", "connectionId", connectionID, "state", connection.State) 80 } 81 82 // GetTimestampAtHeight returns the timestamp in nanoseconds of the consensus state at the 83 // given height. 84 func (k Keeper) GetTimestampAtHeight(ctx sdk.Context, connection types.ConnectionEnd, height exported.Height) (uint64, error) { 85 consensusState, found := k.clientKeeper.GetClientConsensusState( 86 ctx, connection.GetClientID(), height, 87 ) 88 89 if !found { 90 return 0, sdkerrors.Wrapf( 91 clienttypes.ErrConsensusStateNotFound, 92 "clientID (%s), height (%s)", connection.GetClientID(), height, 93 ) 94 } 95 96 return consensusState.GetTimestamp(), nil 97 } 98 99 // GetClientConnectionPaths returns all the connection paths stored under a 100 // particular client 101 func (k Keeper) GetClientConnectionPaths(ctx sdk.Context, clientID string) ([]string, bool) { 102 store := ctx.KVStore(k.storeKey) 103 bz := store.Get(host.ClientConnectionsKey(clientID)) 104 if bz == nil { 105 return nil, false 106 } 107 108 var clientPaths types.ClientPaths 109 k.cdc.GetProtocMarshal().MustUnmarshalBinaryBare(bz, &clientPaths) 110 return clientPaths.Paths, true 111 } 112 113 // SetClientConnectionPaths sets the connections paths for client 114 func (k Keeper) SetClientConnectionPaths(ctx sdk.Context, clientID string, paths []string) { 115 store := ctx.KVStore(k.storeKey) 116 clientPaths := types.ClientPaths{Paths: paths} 117 bz := k.cdc.GetProtocMarshal().MustMarshalBinaryBare(&clientPaths) 118 store.Set(host.ClientConnectionsKey(clientID), bz) 119 } 120 121 // GetNextConnectionSequence gets the next connection sequence from the store. 122 func (k Keeper) GetNextConnectionSequence(ctx sdk.Context) uint64 { 123 store := ctx.KVStore(k.storeKey) 124 bz := store.Get([]byte(types.KeyNextConnectionSequence)) 125 if bz == nil { 126 panic("next connection sequence is nil") 127 } 128 129 return sdk.BigEndianToUint64(bz) 130 } 131 132 // SetNextConnectionSequence sets the next connection sequence to the store. 133 func (k Keeper) SetNextConnectionSequence(ctx sdk.Context, sequence uint64) { 134 store := ctx.KVStore(k.storeKey) 135 bz := sdk.Uint64ToBigEndian(sequence) 136 store.Set([]byte(types.KeyNextConnectionSequence), bz) 137 } 138 139 // GetAllClientConnectionPaths returns all stored clients connection id paths. It 140 // will ignore the clients that haven't initialized a connection handshake since 141 // no paths are stored. 142 func (k Keeper) GetAllClientConnectionPaths(ctx sdk.Context) []types.ConnectionPaths { 143 var allConnectionPaths []types.ConnectionPaths 144 k.clientKeeper.IterateClients(ctx, func(clientID string, cs exported.ClientState) bool { 145 paths, found := k.GetClientConnectionPaths(ctx, clientID) 146 if !found { 147 // continue when connection handshake is not initialized 148 return false 149 } 150 connPaths := types.NewConnectionPaths(clientID, paths) 151 allConnectionPaths = append(allConnectionPaths, connPaths) 152 return false 153 }) 154 155 return allConnectionPaths 156 } 157 158 // IterateConnections provides an iterator over all ConnectionEnd objects. 159 // For each ConnectionEnd, cb will be called. If the cb returns true, the 160 // iterator will close and stop. 161 func (k Keeper) IterateConnections(ctx sdk.Context, cb func(types.IdentifiedConnection) bool) { 162 store := ctx.KVStore(k.storeKey) 163 iterator := sdk.KVStorePrefixIterator(store, []byte(host.KeyConnectionPrefix)) 164 165 defer iterator.Close() 166 for ; iterator.Valid(); iterator.Next() { 167 var connection types.ConnectionEnd 168 k.cdc.GetProtocMarshal().UnmarshalBinaryBare(iterator.Value(), &connection) 169 170 connectionID := host.MustParseConnectionPath(string(iterator.Key())) 171 identifiedConnection := types.NewIdentifiedConnection(connectionID, connection) 172 if cb(identifiedConnection) { 173 break 174 } 175 } 176 } 177 178 // GetAllConnections returns all stored ConnectionEnd objects. 179 func (k Keeper) GetAllConnections(ctx sdk.Context) (connections []types.IdentifiedConnection) { 180 k.IterateConnections(ctx, func(connection types.IdentifiedConnection) bool { 181 connections = append(connections, connection) 182 return false 183 }) 184 return connections 185 } 186 187 // addConnectionToClient is used to add a connection identifier to the set of 188 // connections associated with a client. 189 func (k Keeper) addConnectionToClient(ctx sdk.Context, clientID, connectionID string) error { 190 _, found := k.clientKeeper.GetClientState(ctx, clientID) 191 if !found { 192 return sdkerrors.Wrap(clienttypes.ErrClientNotFound, clientID) 193 } 194 195 conns, found := k.GetClientConnectionPaths(ctx, clientID) 196 if !found { 197 conns = []string{} 198 } 199 200 conns = append(conns, connectionID) 201 k.SetClientConnectionPaths(ctx, clientID, conns) 202 return nil 203 }