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 }