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  }