github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/apps/transfer/module.go (about) 1 package transfer 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "math" 8 "math/rand" 9 10 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/upgrade" 11 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/params" 12 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/base" 13 14 clientCtx "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/context" 15 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec" 16 codectypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec/types" 17 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 18 sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors" 19 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/module" 20 capabilitytypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/capability/types" 21 simtypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/simulation" 22 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/transfer/client/cli" 23 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/transfer/keeper" 24 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/transfer/simulation" 25 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/transfer/types" 26 channeltypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/types" 27 porttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/05-port/types" 28 host "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/24-host" 29 ibcexported "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/exported" 30 abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types" 31 "github.com/gorilla/mux" 32 "github.com/grpc-ecosystem/grpc-gateway/runtime" 33 "github.com/spf13/cobra" 34 ) 35 36 var ( 37 _ module.AppModuleAdapter = AppModule{} 38 _ porttypes.IBCModule = AppModule{} 39 _ module.AppModuleBasicAdapter = AppModuleBasic{} 40 ) 41 42 // AppModuleBasic is the IBC Transfer AppModuleBasic 43 type AppModuleBasic struct{} 44 45 // Name implements AppModuleBasic interface 46 func (AppModuleBasic) Name() string { 47 return types.ModuleName 48 } 49 50 // RegisterLegacyAminoCodec implements AppModuleBasic interface 51 //func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { 52 // types.RegisterLegacyAminoCodec(cdc) 53 //} 54 55 func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) { 56 types.RegisterLegacyAminoCodec(cdc) 57 } 58 59 // RegisterInterfaces registers module concrete types into protobuf Any. 60 func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { 61 types.RegisterInterfaces(registry) 62 } 63 64 // DefaultGenesis returns default genesis state as raw bytes for the ibc 65 // transfer module. 66 func (AppModuleBasic) DefaultGenesis() json.RawMessage { 67 return nil 68 } 69 70 // ValidateGenesis performs genesis state validation for the mint module. 71 func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error { 72 return nil 73 } 74 75 // RegisterRESTRoutes implements AppModuleBasic interface 76 func (AppModuleBasic) RegisterRESTRoutes(ctx clientCtx.CLIContext, rtr *mux.Router) {} 77 78 // RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the ibc-transfer module. 79 func (AppModuleBasic) RegisterGRPCGatewayRoutes(ctx clientCtx.CLIContext, mux *runtime.ServeMux) { 80 types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(ctx)) 81 82 } 83 84 // GetTxCmd implements AppModuleBasic interface 85 func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command { 86 return nil 87 } 88 89 func (am AppModuleBasic) GetTxCmdV2(cdc *codec.CodecProxy, reg codectypes.InterfaceRegistry) *cobra.Command { 90 return cli.NewTxCmd(cdc, reg) 91 } 92 93 // GetQueryCmd implements AppModuleBasic interface 94 func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command { 95 return nil 96 } 97 98 func (AppModuleBasic) GetQueryCmdV2(cdc *codec.CodecProxy, reg codectypes.InterfaceRegistry) *cobra.Command { 99 return cli.GetQueryCmd(cdc, reg) 100 } 101 102 func (am AppModuleBasic) RegisterRouterForGRPC(cliCtx clientCtx.CLIContext, r *mux.Router) {} 103 104 // AppModule represents the AppModule for this module 105 type AppModule struct { 106 AppModuleBasic 107 *base.BaseIBCUpgradeModule 108 keeper keeper.Keeper 109 m *codec.CodecProxy 110 } 111 112 // NewAppModule creates a new 20-transfer module 113 func NewAppModule(k keeper.Keeper, m *codec.CodecProxy) AppModule { 114 ret := AppModule{ 115 keeper: k, 116 } 117 ret.BaseIBCUpgradeModule = base.NewBaseIBCUpgradeModule(ret.AppModuleBasic) 118 return ret 119 } 120 121 // RegisterInvariants implements the AppModule interface 122 func (AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {} 123 124 // Route implements the AppModule interface 125 func (am AppModule) Route() string { 126 return types.RouterKey 127 } 128 129 // QuerierRoute implements the AppModule interface 130 func (AppModule) QuerierRoute() string { 131 return types.QuerierRoute 132 } 133 134 func (a AppModule) NewHandler() sdk.Handler { 135 return NewHandler(a.keeper) 136 } 137 138 // TODO 139 func (a AppModule) NewQuerierHandler() sdk.Querier { 140 return nil 141 } 142 143 // LegacyQuerierHandler implements the AppModule interface 144 func (am AppModule) LegacyQuerierHandler(codec2 *codec.Codec) sdk.Querier { 145 return nil 146 } 147 148 // RegisterServices registers module services. 149 func (am AppModule) RegisterServices(cfg module.Configurator) { 150 types.RegisterMsgServer(cfg.MsgServer(), am.keeper) 151 types.RegisterQueryServer(cfg.QueryServer(), am.keeper) 152 } 153 154 // InitGenesis performs genesis initialization for the ibc-transfer module. It returns 155 // no validator updates. 156 func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate { 157 return nil 158 } 159 160 func (am AppModule) initGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate { 161 var genesisState types.GenesisState 162 ModuleCdc.MustUnmarshalJSON(data, &genesisState) 163 am.keeper.InitGenesis(ctx, genesisState) 164 return []abci.ValidatorUpdate{} 165 } 166 167 // ExportGenesis returns the exported genesis state as raw bytes for the ibc-transfer 168 // module. 169 func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage { 170 return nil 171 } 172 func (am AppModule) exportGenesis(ctx sdk.Context) json.RawMessage { 173 gs := am.keeper.ExportGenesis(ctx) 174 return ModuleCdc.MustMarshalJSON(gs) 175 } 176 func lazeGenesis() json.RawMessage { 177 ret := types.DefaultGenesisState() 178 return ModuleCdc.MustMarshalJSON(ret) 179 } 180 181 // ConsensusVersion implements AppModule/ConsensusVersion. 182 func (AppModule) ConsensusVersion() uint64 { return 1 } 183 184 // BeginBlock implements the AppModule interface 185 func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) { 186 } 187 188 // EndBlock implements the AppModule interface 189 func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate { 190 return []abci.ValidatorUpdate{} 191 } 192 193 // ____________________________________________________________________________ 194 195 // AppModuleSimulation functions 196 197 // GenerateGenesisState creates a randomized GenState of the transfer module. 198 func (AppModule) GenerateGenesisState(simState *module.SimulationState) { 199 simulation.RandomizedGenState(simState) 200 } 201 202 // ProposalContents doesn't return any content functions for governance proposals. 203 func (AppModule) ProposalContents(_ module.SimulationState) []simtypes.WeightedProposalContent { 204 return nil 205 } 206 207 // RandomizedParams creates randomized ibc-transfer param changes for the simulator. 208 func (AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange { 209 return simulation.ParamChanges(r) 210 } 211 212 // RegisterStoreDecoder registers a decoder for transfer module's types 213 func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { 214 sdr[types.StoreKey] = simulation.NewDecodeStore(am.keeper) 215 } 216 217 // WeightedOperations returns the all the transfer module operations with their respective weights. 218 func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation { 219 return nil 220 } 221 222 // ____________________________________________________________________________ 223 224 // ValidateTransferChannelParams does validation of a newly created transfer channel. A transfer 225 // channel must be UNORDERED, use the correct port (by default 'transfer'), and use the current 226 // supported version. Only 2^32 channels are allowed to be created. 227 func ValidateTransferChannelParams( 228 ctx sdk.Context, 229 keeper keeper.Keeper, 230 order channeltypes.Order, 231 portID string, 232 channelID string, 233 version string, 234 ) error { 235 if err := ValidateTransferChannelParamsV4(ctx, keeper, order, portID, channelID); nil != err { 236 return err 237 } 238 239 if version != types.Version { 240 return sdkerrors.Wrapf(types.ErrInvalidVersion, "got %s, expected %s", version, types.Version) 241 } 242 return nil 243 } 244 245 // ValidateTransferChannelParams does validation of a newly created transfer channel. A transfer 246 // channel must be UNORDERED, use the correct port (by default 'transfer'), and use the current 247 // supported version. Only 2^32 channels are allowed to be created. 248 func ValidateTransferChannelParamsV4( 249 ctx sdk.Context, 250 keeper keeper.Keeper, 251 order channeltypes.Order, 252 portID string, 253 channelID string, 254 ) error { 255 // NOTE: for escrow address security only 2^32 channels are allowed to be created 256 // Issue: https://github.com/cosmos/cosmos-sdk/issues/7737 257 channelSequence, err := channeltypes.ParseChannelSequence(channelID) 258 if err != nil { 259 return err 260 } 261 if channelSequence > uint64(math.MaxUint32) { 262 return sdkerrors.Wrapf(types.ErrMaxTransferChannels, "channel sequence %d is greater than max allowed transfer channels %d", channelSequence, uint64(math.MaxUint32)) 263 } 264 if order != channeltypes.UNORDERED { 265 return sdkerrors.Wrapf(channeltypes.ErrInvalidChannelOrdering, "expected %s channel, got %s ", channeltypes.UNORDERED, order) 266 } 267 268 // Require portID is the portID transfer module is bound to 269 boundPort := keeper.GetPort(ctx) 270 if boundPort != portID { 271 return sdkerrors.Wrapf(porttypes.ErrInvalidPort, "invalid port: %s, expected %s", portID, boundPort) 272 } 273 274 return nil 275 } 276 277 // OnChanOpenInit implements the IBCModule interface 278 func (am AppModule) OnChanOpenInit( 279 ctx sdk.Context, 280 order channeltypes.Order, 281 connectionHops []string, 282 portID string, 283 channelID string, 284 chanCap *capabilitytypes.Capability, 285 counterparty channeltypes.Counterparty, 286 version string, 287 ) (string, error) { 288 if err := ValidateTransferChannelParams(ctx, am.keeper, order, portID, channelID, version); err != nil { 289 return "", err 290 } 291 292 // Claim channel capability passed back by IBC module 293 if err := am.keeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { 294 return "", err 295 } 296 297 return version, nil 298 } 299 300 // OnChanOpenTry implements the IBCModule interface 301 func (am AppModule) OnChanOpenTry( 302 ctx sdk.Context, 303 order channeltypes.Order, 304 connectionHops []string, 305 portID, 306 channelID string, 307 chanCap *capabilitytypes.Capability, 308 counterparty channeltypes.Counterparty, 309 version, 310 counterpartyVersion string, 311 ) (string, error) { 312 if err := ValidateTransferChannelParams(ctx, am.keeper, order, portID, channelID, version); err != nil { 313 return "", err 314 } 315 316 if counterpartyVersion != types.Version { 317 return "", sdkerrors.Wrapf(types.ErrInvalidVersion, "invalid counterparty version: got: %s, expected %s", counterpartyVersion, types.Version) 318 } 319 320 // Module may have already claimed capability in OnChanOpenInit in the case of crossing hellos 321 // (ie chainA and chainB both call ChanOpenInit before one of them calls ChanOpenTry) 322 // If module can already authenticate the capability then module already owns it so we don't need to claim 323 // Otherwise, module does not have channel capability and we must claim it from IBC 324 if !am.keeper.AuthenticateCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)) { 325 // Only claim channel capability passed back by IBC module if we do not already own it 326 if err := am.keeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { 327 return "", err 328 } 329 } 330 331 return types.Version, nil 332 } 333 334 // OnChanOpenAck implements the IBCModule interface 335 func (im AppModule) OnChanOpenAck( 336 ctx sdk.Context, 337 portID, 338 channelID string, 339 _ string, 340 counterpartyVersion string, 341 ) error { 342 if counterpartyVersion != types.Version { 343 return sdkerrors.Wrapf(types.ErrInvalidVersion, "invalid counterparty version: %s, expected %s", counterpartyVersion, types.Version) 344 } 345 return nil 346 } 347 348 // OnChanOpenConfirm implements the IBCModule interface 349 func (am AppModule) OnChanOpenConfirm( 350 ctx sdk.Context, 351 portID, 352 channelID string, 353 ) error { 354 return nil 355 } 356 357 // OnChanCloseInit implements the IBCModule interface 358 func (am AppModule) OnChanCloseInit( 359 ctx sdk.Context, 360 portID, 361 channelID string, 362 ) error { 363 // Disallow user-initiated channel closing for transfer channels 364 return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "user cannot close channel") 365 } 366 367 // OnChanCloseConfirm implements the IBCModule interface 368 func (am AppModule) OnChanCloseConfirm( 369 ctx sdk.Context, 370 portID, 371 channelID string, 372 ) error { 373 return nil 374 } 375 376 // OnRecvPacket implements the IBCModule interface. A successful acknowledgement 377 // is returned if the packet data is succesfully decoded and the receive application 378 // logic returns without error. 379 func (am AppModule) OnRecvPacket( 380 ctx sdk.Context, 381 packet channeltypes.Packet, 382 relayer sdk.AccAddress, 383 ) ibcexported.Acknowledgement { 384 ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) 385 386 var data types.FungibleTokenPacketData 387 if err := types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { 388 ack = channeltypes.NewErrorAcknowledgement("cannot unmarshal ICS-20 transfer packet data") 389 } 390 391 // only attempt the application logic if the packet data 392 // was successfully decoded 393 if ack.Success() { 394 err := am.keeper.OnRecvPacket(ctx, packet, data) 395 if err != nil { 396 ack = channeltypes.NewErrorAcknowledgement(err.Error()) 397 } 398 } 399 400 ctx.EventManager().EmitEvent( 401 sdk.NewEvent( 402 types.EventTypePacket, 403 sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), 404 sdk.NewAttribute(types.AttributeKeyReceiver, data.Receiver), 405 sdk.NewAttribute(types.AttributeKeyDenom, data.Denom), 406 sdk.NewAttribute(types.AttributeKeyAmount, data.Amount), 407 sdk.NewAttribute(types.AttributeKeyAckSuccess, fmt.Sprintf("%t", ack.Success())), 408 ), 409 ) 410 411 // NOTE: acknowledgement will be written synchronously during IBC handler execution. 412 return ack 413 } 414 415 // OnAcknowledgementPacket implements the IBCModule interface 416 func (am AppModule) OnAcknowledgementPacket( 417 ctx sdk.Context, 418 packet channeltypes.Packet, 419 acknowledgement []byte, 420 relayer sdk.AccAddress, 421 ) error { 422 var ack channeltypes.Acknowledgement 423 if err := types.Marshal.GetProtocMarshal().UnmarshalJSON(acknowledgement, &ack); err != nil { 424 return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet acknowledgement: %v", err) 425 } 426 var data types.FungibleTokenPacketData 427 if err := types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { 428 return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet data: %s", err.Error()) 429 } 430 431 if err := am.keeper.OnAcknowledgementPacket(ctx, packet, data, ack); err != nil { 432 return err 433 } 434 435 ctx.EventManager().EmitEvent( 436 sdk.NewEvent( 437 types.EventTypePacket, 438 sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), 439 sdk.NewAttribute(types.AttributeKeyReceiver, data.Receiver), 440 sdk.NewAttribute(types.AttributeKeyDenom, data.Denom), 441 sdk.NewAttribute(types.AttributeKeyAmount, data.Amount), 442 sdk.NewAttribute(types.AttributeKeyAck, ack.String()), 443 ), 444 ) 445 446 switch resp := ack.Response.(type) { 447 case *channeltypes.Acknowledgement_Result: 448 ctx.EventManager().EmitEvent( 449 sdk.NewEvent( 450 types.EventTypePacket, 451 sdk.NewAttribute(types.AttributeKeyAckSuccess, string(resp.Result)), 452 ), 453 ) 454 case *channeltypes.Acknowledgement_Error: 455 ctx.EventManager().EmitEvent( 456 sdk.NewEvent( 457 types.EventTypePacket, 458 sdk.NewAttribute(types.AttributeKeyAckError, resp.Error), 459 ), 460 ) 461 } 462 463 return nil 464 } 465 466 // OnTimeoutPacket implements the IBCModule interface 467 func (am AppModule) OnTimeoutPacket( 468 ctx sdk.Context, 469 packet channeltypes.Packet, 470 relayer sdk.AccAddress, 471 ) error { 472 var data types.FungibleTokenPacketData 473 if err := types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { 474 return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet data: %s", err.Error()) 475 } 476 // refund tokens 477 if err := am.keeper.OnTimeoutPacket(ctx, packet, data); err != nil { 478 return err 479 } 480 481 ctx.EventManager().EmitEvent( 482 sdk.NewEvent( 483 types.EventTypeTimeout, 484 sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), 485 sdk.NewAttribute(types.AttributeKeyRefundReceiver, data.Sender), 486 sdk.NewAttribute(types.AttributeKeyRefundDenom, data.Denom), 487 sdk.NewAttribute(types.AttributeKeyRefundAmount, data.Amount), 488 ), 489 ) 490 491 return nil 492 } 493 494 // NegotiateAppVersion implements the IBCModule interface 495 func (am AppModule) NegotiateAppVersion( 496 ctx sdk.Context, 497 order channeltypes.Order, 498 connectionID string, 499 portID string, 500 counterparty channeltypes.Counterparty, 501 proposedVersion string, 502 ) (string, error) { 503 if proposedVersion != types.Version { 504 return "", sdkerrors.Wrapf(types.ErrInvalidVersion, "failed to negotiate app version: expected %s, got %s", types.Version, proposedVersion) 505 } 506 507 return types.Version, nil 508 } 509 510 func (am AppModule) RegisterTask() upgrade.HeightTask { 511 return upgrade.NewHeightTask(2, func(ctx sdk.Context) error { 512 if am.Sealed() { 513 return nil 514 } 515 data := lazeGenesis() 516 am.initGenesis(ctx, data) 517 return nil 518 }) 519 } 520 521 func (am AppModule) RegisterParam() params.ParamSet { 522 return nil 523 }