github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/testing/endpoint.go (about)

     1  package ibctesting
     2  
     3  import (
     4  	"fmt"
     5  
     6  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     7  
     8  	//	sdk "github.com/cosmos/cosmos-sdk/types"
     9  	"github.com/stretchr/testify/require"
    10  
    11  	clienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types"
    12  	connectiontypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/03-connection/types"
    13  	channeltypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/types"
    14  	commitmenttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/23-commitment/types"
    15  	host "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/24-host"
    16  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/exported"
    17  	ibctmtypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/light-clients/07-tendermint/types"
    18  )
    19  
    20  // Endpoint is a which represents a channel endpoint and its associated
    21  // client and connections. It contains client, connection, and channel
    22  // configuration parameters. Endpoint functions will utilize the parameters
    23  // set in the configuration structs when executing IBC messages.
    24  type Endpoint struct {
    25  	Chain        TestChainI
    26  	Counterparty *Endpoint
    27  	ClientID     string
    28  	ConnectionID string
    29  	ChannelID    string
    30  
    31  	ClientConfig     ClientConfig
    32  	ConnectionConfig *ConnectionConfig
    33  	ChannelConfig    *ChannelConfig
    34  }
    35  
    36  // NewEndpoint constructs a new endpoint without the counterparty.
    37  // CONTRACT: the counterparty endpoint must be set by the caller.
    38  func NewEndpoint(
    39  	chain TestChainI, clientConfig ClientConfig,
    40  	connectionConfig *ConnectionConfig, channelConfig *ChannelConfig,
    41  ) *Endpoint {
    42  	return &Endpoint{
    43  		Chain:            chain,
    44  		ClientConfig:     clientConfig,
    45  		ConnectionConfig: connectionConfig,
    46  		ChannelConfig:    channelConfig,
    47  	}
    48  }
    49  
    50  // NewDefaultEndpoint constructs a new endpoint using default values.
    51  // CONTRACT: the counterparty endpoitn must be set by the caller.
    52  func NewDefaultEndpoint(chain TestChainI) *Endpoint {
    53  	return &Endpoint{
    54  		Chain:            chain,
    55  		ClientConfig:     NewTendermintConfig(),
    56  		ConnectionConfig: NewConnectionConfig(),
    57  		ChannelConfig:    NewChannelConfig(),
    58  	}
    59  }
    60  
    61  // QueryProof queries proof associated with this endpoint using the lastest client state
    62  // height on the counterparty chain.
    63  func (endpoint *Endpoint) QueryProof(key []byte) ([]byte, clienttypes.Height) {
    64  	// obtain the counterparty client representing the chain associated with the endpoint
    65  	clientState := endpoint.Counterparty.Chain.GetClientState(endpoint.Counterparty.ClientID)
    66  
    67  	// query proof on the counterparty using the latest height of the IBC client
    68  	return endpoint.QueryProofAtHeight(key, clientState.GetLatestHeight().GetRevisionHeight())
    69  }
    70  
    71  // QueryProofAtHeight queries proof associated with this endpoint using the proof height
    72  // providied
    73  func (endpoint *Endpoint) QueryProofAtHeight(key []byte, height uint64) ([]byte, clienttypes.Height) {
    74  	// query proof on the counterparty using the latest height of the IBC client
    75  	return endpoint.Chain.QueryProofAtHeight(key, int64(height))
    76  }
    77  
    78  // CreateClient creates an IBC client on the endpoint. It will update the
    79  // clientID for the endpoint if the message is successfully executed.
    80  // NOTE: a solo machine client will be created with an empty diversifier.
    81  func (endpoint *Endpoint) CreateClient() (err error) {
    82  	// ensure counterparty has committed state
    83  	endpoint.Chain.Coordinator().CommitBlock(endpoint.Counterparty.Chain)
    84  
    85  	var (
    86  		clientState    exported.ClientState
    87  		consensusState exported.ConsensusState
    88  	)
    89  
    90  	switch endpoint.ClientConfig.GetClientType() {
    91  	case exported.Tendermint:
    92  		tmConfig, ok := endpoint.ClientConfig.(*TendermintConfig)
    93  		require.True(endpoint.Chain.T(), ok)
    94  
    95  		height := endpoint.Counterparty.Chain.LastHeader().GetHeight().(clienttypes.Height)
    96  		clientState = ibctmtypes.NewClientState(
    97  			endpoint.Counterparty.Chain.ChainID(), tmConfig.TrustLevel, tmConfig.TrustingPeriod, tmConfig.UnbondingPeriod, tmConfig.MaxClockDrift,
    98  			height, commitmenttypes.GetSDKSpecs(), UpgradePath, tmConfig.AllowUpdateAfterExpiry, tmConfig.AllowUpdateAfterMisbehaviour,
    99  		)
   100  		consensusState = endpoint.Counterparty.Chain.LastHeader().ConsensusState()
   101  	case exported.Solomachine:
   102  		// TODO
   103  		//		solo := NewSolomachine(chain.t, endpoint.Chain.Codec, clientID, "", 1)
   104  		//		clientState = solo.ClientState()
   105  		//		consensusState = solo.ConsensusState()
   106  
   107  	default:
   108  		err = fmt.Errorf("client type %s is not supported", endpoint.ClientConfig.GetClientType())
   109  	}
   110  
   111  	if err != nil {
   112  		return err
   113  	}
   114  
   115  	msg, err := clienttypes.NewMsgCreateClient(
   116  		clientState, consensusState, endpoint.Chain.SenderAccount().GetAddress(),
   117  	)
   118  	require.NoError(endpoint.Chain.T(), err)
   119  
   120  	res, err := endpoint.Chain.SendMsgs(msg)
   121  	if err != nil {
   122  		return err
   123  	}
   124  
   125  	endpoint.ClientID, err = ParseClientIDFromEvents(res.Events)
   126  	require.NoError(endpoint.Chain.T(), err)
   127  
   128  	return nil
   129  }
   130  
   131  // UpdateClient updates the IBC client associated with the endpoint.
   132  func (endpoint *Endpoint) UpdateClient() (err error) {
   133  	// ensure counterparty has committed state
   134  	endpoint.Chain.Coordinator().CommitBlock(endpoint.Counterparty.Chain)
   135  
   136  	var (
   137  		header exported.Header
   138  	)
   139  
   140  	switch endpoint.ClientConfig.GetClientType() {
   141  	case exported.Tendermint:
   142  		header, err = endpoint.Chain.ConstructUpdateTMClientHeader(endpoint.Counterparty.Chain, endpoint.ClientID)
   143  
   144  	default:
   145  		err = fmt.Errorf("client type %s is not supported", endpoint.ClientConfig.GetClientType())
   146  	}
   147  
   148  	if err != nil {
   149  		return err
   150  	}
   151  
   152  	msg, err := clienttypes.NewMsgUpdateClient(
   153  		endpoint.ClientID, header,
   154  		endpoint.Chain.SenderAccount().GetAddress(),
   155  	)
   156  	require.NoError(endpoint.Chain.T(), err)
   157  
   158  	return endpoint.Chain.sendMsgs(msg)
   159  
   160  }
   161  
   162  // ConnOpenInit will construct and execute a MsgConnectionOpenInit on the associated endpoint.
   163  func (endpoint *Endpoint) ConnOpenInit() error {
   164  	msg := connectiontypes.NewMsgConnectionOpenInit(
   165  		endpoint.ClientID,
   166  		endpoint.Counterparty.ClientID,
   167  		endpoint.Counterparty.Chain.GetPrefix(), DefaultOpenInitVersion, endpoint.ConnectionConfig.DelayPeriod,
   168  		endpoint.Chain.SenderAccount().GetAddress().String(),
   169  	)
   170  	res, err := endpoint.Chain.SendMsgs(msg)
   171  	if err != nil {
   172  		return err
   173  	}
   174  
   175  	endpoint.ConnectionID, err = ParseConnectionIDFromEvents(res.Events)
   176  	require.NoError(endpoint.Chain.T(), err)
   177  
   178  	return nil
   179  }
   180  
   181  // ConnOpenTry will construct and execute a MsgConnectionOpenTry on the associated endpoint.
   182  func (endpoint *Endpoint) ConnOpenTry() error {
   183  	endpoint.UpdateClient()
   184  
   185  	counterpartyClient, proofClient, proofConsensus, consensusHeight, proofInit, proofHeight := endpoint.QueryConnectionHandshakeProof()
   186  
   187  	msg := connectiontypes.NewMsgConnectionOpenTry(
   188  		"", endpoint.ClientID, // does not support handshake continuation
   189  		endpoint.Counterparty.ConnectionID, endpoint.Counterparty.ClientID,
   190  		counterpartyClient, endpoint.Counterparty.Chain.GetPrefix(), []*connectiontypes.Version{ConnectionVersion}, endpoint.ConnectionConfig.DelayPeriod,
   191  		proofInit, proofClient, proofConsensus,
   192  		proofHeight, consensusHeight,
   193  		endpoint.Chain.SenderAccount().GetAddress().String(),
   194  	)
   195  	res, err := endpoint.Chain.SendMsgs(msg)
   196  	if err != nil {
   197  		return err
   198  	}
   199  
   200  	if endpoint.ConnectionID == "" {
   201  		endpoint.ConnectionID, err = ParseConnectionIDFromEvents(res.Events)
   202  		require.NoError(endpoint.Chain.T(), err)
   203  	}
   204  
   205  	return nil
   206  }
   207  
   208  // ConnOpenAck will construct and execute a MsgConnectionOpenAck on the associated endpoint.
   209  func (endpoint *Endpoint) ConnOpenAck() error {
   210  	endpoint.UpdateClient()
   211  
   212  	counterpartyClient, proofClient, proofConsensus, consensusHeight, proofTry, proofHeight := endpoint.QueryConnectionHandshakeProof()
   213  
   214  	msg := connectiontypes.NewMsgConnectionOpenAck(
   215  		endpoint.ConnectionID, endpoint.Counterparty.ConnectionID, counterpartyClient, // testing doesn't use flexible selection
   216  		proofTry, proofClient, proofConsensus,
   217  		proofHeight, consensusHeight,
   218  		ConnectionVersion,
   219  		endpoint.Chain.SenderAccount().GetAddress().String(),
   220  	)
   221  	return endpoint.Chain.sendMsgs(msg)
   222  }
   223  
   224  // ConnOpenConfirm will construct and execute a MsgConnectionOpenConfirm on the associated endpoint.
   225  func (endpoint *Endpoint) ConnOpenConfirm() error {
   226  	endpoint.UpdateClient()
   227  
   228  	connectionKey := host.ConnectionKey(endpoint.Counterparty.ConnectionID)
   229  	proof, height := endpoint.Counterparty.Chain.QueryProof(connectionKey)
   230  
   231  	msg := connectiontypes.NewMsgConnectionOpenConfirm(
   232  		endpoint.ConnectionID,
   233  		proof, height,
   234  		endpoint.Chain.SenderAccount().GetAddress().String(),
   235  	)
   236  	return endpoint.Chain.sendMsgs(msg)
   237  }
   238  
   239  // QueryConnectionHandshakeProof returns all the proofs necessary to execute OpenTry or Open Ack of
   240  // the connection handshakes. It returns the counterparty client state, proof of the counterparty
   241  // client state, proof of the counterparty consensus state, the consensus state height, proof of
   242  // the counterparty connection, and the proof height for all the proofs returned.
   243  func (endpoint *Endpoint) QueryConnectionHandshakeProof() (
   244  	clientState exported.ClientState, proofClient,
   245  	proofConsensus []byte, consensusHeight clienttypes.Height,
   246  	proofConnection []byte, proofHeight clienttypes.Height,
   247  ) {
   248  	// obtain the client state on the counterparty chain
   249  	clientState = endpoint.Counterparty.Chain.GetClientState(endpoint.Counterparty.ClientID)
   250  
   251  	// query proof for the client state on the counterparty
   252  	clientKey := host.FullClientStateKey(endpoint.Counterparty.ClientID)
   253  	proofClient, proofHeight = endpoint.Counterparty.QueryProof(clientKey)
   254  
   255  	consensusHeight = clientState.GetLatestHeight().(clienttypes.Height)
   256  
   257  	// query proof for the consensus state on the counterparty
   258  	consensusKey := host.FullConsensusStateKey(endpoint.Counterparty.ClientID, consensusHeight)
   259  	proofConsensus, _ = endpoint.Counterparty.QueryProofAtHeight(consensusKey, proofHeight.GetRevisionHeight())
   260  
   261  	// query proof for the connection on the counterparty
   262  	connectionKey := host.ConnectionKey(endpoint.Counterparty.ConnectionID)
   263  	proofConnection, _ = endpoint.Counterparty.QueryProofAtHeight(connectionKey, proofHeight.GetRevisionHeight())
   264  
   265  	return
   266  }
   267  
   268  // ChanOpenInit will construct and execute a MsgChannelOpenInit on the associated endpoint.
   269  func (endpoint *Endpoint) ChanOpenInit() error {
   270  	msg := channeltypes.NewMsgChannelOpenInit(
   271  		endpoint.ChannelConfig.PortID,
   272  		endpoint.ChannelConfig.Version, endpoint.ChannelConfig.Order, []string{endpoint.ConnectionID},
   273  		endpoint.Counterparty.ChannelConfig.PortID,
   274  		endpoint.Chain.SenderAccount().GetAddress(),
   275  	)
   276  	res, err := endpoint.Chain.SendMsgs(msg)
   277  	if err != nil {
   278  		return err
   279  	}
   280  
   281  	endpoint.ChannelID, err = ParseChannelIDFromEvents(res.Events)
   282  	require.NoError(endpoint.Chain.T(), err)
   283  
   284  	endpoint.ChannelConfig.Version = endpoint.GetChannel().Version
   285  
   286  	return nil
   287  }
   288  
   289  // ChanOpenTry will construct and execute a MsgChannelOpenTry on the associated endpoint.
   290  func (endpoint *Endpoint) ChanOpenTry() error {
   291  	endpoint.UpdateClient()
   292  
   293  	channelKey := host.ChannelKey(endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID)
   294  	proof, height := endpoint.Counterparty.Chain.QueryProof(channelKey)
   295  
   296  	msg := channeltypes.NewMsgChannelOpenTry(
   297  		endpoint.ChannelConfig.PortID, "", // does not support handshake continuation
   298  		endpoint.ChannelConfig.Version, endpoint.ChannelConfig.Order, []string{endpoint.ConnectionID},
   299  		endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID, endpoint.Counterparty.ChannelConfig.Version,
   300  		proof, height,
   301  		endpoint.Chain.SenderAccount().GetAddress().String(),
   302  	)
   303  	res, err := endpoint.Chain.SendMsgs(msg)
   304  	if err != nil {
   305  		return err
   306  	}
   307  
   308  	if endpoint.ChannelID == "" {
   309  		endpoint.ChannelID, err = ParseChannelIDFromEvents(res.Events)
   310  		require.NoError(endpoint.Chain.T(), err)
   311  	}
   312  	endpoint.ChannelConfig.Version = endpoint.GetChannel().Version
   313  
   314  	return nil
   315  }
   316  
   317  // ChanOpenAck will construct and execute a MsgChannelOpenAck on the associated endpoint.
   318  func (endpoint *Endpoint) ChanOpenAck() error {
   319  	endpoint.UpdateClient()
   320  
   321  	channelKey := host.ChannelKey(endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID)
   322  	proof, height := endpoint.Counterparty.Chain.QueryProof(channelKey)
   323  
   324  	msg := channeltypes.NewMsgChannelOpenAck(
   325  		endpoint.ChannelConfig.PortID, endpoint.ChannelID,
   326  		endpoint.Counterparty.ChannelID, endpoint.Counterparty.ChannelConfig.Version, // testing doesn't use flexible selection
   327  		proof, height,
   328  		endpoint.Chain.SenderAccount().GetAddress().String(),
   329  	)
   330  
   331  	if err := endpoint.Chain.sendMsgs(msg); nil != err {
   332  		return err
   333  	}
   334  
   335  	endpoint.ChannelConfig.Version = endpoint.GetChannel().Version
   336  
   337  	return nil
   338  }
   339  
   340  // ChanOpenConfirm will construct and execute a MsgChannelOpenConfirm on the associated endpoint.
   341  func (endpoint *Endpoint) ChanOpenConfirm() error {
   342  	endpoint.UpdateClient()
   343  
   344  	channelKey := host.ChannelKey(endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID)
   345  	proof, height := endpoint.Counterparty.Chain.QueryProof(channelKey)
   346  
   347  	msg := channeltypes.NewMsgChannelOpenConfirm(
   348  		endpoint.ChannelConfig.PortID, endpoint.ChannelID,
   349  		proof, height,
   350  		endpoint.Chain.SenderAccount().GetAddress().String(),
   351  	)
   352  	return endpoint.Chain.sendMsgs(msg)
   353  }
   354  
   355  // ChanCloseInit will construct and execute a MsgChannelCloseInit on the associated endpoint.
   356  //
   357  // NOTE: does not work with ibc-transfer module
   358  func (endpoint *Endpoint) ChanCloseInit() error {
   359  	msg := channeltypes.NewMsgChannelCloseInit(
   360  		endpoint.ChannelConfig.PortID, endpoint.ChannelID,
   361  		endpoint.Chain.SenderAccount().GetAddress().String(),
   362  	)
   363  	return endpoint.Chain.sendMsgs(msg)
   364  }
   365  
   366  // SendPacket sends a packet through the channel keeper using the associated endpoint
   367  // The counterparty client is updated so proofs can be sent to the counterparty chain.
   368  func (endpoint *Endpoint) SendPacket(packet exported.PacketI) error {
   369  	channelCap := endpoint.Chain.GetChannelCapability(packet.GetSourcePort(), packet.GetSourceChannel())
   370  
   371  	// no need to send message, acting as a module
   372  	err := endpoint.Chain.App().GetIBCKeeper().ChannelKeeper.SendPacket(endpoint.Chain.GetContext(), channelCap, packet)
   373  	if err != nil {
   374  		return err
   375  	}
   376  
   377  	// commit changes since no message was sent
   378  	endpoint.Chain.Coordinator().CommitBlock(endpoint.Chain)
   379  
   380  	return endpoint.Counterparty.UpdateClient()
   381  }
   382  
   383  // RecvPacket receives a packet on the associated endpoint.
   384  // The counterparty client is updated.
   385  func (endpoint *Endpoint) RecvPacket(packet channeltypes.Packet) error {
   386  	// get proof of packet commitment on source
   387  	packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
   388  	proof, proofHeight := endpoint.Counterparty.Chain.QueryProof(packetKey)
   389  
   390  	recvMsg := channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, endpoint.Chain.SenderAccount().GetAddress().String())
   391  
   392  	// receive on counterparty and update source client
   393  	if err := endpoint.Chain.sendMsgs(recvMsg); err != nil {
   394  		return err
   395  	}
   396  
   397  	return endpoint.Counterparty.UpdateClient()
   398  }
   399  
   400  // WriteAcknowledgement writes an acknowledgement on the channel associated with the endpoint.
   401  // The counterparty client is updated.
   402  func (endpoint *Endpoint) WriteAcknowledgement(ack exported.Acknowledgement, packet exported.PacketI) error {
   403  	channelCap := endpoint.Chain.GetChannelCapability(packet.GetDestPort(), packet.GetDestChannel())
   404  
   405  	// no need to send message, acting as a handler
   406  	err := endpoint.Chain.App().GetIBCKeeper().ChannelKeeper.WriteAcknowledgement(endpoint.Chain.GetContext(), channelCap, packet, ack)
   407  	if err != nil {
   408  		return err
   409  	}
   410  
   411  	// commit changes since no message was sent
   412  	endpoint.Chain.Coordinator().CommitBlock(endpoint.Chain)
   413  
   414  	return endpoint.Counterparty.UpdateClient()
   415  }
   416  
   417  // AcknowledgePacket sends a MsgAcknowledgement to the channel associated with the endpoint.
   418  func (endpoint *Endpoint) AcknowledgePacket(packet channeltypes.Packet, ack []byte) error {
   419  	// get proof of acknowledgement on counterparty
   420  	packetKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
   421  	proof, proofHeight := endpoint.Counterparty.QueryProof(packetKey)
   422  
   423  	ackMsg := channeltypes.NewMsgAcknowledgement(packet, ack, proof, proofHeight, endpoint.Chain.SenderAccount().GetAddress().String())
   424  
   425  	return endpoint.Chain.sendMsgs(ackMsg)
   426  }
   427  
   428  // TimeoutPacket sends a MsgTimeout to the channel associated with the endpoint.
   429  func (endpoint *Endpoint) TimeoutPacket(packet channeltypes.Packet) error {
   430  	// get proof for timeout based on channel order
   431  	var packetKey []byte
   432  
   433  	switch endpoint.ChannelConfig.Order {
   434  	case channeltypes.ORDERED:
   435  		packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel())
   436  	case channeltypes.UNORDERED:
   437  		packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
   438  	default:
   439  		return fmt.Errorf("unsupported order type %s", endpoint.ChannelConfig.Order)
   440  	}
   441  
   442  	proof, proofHeight := endpoint.Counterparty.QueryProof(packetKey)
   443  	nextSeqRecv, found := endpoint.Counterparty.Chain.App().GetIBCKeeper().ChannelKeeper.GetNextSequenceRecv(endpoint.Counterparty.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID)
   444  	require.True(endpoint.Chain.T(), found)
   445  
   446  	timeoutMsg := channeltypes.NewMsgTimeout(
   447  		packet, nextSeqRecv,
   448  		proof, proofHeight, endpoint.Chain.SenderAccount().GetAddress().String(),
   449  	)
   450  
   451  	return endpoint.Chain.sendMsgs(timeoutMsg)
   452  }
   453  
   454  // SetChannelClosed sets a channel state to CLOSED.
   455  func (endpoint *Endpoint) SetChannelClosed() error {
   456  	channel := endpoint.GetChannel()
   457  
   458  	channel.State = channeltypes.CLOSED
   459  	endpoint.Chain.App().GetIBCKeeper().ChannelKeeper.SetChannel(endpoint.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID, channel)
   460  
   461  	endpoint.Chain.Coordinator().CommitBlock(endpoint.Chain)
   462  
   463  	return endpoint.Counterparty.UpdateClient()
   464  }
   465  
   466  // GetClientState retrieves the Client State for this endpoint. The
   467  // client state is expected to exist otherwise testing will fail.
   468  func (endpoint *Endpoint) GetClientState() exported.ClientState {
   469  	return endpoint.Chain.GetClientState(endpoint.ClientID)
   470  }
   471  
   472  // SetClientState sets the client state for this endpoint.
   473  func (endpoint *Endpoint) SetClientState(clientState exported.ClientState) {
   474  	endpoint.Chain.App().GetIBCKeeper().ClientKeeper.SetClientState(endpoint.Chain.GetContext(), endpoint.ClientID, clientState)
   475  }
   476  
   477  // GetConsensusState retrieves the Consensus State for this endpoint at the provided height.
   478  // The consensus state is expected to exist otherwise testing will fail.
   479  func (endpoint *Endpoint) GetConsensusState(height exported.Height) exported.ConsensusState {
   480  	consensusState, found := endpoint.Chain.GetConsensusState(endpoint.ClientID, height)
   481  	require.True(endpoint.Chain.T(), found)
   482  
   483  	return consensusState
   484  }
   485  
   486  // SetConsensusState sets the consensus state for this endpoint.
   487  func (endpoint *Endpoint) SetConsensusState(consensusState exported.ConsensusState, height exported.Height) {
   488  	endpoint.Chain.App().GetIBCKeeper().ClientKeeper.SetClientConsensusState(endpoint.Chain.GetContext(), endpoint.ClientID, height, consensusState)
   489  }
   490  
   491  // GetConnection retrieves an IBC Connection for the endpoint. The
   492  // connection is expected to exist otherwise testing will fail.
   493  func (endpoint *Endpoint) GetConnection() connectiontypes.ConnectionEnd {
   494  	connection, found := endpoint.Chain.App().GetIBCKeeper().ConnectionKeeper.GetConnection(endpoint.Chain.GetContext(), endpoint.ConnectionID)
   495  	require.True(endpoint.Chain.T(), found)
   496  
   497  	return connection
   498  }
   499  
   500  // SetConnection sets the connection for this endpoint.
   501  func (endpoint *Endpoint) SetConnection(connection connectiontypes.ConnectionEnd) {
   502  	endpoint.Chain.App().GetIBCKeeper().ConnectionKeeper.SetConnection(endpoint.Chain.GetContext(), endpoint.ConnectionID, connection)
   503  }
   504  
   505  // GetChannel retrieves an IBC Channel for the endpoint. The channel
   506  // is expected to exist otherwise testing will fail.
   507  func (endpoint *Endpoint) GetChannel() channeltypes.Channel {
   508  	channel, found := endpoint.Chain.App().GetIBCKeeper().ChannelKeeper.GetChannel(endpoint.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID)
   509  	require.True(endpoint.Chain.T(), found)
   510  
   511  	return channel
   512  }
   513  
   514  // SetChannel sets the channel for this endpoint.
   515  func (endpoint *Endpoint) SetChannel(channel channeltypes.Channel) {
   516  	endpoint.Chain.App().GetIBCKeeper().ChannelKeeper.SetChannel(endpoint.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID, channel)
   517  }
   518  
   519  // QueryClientStateProof performs and abci query for a client stat associated
   520  // with this endpoint and returns the ClientState along with the proof.
   521  func (endpoint *Endpoint) QueryClientStateProof() (exported.ClientState, []byte) {
   522  	// retrieve client state to provide proof for
   523  	clientState := endpoint.GetClientState()
   524  
   525  	clientKey := host.FullClientStateKey(endpoint.ClientID)
   526  	proofClient, _ := endpoint.QueryProof(clientKey)
   527  
   528  	return clientState, proofClient
   529  }
   530  
   531  // RecvPacketWithResult receives a packet on the associated endpoint and the result
   532  // of the transaction is returned. The counterparty client is updated.
   533  func (endpoint *Endpoint) RecvPacketWithResult(packet channeltypes.Packet) (*sdk.Result, error) {
   534  	// get proof of packet commitment on source
   535  	packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
   536  	proof, proofHeight := endpoint.Counterparty.Chain.QueryProof(packetKey)
   537  
   538  	recvMsg := channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, endpoint.Chain.SenderAccount().GetAddress().String())
   539  
   540  	// receive on counterparty and update source client
   541  	res, err := endpoint.Chain.SendMsgs(recvMsg)
   542  	if err != nil {
   543  		return nil, err
   544  	}
   545  
   546  	if err := endpoint.Counterparty.UpdateClient(); err != nil {
   547  		return nil, err
   548  	}
   549  
   550  	return res, nil
   551  }