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  }