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

     1  package keeper
     2  
     3  import (
     4  	"context"
     5  	"strings"
     6  
     7  	clienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types"
     8  	connectiontypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/03-connection/types"
     9  
    10  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    11  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
    12  	channeltypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/types"
    13  	porttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/05-port/types"
    14  )
    15  
    16  var (
    17  	_ IBCServerKeeper = (*V4Keeper)(nil)
    18  )
    19  
    20  type V4Keeper struct {
    21  	*Keeper
    22  }
    23  
    24  func NewV4Keeper(keeper *Keeper) *V4Keeper {
    25  	return &V4Keeper{Keeper: keeper}
    26  }
    27  
    28  // ConnectionOpenTry defines a rpc handler method for MsgConnectionOpenTry.
    29  func (k V4Keeper) ConnectionOpenTry(goCtx context.Context, msg *connectiontypes.MsgConnectionOpenTry) (*connectiontypes.MsgConnectionOpenTryResponse, error) {
    30  	ctx := sdk.UnwrapSDKContext(goCtx)
    31  
    32  	targetClient, err := clienttypes.UnpackClientState(msg.ClientState)
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  
    37  	if _, err := k.ConnectionKeeper.ConnOpenTryV4(
    38  		ctx, msg.Counterparty, msg.DelayPeriod, msg.ClientId, targetClient,
    39  		connectiontypes.ProtoVersionsToExported(msg.CounterpartyVersions), msg.ProofInit, msg.ProofClient, msg.ProofConsensus,
    40  		msg.ProofHeight, msg.ConsensusHeight,
    41  	); err != nil {
    42  		return nil, sdkerrors.Wrap(err, "connection handshake open try failed")
    43  	}
    44  
    45  	return &connectiontypes.MsgConnectionOpenTryResponse{}, nil
    46  }
    47  
    48  func (k V4Keeper) ConnectionOpenAck(goCtx context.Context, msg *connectiontypes.MsgConnectionOpenAck) (*connectiontypes.MsgConnectionOpenAckResponse, error) {
    49  	ctx := sdk.UnwrapSDKContext(goCtx)
    50  	targetClient, err := clienttypes.UnpackClientState(msg.ClientState)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  
    55  	if err := k.ConnectionKeeper.ConnOpenAckV4(
    56  		ctx, msg.ConnectionId, targetClient, msg.Version, msg.CounterpartyConnectionId,
    57  		msg.ProofTry, msg.ProofClient, msg.ProofConsensus,
    58  		msg.ProofHeight, msg.ConsensusHeight,
    59  	); err != nil {
    60  		return nil, sdkerrors.Wrap(err, "connection handshake open ack failed")
    61  	}
    62  
    63  	return &connectiontypes.MsgConnectionOpenAckResponse{}, nil
    64  }
    65  
    66  func (k V4Keeper) ChannelOpenInit(goCtx context.Context, msg *channeltypes.MsgChannelOpenInit) (*channeltypes.MsgChannelOpenInitResponse, error) {
    67  	ctx := sdk.UnwrapSDKContext(goCtx)
    68  
    69  	// Lookup module by port capability
    70  	module, portCap, err := k.PortKeeper.LookupModuleByPort(ctx, msg.PortId)
    71  	if err != nil {
    72  		return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
    73  	}
    74  
    75  	// Retrieve application callbacks from router
    76  	cbs, ok := k.Router.GetRoute(module)
    77  	if !ok {
    78  		return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
    79  	}
    80  
    81  	// Perform 04-channel verification
    82  	channelID, cap, err := k.ChannelKeeper.ChanOpenInitV4(
    83  		ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId,
    84  		portCap, msg.Channel.Counterparty, msg.Channel.Version,
    85  	)
    86  	if err != nil {
    87  		return nil, sdkerrors.Wrap(err, "channel handshake open init failed")
    88  	}
    89  
    90  	version := strings.TrimSpace(msg.Channel.Version)
    91  	// Perform application logic callback
    92  	version, err = cbs.OnChanOpenInit(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, channelID, cap, msg.Channel.Counterparty, msg.Channel.Version)
    93  	if err != nil {
    94  		return nil, sdkerrors.Wrap(err, "channel open init callback failed")
    95  	}
    96  
    97  	// Write channel into state
    98  	k.ChannelKeeper.WriteOpenInitChannel(ctx, msg.PortId, channelID, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.Channel.Counterparty, version)
    99  
   100  	return &channeltypes.MsgChannelOpenInitResponse{
   101  		ChannelId: channelID,
   102  		Version:   version,
   103  	}, nil
   104  }
   105  
   106  func (k V4Keeper) ChannelOpenTry(goCtx context.Context, msg *channeltypes.MsgChannelOpenTry) (*channeltypes.MsgChannelOpenTryResponse, error) {
   107  	ctx := sdk.UnwrapSDKContext(goCtx)
   108  
   109  	// Lookup module by port capability
   110  	module, portCap, err := k.PortKeeper.LookupModuleByPort(ctx, msg.PortId)
   111  	if err != nil {
   112  		return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
   113  	}
   114  
   115  	// Retrieve application callbacks from router
   116  	cbs, ok := k.Router.GetRoute(module)
   117  	if !ok {
   118  		return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
   119  	}
   120  
   121  	// Perform 04-channel verification
   122  	channelID, cap, err := k.ChannelKeeper.ChanOpenTryV4(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId,
   123  		portCap, msg.Channel.Counterparty, msg.CounterpartyVersion, msg.ProofInit, msg.ProofHeight,
   124  	)
   125  	if err != nil {
   126  		return nil, sdkerrors.Wrap(err, "channel handshake open try failed")
   127  	}
   128  
   129  	// Perform application logic callback
   130  	msg.Channel.Version, err = cbs.OnChanOpenTry(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, channelID, cap, msg.Channel.Counterparty, msg.Channel.Version, msg.CounterpartyVersion)
   131  	if err != nil {
   132  		return nil, sdkerrors.Wrap(err, "channel open try callback failed")
   133  	}
   134  
   135  	// Write channel into state
   136  	k.ChannelKeeper.WriteOpenTryChannel(ctx, msg.PortId, channelID, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.Channel.Counterparty, msg.Channel.Version)
   137  
   138  	return &channeltypes.MsgChannelOpenTryResponse{
   139  		Version: msg.Channel.Version,
   140  	}, nil
   141  }
   142  
   143  func (k V4Keeper) ChannelOpenAck(goCtx context.Context, msg *channeltypes.MsgChannelOpenAck) (*channeltypes.MsgChannelOpenAckResponse, error) {
   144  	ctx := sdk.UnwrapSDKContext(goCtx)
   145  
   146  	// Lookup module by channel capability
   147  	module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortId, msg.ChannelId)
   148  	if err != nil {
   149  		return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
   150  	}
   151  
   152  	// Retrieve application callbacks from router
   153  	cbs, ok := k.Router.GetRoute(module)
   154  	if !ok {
   155  		return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
   156  	}
   157  
   158  	// Perform 04-channel verification
   159  	if err = k.ChannelKeeper.ChanOpenAckV4(
   160  		ctx, msg.PortId, msg.ChannelId, cap, msg.CounterpartyVersion, msg.CounterpartyChannelId, msg.ProofTry, msg.ProofHeight,
   161  	); err != nil {
   162  		return nil, sdkerrors.Wrap(err, "channel handshake open ack failed")
   163  	}
   164  
   165  	// Perform application logic callback
   166  	if err = cbs.OnChanOpenAck(ctx, msg.PortId, msg.ChannelId, msg.CounterpartyChannelId, msg.CounterpartyVersion); err != nil {
   167  		return nil, sdkerrors.Wrap(err, "channel open ack callback failed")
   168  	}
   169  
   170  	// Write channel into state
   171  	k.ChannelKeeper.WriteOpenAckChannel(ctx, msg.PortId, msg.ChannelId, msg.CounterpartyVersion, msg.CounterpartyChannelId)
   172  
   173  	return &channeltypes.MsgChannelOpenAckResponse{}, nil
   174  }
   175  
   176  func (k V4Keeper) ChannelOpenConfirm(goCtx context.Context, msg *channeltypes.MsgChannelOpenConfirm) (*channeltypes.MsgChannelOpenConfirmResponse, error) {
   177  	ctx := sdk.UnwrapSDKContext(goCtx)
   178  
   179  	// Lookup module by channel capability
   180  	module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortId, msg.ChannelId)
   181  	if err != nil {
   182  		return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
   183  	}
   184  
   185  	// Retrieve application callbacks from router
   186  	cbs, ok := k.Router.GetRoute(module)
   187  	if !ok {
   188  		return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
   189  	}
   190  
   191  	// Perform 04-channel verification
   192  	if err = k.ChannelKeeper.ChanOpenConfirmV4(ctx, msg.PortId, msg.ChannelId, cap, msg.ProofAck, msg.ProofHeight); err != nil {
   193  		return nil, sdkerrors.Wrap(err, "channel handshake open confirm failed")
   194  	}
   195  
   196  	// Perform application logic callback
   197  	if err = cbs.OnChanOpenConfirm(ctx, msg.PortId, msg.ChannelId); err != nil {
   198  		return nil, sdkerrors.Wrap(err, "channel open confirm callback failed")
   199  	}
   200  
   201  	// Write channel into state
   202  	k.ChannelKeeper.WriteOpenConfirmChannel(ctx, msg.PortId, msg.ChannelId)
   203  
   204  	return &channeltypes.MsgChannelOpenConfirmResponse{}, nil
   205  }
   206  
   207  // RecvPacket defines a rpc handler method for MsgRecvPacket.
   208  func (k V4Keeper) RecvPacket(goCtx context.Context, msg *channeltypes.MsgRecvPacket) (*channeltypes.MsgRecvPacketResponse, error) {
   209  	ctx := sdk.UnwrapSDKContext(goCtx)
   210  
   211  	relayer, err := sdk.AccAddressFromBech32(msg.Signer)
   212  	if err != nil {
   213  		return nil, sdkerrors.Wrap(err, "Invalid address for msg Signer")
   214  	}
   215  
   216  	// Lookup module by channel capability
   217  	module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.DestinationPort, msg.Packet.DestinationChannel)
   218  	if err != nil {
   219  		return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
   220  	}
   221  
   222  	// Retrieve callbacks from router
   223  	cbs, ok := k.Router.GetRoute(module)
   224  	if !ok {
   225  		return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
   226  	}
   227  
   228  	// Perform TAO verification
   229  	//
   230  	// If the packet was already received, perform a no-op
   231  	// Use a cached context to prevent accidental state changes
   232  	cacheCtx, writeFn := ctx.CacheContext()
   233  	err = k.ChannelKeeper.RecvPacket(cacheCtx, cap, msg.Packet, msg.ProofCommitment, msg.ProofHeight)
   234  
   235  	// NOTE: The context returned by CacheContext() refers to a new EventManager, so it needs to explicitly set events to the original context.
   236  	ctx.EventManager().EmitEvents(cacheCtx.EventManager().Events())
   237  
   238  	switch err {
   239  	case nil:
   240  		writeFn()
   241  	case channeltypes.ErrNoOpMsg:
   242  		return &channeltypes.MsgRecvPacketResponse{Result: channeltypes.NOOP}, nil
   243  	default:
   244  		return nil, sdkerrors.Wrap(err, "receive packet verification failed")
   245  	}
   246  
   247  	// Perform application logic callback
   248  	//
   249  	// Cache context so that we may discard state changes from callback if the acknowledgement is unsuccessful.
   250  	cacheCtx, writeFn = ctx.CacheContext()
   251  	ack := cbs.OnRecvPacket(cacheCtx, msg.Packet, relayer)
   252  	// NOTE: The context returned by CacheContext() refers to a new EventManager, so it needs to explicitly set events to the original context.
   253  	// Events from callback are emitted regardless of acknowledgement success
   254  	ctx.EventManager().EmitEvents(cacheCtx.EventManager().Events())
   255  	if ack == nil || ack.Success() {
   256  		// write application state changes for asynchronous and successful acknowledgements
   257  		writeFn()
   258  	}
   259  
   260  	// Set packet acknowledgement only if the acknowledgement is not nil.
   261  	// NOTE: IBC applications modules may call the WriteAcknowledgement asynchronously if the
   262  	// acknowledgement is nil.
   263  	if ack != nil {
   264  		if err := k.ChannelKeeper.WriteAcknowledgement(ctx, cap, msg.Packet, ack); err != nil {
   265  			return nil, err
   266  		}
   267  	}
   268  
   269  	return &channeltypes.MsgRecvPacketResponse{Result: channeltypes.SUCCESS}, nil
   270  }
   271  
   272  func (k V4Keeper) Acknowledgement(goCtx context.Context, msg *channeltypes.MsgAcknowledgement) (*channeltypes.MsgAcknowledgementResponse, error) {
   273  	ctx := sdk.UnwrapSDKContext(goCtx)
   274  
   275  	relayer, err := sdk.AccAddressFromBech32(msg.Signer)
   276  	if err != nil {
   277  		return nil, sdkerrors.Wrap(err, "Invalid address for msg Signer")
   278  	}
   279  
   280  	// Lookup module by channel capability
   281  	module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel)
   282  	if err != nil {
   283  		return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
   284  	}
   285  
   286  	// Retrieve callbacks from router
   287  	cbs, ok := k.Router.GetRoute(module)
   288  	if !ok {
   289  		return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
   290  	}
   291  
   292  	// Perform TAO verification
   293  	//
   294  	// If the acknowledgement was already received, perform a no-op
   295  	// Use a cached context to prevent accidental state changes
   296  	cacheCtx, writeFn := ctx.CacheContext()
   297  	err = k.ChannelKeeper.AcknowledgePacket(cacheCtx, cap, msg.Packet, msg.Acknowledgement, msg.ProofAcked, msg.ProofHeight)
   298  
   299  	// NOTE: The context returned by CacheContext() refers to a new EventManager, so it needs to explicitly set events to the original context.
   300  	ctx.EventManager().EmitEvents(cacheCtx.EventManager().Events())
   301  
   302  	switch err {
   303  	case nil:
   304  		writeFn()
   305  	case channeltypes.ErrNoOpMsg:
   306  		return &channeltypes.MsgAcknowledgementResponse{Result: channeltypes.NOOP}, nil
   307  	default:
   308  		return nil, sdkerrors.Wrap(err, "acknowledge packet verification failed")
   309  	}
   310  
   311  	// Perform application logic callback
   312  	err = cbs.OnAcknowledgementPacket(ctx, msg.Packet, msg.Acknowledgement, relayer)
   313  	if err != nil {
   314  		return nil, sdkerrors.Wrap(err, "acknowledge packet callback failed")
   315  	}
   316  
   317  	return &channeltypes.MsgAcknowledgementResponse{Result: channeltypes.SUCCESS}, nil
   318  }
   319  
   320  func (k V4Keeper) Timeout(goCtx context.Context, msg *channeltypes.MsgTimeout) (*channeltypes.MsgTimeoutResponse, error) {
   321  	ctx := sdk.UnwrapSDKContext(goCtx)
   322  
   323  	relayer, err := sdk.AccAddressFromBech32(msg.Signer)
   324  	if err != nil {
   325  		return nil, sdkerrors.Wrap(err, "Invalid address for msg Signer")
   326  	}
   327  
   328  	// Lookup module by channel capability
   329  	module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel)
   330  	if err != nil {
   331  		return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
   332  	}
   333  
   334  	// Retrieve callbacks from router
   335  	cbs, ok := k.Router.GetRoute(module)
   336  	if !ok {
   337  		return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
   338  	}
   339  
   340  	// Perform TAO verification
   341  	//
   342  	// If the timeout was already received, perform a no-op
   343  	// Use a cached context to prevent accidental state changes
   344  	cacheCtx, writeFn := ctx.CacheContext()
   345  	err = k.ChannelKeeper.TimeoutPacket(cacheCtx, msg.Packet, msg.ProofUnreceived, msg.ProofHeight, msg.NextSequenceRecv)
   346  
   347  	// NOTE: The context returned by CacheContext() refers to a new EventManager, so it needs to explicitly set events to the original context.
   348  	ctx.EventManager().EmitEvents(cacheCtx.EventManager().Events())
   349  
   350  	switch err {
   351  	case nil:
   352  		writeFn()
   353  	case channeltypes.ErrNoOpMsg:
   354  		return &channeltypes.MsgTimeoutResponse{Result: channeltypes.NOOP}, nil
   355  	default:
   356  		return nil, sdkerrors.Wrap(err, "timeout packet verification failed")
   357  	}
   358  
   359  	// Perform application logic callback
   360  	err = cbs.OnTimeoutPacket(ctx, msg.Packet, relayer)
   361  	if err != nil {
   362  		return nil, sdkerrors.Wrap(err, "timeout packet callback failed")
   363  	}
   364  
   365  	// Delete packet commitment
   366  	if err = k.ChannelKeeper.TimeoutExecuted(ctx, cap, msg.Packet); err != nil {
   367  		return nil, err
   368  	}
   369  
   370  	return &channeltypes.MsgTimeoutResponse{Result: channeltypes.SUCCESS}, nil
   371  }
   372  
   373  func (k V4Keeper) TimeoutOnClose(goCtx context.Context, msg *channeltypes.MsgTimeoutOnClose) (*channeltypes.MsgTimeoutOnCloseResponse, error) {
   374  	ctx := sdk.UnwrapSDKContext(goCtx)
   375  
   376  	relayer, err := sdk.AccAddressFromBech32(msg.Signer)
   377  	if err != nil {
   378  		return nil, sdkerrors.Wrap(err, "Invalid address for msg Signer")
   379  	}
   380  
   381  	// Lookup module by channel capability
   382  	module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel)
   383  	if err != nil {
   384  		return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
   385  	}
   386  
   387  	// Retrieve callbacks from router
   388  	cbs, ok := k.Router.GetRoute(module)
   389  	if !ok {
   390  		return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
   391  	}
   392  
   393  	// Perform TAO verification
   394  	//
   395  	// If the timeout was already received, perform a no-op
   396  	// Use a cached context to prevent accidental state changes
   397  	cacheCtx, writeFn := ctx.CacheContext()
   398  	err = k.ChannelKeeper.TimeoutOnClose(cacheCtx, cap, msg.Packet, msg.ProofUnreceived, msg.ProofClose, msg.ProofHeight, msg.NextSequenceRecv)
   399  
   400  	// NOTE: The context returned by CacheContext() refers to a new EventManager, so it needs to explicitly set events to the original context.
   401  	ctx.EventManager().EmitEvents(cacheCtx.EventManager().Events())
   402  
   403  	switch err {
   404  	case nil:
   405  		writeFn()
   406  	case channeltypes.ErrNoOpMsg:
   407  		return &channeltypes.MsgTimeoutOnCloseResponse{Result: channeltypes.NOOP}, nil
   408  	default:
   409  		return nil, sdkerrors.Wrap(err, "timeout on close packet verification failed")
   410  	}
   411  
   412  	// Perform application logic callback
   413  	//
   414  	// NOTE: MsgTimeout and MsgTimeoutOnClose use the same "OnTimeoutPacket"
   415  	// application logic callback.
   416  	err = cbs.OnTimeoutPacket(ctx, msg.Packet, relayer)
   417  	if err != nil {
   418  		return nil, sdkerrors.Wrap(err, "timeout packet callback failed")
   419  	}
   420  
   421  	// Delete packet commitment
   422  	if err = k.ChannelKeeper.TimeoutExecuted(ctx, cap, msg.Packet); err != nil {
   423  		return nil, err
   424  	}
   425  
   426  	return &channeltypes.MsgTimeoutOnCloseResponse{Result: channeltypes.SUCCESS}, nil
   427  }