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

     1  package keeper
     2  
     3  import (
     4  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     5  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
     6  	clienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types"
     7  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/03-connection/types"
     8  	commitmenttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/23-commitment/types"
     9  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/exported"
    10  )
    11  
    12  func (k Keeper) ConnOpenTryV4(
    13  	ctx sdk.Context,
    14  	counterparty types.Counterparty, // counterpartyConnectionIdentifier, counterpartyPrefix and counterpartyClientIdentifier
    15  	delayPeriod uint64,
    16  	clientID string, // clientID of chainA
    17  	clientState exported.ClientState, // clientState that chainA has for chainB
    18  	counterpartyVersions []exported.Version, // supported versions of chain A
    19  	proofInit []byte, // proof that chainA stored connectionEnd in state (on ConnOpenInit)
    20  	proofClient []byte, // proof that chainA stored a light client of chainB
    21  	proofConsensus []byte, // proof that chainA stored chainB's consensus state at consensus height
    22  	proofHeight exported.Height, // height at which relayer constructs proof of A storing connectionEnd in state
    23  	consensusHeight exported.Height, // latest height of chain B which chain A has stored in its chain B client
    24  ) (string, error) {
    25  	// generate a new connection
    26  	connectionID := k.GenerateConnectionIdentifier(ctx)
    27  
    28  	selfHeight := clienttypes.GetSelfHeight(ctx)
    29  	if consensusHeight.GTE(selfHeight) {
    30  		return "", sdkerrors.Wrapf(
    31  			sdkerrors.ErrInvalidHeight,
    32  			"consensus height is greater than or equal to the current block height (%s >= %s)", consensusHeight, selfHeight,
    33  		)
    34  	}
    35  
    36  	// validate client parameters of a chainB client stored on chainA
    37  	if err := k.clientKeeper.ValidateSelfClient(ctx, clientState); err != nil {
    38  		return "", err
    39  	}
    40  
    41  	expectedConsensusState, err := k.clientKeeper.GetSelfConsensusStateV4(ctx, consensusHeight)
    42  	if err != nil {
    43  		return "", sdkerrors.Wrapf(err, "self consensus state not found for height %s", consensusHeight.String())
    44  	}
    45  
    46  	// expectedConnection defines Chain A's ConnectionEnd
    47  	// NOTE: chain A's counterparty is chain B (i.e where this code is executed)
    48  	// NOTE: chainA and chainB must have the same delay period
    49  	prefix := k.GetCommitmentPrefix()
    50  	expectedCounterparty := types.NewCounterparty(clientID, "", commitmenttypes.NewMerklePrefix(prefix.Bytes()))
    51  	expectedConnection := types.NewConnectionEnd(types.INIT, counterparty.ClientId, expectedCounterparty, types.ExportedVersionsToProto(counterpartyVersions), delayPeriod)
    52  
    53  	// chain B picks a version from Chain A's available versions that is compatible
    54  	// with Chain B's supported IBC versions. PickVersion will select the intersection
    55  	// of the supported versions and the counterparty versions.
    56  	version, err2 := types.PickVersion(types.GetCompatibleVersions(), counterpartyVersions)
    57  	if err2 != nil {
    58  		return "", err2
    59  	}
    60  
    61  	// connection defines chain B's ConnectionEnd
    62  	connection := types.NewConnectionEnd(types.TRYOPEN, clientID, counterparty, []*types.Version{version}, delayPeriod)
    63  
    64  	// Check that ChainA committed expectedConnectionEnd to its state
    65  	if err := k.VerifyConnectionState(
    66  		ctx, connection, proofHeight, proofInit, counterparty.ConnectionId,
    67  		expectedConnection,
    68  	); err != nil {
    69  		return "", err
    70  	}
    71  
    72  	// Check that ChainA stored the clientState provided in the msg
    73  	if err := k.VerifyClientState(ctx, connection, proofHeight, proofClient, clientState); err != nil {
    74  		return "", err
    75  	}
    76  
    77  	// Check that ChainA stored the correct ConsensusState of chainB at the given consensusHeight
    78  	if err := k.VerifyClientConsensusState(
    79  		ctx, connection, proofHeight, consensusHeight, proofConsensus, expectedConsensusState,
    80  	); err != nil {
    81  		return "", err
    82  	}
    83  
    84  	// store connection in chainB state
    85  	if err := k.addConnectionToClient(ctx, clientID, connectionID); err != nil {
    86  		return "", sdkerrors.Wrapf(err, "failed to add connection with ID %s to client with ID %s", connectionID, clientID)
    87  	}
    88  
    89  	k.SetConnection(ctx, connectionID, connection)
    90  	k.Logger(ctx).Info("connection state updated", "connection-id", connectionID, "previous-state", "NONE", "new-state", "TRYOPEN")
    91  
    92  	EmitConnectionOpenTryEvent(ctx, connectionID, clientID, counterparty)
    93  
    94  	return connectionID, nil
    95  }
    96  
    97  func (k Keeper) ConnOpenAckV4(
    98  	ctx sdk.Context,
    99  	connectionID string,
   100  	clientState exported.ClientState, // client state for chainA on chainB
   101  	version *types.Version, // version that ChainB chose in ConnOpenTry
   102  	counterpartyConnectionID string,
   103  	proofTry []byte, // proof that connectionEnd was added to ChainB state in ConnOpenTry
   104  	proofClient []byte, // proof of client state on chainB for chainA
   105  	proofConsensus []byte, // proof that chainB has stored ConsensusState of chainA on its client
   106  	proofHeight exported.Height, // height that relayer constructed proofTry
   107  	consensusHeight exported.Height, // latest height of chainA that chainB has stored on its chainA client
   108  ) error {
   109  	// Check that chainB client hasn't stored invalid height
   110  	selfHeight := clienttypes.GetSelfHeight(ctx)
   111  	if consensusHeight.GTE(selfHeight) {
   112  		return sdkerrors.Wrapf(
   113  			sdkerrors.ErrInvalidHeight,
   114  			"consensus height is greater than or equal to the current block height (%s >= %s)", consensusHeight, selfHeight,
   115  		)
   116  	}
   117  
   118  	// Retrieve connection
   119  	connection, found := k.GetConnection(ctx, connectionID)
   120  	if !found {
   121  		return sdkerrors.Wrap(types.ErrConnectionNotFound, connectionID)
   122  	}
   123  
   124  	// verify the previously set connection state
   125  	if connection.State != types.INIT {
   126  		return sdkerrors.Wrapf(
   127  			types.ErrInvalidConnectionState,
   128  			"connection state is not INIT (got %s)", connection.State.String(),
   129  		)
   130  	}
   131  
   132  	// ensure selected version is supported
   133  	if !types.IsSupportedVersionV4(types.ProtoVersionsToExported(connection.Versions), version) {
   134  		return sdkerrors.Wrapf(
   135  			types.ErrInvalidConnectionState,
   136  			"the counterparty selected version %s is not supported by versions selected on INIT", version,
   137  		)
   138  	}
   139  
   140  	// validate client parameters of a chainA client stored on chainB
   141  	if err := k.clientKeeper.ValidateSelfClient(ctx, clientState); err != nil {
   142  		return err
   143  	}
   144  
   145  	// Retrieve chainA's consensus state at consensusheight
   146  	expectedConsensusState, err := k.clientKeeper.GetSelfConsensusStateV4(ctx, consensusHeight)
   147  	if err != nil {
   148  		return sdkerrors.Wrapf(err, "self consensus state not found for height %s", consensusHeight.String())
   149  	}
   150  
   151  	prefix := k.GetCommitmentPrefix()
   152  	expectedCounterparty := types.NewCounterparty(connection.ClientId, connectionID, commitmenttypes.NewMerklePrefix(prefix.Bytes()))
   153  	expectedConnection := types.NewConnectionEnd(types.TRYOPEN, connection.Counterparty.ClientId, expectedCounterparty, []*types.Version{version}, connection.DelayPeriod)
   154  
   155  	// Ensure that ChainB stored expected connectionEnd in its state during ConnOpenTry
   156  	if err := k.VerifyConnectionState(
   157  		ctx, connection, proofHeight, proofTry, counterpartyConnectionID,
   158  		expectedConnection,
   159  	); err != nil {
   160  		return err
   161  	}
   162  
   163  	// Check that ChainB stored the clientState provided in the msg
   164  	if err := k.VerifyClientState(ctx, connection, proofHeight, proofClient, clientState); err != nil {
   165  		return err
   166  	}
   167  
   168  	// Ensure that ChainB has stored the correct ConsensusState for chainA at the consensusHeight
   169  	if err := k.VerifyClientConsensusState(
   170  		ctx, connection, proofHeight, consensusHeight, proofConsensus, expectedConsensusState,
   171  	); err != nil {
   172  		return err
   173  	}
   174  
   175  	k.Logger(ctx).Info("connection state updated", "connection-id", connectionID, "previous-state", "INIT", "new-state", "OPEN")
   176  
   177  	// Update connection state to Open
   178  	connection.State = types.OPEN
   179  	connection.Versions = []*types.Version{version}
   180  	connection.Counterparty.ConnectionId = counterpartyConnectionID
   181  	k.SetConnection(ctx, connectionID, connection)
   182  
   183  	EmitConnectionOpenAckEvent(ctx, connectionID, connection)
   184  
   185  	return nil
   186  }