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 }