diff --git a/go.mod b/go.mod index b039dc14..bc564bd4 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d - github.com/irisnet/irismod v1.5.2-alpha1 + github.com/irisnet/irismod v1.5.2-alpha1.0.20220307063410-7b1dd26ad4d6 github.com/pkg/errors v0.9.1 github.com/rakyll/statik v0.1.7 github.com/spf13/cast v1.4.0 @@ -27,6 +27,7 @@ require ( golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67 google.golang.org/grpc v1.40.0 + google.golang.org/protobuf v1.27.1 ) replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 diff --git a/go.sum b/go.sum index d857d816..5c1eb289 100644 --- a/go.sum +++ b/go.sum @@ -661,8 +661,8 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= -github.com/irisnet/irismod v1.5.2-alpha1 h1:Xv3cU8Yj+B4nhbGKwIykVGCFM6S4vOPAlvxES/lCtd0= -github.com/irisnet/irismod v1.5.2-alpha1/go.mod h1:IrhKhC64ZkZ8gGkXS1+XXnZNLQWGocZv9W/gGmynEFA= +github.com/irisnet/irismod v1.5.2-alpha1.0.20220307063410-7b1dd26ad4d6 h1:6NcnSNo0TbEiPFGDEv4dIeQ8nqulUYeFBBGNL5qWZl8= +github.com/irisnet/irismod v1.5.2-alpha1.0.20220307063410-7b1dd26ad4d6/go.mod h1:IrhKhC64ZkZ8gGkXS1+XXnZNLQWGocZv9W/gGmynEFA= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= diff --git a/modules/tibc/apps/mt_transfer/client/cli/cli.go b/modules/tibc/apps/mt_transfer/client/cli/cli.go new file mode 100644 index 00000000..bae8a925 --- /dev/null +++ b/modules/tibc/apps/mt_transfer/client/cli/cli.go @@ -0,0 +1,41 @@ +package cli + +import ( + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" +) + +// NewTxCmd returns the transaction commands for TIBC multi token transfer +func NewTxCmd() *cobra.Command { + txCmd := &cobra.Command{ + Use: "tibc-mt-transfer", + Short: "TIBC multi token transfer transaction subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + txCmd.AddCommand( + NewTransferTxCmd(), + ) + + return txCmd +} + +// GetQueryCmd returns the query commands for TIBC multi token transfer +func GetQueryCmd() *cobra.Command { + queryCmd := &cobra.Command{ + Use: "tibc-mt-transfer", + Short: "TIBC multi token transfer query subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + } + + queryCmd.AddCommand( + GetCmdQueryClassTrace(), + GetCmdQueryClassTraces(), + ) + + return queryCmd +} diff --git a/modules/tibc/apps/mt_transfer/client/cli/flags.go b/modules/tibc/apps/mt_transfer/client/cli/flags.go new file mode 100644 index 00000000..b62dad59 --- /dev/null +++ b/modules/tibc/apps/mt_transfer/client/cli/flags.go @@ -0,0 +1,19 @@ +package cli + +import ( + flag "github.com/spf13/pflag" +) + +const ( + FlagRelayChain = "relay-chain" + FlagDestContract = "dest-contract" +) + +var ( + FsMtTransfer = flag.NewFlagSet("", flag.ContinueOnError) +) + +func init() { + FsMtTransfer.String(FlagRelayChain, "", "relay chain used by cross-chain mt") + FsMtTransfer.String(FlagDestContract, "", "the destination contract address to receive the mt") +} diff --git a/modules/tibc/apps/mt_transfer/client/cli/query.go b/modules/tibc/apps/mt_transfer/client/cli/query.go new file mode 100644 index 00000000..13975268 --- /dev/null +++ b/modules/tibc/apps/mt_transfer/client/cli/query.go @@ -0,0 +1,83 @@ +package cli + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/version" + "github.com/spf13/cobra" + + "github.com/bianjieai/tibc-go/modules/tibc/apps/nft_transfer/types" +) + +// GetCmdQueryClassTrace defines the command to query a class trace from a given hash. +func GetCmdQueryClassTrace() *cobra.Command { + cmd := &cobra.Command{ + Use: "class-trace [hash]", + Short: "Query the class trace info from a given trace hash", + Long: "Query the class trace info from a given trace hash", + Example: fmt.Sprintf("%s query tibc-mt-transfer class-trace [hash]", version.AppName), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + req := &types.QueryClassTraceRequest{ + Hash: args[0], + } + + res, err := queryClient.ClassTrace(cmd.Context(), req) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + return cmd +} + +// GetCmdQueryClassTraces defines the command to query all the class trace infos +// that this chain mantains. +func GetCmdQueryClassTraces() *cobra.Command { + cmd := &cobra.Command{ + Use: "class-traces", + Short: "Query the trace info for all mt classes", + Long: "Query the trace info for all mt classes", + Example: fmt.Sprintf("%s query tibc-mt-transfer class-traces", version.AppName), + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, _ []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + req := &types.QueryClassTracesRequest{ + Pagination: pageReq, + } + + res, err := queryClient.ClassTraces(cmd.Context(), req) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "class trace") + + return cmd +} diff --git a/modules/tibc/apps/mt_transfer/client/cli/tx.go b/modules/tibc/apps/mt_transfer/client/cli/tx.go new file mode 100644 index 00000000..36da7e1f --- /dev/null +++ b/modules/tibc/apps/mt_transfer/client/cli/tx.go @@ -0,0 +1,71 @@ +package cli + +import ( + "fmt" + "strconv" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/version" + + "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types" +) + +// NewTransferTxCmd returns the command to create a NewMsgTransfer transaction +func NewTransferTxCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "transfer [dest-chain] [receiver] [class] [id] [amount]", + Short: "Transfer a mt through TIBC", + Example: fmt.Sprintf( + "%s tx tibc-mt-transfer transfer "+ + "--relay-chain= "+ + "--dest-contract=", + version.AppName, + ), + Args: cobra.ExactArgs(5), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + sender := clientCtx.GetFromAddress().String() + destChain := args[0] + receiver := args[1] + class := args[2] + id := args[3] + amount := args[4] + + relayChain, err := cmd.Flags().GetString(FlagRelayChain) + if err != nil { + return err + } + + destContract, err := cmd.Flags().GetString(FlagDestContract) + if err != nil { + return err + } + + amt, err := strconv.ParseUint(amount, 10, 64) + if err != nil { + return err + } + + msg := types.NewMsgMtTransfer( + class, id, sender, receiver, + destChain, relayChain, destContract, amt, + ) + if err := msg.ValidateBasic(); err != nil { + return err + } + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().AddFlagSet(FsMtTransfer) + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/modules/tibc/apps/mt_transfer/handler.go b/modules/tibc/apps/mt_transfer/handler.go new file mode 100644 index 00000000..cc25046b --- /dev/null +++ b/modules/tibc/apps/mt_transfer/handler.go @@ -0,0 +1,25 @@ +package mt_transfer + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/keeper" + mttransfertypes "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types" +) + +// NewHandler defines the TIBC mt transfer handler +func NewHandler(k keeper.Keeper) sdk.Handler { + return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { + ctx = ctx.WithEventManager(sdk.NewEventManager()) + + switch msg := msg.(type) { + case *mttransfertypes.MsgMtTransfer: + res, err := k.MtTransfer(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) + + default: + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized TIBC message type: %T", msg) + } + } +} diff --git a/modules/tibc/apps/mt_transfer/keeper/encoding.go b/modules/tibc/apps/mt_transfer/keeper/encoding.go new file mode 100644 index 00000000..c9f53c89 --- /dev/null +++ b/modules/tibc/apps/mt_transfer/keeper/encoding.go @@ -0,0 +1,22 @@ +package keeper + +import ( + "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types" +) + +// MustMarshalClassTrace attempts to encode an ClassTrace object and returns the +// raw encoded bytes. It panics on error. +func (k Keeper) MustMarshalClassTrace(classTrace types.ClassTrace) []byte { + return k.cdc.MustMarshal(&classTrace) +} + +// UnmarshalClassTrace attempts to decode and return an ClassTrace object from +// raw encoded bytes. +func (k Keeper) UnmarshalClassTrace(bz []byte) (types.ClassTrace, error) { + var classTrace types.ClassTrace + if err := k.cdc.Unmarshal(bz, &classTrace); err != nil { + return types.ClassTrace{}, err + } + + return classTrace, nil +} diff --git a/modules/tibc/apps/mt_transfer/keeper/grpc_query.go b/modules/tibc/apps/mt_transfer/keeper/grpc_query.go new file mode 100644 index 00000000..d5f5ea7e --- /dev/null +++ b/modules/tibc/apps/mt_transfer/keeper/grpc_query.go @@ -0,0 +1,73 @@ +package keeper + +import ( + "context" + "fmt" + + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/query" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types" +) + +var _ types.QueryServer = Keeper{} + +// ClassTrace implements the Query/ClassTrace gRPC method +func (q Keeper) ClassTrace(c context.Context, req *types.QueryClassTraceRequest) (*types.QueryClassTraceResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + hash, err := types.ParseHexHash(req.Hash) + if err != nil { + return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("invalid class trace hash %s, %s", req.Hash, err)) + } + + ctx := sdk.UnwrapSDKContext(c) + classTrace, found := q.GetClassTrace(ctx, hash) + if !found { + return nil, status.Error( + codes.NotFound, + sdkerrors.Wrap(types.ErrTraceNotFound, req.Hash).Error(), + ) + } + + return &types.QueryClassTraceResponse{ + ClassTrace: &classTrace, + }, nil +} + +// ClassTraces implements the Query/ClassTraces gRPC method +func (q Keeper) ClassTraces(c context.Context, req *types.QueryClassTracesRequest) (*types.QueryClassTracesResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(c) + + traces := types.Traces{} + store := prefix.NewStore(ctx.KVStore(q.storeKey), types.ClassTraceKey) + + pageRes, err := query.Paginate(store, req.Pagination, func(_, value []byte) error { + result, err := q.UnmarshalClassTrace(value) + if err != nil { + return err + } + + traces = append(traces, result) + return nil + }) + + if err != nil { + return nil, err + } + + return &types.QueryClassTracesResponse{ + ClassTraces: traces.Sort(), + Pagination: pageRes, + }, nil +} diff --git a/modules/tibc/apps/mt_transfer/keeper/grpc_query_test.go b/modules/tibc/apps/mt_transfer/keeper/grpc_query_test.go new file mode 100644 index 00000000..6f931531 --- /dev/null +++ b/modules/tibc/apps/mt_transfer/keeper/grpc_query_test.go @@ -0,0 +1,135 @@ +package keeper_test + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + + "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types" +) + +func (suite *KeeperTestSuite) TestQueryClassTrace() { + var ( + req *types.QueryClassTraceRequest + expTrace types.ClassTrace + ) + + testCases := []struct { + msg string + malleate func() + expPass bool + }{ + { + "invalid hex hash", + func() { + req = &types.QueryClassTraceRequest{ + Hash: "!@#!@#!", + } + }, + false, + }, + { + "not found denom trace", + func() { + expTrace.Path = "mt/A/B" + expTrace.BaseClass = "uiris" + req = &types.QueryClassTraceRequest{ + Hash: expTrace.Hash().String(), + } + }, + false, + }, + { + "success", + func() { + expTrace.Path = "mt/A/B" + expTrace.BaseClass = "uiris" + suite.chainA.App.MtTransferKeeper.SetClassTrace(suite.chainA.GetContext(), expTrace) + req = &types.QueryClassTraceRequest{ + Hash: expTrace.Hash().String(), + } + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + + tc.malleate() + ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) + + res, err := suite.queryClient.ClassTrace(ctx, req) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotNil(res) + suite.Require().Equal(&expTrace, res.ClassTrace) + } else { + suite.Require().Error(err) + } + }) + } +} + +func (suite *KeeperTestSuite) TestQueryDenomTraces() { + var ( + req *types.QueryClassTracesRequest + expTraces = types.Traces(nil) + ) + + testCases := []struct { + msg string + malleate func() + expPass bool + }{ + { + "empty pagination", + func() { + req = &types.QueryClassTracesRequest{} + }, + true, + }, + { + "success", + func() { + expTraces = append(expTraces, types.ClassTrace{Path: "", BaseClass: "uiris"}) + expTraces = append(expTraces, types.ClassTrace{Path: "mt/B", BaseClass: "uiris"}) + expTraces = append(expTraces, types.ClassTrace{Path: "mt/A/B", BaseClass: "uiris"}) + + for _, trace := range expTraces { + suite.chainA.App.MtTransferKeeper.SetClassTrace(suite.chainA.GetContext(), trace) + } + + req = &types.QueryClassTracesRequest{ + Pagination: &query.PageRequest{ + Limit: 5, + CountTotal: false, + }, + } + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + + tc.malleate() + ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) + + res, err := suite.queryClient.ClassTraces(ctx, req) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotNil(res) + suite.Require().Equal(expTraces.Sort(), res.ClassTraces) + } else { + suite.Require().Error(err) + } + }) + } +} diff --git a/modules/tibc/apps/mt_transfer/keeper/keeper.go b/modules/tibc/apps/mt_transfer/keeper/keeper.go new file mode 100644 index 00000000..377fd07f --- /dev/null +++ b/modules/tibc/apps/mt_transfer/keeper/keeper.go @@ -0,0 +1,85 @@ +package keeper + +import ( + "github.com/tendermint/tendermint/libs/log" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" + tmbytes "github.com/tendermint/tendermint/libs/bytes" + + "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types" + host "github.com/bianjieai/tibc-go/modules/tibc/core/24-host" +) + +type Keeper struct { + storeKey sdk.StoreKey + cdc codec.BinaryCodec + paramSpace paramtypes.Subspace + + ak types.AccountKeeper + mk types.MtKeeper + pk types.PacketKeeper + ck types.ClientKeeper +} + +// NewKeeper creates a new TIBC transfer Keeper instance +func NewKeeper( + cdc codec.BinaryCodec, + key sdk.StoreKey, + paramSpace paramtypes.Subspace, + ak types.AccountKeeper, + mk types.MtKeeper, + pk types.PacketKeeper, + ck types.ClientKeeper, +) Keeper { + if addr := ak.GetModuleAddress(types.ModuleName); addr == nil { + panic("the TIBC mt-transfer module account has not been set") + } + + return Keeper{ + cdc: cdc, + storeKey: key, + paramSpace: paramSpace, + ak: ak, + mk: mk, + pk: pk, + ck: ck, + } +} + +// Logger returns a module-specific logger. +func (k Keeper) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("module", "x/"+host.ModuleName+"-"+types.ModuleName) +} + +// GetMtTransferModuleAddr returns the mt transfer module addr +func (k Keeper) GetMtTransferModuleAddr(name string) sdk.AccAddress { + return k.ak.GetModuleAddress(name) +} + +// HasClassTrace checks if a the key with the given class trace hash exists on the store. +func (k Keeper) HasClassTrace(ctx sdk.Context, classTraceHash tmbytes.HexBytes) bool { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.ClassTraceKey) + return store.Has(classTraceHash) +} + +// SetClassTrace sets a new {trace hash -> class trace} pair to the store. +func (k Keeper) SetClassTrace(ctx sdk.Context, classTrace types.ClassTrace) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.ClassTraceKey) + bz := k.MustMarshalClassTrace(classTrace) + store.Set(classTrace.Hash(), bz) +} + +// GetClassTrace retreives the full identifiers trace and base class from the store. +func (k Keeper) GetClassTrace(ctx sdk.Context, classTraceHash tmbytes.HexBytes) (types.ClassTrace, bool) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.ClassTraceKey) + bz := store.Get(classTraceHash) + if bz == nil { + return types.ClassTrace{}, false + } + var classTrace types.ClassTrace + k.cdc.MustUnmarshal(bz, &classTrace) + return classTrace, true +} diff --git a/modules/tibc/apps/mt_transfer/keeper/keeper_test.go b/modules/tibc/apps/mt_transfer/keeper/keeper_test.go new file mode 100644 index 00000000..35bb2f55 --- /dev/null +++ b/modules/tibc/apps/mt_transfer/keeper/keeper_test.go @@ -0,0 +1,58 @@ +package keeper_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/baseapp" + + "github.com/stretchr/testify/suite" + + "github.com/tendermint/tendermint/crypto" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types" + tibctesting "github.com/bianjieai/tibc-go/modules/tibc/testing" +) + +type KeeperTestSuite struct { + suite.Suite + ctx sdk.Context + + coordinator *tibctesting.Coordinator + + // testing chains used for convenience and readability + chainA *tibctesting.TestChain + chainB *tibctesting.TestChain + chainC *tibctesting.TestChain + queryClient types.QueryClient +} + +func (suite *KeeperTestSuite) SetupTest() { + suite.coordinator = tibctesting.NewCoordinator(suite.T(), 3) + suite.chainA = suite.coordinator.GetChain(tibctesting.GetChainID(0)) + suite.chainB = suite.coordinator.GetChain(tibctesting.GetChainID(1)) + suite.chainC = suite.coordinator.GetChain(tibctesting.GetChainID(2)) + + queryHelper := baseapp.NewQueryServerTestHelper(suite.chainA.GetContext(), suite.chainA.App.InterfaceRegistry()) + types.RegisterQueryServer(queryHelper, suite.chainA.App.MtTransferKeeper) + suite.queryClient = types.NewQueryClient(queryHelper) +} + +func (suite *KeeperTestSuite) TestGetTransferMoudleAddr() { + expectedMaccAddr := sdk.AccAddress(crypto.AddressHash([]byte(types.ModuleName))) + + macc := suite.chainA.App.NftTransferKeeper.GetNftTransferModuleAddr(types.ModuleName) + + suite.Require().NotNil(macc) + suite.Require().Equal(expectedMaccAddr, macc) +} + +func NewTransferPath(scChain, destChain *tibctesting.TestChain) *tibctesting.Path { + path := tibctesting.NewPath(scChain, destChain) + return path +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(KeeperTestSuite)) +} diff --git a/modules/tibc/apps/mt_transfer/keeper/msg_server.go b/modules/tibc/apps/mt_transfer/keeper/msg_server.go new file mode 100644 index 00000000..a85abcec --- /dev/null +++ b/modules/tibc/apps/mt_transfer/keeper/msg_server.go @@ -0,0 +1,45 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types" +) + +var _ types.MsgServer = Keeper{} + +func (k Keeper) MtTransfer(goCtx context.Context, msg *types.MsgMtTransfer) (*types.MsgMtTransferResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + sender, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return nil, err + } + + if err := k.SendMtTransfer( + ctx, msg.Class, msg.Id, + sender, msg.Receiver, + msg.DestChain, msg.RealayChain, msg.DestContract, + msg.Amount, + ); err != nil { + return nil, err + } + + k.Logger(ctx).Info("TIBC multi token transfer", "mt", msg.Id, "sender", msg.Sender, "receiver", msg.Receiver) + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + types.EventTypeMtTransfer, + sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), + sdk.NewAttribute(types.AttributeKeyReceiver, msg.Receiver), + ), + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), + ), + }) + + return &types.MsgMtTransferResponse{}, nil +} diff --git a/modules/tibc/apps/mt_transfer/keeper/relay.go b/modules/tibc/apps/mt_transfer/keeper/relay.go new file mode 100644 index 00000000..a8c32b31 --- /dev/null +++ b/modules/tibc/apps/mt_transfer/keeper/relay.go @@ -0,0 +1,343 @@ +package keeper + +import ( + "strconv" + "strings" + + "github.com/armon/go-metrics" + "github.com/cosmos/cosmos-sdk/telemetry" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types" + packetType "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/types" + routingtypes "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" + coretypes "github.com/bianjieai/tibc-go/modules/tibc/core/types" +) + +const ( + CLASSPREFIX = "tibc-" + + CLASSPATHPREFIX = "mt" + + DELIMITER = "/" +) + +func (k Keeper) SendMtTransfer( + ctx sdk.Context, + class, id string, + sender sdk.AccAddress, + receiver string, + destChain string, + relayChain string, + destContract string, + amount uint64, +) error { + _, found := k.mk.GetDenom(ctx, class) + if !found { + return sdkerrors.Wrapf(types.ErrInvalidDenom, "class %s not existed ", class) + } + + mt, err := k.mk.GetMT(ctx, class, id) + if err != nil { + return sdkerrors.Wrapf(types.ErrUnknownNFT, "invalid mt %s from class %s", id, class) + } + + sourceChain := k.ck.GetChainName(ctx) + if sourceChain == destChain { + return sdkerrors.Wrapf(types.ErrScChainEqualToDestChain, "invalid destChain %s equals to scChain %s", destChain, sourceChain) + } + + fullClassPath := class + + // deconstruct the mt class into the class trace info to determine if the sender is the source chain + if strings.HasPrefix(class, CLASSPREFIX) { + fullClassPath, err = k.ClassPathFromHash(ctx, class) + if err != nil { + return err + } + } + + labels := []metrics.Label{ + telemetry.NewLabel(coretypes.LabelSourceChain, sourceChain), + telemetry.NewLabel(coretypes.LabelDestinationChain, destChain), + } + + // determine whether mt is sent from the source chain or sent back to the source chain from other chains + awayFromOrigin := k.determineAwayFromOrigin(fullClassPath, destChain) + + // get the next sequence + sequence := k.pk.GetNextSequenceSend(ctx, sourceChain, destChain) + + // get moudle address + moudleAddr := k.GetMtTransferModuleAddr(types.ModuleName) + + labels = append(labels, telemetry.NewLabel(coretypes.LabelSource, strconv.FormatBool(awayFromOrigin))) + if awayFromOrigin { + // Two conversion scenarios + // 1. mtClass -> tibc-hash(mt/A/B/mtClass) + // 2. tibc-hash(mt/A/B/mtClass) -> tibc-hash(mt/A/B/C/mtClass) + + // Two things need to be done + // 1. lock mt |send to moduleAccount + // 2. send packet + // The mt attribute must be marked as unchanged (it cannot be changed in practice) + // because the TransferOwner method will verify when UpdateRestricted is true + if err := k.mk.TransferOwner(ctx, class, id, amount, sender, moudleAddr); err != nil { + return err + } + } else { + // burn mt + if err := k.mk.BurnMT(ctx, class, id, amount, sender); err != nil { + return err + } + } + + // constructs packet + packetData := types.NewMultiTokenPacketData( + fullClassPath, + id, + sender.String(), + receiver, + awayFromOrigin, + destContract, + amount, + mt.GetData(), + ) + + packet := packetType.NewPacket(packetData.GetBytes(), sequence, sourceChain, destChain, relayChain, string(routingtypes.MT)) + + defer func() { + telemetry.SetGaugeWithLabels( + []string{"tx", "msg", "tibc", "mttransfer"}, + 1, + []metrics.Label{telemetry.NewLabel(coretypes.LabelDenom, fullClassPath)}, + ) + + telemetry.IncrCounterWithLabels( + []string{"tibc", types.ModuleName, "send"}, + 1, + labels, + ) + }() + // send packet + return k.pk.SendPacket(ctx, packet) +} + +/* +OnRecvPacket +A->B->C away_from_source == true + B receive packet from A : class -> mt/A/B/class + c receive packet from B : mt/A/B/class -> mt/A/B/C/class +C->B->A away_from_source == flase + B receive packet from C : mt/A/B/C/class -> mt/A/B/class + A receive packet from B : mt/A/B/class -> class +*/ +func (k Keeper) OnRecvPacket(ctx sdk.Context, packet packetType.Packet, data types.MultiTokenPacketData) error { + // validate packet data upon receiving + if err := data.ValidateBasic(); err != nil { + return err + } + + receiver, err := sdk.AccAddressFromBech32(data.Receiver) + if err != nil { + return err + } + + labels := []metrics.Label{ + telemetry.NewLabel(coretypes.LabelSourceChain, packet.SourceChain), + telemetry.NewLabel(coretypes.LabelDestinationChain, packet.DestinationChain), + } + + moudleAddr := k.GetMtTransferModuleAddr(types.ModuleName) + var newClassPath string + if data.AwayFromOrigin { + labels = append(labels, telemetry.NewLabel(coretypes.LabelSource, "true")) + newClassPath = k.getAwayNewClassPath(packet.SourceChain, packet.DestinationChain, data.Class) + voucherClass := k.getIBCClassFromClassPath(ctx, newClassPath) + + _, found := k.mk.GetDenom(ctx, voucherClass) + if !found { + _ = k.mk.IssueDenom(ctx, voucherClass, "", moudleAddr, data.Data) + } + + if !k.mk.HasMT(ctx, voucherClass, data.Id) { + _ = k.mk.IssueMT(ctx, voucherClass, data.Id, data.Amount, data.Data, moudleAddr) + } else { + k.mk.MintMT(ctx, voucherClass, data.Id, data.Amount, moudleAddr) + } + + if err := k.mk.TransferOwner(ctx, voucherClass, data.Id, data.Amount, moudleAddr, receiver); err != nil { + return err + } + } else { + labels = append(labels, telemetry.NewLabel(coretypes.LabelSource, "false")) + + if !strings.HasPrefix(data.Class, CLASSPATHPREFIX) { + return sdkerrors.Wrapf(types.ErrInvalidDenom, "class has no prefix: %s", data.Class) + } + + newClassPath = k.getBackNewClassPath(data.Class) + classTrace := types.ParseClassTrace(newClassPath) + voucherClass := classTrace.IBCClass() + // unlock + if err := k.mk.TransferOwner(ctx, voucherClass, data.Id, data.Amount, moudleAddr, receiver); err != nil { + return err + } + } + + defer func() { + telemetry.SetGaugeWithLabels( + []string{"tx", "msg", "ibc", "transfer"}, + 1, + []metrics.Label{telemetry.NewLabel(coretypes.LabelDenom, newClassPath)}, + ) + + telemetry.IncrCounterWithLabels( + []string{"ibc", types.ModuleName, "send"}, + 1, + labels, + ) + }() + + return nil +} + +func (k Keeper) OnAcknowledgementPacket(ctx sdk.Context, data types.MultiTokenPacketData, ack packetType.Acknowledgement) error { + switch ack.Response.(type) { + case *packetType.Acknowledgement_Error: + return k.refundPacketToken(ctx, data) + default: + // the acknowledgement succeeded on the receiving chain so nothing + // needs to be executed and no error needs to be returned + return nil + } +} + +func (k Keeper) refundPacketToken(ctx sdk.Context, data types.MultiTokenPacketData) error { + sender, err := sdk.AccAddressFromBech32(data.Sender) + if err != nil { + return err + } + + moudleAddr := k.GetMtTransferModuleAddr(types.ModuleName) + classTrace := types.ParseClassTrace(data.Class) + voucherClass := classTrace.IBCClass() + + if data.AwayFromOrigin { + // unlock + if err := k.mk.TransferOwner(ctx, voucherClass, data.Id, data.Amount, + k.GetMtTransferModuleAddr(types.ModuleName), sender); err != nil { + return err + } + } else { + k.mk.MintMT(ctx, voucherClass, data.Id, data.Amount, moudleAddr) + if err := k.mk.TransferOwner(ctx, voucherClass, data.Id, data.Amount, moudleAddr, sender); err != nil { + return err + } + } + return nil +} + +// determineAwayFromOrigin determine whether nft is sent from the source chain or sent back to the source chain from other chains +func (k Keeper) determineAwayFromOrigin(class, destChain string) (awayFromOrigin bool) { + /* + -- not has prefix + 1. A -> B class:class | sourceChain:A | destChain:B |awayFromOrigin = true + -- has prefix + First take the source chain from the path + (this path represents the path generated from the source chain in the target chain), + and then judge whether the source chain is equal to the target chain, + if it is equal, it means it is close to the source chain, + if it is not equal then Indicates that we continue to stay away from the source chain + + 1. B -> C class:mt/A/B/class | sourceChain:B | destChain:C |awayFromOrigin = true + 2. C -> B class:mt/A/B/C/class | sourceChain:C | destChain:B |awayFromOrigin = false + 3. B -> A class:mt/A/B/class | sourceChain:B | destChain:A |awayFromOrigin = false + */ + if !strings.HasPrefix(class, CLASSPATHPREFIX) || + (strings.HasPrefix(class, CLASSPATHPREFIX) && !strings.Contains(class, DELIMITER)) { + return true + } + + classSplit := strings.Split(class, DELIMITER) + + return classSplit[len(classSplit)-3] != destChain +} + +//fullClassPath = "tibcmt" + "/" + packet.SourceChain + "/" + packet.DestinationChain + "/" + data.Class +func (k Keeper) concatClassPath(scChain, destChain, class string) string { + var b strings.Builder + b.WriteString(CLASSPATHPREFIX) + b.WriteString(DELIMITER) + b.WriteString(scChain) + b.WriteString(DELIMITER) + b.WriteString(destChain) + b.WriteString(DELIMITER) + b.WriteString(class) + return b.String() +} + +// getAwayNewClassPath +func (k Keeper) getAwayNewClassPath(scChain, destChain, class string) (newClassPath string) { + if strings.HasPrefix(class, CLASSPATHPREFIX) && strings.Contains(class, DELIMITER) { + // mt/A/B/class -> mt/A/B/C/class + // [mt][A][B][class] -> [mt][A][B][C][class] + classSplit := strings.Split(class, DELIMITER) + classSplit = append(classSplit[:len(classSplit)-1], append([]string{destChain}, classSplit[len(classSplit)-1:]...)...) + newClassPath = strings.Join(classSplit, DELIMITER) + } else { + // class -> nft/A/B/class + newClassPath = k.concatClassPath(scChain, destChain, class) + } + return +} + +// getBackNewClassPath +func (k Keeper) getBackNewClassPath(class string) (newClassPath string) { + classSplit := strings.Split(class, DELIMITER) + + if len(classSplit) == 4 { + // mt/A/B/class -> class + newClassPath = classSplit[len(classSplit)-1] + } else { + // mt/A/B/C/class -> mt/A/B/class + classSplit = append(classSplit[:len(classSplit)-2], classSplit[len(classSplit)-1]) + newClassPath = strings.Join(classSplit, DELIMITER) + } + return +} + +// example : mt/A/B/class -> tibc-hash(mt/A/B/class) +func (k Keeper) getIBCClassFromClassPath(ctx sdk.Context, classPath string) string { + // construct the class trace from the full raw class + classTrace := types.ParseClassTrace(classPath) + traceHash := classTrace.Hash() + + if !k.HasClassTrace(ctx, traceHash) { + k.SetClassTrace(ctx, classTrace) + } + + return classTrace.IBCClass() +} + +// ClassPathFromHash returns the full class path prefix from an ibc class with a hash +// component. +func (k Keeper) ClassPathFromHash(ctx sdk.Context, class string) (string, error) { + // trim the class prefix, by default "tibc-" + hexHash := class[len(types.ClassPrefix+"-"):] + + hash, err := types.ParseHexHash(hexHash) + if err != nil { + return "", sdkerrors.Wrap(types.ErrInvalidDenom, err.Error()) + } + + denomTrace, found := k.GetClassTrace(ctx, hash) + if !found { + return "", sdkerrors.Wrap(types.ErrTraceNotFound, hexHash) + } + + fullDenomPath := denomTrace.GetFullClassPath() + return fullDenomPath, nil +} diff --git a/modules/tibc/apps/mt_transfer/keeper/relay_test.go b/modules/tibc/apps/mt_transfer/keeper/relay_test.go new file mode 100644 index 00000000..b3968ae2 --- /dev/null +++ b/modules/tibc/apps/mt_transfer/keeper/relay_test.go @@ -0,0 +1,355 @@ +package keeper_test + +import ( + "fmt" + + mttypes "github.com/irisnet/irismod/modules/mt/types" + + "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types" + packettypes "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/types" + routingtypes "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" + ibctesting "github.com/bianjieai/tibc-go/modules/tibc/testing" +) + +const ( + CLASS = "c02a799c8fee067a7f9b944554d8431ee539847234441833e45a3a2d3123fd99" //sha256("mt-denom-1") + PREFIX = "tibc/mt" + MTID = "ff6e57b41cb52ae7d58d854b2123da2c5657fd15d525821a13fe7da1b9cebd80" //sha256("mt-1") +) + +func (suite *KeeperTestSuite) TestSendTransfer() { + + var ( + path *ibctesting.Path + newClass string + ) + + testCases := []struct { + msg string + malleate func() + awayFromSource bool + expPass bool + }{{ + "successful transfer from source chain", + func() { + // issue denom + issueDenomMsg := mttypes.NewMsgIssueDenom( + "dog-name", "", + suite.chainA.SenderAccount.GetAddress().String(), + ) + _, _ = suite.chainA.SendMsgs(issueDenomMsg) + + // mint nft + mintNftMsg := mttypes.NewMsgMintMT( + "", CLASS, 2, "", + suite.chainA.SenderAccount.GetAddress().String(), + suite.chainA.SenderAccount.GetAddress().String(), + ) + _, _ = suite.chainA.SendMsgs(mintNftMsg) + }, + true, true, + }, { + "successful transfer from sink chain", + func() { + // issue denom + issueDenomMsg := mttypes.NewMsgIssueDenom( + "dog-name", "", + suite.chainA.SenderAccount.GetAddress().String(), + ) + _, _ = suite.chainA.SendMsgs(issueDenomMsg) + + // mint nft + mintNftMsg := mttypes.NewMsgMintMT( + "", CLASS, 2, "none", + suite.chainA.SenderAccount.GetAddress().String(), + suite.chainA.SenderAccount.GetAddress().String(), + ) + _, _ = suite.chainA.SendMsgs(mintNftMsg) + + data := types.NewMultiTokenPacketData( + CLASS, MTID, + suite.chainA.SenderAccount.GetAddress().String(), + suite.chainB.SenderAccount.GetAddress().String(), + true, + "0xabcsda", + 1, + []byte(""), + ) + + packet := packettypes.NewPacket(data.GetBytes(), uint64(1), suite.chainA.ChainID, suite.chainB.ChainID, "", string(routingtypes.MT)) + _ = suite.chainB.App.MtTransferKeeper.OnRecvPacket(suite.chainB.GetContext(), packet, data) + }, + false, true, + }} + + for _, tc := range testCases { + tc := tc + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() + path = NewTransferPath(suite.chainA, suite.chainB) + suite.coordinator.SetupClients(path) + + tc.malleate() + if !tc.awayFromSource { + newClass = "tibc-1AA90CD7273981C2E2CFFC5415D887C17FB03A7FCB49EFE4A7B6878E384F1670" + //newClass = PREFIX + "/" + suite.chainA.ChainID + "/" + CLASS + // send nft from chainB to chainA + err := suite.chainB.App.MtTransferKeeper.SendMtTransfer( + suite.chainB.GetContext(), + newClass, + MTID, + suite.chainB.SenderAccount.GetAddress(), + suite.chainA.SenderAccount.GetAddress().String(), + suite.chainA.ChainID, "", + "0xabcsda", 1) + + suite.Require().NoError(err) // message committed + + } + err := suite.chainA.App.MtTransferKeeper.SendMtTransfer( + suite.chainA.GetContext(), + CLASS, + MTID, + suite.chainA.SenderAccount.GetAddress(), + suite.chainB.SenderAccount.GetAddress().String(), + suite.chainB.ChainID, "", + "0xabcsda", 1) + if tc.expPass { + suite.Require().NoError(err) + } else { + suite.Require().Error(err) + } + + }) + } +} + +func (suite *KeeperTestSuite) TestOnRecvPacket() { + var newClass string + testCases := []struct { + msg string + malleate func() + awayfromSource bool + expPass bool + }{{ + "success receive on awayfromSource chain", func() {}, true, true, + }, { + "failed receive on nearToSource chain", + func() { + // issue denom + issueDenomMsg := mttypes.NewMsgIssueDenom( + "dog-name", "", + suite.chainA.SenderAccount.GetAddress().String(), + ) + _, _ = suite.chainA.SendMsgs(issueDenomMsg) + + // mint nft + mintNftMsg := mttypes.NewMsgMintMT( + "", CLASS, 2, "", + suite.chainA.SenderAccount.GetAddress().String(), + suite.chainA.SenderAccount.GetAddress().String(), + ) + _, _ = suite.chainA.SendMsgs(mintNftMsg) + }, + false, false, + }, { + "failed receive on nearToSource chain without prefix ", + func() { newClass = CLASS }, + false, false, + }} + + for _, tc := range testCases { + tc := tc + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + path := NewTransferPath(suite.chainA, suite.chainB) + suite.coordinator.SetupClients(path) + + seq := uint64(1) + if tc.awayfromSource { + // // send nft from A to B + data := types.NewMultiTokenPacketData( + CLASS, MTID, + suite.chainA.SenderAccount.GetAddress().String(), + suite.chainB.SenderAccount.GetAddress().String(), + true, + "0xabcsda", 1, []byte(""), + ) + + packet := packettypes.NewPacket(data.GetBytes(), seq, suite.chainA.ChainID, suite.chainB.ChainID, "", string(routingtypes.NFT)) + err := suite.chainB.App.MtTransferKeeper.OnRecvPacket(suite.chainB.GetContext(), packet, data) + if tc.expPass { + suite.Require().NoError(err) + } else { + suite.Require().Error(err) + } + } else { + // send nft from B to A + tc.malleate() + + data := types.NewMultiTokenPacketData( + newClass, MTID, + suite.chainB.SenderAccount.GetAddress().String(), + suite.chainA.SenderAccount.GetAddress().String(), + false, + "0xabcsda", 1, []byte(""), + ) + packet := packettypes.NewPacket(data.GetBytes(), seq, suite.chainB.ChainID, suite.chainA.ChainID, "", string(routingtypes.NFT)) + err := suite.chainA.App.MtTransferKeeper.OnRecvPacket(suite.chainA.GetContext(), packet, data) + if tc.expPass { + suite.Require().NoError(err) + } else { + suite.Require().Error(err) + } + } + }) + } +} + +func (suite *KeeperTestSuite) TestOnAcknowledgementPacket() { + var ( + failedAck = packettypes.NewErrorAcknowledgement("failed packet transfer") + path *ibctesting.Path + newClass string + fullClassPath string + ) + + testCases := []struct { + msg string + ack packettypes.Acknowledgement + malleate func() + success bool // success of ack + awayFromOrigin bool + expPass bool + }{{ + "successful refund from source chain ", failedAck, + func() { + // issue denom + issueDenomMsg := mttypes.NewMsgIssueDenom( + "dog-name", "", + suite.chainA.SenderAccount.GetAddress().String(), + ) + _, _ = suite.chainA.SendMsgs(issueDenomMsg) + + // mint mt + mintNftMsg := mttypes.NewMsgMintMT( + "", CLASS, 2, "", + suite.chainA.SenderAccount.GetAddress().String(), + suite.chainA.SenderAccount.GetAddress().String(), + ) + _, _ = suite.chainA.SendMsgs(mintNftMsg) + + // sendTransfer + if err := suite.chainA.App.MtTransferKeeper.SendMtTransfer( + suite.chainA.GetContext(), CLASS, MTID, + suite.chainA.SenderAccount.GetAddress(), + suite.chainB.SenderAccount.GetAddress().String(), + suite.chainB.ChainID, "", "0xabcsda", 1, + ); err != nil { + fmt.Println("occur err :", err.Error()) + } + }, + true, true, true, + }, { + "successful refund from sink chain ", failedAck, + func() { + data := types.NewMultiTokenPacketData( + CLASS, MTID, + suite.chainA.SenderAccount.GetAddress().String(), + suite.chainB.SenderAccount.GetAddress().String(), + true, + "0xabcsda", 1, []byte(""), + ) + packet := packettypes.NewPacket( + data.GetBytes(), + uint64(1), + suite.chainA.ChainID, + suite.chainB.ChainID, + "", + string(routingtypes.MT)) + _ = suite.chainB.App.MtTransferKeeper.OnRecvPacket(suite.chainB.GetContext(), packet, data) + + }, true, false, true}, + } + + for _, tc := range testCases { + tc := tc + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + path = NewTransferPath(suite.chainA, suite.chainB) + suite.coordinator.SetupClients(path) + + tc.malleate() + if tc.awayFromOrigin { + data := types.NewMultiTokenPacketData( + CLASS, + MTID, + suite.chainA.SenderAccount.GetAddress().String(), + suite.chainB.SenderAccount.GetAddress().String(), + true, + "0xabcsda", + 1, + []byte(""), + ) + + err := suite.chainA.App.MtTransferKeeper.OnAcknowledgementPacket(suite.chainA.GetContext(), data, tc.ack) + if tc.expPass { + suite.Require().NoError(err) + if tc.success { + exist := suite.chainA.App.MtKeeper.HasMT(suite.chainA.GetContext(), CLASS, MTID) + suite.Require().True(exist, "not found mt") + + balance := suite.chainA.App.MtKeeper.GetBalance(suite.chainA.GetContext(), CLASS, MTID, suite.chainA.SenderAccount.GetAddress()) + suite.Require().EqualValues(balance, 2) + } + } + } else { + fullClassPath = "mt" + "/" + suite.chainA.ChainID + "/" + suite.chainB.ChainID + "/" + CLASS + newClass = "tibc-1AA90CD7273981C2E2CFFC5415D887C17FB03A7FCB49EFE4A7B6878E384F1670" + // send nft from chainB to chainA + _ = suite.chainB.App.MtTransferKeeper.SendMtTransfer( + suite.chainB.GetContext(), newClass, + MTID, + suite.chainB.SenderAccount.GetAddress(), + suite.chainA.SenderAccount.GetAddress().String(), + suite.chainA.ChainID, + "", + "0xabcsda", 1) + + data := types.NewMultiTokenPacketData( + fullClassPath, + MTID, + suite.chainB.SenderAccount.GetAddress().String(), + suite.chainA.SenderAccount.GetAddress().String(), + false, + "0xabcsda", + 1, + []byte(""), + ) + + err := suite.chainB.App.MtTransferKeeper.OnAcknowledgementPacket(suite.chainB.GetContext(), data, tc.ack) + + if tc.expPass { + suite.Require().NoError(err) + if tc.success { + // nft, err := suite.chainA.App.MtKeeper.GetMT(suite.chainA.GetContext(), newClass, "taidy") + // if err == nil { + // fmt.Println("found nft", nft.GetOwner()) + // } else { + // fmt.Println("not found nft") + // } + + // exist := suite.chainA.App.MtKeeper.HasMT(suite.chainA.GetContext(), newClass, MTID) + // suite.Require().True(exist, "not found mt") + + balanceInChainA := suite.chainA.App.MtKeeper.GetBalance(suite.chainA.GetContext(), CLASS, MTID, suite.chainA.SenderAccount.GetAddress()) + suite.Require().EqualValues(0, balanceInChainA) + + balanceInChainB := suite.chainB.App.MtKeeper.GetBalance(suite.chainB.GetContext(), newClass, MTID, suite.chainB.SenderAccount.GetAddress()) + suite.Require().EqualValues(1, balanceInChainB) + } + } + } + }) + } +} diff --git a/modules/tibc/apps/mt_transfer/moudle.go b/modules/tibc/apps/mt_transfer/moudle.go new file mode 100644 index 00000000..7ca8cfbd --- /dev/null +++ b/modules/tibc/apps/mt_transfer/moudle.go @@ -0,0 +1,234 @@ +package mt_transfer + +import ( + "context" + "encoding/hex" + "encoding/json" + "fmt" + "math/rand" + + "github.com/gorilla/mux" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + abci "github.com/tendermint/tendermint/abci/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + + "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/client/cli" + "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/keeper" + "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types" + packettypes "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/types" + porttypes "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" + "github.com/bianjieai/tibc-go/modules/tibc/core/simulation" +) + +var ( + _ module.AppModule = AppModule{} + _ porttypes.TIBCModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} +) + +// AppModuleBasic is the TIBC mt Transfer AppModuleBasic +type AppModuleBasic struct{} + +func (a AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return nil +} + +func (a AppModuleBasic) ValidateGenesis(jsonCodec codec.JSONCodec, config client.TxEncodingConfig, message json.RawMessage) error { + return nil +} + +func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) { +} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the tibc-mt-transfer module. +func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + _ = types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) +} + +func (a AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.NewTxCmd() +} + +// GetQueryCmd returns no root query command for the tibc-nft-transfer module. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd() +} + +func (a AppModuleBasic) Name() string { + return types.ModuleName +} + +// RegisterLegacyAminoCodec implements AppModuleBasic interface +func (a AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} + +// RegisterInterfaces registers module concrete types into protobuf Any. +func (a AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { + types.RegisterInterfaces(registry) +} + +// AppModule represents the AppModule for this module +type AppModule struct { + AppModuleBasic + keeper keeper.Keeper +} + +func (a AppModule) GenerateGenesisState(simState *module.SimulationState) { + simulation.RandomizedGenState(simState) +} + +func (a AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent { + return nil +} + +func (a AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange { + return nil +} + +func (a AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {} + +func (a AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { + panic("implement me") +} + +// NewAppModule creates a new tibc-mt-transfer module +func NewAppModule(k keeper.Keeper) AppModule { + return AppModule{ + keeper: k, + } +} + +func (a AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate { + return nil +} + +func (a AppModule) ExportGenesis(context sdk.Context, jsonCodec codec.JSONCodec) json.RawMessage { + return nil +} + +func (a AppModule) RegisterInvariants(registry sdk.InvariantRegistry) { + // TODO +} + +func (a AppModule) Route() sdk.Route { + return sdk.NewRoute(types.RouterKey, NewHandler(a.keeper)) +} + +func (a AppModule) QuerierRoute() string { + return types.QuerierRoute +} + +func (a AppModule) LegacyQuerierHandler(amino *codec.LegacyAmino) sdk.Querier { + return nil +} + +// RegisterServices registers module services. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterMsgServer(cfg.MsgServer(), am.keeper) + types.RegisterQueryServer(cfg.QueryServer(), am.keeper) +} + +// ConsensusVersion implements AppModule/ConsensusVersion. +func (am AppModule) ConsensusVersion() uint64 { return 1 } + +// BeginBlock implements the AppModule interface +func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { +} + +// EndBlock implements the AppModule interface +func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +func (a AppModule) OnRecvPacket(ctx sdk.Context, packet packettypes.Packet) (*sdk.Result, []byte, error) { + + var data types.MultiTokenPacketData + if err := data.Unmarshal(packet.GetData()); err != nil { + return nil, nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal TICS-30 nft-transfer packet data: %s", err.Error()) + } + + acknowledgement := packettypes.NewResultAcknowledgement([]byte{byte(1)}) + + err := a.keeper.OnRecvPacket(ctx, packet, data) + if err != nil { + acknowledgement = packettypes.NewErrorAcknowledgement(err.Error()) + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypePacket, + sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), + sdk.NewAttribute(types.AttributeKeyReceiver, data.Receiver), + sdk.NewAttribute(types.AttributeKeyClass, data.Class), + sdk.NewAttribute(types.AttributeKeyId, data.Id), + sdk.NewAttribute(types.AttributeKeyAmount, fmt.Sprintf("%d", data.Amount)), + sdk.NewAttribute(types.AttributeKeyData, hex.EncodeToString(data.Data)), + sdk.NewAttribute(types.AttributeKeyAckSuccess, fmt.Sprintf("%t", err == nil)), + ), + ) + + // NOTE: acknowledgement will be written synchronously during TIBC handler execution. + return &sdk.Result{ + Events: ctx.EventManager().Events().ToABCIEvents(), + }, acknowledgement.GetBytes(), nil +} + +func (a AppModule) OnAcknowledgementPacket(ctx sdk.Context, packet packettypes.Packet, acknowledgement []byte) (*sdk.Result, error) { + var ack packettypes.Acknowledgement + if err := ack.Unmarshal(acknowledgement); err != nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal TICS-30 transfer packet acknowledgement: %v", err) + } + var data types.MultiTokenPacketData + if err := data.Unmarshal(packet.GetData()); err != nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal TICS-30 transfer packet data: %s", err.Error()) + } + + if err := a.keeper.OnAcknowledgementPacket(ctx, data, ack); err != nil { + return nil, err + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypePacket, + sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), + sdk.NewAttribute(types.AttributeKeyReceiver, data.Receiver), + sdk.NewAttribute(types.AttributeKeyReceiver, data.Receiver), + sdk.NewAttribute(types.AttributeKeyClass, data.Class), + sdk.NewAttribute(types.AttributeKeyId, data.Id), + sdk.NewAttribute(types.AttributeKeyAmount, fmt.Sprintf("%d", data.Amount)), + sdk.NewAttribute(types.AttributeKeyData, hex.EncodeToString(data.Data)), + sdk.NewAttribute(types.AttributeKeyAck, fmt.Sprintf("%v", ack)), + ), + ) + + switch resp := ack.Response.(type) { + case *packettypes.Acknowledgement_Result: + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypePacket, + sdk.NewAttribute(types.AttributeKeyAckSuccess, string(resp.Result)), + ), + ) + case *packettypes.Acknowledgement_Error: + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypePacket, + sdk.NewAttribute(types.AttributeKeyAckError, resp.Error), + ), + ) + } + + return &sdk.Result{ + Events: ctx.EventManager().Events().ToABCIEvents(), + }, nil +} diff --git a/modules/tibc/apps/mt_transfer/transfer_test.go b/modules/tibc/apps/mt_transfer/transfer_test.go new file mode 100644 index 00000000..e2df9d4b --- /dev/null +++ b/modules/tibc/apps/mt_transfer/transfer_test.go @@ -0,0 +1,306 @@ +package mt_transfer_test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/suite" + + mttypes "github.com/irisnet/irismod/modules/mt/types" + + "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types" + packettypes "github.com/bianjieai/tibc-go/modules/tibc/core/04-packet/types" + routingtypes "github.com/bianjieai/tibc-go/modules/tibc/core/26-routing/types" + tibctesting "github.com/bianjieai/tibc-go/modules/tibc/testing" +) + +const ( + ClassID = "c02a799c8fee067a7f9b944554d8431ee539847234441833e45a3a2d3123fd99" //sha256("mt-denom-1") + MtID = "ff6e57b41cb52ae7d58d854b2123da2c5657fd15d525821a13fe7da1b9cebd80" //sha256("mt-1") + Amount = 2 +) + +type TransferTestSuite struct { + suite.Suite + + coordinator *tibctesting.Coordinator + + // testing chains used for convenience and readability + chainA *tibctesting.TestChain + chainB *tibctesting.TestChain + chainC *tibctesting.TestChain +} + +func (suite *TransferTestSuite) SetupTest() { + suite.coordinator = tibctesting.NewCoordinator(suite.T(), 3) + suite.chainA = suite.coordinator.GetChain(tibctesting.GetChainID(0)) + suite.chainB = suite.coordinator.GetChain(tibctesting.GetChainID(1)) + suite.chainC = suite.coordinator.GetChain(tibctesting.GetChainID(2)) +} + +/* +mt +A->B B->C +*/ +func (suite *TransferTestSuite) TestHandleMsgTransfer() { + // setup between chainA and chainB + + path := tibctesting.NewPath(suite.chainA, suite.chainB) + + suite.coordinator.SetupClients(path) + + // issue denom + issueDenomMsg := mttypes.NewMsgIssueDenom( + "mobile-name", "", + suite.chainA.SenderAccount.GetAddress().String(), + ) + _, _ = suite.chainA.SendMsgs(issueDenomMsg) + + // mint mt + mintMtMsg := mttypes.NewMsgMintMT( + "", ClassID, Amount, "", + suite.chainA.SenderAccount.GetAddress().String(), + suite.chainA.SenderAccount.GetAddress().String(), + ) + _, _ = suite.chainA.SendMsgs(mintMtMsg) + + dd, has := suite.chainA.App.MtKeeper.GetDenom(suite.chainA.GetContext(), ClassID) + suite.Require().Truef(has, "denom %s not found", ClassID) + + // send mt from A To B + msg := types.NewMsgMtTransfer( + dd.Id, MtID, + suite.chainA.SenderAccount.GetAddress().String(), + suite.chainB.SenderAccount.GetAddress().String(), + suite.chainB.ChainID, "", "0xabcsda", 1, + ) + + _, err := suite.chainA.SendMsgs(msg) + suite.Require().NoError(err) // message committed + //// relay send + multiTokenPacketData := types.NewMultiTokenPacketData( + dd.Id, MtID, + suite.chainA.SenderAccount.GetAddress().String(), + suite.chainB.SenderAccount.GetAddress().String(), + true, + "0xabcsda", + 1, + []byte(""), + ) + packet := packettypes.NewPacket( + multiTokenPacketData.GetBytes(), 1, + path.EndpointA.ChainName, path.EndpointB.ChainName, + "", string(routingtypes.MT), + ) + + ack := packettypes.NewResultAcknowledgement([]byte{byte(1)}) + err = path.RelayPacket(packet, ack.GetBytes()) + suite.Require().NoError(err) // relay committed + + // check that voucher exists on chain B + // denomID :tibc-hash(mt/chainA.chainID/chainB.chainId/mobile) + classInChainB := "tibc-1AA90CD7273981C2E2CFFC5415D887C17FB03A7FCB49EFE4A7B6878E384F1670" + mt, err := suite.chainB.App.MtKeeper.GetMT(suite.chainB.GetContext(), classInChainB, MtID) + suite.Require().NoError(err) // message committed + suite.Require().Equal(MtID, mt.GetID()) + + balanceInChainA := suite.chainA.App.MtKeeper.GetBalance(suite.chainA.GetContext(), ClassID, MtID, suite.chainA.SenderAccount.GetAddress()) + suite.Require().Equal(uint64(1), balanceInChainA) + + balanceInChainB := suite.chainB.App.MtKeeper.GetBalance(suite.chainB.GetContext(), classInChainB, MtID, suite.chainB.SenderAccount.GetAddress()) + suite.Require().Equal(uint64(1), balanceInChainB) + + // setup between chainB to chainC + pathBtoC := tibctesting.NewPath(suite.chainB, suite.chainC) + suite.coordinator.SetupClients(pathBtoC) + + // send ft from chainB to chainC + msgfromBToC := types.NewMsgMtTransfer( + classInChainB, MtID, + suite.chainB.SenderAccount.GetAddress().String(), + suite.chainC.SenderAccount.GetAddress().String(), + suite.chainC.ChainID, "", + "0xabcsda", + 1, + ) + + _, err1 := suite.chainB.SendMsgs(msgfromBToC) + suite.Require().NoError(err1) // message committed + + fullClassPathFromBToC := "mt" + "/" + suite.chainA.ChainID + "/" + suite.chainB.ChainID + "/" + ClassID + // relay send + mtPacketFromBToC := types.NewMultiTokenPacketData( + fullClassPathFromBToC, MtID, + suite.chainB.SenderAccount.GetAddress().String(), + suite.chainC.SenderAccount.GetAddress().String(), + true, + "0xabcsda", + 1, + []byte(""), + ) + packetFromBToC := packettypes.NewPacket( + mtPacketFromBToC.GetBytes(), 1, + pathBtoC.EndpointA.ChainName, + pathBtoC.EndpointB.ChainName, + "", string(routingtypes.MT), + ) + + ack1 := packettypes.NewResultAcknowledgement([]byte{byte(1)}) + err = pathBtoC.RelayPacket(packetFromBToC, ack1.GetBytes()) + suite.Require().NoError(err) // relay committed + + // check that voucher exists on chain C + // denomID : tibc-{hash(mt/chainA.chainID/chainB.chainID/chainC.chainID/ClassID)} + classInchainC := "tibc-14B78BCCA85B511A58AF995DFFE2621CC6BD00FAF43FC33B2270508709DE2C94" + mtInC, err := suite.chainC.App.MtKeeper.GetMT(suite.chainC.GetContext(), classInchainC, MtID) + suite.Require().NoError(err) + suite.Require().Equal(MtID, mtInC.GetID()) + + balanceInChainB = suite.chainB.App.MtKeeper.GetBalance(suite.chainB.GetContext(), classInChainB, MtID, suite.chainB.SenderAccount.GetAddress()) + suite.Require().Equal(uint64(0), balanceInChainB) + + balanceInChainC := suite.chainC.App.MtKeeper.GetBalance(suite.chainC.GetContext(), classInchainC, MtID, suite.chainC.SenderAccount.GetAddress()) + suite.Require().Equal(uint64(1), balanceInChainC) + + // send mt from chainC back to chainB + msgfromCToB := types.NewMsgMtTransfer( + classInchainC, MtID, + suite.chainC.SenderAccount.GetAddress().String(), + suite.chainB.SenderAccount.GetAddress().String(), + suite.chainB.ChainID, "", + "0xabcsda", + 1, + ) + + _, err2 := suite.chainC.SendMsgs(msgfromCToB) + suite.Require().NoError(err2) // message committed + + fullClassPathFromCToB := "mt" + "/" + suite.chainA.ChainID + "/" + suite.chainB.ChainID + "/" + suite.chainC.ChainID + "/" + ClassID + // relay send + mtPacket := types.NewMultiTokenPacketData( + fullClassPathFromCToB, MtID, + suite.chainC.SenderAccount.GetAddress().String(), + suite.chainB.SenderAccount.GetAddress().String(), + false, + "0xabcsda", + 1, + []byte(""), + ) + packetFromCToB := packettypes.NewPacket( + mtPacket.GetBytes(), 1, + pathBtoC.EndpointB.ChainName, + pathBtoC.EndpointA.ChainName, + "", string(routingtypes.MT), + ) + + ack2 := packettypes.NewResultAcknowledgement([]byte{byte(1)}) + err = pathBtoC.RelayPacket(packetFromCToB, ack2.GetBytes()) + suite.Require().NoError(err) // relay committed + balanceInChainB = suite.chainB.App.MtKeeper.GetBalance(suite.chainB.GetContext(), classInChainB, MtID, suite.chainB.SenderAccount.GetAddress()) + suite.Require().Equal(uint64(1), balanceInChainB) + + balanceInChainC = suite.chainC.App.MtKeeper.GetBalance(suite.chainC.GetContext(), classInchainC, MtID, suite.chainC.SenderAccount.GetAddress()) + suite.Require().Equal(uint64(0), balanceInChainC) + + // send nft from chainB back to chainA + msgFromBToA := types.NewMsgMtTransfer( + classInChainB, MtID, + suite.chainB.SenderAccount.GetAddress().String(), + suite.chainA.SenderAccount.GetAddress().String(), + suite.chainA.ChainID, "", "0xabcsda", 1, + ) + + _, err = suite.chainB.SendMsgs(msgFromBToA) + suite.Require().NoError(err) // message committed + + fullClassPathFromBToA := "mt" + "/" + suite.chainA.ChainID + "/" + suite.chainB.ChainID + "/" + ClassID + // relay send + multiTokenPacketData = types.NewMultiTokenPacketData( + fullClassPathFromBToA, MtID, + suite.chainB.SenderAccount.GetAddress().String(), + suite.chainA.SenderAccount.GetAddress().String(), + false, + "0xabcsda", + 1, + []byte(""), + ) + packet = packettypes.NewPacket( + multiTokenPacketData.GetBytes(), 1, + path.EndpointB.ChainName, path.EndpointA.ChainName, + "", string(routingtypes.MT), + ) + + ack = packettypes.NewResultAcknowledgement([]byte{byte(1)}) + err = path.RelayPacket(packet, ack.GetBytes()) + suite.Require().NoError(err) // relay committed + + // Query whether there are corresponding mt for C, B, and A respectively + /* just do A->B->C + denom found in A: ClassID + mt found in A: MtID + + denom found in B: tibc/mt/testchain0/ClassID + nft found in B: MtID + + denom found in C: tibc/mt/testchain0/testchain1/ClassID + nft found in C: MtID + */ + + /* do A->B->C then do C->B->A + denom found in A: ClassID + mt found in A: MtID + + denom found in B: tibc/mt/testchain0/ClassID + mt not found in B + + denom found in C: tibc/mt/testchain0/testchain1/ClassID + mt not found in C + + */ + // query A + denomInA, found := suite.chainA.App.MtKeeper.GetDenom(suite.chainA.GetContext(), ClassID) + if found { + fmt.Println("denom found in A:", denomInA.Id) + } else { + fmt.Println("denom not found in A:", denomInA.Id) + } + mtInA, errA := suite.chainA.App.MtKeeper.GetMT(suite.chainA.GetContext(), ClassID, MtID) + + if errA != nil { + fmt.Println("mt not found in A") + } else { + fmt.Println("mt found in A:", mtInA.GetID()) + } + + // query B + denomInB, found := suite.chainB.App.MtKeeper.GetDenom(suite.chainB.GetContext(), classInChainB) + if found { + fmt.Println("denom found in B:", denomInB.Id) + } else { + fmt.Println("denom not found in B:", denomInB.Id) + } + mtInB, errB := suite.chainB.App.MtKeeper.GetMT(suite.chainB.GetContext(), classInChainB, MtID) + if errB != nil { + fmt.Println("mt not found in B") + } else { + fmt.Println("mt found in B:", mtInB.GetID()) + } + + // query C + denomInC, found := suite.chainC.App.MtKeeper.GetDenom(suite.chainC.GetContext(), classInchainC) + if found { + fmt.Println("denom found in C:", denomInC.Id) + } else { + fmt.Println("denom not found in C:", denomInC.Id) + } + mtInC, errC := suite.chainC.App.MtKeeper.GetMT(suite.chainC.GetContext(), classInchainC, MtID) + if errC != nil { + fmt.Println("mt not found in C") + } else { + fmt.Println("mt found in C:", mtInC.GetID()) + } +} + +func TestTransferTestSuite(t *testing.T) { + suite.Run(t, new(TransferTestSuite)) +} diff --git a/modules/tibc/apps/mt_transfer/types/codec.go b/modules/tibc/apps/mt_transfer/types/codec.go new file mode 100644 index 00000000..110e19d9 --- /dev/null +++ b/modules/tibc/apps/mt_transfer/types/codec.go @@ -0,0 +1,32 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" +) + +var ( + amino = codec.NewLegacyAmino() + ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) + // AminoCdc is a amino codec created to support amino json compatible msgs. + AminoCdc = codec.NewAminoCodec(amino) +) + +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(&MsgMtTransfer{}, "cosmos-sdk/MsgMtTransfer", nil) +} + +// RegisterInterfaces register the tibc-transfer module interfaces to protobuf +// Any. +func RegisterInterfaces(registry codectypes.InterfaceRegistry) { + registry.RegisterImplementations((*sdk.Msg)(nil), &MsgMtTransfer{}) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} + +func init() { + RegisterLegacyAminoCodec(amino) + amino.Seal() +} diff --git a/modules/tibc/apps/mt_transfer/types/errors.go b/modules/tibc/apps/mt_transfer/types/errors.go new file mode 100644 index 00000000..f4e4dfea --- /dev/null +++ b/modules/tibc/apps/mt_transfer/types/errors.go @@ -0,0 +1,13 @@ +package types + +import ( + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +var ( + ErrInvalidDenom = sdkerrors.Register(ModuleName, 2, "invalid denom") + ErrUnknownNFT = sdkerrors.Register(ModuleName, 3, "unknown mt") + ErrScChainEqualToDestChain = sdkerrors.Register(ModuleName, 4, "source chain equals to destination chain") + ErrTraceNotFound = sdkerrors.Register(ModuleName, 5, "class trace not found") + ErrInvalidAmount = sdkerrors.Register(ModuleName, 6, "the amount must be greater than 0") +) diff --git a/modules/tibc/apps/mt_transfer/types/events.go b/modules/tibc/apps/mt_transfer/types/events.go new file mode 100644 index 00000000..64b6b020 --- /dev/null +++ b/modules/tibc/apps/mt_transfer/types/events.go @@ -0,0 +1,18 @@ +package types + +// TIBC transfer events +const ( + EventTypePacket = "multi_token_packet" + EventTypeMtTransfer = "tibc_mt_transfer" + EventTypeClassTrace = "class_trace" + + AttributeKeyClass = "class" + AttributeKeyId = "id" + AttributeKeyData = "data" + AttributeKeyAmount = "amount" + AttributeKeyReceiver = "receiver" + AttributeKeyAck = "ack" + AttributeKeyAckSuccess = "success" + AttributeKeyAckError = "error" + AttributeKeyTraceHash = "trace_hash" +) diff --git a/modules/tibc/apps/mt_transfer/types/expected_keepers.go b/modules/tibc/apps/mt_transfer/types/expected_keepers.go new file mode 100644 index 00000000..99bc5a35 --- /dev/null +++ b/modules/tibc/apps/mt_transfer/types/expected_keepers.go @@ -0,0 +1,61 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + mtexported "github.com/irisnet/irismod/modules/mt/exported" + "github.com/irisnet/irismod/modules/mt/types" + + "github.com/bianjieai/tibc-go/modules/tibc/core/exported" +) + +// MtKeeper defines the expected mt keeper +type MtKeeper interface { + IssueDenom(ctx sdk.Context, + id, name string, sender sdk.AccAddress, data []byte, + ) types.Denom + + IssueMT(ctx sdk.Context, + denomID string, mtID string, + amount uint64, + data []byte, + recipient sdk.AccAddress, + ) types.MT + + MintMT(ctx sdk.Context, + denomID, mtID string, + amount uint64, + recipient sdk.AccAddress, + ) + + TransferOwner(ctx sdk.Context, + denomID, mtID string, + amount uint64, + srcOwner, dstOwner sdk.AccAddress, + ) error + + BurnMT(ctx sdk.Context, + denomID, mtID string, + amount uint64, + owner sdk.AccAddress) error + + HasMT(ctx sdk.Context, denomID, mtID string) bool + GetMT(ctx sdk.Context, denomID, mtID string) (mt mtexported.MT, err error) + GetDenom(ctx sdk.Context, id string) (denom types.Denom, found bool) +} + +// AccountKeeper defines the expected account keeper +type AccountKeeper interface { + GetModuleAddress(name string) sdk.AccAddress +} + +// PacketKeeper defines the expected packet keeper +type PacketKeeper interface { + GetNextSequenceSend(ctx sdk.Context, sourceChain, destChain string) uint64 + SendPacket(ctx sdk.Context, packet exported.PacketI) error +} + +// ClientKeeper defines the expected client keeper +type ClientKeeper interface { + GetChainName(ctx sdk.Context) string +} diff --git a/modules/tibc/apps/mt_transfer/types/keys.go b/modules/tibc/apps/mt_transfer/types/keys.go new file mode 100644 index 00000000..7dabf669 --- /dev/null +++ b/modules/tibc/apps/mt_transfer/types/keys.go @@ -0,0 +1,26 @@ +package types + +const ( + // ModuleName defines the TIBC mt_transfer name + ModuleName = "MT" + + // RouterKey is the message route for the mt-transfer module + RouterKey = ModuleName + + // PortID is the default port id that mt-transfer module binds to + PortID = ModuleName + + // StoreKey is the store key string for TIBC mt-transfer + StoreKey = ModuleName + + // QuerierRoute is the querier route for TIBC mt-transfer + QuerierRoute = ModuleName + + // ClassPrefix is the prefix used for mt class. + ClassPrefix = "tibc" +) + +var ( + // ClassTraceKey defines the key to store the class trace info in store + ClassTraceKey = []byte{0x01} +) diff --git a/modules/tibc/apps/mt_transfer/types/msgs.go b/modules/tibc/apps/mt_transfer/types/msgs.go new file mode 100644 index 00000000..bf5db1c5 --- /dev/null +++ b/modules/tibc/apps/mt_transfer/types/msgs.go @@ -0,0 +1,39 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + TypeMsgMtTransfer = "tibc_mt_transfer" +) + +var _ sdk.Msg = &MsgMtTransfer{} + +// NewMsgMtTransfer creates a new NewMsgMtTransfer instance +func NewMsgMtTransfer(class, id, sender, receiver, destChain, realayChain, destContract string, amount uint64) *MsgMtTransfer { + return &MsgMtTransfer{ + Class: class, + Id: id, + Sender: sender, + Receiver: receiver, + DestChain: destChain, + RealayChain: realayChain, + DestContract: destContract, + Amount: amount, + } +} + +// GetSigners implements sdk.Msg +func (msg MsgMtTransfer) GetSigners() []sdk.AccAddress { + signer, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + panic(err) + } + return []sdk.AccAddress{signer} +} + +// ValidateBasic Implements Msg. +func (msg MsgMtTransfer) ValidateBasic() error { + return nil +} diff --git a/modules/tibc/apps/mt_transfer/types/mt_transfer.pb.go b/modules/tibc/apps/mt_transfer/types/mt_transfer.pb.go new file mode 100644 index 00000000..58911c4a --- /dev/null +++ b/modules/tibc/apps/mt_transfer/types/mt_transfer.pb.go @@ -0,0 +1,896 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: tibc/apps/mt_transfer/v1/mt_transfer.proto + +package types + +import ( + fmt "fmt" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type MultiTokenPacketData struct { + // the class to which the Mt to be transferred belongs + Class string `protobuf:"bytes,1,opt,name=class,proto3" json:"class,omitempty"` + // the mt id + Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` + // the address defined by MT outside the chain + Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` + // the mt sender + Sender string `protobuf:"bytes,4,opt,name=sender,proto3" json:"sender,omitempty"` + // the mt receiver + Receiver string `protobuf:"bytes,5,opt,name=receiver,proto3" json:"receiver,omitempty"` + // identify whether it is far away from the source chain + AwayFromOrigin bool `protobuf:"varint,6,opt,name=away_from_origin,json=awayFromOrigin,proto3" json:"away_from_origin,omitempty"` + // the destination contract address to receive the nft + DestContract string `protobuf:"bytes,7,opt,name=dest_contract,json=destContract,proto3" json:"dest_contract,omitempty"` + // the amount defined by MT outside the chain + Amount uint64 `protobuf:"varint,8,opt,name=amount,proto3" json:"amount,omitempty"` +} + +func (m *MultiTokenPacketData) Reset() { *m = MultiTokenPacketData{} } +func (m *MultiTokenPacketData) String() string { return proto.CompactTextString(m) } +func (*MultiTokenPacketData) ProtoMessage() {} +func (*MultiTokenPacketData) Descriptor() ([]byte, []int) { + return fileDescriptor_c6e1dfa992d03735, []int{0} +} +func (m *MultiTokenPacketData) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MultiTokenPacketData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MultiTokenPacketData.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MultiTokenPacketData) XXX_Merge(src proto.Message) { + xxx_messageInfo_MultiTokenPacketData.Merge(m, src) +} +func (m *MultiTokenPacketData) XXX_Size() int { + return m.Size() +} +func (m *MultiTokenPacketData) XXX_DiscardUnknown() { + xxx_messageInfo_MultiTokenPacketData.DiscardUnknown(m) +} + +var xxx_messageInfo_MultiTokenPacketData proto.InternalMessageInfo + +func (m *MultiTokenPacketData) GetClass() string { + if m != nil { + return m.Class + } + return "" +} + +func (m *MultiTokenPacketData) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +func (m *MultiTokenPacketData) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *MultiTokenPacketData) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *MultiTokenPacketData) GetReceiver() string { + if m != nil { + return m.Receiver + } + return "" +} + +func (m *MultiTokenPacketData) GetAwayFromOrigin() bool { + if m != nil { + return m.AwayFromOrigin + } + return false +} + +func (m *MultiTokenPacketData) GetDestContract() string { + if m != nil { + return m.DestContract + } + return "" +} + +func (m *MultiTokenPacketData) GetAmount() uint64 { + if m != nil { + return m.Amount + } + return 0 +} + +// ClassTrace contains the base class for Multi Token and the +// source tracing information path. +type ClassTrace struct { + // path defines the chain of sourceChain/destChain + // identifiers used for tracing the source of the Non fungible token. + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` + // base class of the relayed non fungible token. + BaseClass string `protobuf:"bytes,2,opt,name=base_class,json=baseClass,proto3" json:"base_class,omitempty"` +} + +func (m *ClassTrace) Reset() { *m = ClassTrace{} } +func (m *ClassTrace) String() string { return proto.CompactTextString(m) } +func (*ClassTrace) ProtoMessage() {} +func (*ClassTrace) Descriptor() ([]byte, []int) { + return fileDescriptor_c6e1dfa992d03735, []int{1} +} +func (m *ClassTrace) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ClassTrace) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ClassTrace.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ClassTrace) XXX_Merge(src proto.Message) { + xxx_messageInfo_ClassTrace.Merge(m, src) +} +func (m *ClassTrace) XXX_Size() int { + return m.Size() +} +func (m *ClassTrace) XXX_DiscardUnknown() { + xxx_messageInfo_ClassTrace.DiscardUnknown(m) +} + +var xxx_messageInfo_ClassTrace proto.InternalMessageInfo + +func (m *ClassTrace) GetPath() string { + if m != nil { + return m.Path + } + return "" +} + +func (m *ClassTrace) GetBaseClass() string { + if m != nil { + return m.BaseClass + } + return "" +} + +func init() { + proto.RegisterType((*MultiTokenPacketData)(nil), "tibc.apps.mt_transfer.v1.MultiTokenPacketData") + proto.RegisterType((*ClassTrace)(nil), "tibc.apps.mt_transfer.v1.ClassTrace") +} + +func init() { + proto.RegisterFile("tibc/apps/mt_transfer/v1/mt_transfer.proto", fileDescriptor_c6e1dfa992d03735) +} + +var fileDescriptor_c6e1dfa992d03735 = []byte{ + // 354 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0xc1, 0x6a, 0x2a, 0x31, + 0x14, 0x86, 0x8d, 0x57, 0xbd, 0x1a, 0xbc, 0x72, 0x09, 0x72, 0x09, 0x17, 0x3a, 0x0c, 0x76, 0x33, + 0x14, 0x3a, 0x83, 0xf4, 0x01, 0x5a, 0x6a, 0xe9, 0xae, 0xb4, 0x0c, 0xae, 0xdc, 0x0c, 0x67, 0x32, + 0x51, 0x53, 0x9d, 0xc9, 0x90, 0x64, 0x2c, 0xbe, 0x45, 0x1f, 0xab, 0x4b, 0x97, 0x5d, 0x16, 0x5d, + 0xf6, 0x25, 0x4a, 0xe2, 0x50, 0x5c, 0x74, 0x77, 0xfe, 0xef, 0xfc, 0x09, 0xe7, 0x3f, 0x07, 0x5f, + 0x18, 0x91, 0xb2, 0x08, 0xca, 0x52, 0x47, 0xb9, 0x49, 0x8c, 0x82, 0x42, 0xcf, 0xb9, 0x8a, 0x36, + 0xe3, 0x53, 0x19, 0x96, 0x4a, 0x1a, 0x49, 0xa8, 0xf5, 0x86, 0xd6, 0x1b, 0x9e, 0x36, 0x37, 0xe3, + 0xd1, 0x27, 0xc2, 0xc3, 0x87, 0x6a, 0x6d, 0xc4, 0x54, 0xae, 0x78, 0xf1, 0x04, 0x6c, 0xc5, 0xcd, + 0x1d, 0x18, 0x20, 0x43, 0xdc, 0x66, 0x6b, 0xd0, 0x9a, 0x22, 0x1f, 0x05, 0xbd, 0xf8, 0x28, 0xc8, + 0x00, 0x37, 0x45, 0x46, 0x9b, 0x0e, 0x35, 0x45, 0x46, 0x08, 0x6e, 0x65, 0x60, 0x80, 0xfe, 0xf2, + 0x51, 0xd0, 0x8f, 0x5d, 0x4d, 0xfe, 0xe1, 0x8e, 0xe6, 0x45, 0xc6, 0x15, 0x6d, 0x39, 0x5f, 0xad, + 0xc8, 0x7f, 0xdc, 0x55, 0x9c, 0x71, 0xb1, 0xe1, 0x8a, 0xb6, 0x5d, 0xe7, 0x5b, 0x93, 0x00, 0xff, + 0x85, 0x17, 0xd8, 0x26, 0x73, 0x25, 0xf3, 0x44, 0x2a, 0xb1, 0x10, 0x05, 0xed, 0xf8, 0x28, 0xe8, + 0xc6, 0x03, 0xcb, 0xef, 0x95, 0xcc, 0x1f, 0x1d, 0x25, 0xe7, 0xf8, 0x4f, 0xc6, 0xb5, 0x49, 0x98, + 0x2c, 0x8c, 0x02, 0x66, 0xe8, 0x6f, 0xf7, 0x55, 0xdf, 0xc2, 0x49, 0xcd, 0xec, 0x08, 0x90, 0xcb, + 0xaa, 0x30, 0xb4, 0xeb, 0xa3, 0xa0, 0x15, 0xd7, 0x6a, 0x74, 0x8d, 0xf1, 0xc4, 0xe6, 0x98, 0x2a, + 0x60, 0xdc, 0x0e, 0x5f, 0x82, 0x59, 0xd6, 0x09, 0x5d, 0x4d, 0xce, 0x30, 0x4e, 0x41, 0xf3, 0xe4, + 0x98, 0xfd, 0x18, 0xb4, 0x67, 0x89, 0x7b, 0x77, 0x3b, 0x7b, 0xdb, 0x7b, 0x68, 0xb7, 0xf7, 0xd0, + 0xc7, 0xde, 0x43, 0xaf, 0x07, 0xaf, 0xb1, 0x3b, 0x78, 0x8d, 0xf7, 0x83, 0xd7, 0x98, 0xdd, 0x2c, + 0x84, 0x59, 0x56, 0x69, 0xc8, 0x64, 0x1e, 0xa5, 0x02, 0x8a, 0x67, 0xc1, 0x41, 0x44, 0x76, 0xef, + 0x97, 0x0b, 0x19, 0xe5, 0x32, 0xab, 0xd6, 0x5c, 0x47, 0x3f, 0xdf, 0xcc, 0x6c, 0x4b, 0xae, 0xd3, + 0x8e, 0xbb, 0xd5, 0xd5, 0x57, 0x00, 0x00, 0x00, 0xff, 0xff, 0x09, 0x39, 0x53, 0x35, 0xd9, 0x01, + 0x00, 0x00, +} + +func (m *MultiTokenPacketData) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MultiTokenPacketData) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MultiTokenPacketData) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Amount != 0 { + i = encodeVarintMtTransfer(dAtA, i, uint64(m.Amount)) + i-- + dAtA[i] = 0x40 + } + if len(m.DestContract) > 0 { + i -= len(m.DestContract) + copy(dAtA[i:], m.DestContract) + i = encodeVarintMtTransfer(dAtA, i, uint64(len(m.DestContract))) + i-- + dAtA[i] = 0x3a + } + if m.AwayFromOrigin { + i-- + if m.AwayFromOrigin { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x30 + } + if len(m.Receiver) > 0 { + i -= len(m.Receiver) + copy(dAtA[i:], m.Receiver) + i = encodeVarintMtTransfer(dAtA, i, uint64(len(m.Receiver))) + i-- + dAtA[i] = 0x2a + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintMtTransfer(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0x22 + } + if len(m.Data) > 0 { + i -= len(m.Data) + copy(dAtA[i:], m.Data) + i = encodeVarintMtTransfer(dAtA, i, uint64(len(m.Data))) + i-- + dAtA[i] = 0x1a + } + if len(m.Id) > 0 { + i -= len(m.Id) + copy(dAtA[i:], m.Id) + i = encodeVarintMtTransfer(dAtA, i, uint64(len(m.Id))) + i-- + dAtA[i] = 0x12 + } + if len(m.Class) > 0 { + i -= len(m.Class) + copy(dAtA[i:], m.Class) + i = encodeVarintMtTransfer(dAtA, i, uint64(len(m.Class))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ClassTrace) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ClassTrace) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ClassTrace) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.BaseClass) > 0 { + i -= len(m.BaseClass) + copy(dAtA[i:], m.BaseClass) + i = encodeVarintMtTransfer(dAtA, i, uint64(len(m.BaseClass))) + i-- + dAtA[i] = 0x12 + } + if len(m.Path) > 0 { + i -= len(m.Path) + copy(dAtA[i:], m.Path) + i = encodeVarintMtTransfer(dAtA, i, uint64(len(m.Path))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintMtTransfer(dAtA []byte, offset int, v uint64) int { + offset -= sovMtTransfer(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MultiTokenPacketData) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Class) + if l > 0 { + n += 1 + l + sovMtTransfer(uint64(l)) + } + l = len(m.Id) + if l > 0 { + n += 1 + l + sovMtTransfer(uint64(l)) + } + l = len(m.Data) + if l > 0 { + n += 1 + l + sovMtTransfer(uint64(l)) + } + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovMtTransfer(uint64(l)) + } + l = len(m.Receiver) + if l > 0 { + n += 1 + l + sovMtTransfer(uint64(l)) + } + if m.AwayFromOrigin { + n += 2 + } + l = len(m.DestContract) + if l > 0 { + n += 1 + l + sovMtTransfer(uint64(l)) + } + if m.Amount != 0 { + n += 1 + sovMtTransfer(uint64(m.Amount)) + } + return n +} + +func (m *ClassTrace) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Path) + if l > 0 { + n += 1 + l + sovMtTransfer(uint64(l)) + } + l = len(m.BaseClass) + if l > 0 { + n += 1 + l + sovMtTransfer(uint64(l)) + } + return n +} + +func sovMtTransfer(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozMtTransfer(x uint64) (n int) { + return sovMtTransfer(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MultiTokenPacketData) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMtTransfer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MultiTokenPacketData: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MultiTokenPacketData: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Class", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMtTransfer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMtTransfer + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMtTransfer + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Class = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMtTransfer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMtTransfer + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMtTransfer + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Id = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMtTransfer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthMtTransfer + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthMtTransfer + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMtTransfer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMtTransfer + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMtTransfer + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Receiver", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMtTransfer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMtTransfer + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMtTransfer + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Receiver = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AwayFromOrigin", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMtTransfer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.AwayFromOrigin = bool(v != 0) + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DestContract", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMtTransfer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMtTransfer + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMtTransfer + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DestContract = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + m.Amount = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMtTransfer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Amount |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipMtTransfer(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMtTransfer + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ClassTrace) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMtTransfer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ClassTrace: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ClassTrace: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMtTransfer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMtTransfer + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMtTransfer + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Path = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BaseClass", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMtTransfer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthMtTransfer + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthMtTransfer + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BaseClass = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMtTransfer(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthMtTransfer + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipMtTransfer(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowMtTransfer + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowMtTransfer + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowMtTransfer + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthMtTransfer + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupMtTransfer + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthMtTransfer + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthMtTransfer = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowMtTransfer = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupMtTransfer = fmt.Errorf("proto: unexpected end of group") +) diff --git a/modules/tibc/apps/mt_transfer/types/packet.go b/modules/tibc/apps/mt_transfer/types/packet.go new file mode 100644 index 00000000..8bd42caf --- /dev/null +++ b/modules/tibc/apps/mt_transfer/types/packet.go @@ -0,0 +1,46 @@ +package types + +import ( + "strings" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// NewMultiTokenPacketData contructs a new MultiTokenPacketData instance +func NewMultiTokenPacketData( + class, id, sender, receiver string, + awayFromOrigin bool, destContract string, + amount uint64, data []byte, +) MultiTokenPacketData { + return MultiTokenPacketData{ + Class: class, + Id: id, + Data: data, + Sender: sender, + Receiver: receiver, + AwayFromOrigin: awayFromOrigin, + DestContract: destContract, + Amount: amount, + } +} + +// ValidateBasic is used for validating the mt transfer. +// NOTE: The addresses formats are not validated as the sender and recipient can have different +// formats defined by their corresponding chains that are not known to TIBC. +func (mtpd MultiTokenPacketData) ValidateBasic() error { + if strings.TrimSpace(mtpd.Sender) == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be blank") + } + if strings.TrimSpace(mtpd.Receiver) == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "receiver address cannot be blank") + } + if mtpd.Amount <= 0 { + return ErrInvalidAmount + } + return nil +} + +// GetBytes is a helper for serialising +func (mtpd MultiTokenPacketData) GetBytes() []byte { + return ModuleCdc.MustMarshal(&mtpd) +} diff --git a/modules/tibc/apps/mt_transfer/types/query.pb.go b/modules/tibc/apps/mt_transfer/types/query.pb.go new file mode 100644 index 00000000..12fe5f30 --- /dev/null +++ b/modules/tibc/apps/mt_transfer/types/query.pb.go @@ -0,0 +1,1076 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: tibc/apps/mt_transfer/v1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + query "github.com/cosmos/cosmos-sdk/types/query" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// QueryClassTraceRequest is the request type for the Query/ClassTrace RPC +// method +type QueryClassTraceRequest struct { + // hash (in hex format) of the class trace information. + Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` +} + +func (m *QueryClassTraceRequest) Reset() { *m = QueryClassTraceRequest{} } +func (m *QueryClassTraceRequest) String() string { return proto.CompactTextString(m) } +func (*QueryClassTraceRequest) ProtoMessage() {} +func (*QueryClassTraceRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_00405040fdfa1b2c, []int{0} +} +func (m *QueryClassTraceRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryClassTraceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryClassTraceRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryClassTraceRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryClassTraceRequest.Merge(m, src) +} +func (m *QueryClassTraceRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryClassTraceRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryClassTraceRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryClassTraceRequest proto.InternalMessageInfo + +func (m *QueryClassTraceRequest) GetHash() string { + if m != nil { + return m.Hash + } + return "" +} + +// QueryClassTraceResponse is the response type for the Query/ClassTrace RPC +// method. +type QueryClassTraceResponse struct { + // class_trace returns the requested class trace information. + ClassTrace *ClassTrace `protobuf:"bytes,1,opt,name=class_trace,json=classTrace,proto3" json:"class_trace,omitempty"` +} + +func (m *QueryClassTraceResponse) Reset() { *m = QueryClassTraceResponse{} } +func (m *QueryClassTraceResponse) String() string { return proto.CompactTextString(m) } +func (*QueryClassTraceResponse) ProtoMessage() {} +func (*QueryClassTraceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_00405040fdfa1b2c, []int{1} +} +func (m *QueryClassTraceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryClassTraceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryClassTraceResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryClassTraceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryClassTraceResponse.Merge(m, src) +} +func (m *QueryClassTraceResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryClassTraceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryClassTraceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryClassTraceResponse proto.InternalMessageInfo + +func (m *QueryClassTraceResponse) GetClassTrace() *ClassTrace { + if m != nil { + return m.ClassTrace + } + return nil +} + +// QueryConnectionsRequest is the request type for the Query/ClassTraces RPC +// method +type QueryClassTracesRequest struct { + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryClassTracesRequest) Reset() { *m = QueryClassTracesRequest{} } +func (m *QueryClassTracesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryClassTracesRequest) ProtoMessage() {} +func (*QueryClassTracesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_00405040fdfa1b2c, []int{2} +} +func (m *QueryClassTracesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryClassTracesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryClassTracesRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryClassTracesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryClassTracesRequest.Merge(m, src) +} +func (m *QueryClassTracesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryClassTracesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryClassTracesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryClassTracesRequest proto.InternalMessageInfo + +func (m *QueryClassTracesRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryConnectionsResponse is the response type for the Query/ClassTraces RPC +// method. +type QueryClassTracesResponse struct { + // class_traces returns all class trace information. + ClassTraces Traces `protobuf:"bytes,1,rep,name=class_traces,json=classTraces,proto3,castrepeated=Traces" json:"class_traces"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryClassTracesResponse) Reset() { *m = QueryClassTracesResponse{} } +func (m *QueryClassTracesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryClassTracesResponse) ProtoMessage() {} +func (*QueryClassTracesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_00405040fdfa1b2c, []int{3} +} +func (m *QueryClassTracesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryClassTracesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryClassTracesResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryClassTracesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryClassTracesResponse.Merge(m, src) +} +func (m *QueryClassTracesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryClassTracesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryClassTracesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryClassTracesResponse proto.InternalMessageInfo + +func (m *QueryClassTracesResponse) GetClassTraces() Traces { + if m != nil { + return m.ClassTraces + } + return nil +} + +func (m *QueryClassTracesResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +func init() { + proto.RegisterType((*QueryClassTraceRequest)(nil), "tibc.apps.mt_transfer.v1.QueryClassTraceRequest") + proto.RegisterType((*QueryClassTraceResponse)(nil), "tibc.apps.mt_transfer.v1.QueryClassTraceResponse") + proto.RegisterType((*QueryClassTracesRequest)(nil), "tibc.apps.mt_transfer.v1.QueryClassTracesRequest") + proto.RegisterType((*QueryClassTracesResponse)(nil), "tibc.apps.mt_transfer.v1.QueryClassTracesResponse") +} + +func init() { + proto.RegisterFile("tibc/apps/mt_transfer/v1/query.proto", fileDescriptor_00405040fdfa1b2c) +} + +var fileDescriptor_00405040fdfa1b2c = []byte{ + // 466 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x93, 0xc1, 0x8a, 0x13, 0x31, + 0x18, 0xc7, 0x9b, 0xaa, 0x0b, 0xa6, 0xe2, 0x21, 0x88, 0x96, 0x22, 0xb3, 0xcb, 0xb0, 0xac, 0x8b, + 0xb8, 0x89, 0x53, 0xf1, 0x2e, 0x2b, 0xea, 0x55, 0x8b, 0x20, 0xec, 0x45, 0x33, 0x63, 0x4c, 0x23, + 0xed, 0x64, 0x76, 0xbe, 0x4c, 0x61, 0x11, 0x2f, 0x3e, 0x81, 0xe0, 0x2b, 0x78, 0x10, 0x9f, 0xc1, + 0x07, 0xd8, 0xe3, 0x82, 0x17, 0xbd, 0xa8, 0xb4, 0x3e, 0x88, 0x24, 0x99, 0xb1, 0x91, 0x3a, 0x6c, + 0xf7, 0xf6, 0x31, 0xf3, 0xff, 0xbe, 0xff, 0xef, 0xfb, 0x27, 0xc1, 0xdb, 0x46, 0xa5, 0x19, 0xe3, + 0x45, 0x01, 0x6c, 0x6a, 0x9e, 0x9b, 0x92, 0xe7, 0xf0, 0x4a, 0x94, 0x6c, 0x96, 0xb0, 0xc3, 0x4a, + 0x94, 0x47, 0xb4, 0x28, 0xb5, 0xd1, 0xa4, 0x6f, 0x55, 0xd4, 0xaa, 0x68, 0xa0, 0xa2, 0xb3, 0x64, + 0x70, 0x45, 0x6a, 0xa9, 0x9d, 0x88, 0xd9, 0xca, 0xeb, 0x07, 0x37, 0x33, 0x0d, 0x53, 0x0d, 0x2c, + 0xe5, 0x20, 0xfc, 0x20, 0x36, 0x4b, 0x52, 0x61, 0x78, 0xc2, 0x0a, 0x2e, 0x55, 0xce, 0x8d, 0xd2, + 0x79, 0xa3, 0x6d, 0x25, 0x08, 0xad, 0xbc, 0xf6, 0xba, 0xd4, 0x5a, 0x4e, 0x04, 0xe3, 0x85, 0x62, + 0x3c, 0xcf, 0xb5, 0x71, 0x83, 0xc0, 0xff, 0x8d, 0x6f, 0xe1, 0xab, 0x4f, 0xac, 0xd7, 0xfd, 0x09, + 0x07, 0x78, 0x5a, 0xf2, 0x4c, 0x8c, 0xc4, 0x61, 0x25, 0xc0, 0x10, 0x82, 0xcf, 0x8f, 0x39, 0x8c, + 0xfb, 0x68, 0x0b, 0xed, 0x5e, 0x1c, 0xb9, 0x3a, 0x7e, 0x81, 0xaf, 0xad, 0xa8, 0xa1, 0xd0, 0x39, + 0x08, 0xf2, 0x00, 0xf7, 0x32, 0xfb, 0xd5, 0xda, 0x67, 0xc2, 0x75, 0xf5, 0x86, 0xdb, 0xb4, 0x2d, + 0x04, 0x1a, 0x8c, 0xc0, 0xd9, 0xdf, 0x3a, 0xe6, 0x2b, 0x0e, 0xd0, 0x00, 0x3d, 0xc4, 0x78, 0x19, + 0x44, 0x6d, 0xb0, 0x43, 0x7d, 0x6a, 0xd4, 0xa6, 0x46, 0x7d, 0xfc, 0x75, 0x6a, 0xf4, 0x31, 0x97, + 0xcd, 0x32, 0xa3, 0xa0, 0x33, 0xfe, 0x82, 0x70, 0x7f, 0xd5, 0xa3, 0x5e, 0xe3, 0x19, 0xbe, 0x14, + 0xac, 0x01, 0x7d, 0xb4, 0x75, 0x6e, 0xdd, 0x3d, 0xf6, 0x2f, 0x1f, 0xff, 0xd8, 0xec, 0x7c, 0xfe, + 0xb9, 0xb9, 0x51, 0xcf, 0xec, 0x2d, 0xf7, 0x02, 0xf2, 0xe8, 0x1f, 0xfa, 0xae, 0xa3, 0xbf, 0x71, + 0x2a, 0xbd, 0xa7, 0x0a, 0xf1, 0x87, 0xdf, 0xbb, 0xf8, 0x82, 0xc3, 0x27, 0x9f, 0x10, 0xc6, 0x4b, + 0x7b, 0x72, 0xbb, 0x1d, 0xf2, 0xff, 0x47, 0x3c, 0x48, 0xce, 0xd0, 0xe1, 0x49, 0xe2, 0xbb, 0xef, + 0xbe, 0xfe, 0xfe, 0xd0, 0x65, 0x64, 0x8f, 0xb5, 0x5e, 0xc1, 0x30, 0x3f, 0xf6, 0xc6, 0xde, 0x9b, + 0xb7, 0xe4, 0x23, 0xc2, 0xbd, 0x20, 0x6e, 0xb2, 0xbe, 0x73, 0x73, 0xfc, 0x83, 0xe1, 0x59, 0x5a, + 0x6a, 0x5a, 0xea, 0x68, 0x77, 0xc9, 0xce, 0x7a, 0xb4, 0xfb, 0x07, 0xc7, 0xf3, 0x08, 0x9d, 0xcc, + 0x23, 0xf4, 0x6b, 0x1e, 0xa1, 0xf7, 0x8b, 0xa8, 0x73, 0xb2, 0x88, 0x3a, 0xdf, 0x16, 0x51, 0xe7, + 0xe0, 0x9e, 0x54, 0x66, 0x5c, 0xa5, 0x34, 0xd3, 0x53, 0x96, 0x2a, 0x9e, 0xbf, 0x56, 0x82, 0x2b, + 0x37, 0x75, 0x4f, 0x6a, 0x36, 0xd5, 0x2f, 0xab, 0x89, 0x80, 0x16, 0x17, 0x73, 0x54, 0x08, 0x48, + 0x37, 0xdc, 0x83, 0xbb, 0xf3, 0x27, 0x00, 0x00, 0xff, 0xff, 0xe3, 0x4e, 0xcb, 0xfd, 0x3e, 0x04, + 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // ClassTrace queries a class trace information. + ClassTrace(ctx context.Context, in *QueryClassTraceRequest, opts ...grpc.CallOption) (*QueryClassTraceResponse, error) + // ClassTraces queries all class traces. + ClassTraces(ctx context.Context, in *QueryClassTracesRequest, opts ...grpc.CallOption) (*QueryClassTracesResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) ClassTrace(ctx context.Context, in *QueryClassTraceRequest, opts ...grpc.CallOption) (*QueryClassTraceResponse, error) { + out := new(QueryClassTraceResponse) + err := c.cc.Invoke(ctx, "/tibc.apps.mt_transfer.v1.Query/ClassTrace", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) ClassTraces(ctx context.Context, in *QueryClassTracesRequest, opts ...grpc.CallOption) (*QueryClassTracesResponse, error) { + out := new(QueryClassTracesResponse) + err := c.cc.Invoke(ctx, "/tibc.apps.mt_transfer.v1.Query/ClassTraces", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // ClassTrace queries a class trace information. + ClassTrace(context.Context, *QueryClassTraceRequest) (*QueryClassTraceResponse, error) + // ClassTraces queries all class traces. + ClassTraces(context.Context, *QueryClassTracesRequest) (*QueryClassTracesResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) ClassTrace(ctx context.Context, req *QueryClassTraceRequest) (*QueryClassTraceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ClassTrace not implemented") +} +func (*UnimplementedQueryServer) ClassTraces(ctx context.Context, req *QueryClassTracesRequest) (*QueryClassTracesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ClassTraces not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_ClassTrace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryClassTraceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ClassTrace(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/tibc.apps.mt_transfer.v1.Query/ClassTrace", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ClassTrace(ctx, req.(*QueryClassTraceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_ClassTraces_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryClassTracesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ClassTraces(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/tibc.apps.mt_transfer.v1.Query/ClassTraces", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ClassTraces(ctx, req.(*QueryClassTracesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "tibc.apps.mt_transfer.v1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "ClassTrace", + Handler: _Query_ClassTrace_Handler, + }, + { + MethodName: "ClassTraces", + Handler: _Query_ClassTraces_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "tibc/apps/mt_transfer/v1/query.proto", +} + +func (m *QueryClassTraceRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryClassTraceRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryClassTraceRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryClassTraceResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryClassTraceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryClassTraceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ClassTrace != nil { + { + size, err := m.ClassTrace.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryClassTracesRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryClassTracesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryClassTracesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryClassTracesResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryClassTracesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryClassTracesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.ClassTraces) > 0 { + for iNdEx := len(m.ClassTraces) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ClassTraces[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryClassTraceRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryClassTraceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ClassTrace != nil { + l = m.ClassTrace.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryClassTracesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryClassTracesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.ClassTraces) > 0 { + for _, e := range m.ClassTraces { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryClassTraceRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryClassTraceRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryClassTraceRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryClassTraceResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryClassTraceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryClassTraceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClassTrace", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ClassTrace == nil { + m.ClassTrace = &ClassTrace{} + } + if err := m.ClassTrace.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryClassTracesRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryClassTracesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryClassTracesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryClassTracesResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryClassTracesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryClassTracesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClassTraces", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClassTraces = append(m.ClassTraces, ClassTrace{}) + if err := m.ClassTraces[len(m.ClassTraces)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/modules/tibc/apps/mt_transfer/types/query.pb.gw.go b/modules/tibc/apps/mt_transfer/types/query.pb.gw.go new file mode 100644 index 00000000..7e36102a --- /dev/null +++ b/modules/tibc/apps/mt_transfer/types/query.pb.gw.go @@ -0,0 +1,264 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: tibc/apps/mt_transfer/v1/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage + +func request_Query_ClassTrace_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClassTraceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["hash"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "hash") + } + + protoReq.Hash, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "hash", err) + } + + msg, err := client.ClassTrace(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_ClassTrace_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClassTraceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["hash"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "hash") + } + + protoReq.Hash, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "hash", err) + } + + msg, err := server.ClassTrace(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_ClassTraces_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_ClassTraces_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClassTracesRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ClassTraces_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.ClassTraces(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_ClassTraces_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClassTracesRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ClassTraces_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ClassTraces(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_ClassTrace_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ClassTrace_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClassTrace_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ClassTraces_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ClassTraces_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClassTraces_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_ClassTrace_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_ClassTrace_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClassTrace_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ClassTraces_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_ClassTraces_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClassTraces_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_ClassTrace_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"tibc", "apps", "mt_transfer", "v1", "class_traces", "hash"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_ClassTraces_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"tibc", "apps", "mt_transfer", "v1", "class_traces"}, "", runtime.AssumeColonVerbOpt(true))) +) + +var ( + forward_Query_ClassTrace_0 = runtime.ForwardResponseMessage + + forward_Query_ClassTraces_0 = runtime.ForwardResponseMessage +) diff --git a/modules/tibc/apps/mt_transfer/types/trace.go b/modules/tibc/apps/mt_transfer/types/trace.go new file mode 100644 index 00000000..b864c479 --- /dev/null +++ b/modules/tibc/apps/mt_transfer/types/trace.go @@ -0,0 +1,101 @@ +package types + +import ( + "crypto/sha256" + "encoding/hex" + "fmt" + "sort" + "strings" + + tmbytes "github.com/tendermint/tendermint/libs/bytes" + tmtypes "github.com/tendermint/tendermint/types" +) + +// Traces defines a wrapper type for a slice of ClassTrace. +type Traces []ClassTrace + +var _ sort.Interface = Traces{} + +// Len implements sort.Interface for Traces +func (t Traces) Len() int { return len(t) } + +// Less implements sort.Interface for Traces +func (t Traces) Less(i, j int) bool { return t[i].GetFullClassPath() < t[j].GetFullClassPath() } + +// Swap implements sort.Interface for Traces +func (t Traces) Swap(i, j int) { t[i], t[j] = t[j], t[i] } + +// Sort is a helper function to sort the set of class traces in-place +func (t Traces) Sort() Traces { + sort.Sort(t) + return t +} + +// ParseClassTrace parses a string with the ibc prefix (class trace) and the base class +// into a ClassTrace type. +// +// Examples: +// +// - "mt/A/B/dog" => ClassTrace{Path: "mt/A/B", BaseClass: "dog"} +// - "dog" => ClassTrace{Path: "", BaseClass: "dog"} +func ParseClassTrace(rawClass string) ClassTrace { + classSplit := strings.Split(rawClass, "/") + + if classSplit[0] == rawClass { + return ClassTrace{ + Path: "", + BaseClass: rawClass, + } + } + + return ClassTrace{ + Path: strings.Join(classSplit[:len(classSplit)-1], "/"), + BaseClass: classSplit[len(classSplit)-1], + } +} + +// Hash returns the hex bytes of the SHA256 hash of the ClassTrace fields using the following formula: +// +// hash = sha256(tracePath + "/" + baseClass) +func (ct ClassTrace) Hash() tmbytes.HexBytes { + hash := sha256.Sum256([]byte(ct.GetFullClassPath())) + return hash[:] +} + +// GetFullClassPath returns the full class according to the ICS20 specification: +// tracePath + "/" + baseClass +// If there exists no trace then the base class is returned. +func (ct ClassTrace) GetFullClassPath() string { + if ct.Path == "" { + return ct.BaseClass + } + return ct.GetPrefix() + ct.BaseClass +} + +// GetPrefix returns the receiving class prefix composed by the trace info and a separator. +func (ct ClassTrace) GetPrefix() string { + return ct.Path + "/" +} + +// IBCClass a nft class for an TICS30 fungible token in the format +// 'tibc-{hash(tracePath + baseClass)}'. If the trace is empty, it will return the base class. +func (ct ClassTrace) IBCClass() string { + if ct.Path != "" { + return fmt.Sprintf("%s-%s", ClassPrefix, ct.Hash()) + } + return ct.BaseClass +} + +// ParseHexHash parses a hex hash in string format to bytes and validates its correctness. +func ParseHexHash(hexHash string) (tmbytes.HexBytes, error) { + hash, err := hex.DecodeString(hexHash) + if err != nil { + return nil, err + } + + if err := tmtypes.ValidateHash(hash); err != nil { + return nil, err + } + + return hash, nil +} diff --git a/modules/tibc/apps/mt_transfer/types/tx.pb.go b/modules/tibc/apps/mt_transfer/types/tx.pb.go new file mode 100644 index 00000000..3c9af473 --- /dev/null +++ b/modules/tibc/apps/mt_transfer/types/tx.pb.go @@ -0,0 +1,828 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: tibc/apps/mt_transfer/v1/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type MsgMtTransfer struct { + // the class to which the mt to be transferred belongs + Class string `protobuf:"bytes,1,opt,name=class,proto3" json:"class,omitempty"` + // the mt id + Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` + // the mt sender + Sender string `protobuf:"bytes,3,opt,name=sender,proto3" json:"sender,omitempty"` + // the mt receiver + Receiver string `protobuf:"bytes,4,opt,name=receiver,proto3" json:"receiver,omitempty"` + // target chain of transmission + DestChain string `protobuf:"bytes,5,opt,name=dest_chain,json=destChain,proto3" json:"dest_chain,omitempty"` + // relay chain during transmission + RealayChain string `protobuf:"bytes,6,opt,name=realay_chain,json=realayChain,proto3" json:"realay_chain,omitempty"` + // the destination contract address to receive the nft + DestContract string `protobuf:"bytes,7,opt,name=dest_contract,json=destContract,proto3" json:"dest_contract,omitempty"` + // the amount defined by MT outside the chain + Amount uint64 `protobuf:"varint,8,opt,name=amount,proto3" json:"amount,omitempty"` +} + +func (m *MsgMtTransfer) Reset() { *m = MsgMtTransfer{} } +func (m *MsgMtTransfer) String() string { return proto.CompactTextString(m) } +func (*MsgMtTransfer) ProtoMessage() {} +func (*MsgMtTransfer) Descriptor() ([]byte, []int) { + return fileDescriptor_2978e16e5405f501, []int{0} +} +func (m *MsgMtTransfer) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgMtTransfer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgMtTransfer.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgMtTransfer) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgMtTransfer.Merge(m, src) +} +func (m *MsgMtTransfer) XXX_Size() int { + return m.Size() +} +func (m *MsgMtTransfer) XXX_DiscardUnknown() { + xxx_messageInfo_MsgMtTransfer.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgMtTransfer proto.InternalMessageInfo + +// MsgMtTransferResponse defines the Msg/MtTransfer response type. +type MsgMtTransferResponse struct { +} + +func (m *MsgMtTransferResponse) Reset() { *m = MsgMtTransferResponse{} } +func (m *MsgMtTransferResponse) String() string { return proto.CompactTextString(m) } +func (*MsgMtTransferResponse) ProtoMessage() {} +func (*MsgMtTransferResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2978e16e5405f501, []int{1} +} +func (m *MsgMtTransferResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgMtTransferResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgMtTransferResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgMtTransferResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgMtTransferResponse.Merge(m, src) +} +func (m *MsgMtTransferResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgMtTransferResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgMtTransferResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgMtTransferResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgMtTransfer)(nil), "tibc.apps.mt_transfer.v1.MsgMtTransfer") + proto.RegisterType((*MsgMtTransferResponse)(nil), "tibc.apps.mt_transfer.v1.MsgMtTransferResponse") +} + +func init() { proto.RegisterFile("tibc/apps/mt_transfer/v1/tx.proto", fileDescriptor_2978e16e5405f501) } + +var fileDescriptor_2978e16e5405f501 = []byte{ + // 362 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xbd, 0x4e, 0xeb, 0x30, + 0x18, 0x86, 0x93, 0xfe, 0x9d, 0xf6, 0x3b, 0xed, 0x19, 0xac, 0x1e, 0xb0, 0x2a, 0x91, 0xfe, 0x30, + 0xd0, 0x85, 0x58, 0x85, 0x8d, 0x09, 0xc1, 0xdc, 0xa5, 0x62, 0xea, 0x52, 0x39, 0x89, 0x9b, 0x1a, + 0x35, 0x71, 0x64, 0xbb, 0x15, 0xbd, 0x03, 0x46, 0x2e, 0xa1, 0x97, 0xc3, 0xd8, 0x91, 0x11, 0xb5, + 0x0b, 0x33, 0x57, 0x80, 0xe2, 0x04, 0xd4, 0x4a, 0x20, 0xb1, 0xe5, 0x7d, 0xbe, 0x47, 0x6f, 0x92, + 0xcf, 0x86, 0xae, 0xe6, 0x9e, 0x4f, 0x68, 0x92, 0x28, 0x12, 0xe9, 0x89, 0x96, 0x34, 0x56, 0x53, + 0x26, 0xc9, 0x72, 0x40, 0xf4, 0x83, 0x9b, 0x48, 0xa1, 0x05, 0xc2, 0xa9, 0xe2, 0xa6, 0x8a, 0xbb, + 0xa7, 0xb8, 0xcb, 0x41, 0xab, 0x19, 0x8a, 0x50, 0x18, 0x89, 0xa4, 0x4f, 0x99, 0xdf, 0x7b, 0xb7, + 0xa1, 0x31, 0x54, 0xe1, 0x50, 0xdf, 0xe5, 0x2a, 0x6a, 0x42, 0xd9, 0x9f, 0x53, 0xa5, 0xb0, 0xdd, + 0xb1, 0xfb, 0xb5, 0x51, 0x16, 0xd0, 0x3f, 0x28, 0xf0, 0x00, 0x17, 0x0c, 0x2a, 0xf0, 0x00, 0x1d, + 0x41, 0x45, 0xb1, 0x38, 0x60, 0x12, 0x17, 0x0d, 0xcb, 0x13, 0x6a, 0x41, 0x55, 0x32, 0x9f, 0xf1, + 0x25, 0x93, 0xb8, 0x64, 0x26, 0x5f, 0x19, 0x9d, 0x00, 0x04, 0x4c, 0xe9, 0x89, 0x3f, 0xa3, 0x3c, + 0xc6, 0x65, 0x33, 0xad, 0xa5, 0xe4, 0x36, 0x05, 0xa8, 0x0b, 0x75, 0xc9, 0xe8, 0x9c, 0xae, 0x72, + 0xa1, 0x62, 0x84, 0xbf, 0x19, 0xcb, 0x94, 0x53, 0x68, 0x64, 0x0d, 0x22, 0xd6, 0x92, 0xfa, 0x1a, + 0xff, 0x31, 0x4e, 0xdd, 0x94, 0xe4, 0x2c, 0xfd, 0x34, 0x1a, 0x89, 0x45, 0xac, 0x71, 0xb5, 0x63, + 0xf7, 0x4b, 0xa3, 0x3c, 0x5d, 0x55, 0x1f, 0xd7, 0x6d, 0xeb, 0x6d, 0xdd, 0xb6, 0x7a, 0xc7, 0xf0, + 0xff, 0xe0, 0x9f, 0x47, 0x4c, 0x25, 0x22, 0x56, 0xec, 0x22, 0x82, 0xe2, 0x50, 0x85, 0x68, 0x0a, + 0xb0, 0xb7, 0x90, 0x33, 0xf7, 0xa7, 0x9d, 0xba, 0x07, 0x2d, 0x2d, 0xf2, 0x4b, 0xf1, 0xf3, 0x75, + 0x37, 0xe3, 0xe7, 0xad, 0x63, 0x6f, 0xb6, 0x8e, 0xfd, 0xba, 0x75, 0xec, 0xa7, 0x9d, 0x63, 0x6d, + 0x76, 0x8e, 0xf5, 0xb2, 0x73, 0xac, 0xf1, 0x75, 0xc8, 0xf5, 0x6c, 0xe1, 0xb9, 0xbe, 0x88, 0x88, + 0xc7, 0x69, 0x7c, 0xcf, 0x19, 0xe5, 0x24, 0xad, 0x3f, 0x0f, 0x05, 0x89, 0x44, 0xb0, 0x98, 0x33, + 0x45, 0xbe, 0xbf, 0x0e, 0x7a, 0x95, 0x30, 0xe5, 0x55, 0xcc, 0xf9, 0x5e, 0x7e, 0x04, 0x00, 0x00, + 0xff, 0xff, 0x1d, 0x0a, 0xa5, 0x3c, 0x34, 0x02, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // MtTransfer defines a rpc handler method for MsgMtTransfer. + MtTransfer(ctx context.Context, in *MsgMtTransfer, opts ...grpc.CallOption) (*MsgMtTransferResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) MtTransfer(ctx context.Context, in *MsgMtTransfer, opts ...grpc.CallOption) (*MsgMtTransferResponse, error) { + out := new(MsgMtTransferResponse) + err := c.cc.Invoke(ctx, "/tibc.apps.mt_transfer.v1.Msg/MtTransfer", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // MtTransfer defines a rpc handler method for MsgMtTransfer. + MtTransfer(context.Context, *MsgMtTransfer) (*MsgMtTransferResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) MtTransfer(ctx context.Context, req *MsgMtTransfer) (*MsgMtTransferResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method MtTransfer not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_MtTransfer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgMtTransfer) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).MtTransfer(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/tibc.apps.mt_transfer.v1.Msg/MtTransfer", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).MtTransfer(ctx, req.(*MsgMtTransfer)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "tibc.apps.mt_transfer.v1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "MtTransfer", + Handler: _Msg_MtTransfer_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "tibc/apps/mt_transfer/v1/tx.proto", +} + +func (m *MsgMtTransfer) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgMtTransfer) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgMtTransfer) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Amount != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Amount)) + i-- + dAtA[i] = 0x40 + } + if len(m.DestContract) > 0 { + i -= len(m.DestContract) + copy(dAtA[i:], m.DestContract) + i = encodeVarintTx(dAtA, i, uint64(len(m.DestContract))) + i-- + dAtA[i] = 0x3a + } + if len(m.RealayChain) > 0 { + i -= len(m.RealayChain) + copy(dAtA[i:], m.RealayChain) + i = encodeVarintTx(dAtA, i, uint64(len(m.RealayChain))) + i-- + dAtA[i] = 0x32 + } + if len(m.DestChain) > 0 { + i -= len(m.DestChain) + copy(dAtA[i:], m.DestChain) + i = encodeVarintTx(dAtA, i, uint64(len(m.DestChain))) + i-- + dAtA[i] = 0x2a + } + if len(m.Receiver) > 0 { + i -= len(m.Receiver) + copy(dAtA[i:], m.Receiver) + i = encodeVarintTx(dAtA, i, uint64(len(m.Receiver))) + i-- + dAtA[i] = 0x22 + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintTx(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0x1a + } + if len(m.Id) > 0 { + i -= len(m.Id) + copy(dAtA[i:], m.Id) + i = encodeVarintTx(dAtA, i, uint64(len(m.Id))) + i-- + dAtA[i] = 0x12 + } + if len(m.Class) > 0 { + i -= len(m.Class) + copy(dAtA[i:], m.Class) + i = encodeVarintTx(dAtA, i, uint64(len(m.Class))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgMtTransferResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgMtTransferResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgMtTransferResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgMtTransfer) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Class) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Id) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Receiver) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.DestChain) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.RealayChain) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.DestContract) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Amount != 0 { + n += 1 + sovTx(uint64(m.Amount)) + } + return n +} + +func (m *MsgMtTransferResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgMtTransfer) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgMtTransfer: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgMtTransfer: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Class", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Class = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Id = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Receiver", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Receiver = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DestChain", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DestChain = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RealayChain", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RealayChain = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DestContract", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DestContract = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + m.Amount = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Amount |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgMtTransferResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgMtTransferResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgMtTransferResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/modules/tibc/core/26-routing/types/port.go b/modules/tibc/core/26-routing/types/port.go index 835816a4..1ad37884 100644 --- a/modules/tibc/core/26-routing/types/port.go +++ b/modules/tibc/core/26-routing/types/port.go @@ -5,6 +5,7 @@ type Port string const ( FT Port = "FT" NFT Port = "NFT" + MT Port = "MT" CONTRACT Port = "CONTRACT" SERVICE Port = "SERVICE" ) diff --git a/modules/tibc/light-clients/07-tendermint/types/tendermint.pb.go b/modules/tibc/light-clients/07-tendermint/types/tendermint.pb.go index e4856487..6b34bf0e 100644 --- a/modules/tibc/light-clients/07-tendermint/types/tendermint.pb.go +++ b/modules/tibc/light-clients/07-tendermint/types/tendermint.pb.go @@ -11,10 +11,10 @@ import ( _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" - _ "github.com/golang/protobuf/ptypes/duration" - _ "github.com/golang/protobuf/ptypes/timestamp" github_com_tendermint_tendermint_libs_bytes "github.com/tendermint/tendermint/libs/bytes" types2 "github.com/tendermint/tendermint/proto/tendermint/types" + _ "google.golang.org/protobuf/types/known/durationpb" + _ "google.golang.org/protobuf/types/known/timestamppb" io "io" math "math" math_bits "math/bits" diff --git a/proto/tibc/apps/mt_transfer/v1/mt_transfer.proto b/proto/tibc/apps/mt_transfer/v1/mt_transfer.proto new file mode 100755 index 00000000..9e5f79c2 --- /dev/null +++ b/proto/tibc/apps/mt_transfer/v1/mt_transfer.proto @@ -0,0 +1,32 @@ + syntax = "proto3"; + + package tibc.apps.mt_transfer.v1; + option go_package = "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types"; + + message MultiTokenPacketData { + // the class to which the Mt to be transferred belongs + string class = 1; + // the mt id + string id = 2; + // the address defined by MT outside the chain + bytes data = 3; + // the mt sender + string sender = 4; + // the mt receiver + string receiver = 5; + // identify whether it is far away from the source chain + bool away_from_origin = 6; + // the destination contract address to receive the nft + string dest_contract = 7; + // the amount defined by MT outside the chain + uint64 amount = 8; +} + // ClassTrace contains the base class for Multi Token and the + // source tracing information path. + message ClassTrace { + // path defines the chain of sourceChain/destChain + // identifiers used for tracing the source of the Non fungible token. + string path = 1; + // base class of the relayed non fungible token. + string base_class = 2; + } \ No newline at end of file diff --git a/proto/tibc/apps/mt_transfer/v1/query.proto b/proto/tibc/apps/mt_transfer/v1/query.proto new file mode 100644 index 00000000..901ac7ea --- /dev/null +++ b/proto/tibc/apps/mt_transfer/v1/query.proto @@ -0,0 +1,56 @@ + syntax = "proto3"; + package tibc.apps.mt_transfer.v1; + + option go_package = "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types"; + + import "gogoproto/gogo.proto"; + import "cosmos/base/query/v1beta1/pagination.proto"; + import "tibc/apps/mt_transfer/v1/mt_transfer.proto"; + import "google/api/annotations.proto"; + + + // Query provides defines the gRPC querier service. + service Query { + // ClassTrace queries a class trace information. + rpc ClassTrace(QueryClassTraceRequest) returns (QueryClassTraceResponse) { + option (google.api.http).get = "/tibc/apps/mt_transfer/v1/class_traces/{hash}"; + } + + // ClassTraces queries all class traces. + rpc ClassTraces(QueryClassTracesRequest) returns (QueryClassTracesResponse) { + option (google.api.http).get = "/tibc/apps/mt_transfer/v1/class_traces"; + } + } + + // QueryClassTraceRequest is the request type for the Query/ClassTrace RPC + // method + message QueryClassTraceRequest { + // hash (in hex format) of the class trace information. + string hash = 1; + } + + // QueryClassTraceResponse is the response type for the Query/ClassTrace RPC + // method. + message QueryClassTraceResponse { + // class_trace returns the requested class trace information. + ClassTrace class_trace = 1; + } + + // QueryConnectionsRequest is the request type for the Query/ClassTraces RPC + // method + message QueryClassTracesRequest { + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 1; + } + + // QueryConnectionsResponse is the response type for the Query/ClassTraces RPC + // method. + message QueryClassTracesResponse { + // class_traces returns all class trace information. + repeated ClassTrace class_traces = 1 [(gogoproto.castrepeated) = "Traces", (gogoproto.nullable) = false]; + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; + } + + + diff --git a/proto/tibc/apps/mt_transfer/v1/tx.proto b/proto/tibc/apps/mt_transfer/v1/tx.proto new file mode 100755 index 00000000..7aef14f2 --- /dev/null +++ b/proto/tibc/apps/mt_transfer/v1/tx.proto @@ -0,0 +1,37 @@ + syntax = "proto3"; + package tibc.apps.mt_transfer.v1; + + option go_package = "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types"; + + import "gogoproto/gogo.proto"; + +// Msg defines the tibc/MtTransfer Msg service. + service Msg { + // MtTransfer defines a rpc handler method for MsgMtTransfer. + rpc MtTransfer(MsgMtTransfer) returns (MsgMtTransferResponse); +} + + message MsgMtTransfer { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + // the class to which the mt to be transferred belongs + string class = 1; + // the mt id + string id = 2; + // the mt sender + string sender = 3; + // the mt receiver + string receiver = 4; + // target chain of transmission + string dest_chain = 5; + // relay chain during transmission + string realay_chain = 6; + // the destination contract address to receive the nft + string dest_contract = 7; + // the amount defined by MT outside the chain + uint64 amount = 8; +} + +// MsgMtTransferResponse defines the Msg/MtTransfer response type. + message MsgMtTransferResponse {} \ No newline at end of file diff --git a/simapp/app.go b/simapp/app.go index acac1604..4ba1dedd 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -89,6 +89,14 @@ import ( nftkeeper "github.com/irisnet/irismod/modules/nft/keeper" nfttypes "github.com/irisnet/irismod/modules/nft/types" + tibcmttransfer "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer" + tibcmttransferkeeper "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/keeper" + tibcmttypes "github.com/bianjieai/tibc-go/modules/tibc/apps/mt_transfer/types" + + mt "github.com/irisnet/irismod/modules/mt" + mtkeeper "github.com/irisnet/irismod/modules/mt/keeper" + mttypes "github.com/irisnet/irismod/modules/mt/types" + tibc "github.com/bianjieai/tibc-go/modules/tibc/core" tibcclient "github.com/bianjieai/tibc-go/modules/tibc/core/02-client" tibcclienttypes "github.com/bianjieai/tibc-go/modules/tibc/core/02-client/types" @@ -128,10 +136,12 @@ var ( feegrantmodule.AppModuleBasic{}, tibc.AppModuleBasic{}, tibcnfttransfer.AppModuleBasic{}, + tibcmttransfer.AppModuleBasic{}, upgrade.AppModuleBasic{}, evidence.AppModuleBasic{}, vesting.AppModuleBasic{}, nft.AppModuleBasic{}, + mt.AppModuleBasic{}, ) // module account permissions @@ -143,6 +153,7 @@ var ( stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, govtypes.ModuleName: {authtypes.Burner}, tibcnfttypes.ModuleName: nil, + tibcmttypes.ModuleName: nil, } ) @@ -172,6 +183,7 @@ type SimApp struct { BankKeeper bankkeeper.Keeper CapabilityKeeper *capabilitykeeper.Keeper NftKeeper nftkeeper.Keeper + MtKeeper mtkeeper.Keeper StakingKeeper stakingkeeper.Keeper SlashingKeeper slashingkeeper.Keeper MintKeeper mintkeeper.Keeper @@ -182,6 +194,7 @@ type SimApp struct { ParamsKeeper paramskeeper.Keeper TIBCKeeper *tibckeeper.Keeper // TIBC Keeper must be a pointer in the app, so we can SetRouter on it correctly NftTransferKeeper tibcnfttransferkeeper.Keeper + MtTransferKeeper tibcmttransferkeeper.Keeper EvidenceKeeper evidencekeeper.Keeper FeeGrantKeeper feegrantkeeper.Keeper @@ -239,7 +252,9 @@ func NewSimApp( evidencetypes.StoreKey, capabilitytypes.StoreKey, nfttypes.StoreKey, + mttypes.StoreKey, tibcnfttypes.StoreKey, + tibcmttypes.StoreKey, ) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) @@ -309,6 +324,7 @@ func NewSimApp( ) app.NftKeeper = nftkeeper.NewKeeper(appCodec, keys[nfttypes.StoreKey]) + app.MtKeeper = mtkeeper.NewKeeper(appCodec, keys[mttypes.StoreKey]) // register the proposal types govRouter := govtypes.NewRouter() @@ -328,7 +344,16 @@ func NewSimApp( app.AccountKeeper, nftkeeper.NewLegacyKeeper(app.NftKeeper), app.TIBCKeeper.PacketKeeper, app.TIBCKeeper.ClientKeeper, ) + + // Create Transfer Keepers + app.MtTransferKeeper = tibcmttransferkeeper.NewKeeper( + appCodec, keys[tibcnfttypes.StoreKey], app.GetSubspace(tibcnfttypes.ModuleName), + app.AccountKeeper, app.MtKeeper, + app.TIBCKeeper.PacketKeeper, app.TIBCKeeper.ClientKeeper, + ) + nfttransferModule := tibcnfttransfer.NewAppModule(app.NftTransferKeeper) + mttransferModule := tibcmttransfer.NewAppModule(app.MtTransferKeeper) // NOTE: the TIBC mock keeper and application module is used only for testing core TIBC. Do // note replicate if you do not need to test core TIBC or light clients. @@ -337,6 +362,7 @@ func NewSimApp( // Create static TIBC router, add nft-transfer route, then set and seal it tibcRouter := tibcroutingtypes.NewRouter() tibcRouter.AddRoute(tibcnfttypes.ModuleName, nfttransferModule) + tibcRouter.AddRoute(tibcmttypes.ModuleName, mttransferModule) tibcRouter.AddRoute(tibcmock.ModuleName, mockModule) app.TIBCKeeper.SetRouter(tibcRouter) @@ -374,6 +400,8 @@ func NewSimApp( params.NewAppModule(app.ParamsKeeper), nfttransferModule, nft.NewAppModule(appCodec, app.NftKeeper, app.AccountKeeper, app.BankKeeper), + mttransferModule, + mt.NewAppModule(appCodec, app.MtKeeper, app.AccountKeeper, app.BankKeeper), ) // During begin block slashing happens after distr.BeginBlocker so that