x/ibc-transfer: custom absolute packet timeout (#6248)

* x/ibc-transfer: custom timeout

* remove destHeight field

* cleanup

* fix test

* replace CLI arg for flag

* update CLI

* viper get flag

* address comments from review

* update cmd example:

* update spec

* address comments from review
This commit is contained in:
Federico Kunze 2020-06-04 15:30:56 -04:00 committed by GitHub
parent c1355d0b45
commit 1a5f2b7859
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 296 additions and 242 deletions

View File

@ -11,21 +11,19 @@ import (
) )
const ( const (
DefaultPacketTimeoutHeight = keeper.DefaultPacketTimeoutHeight EventTypeTimeout = types.EventTypeTimeout
DefaultPacketTimeoutTimestamp = keeper.DefaultPacketTimeoutTimestamp EventTypePacket = types.EventTypePacket
EventTypeTimeout = types.EventTypeTimeout EventTypeChannelClose = types.EventTypeChannelClose
EventTypePacket = types.EventTypePacket AttributeKeyReceiver = types.AttributeKeyReceiver
EventTypeChannelClose = types.EventTypeChannelClose AttributeKeyValue = types.AttributeKeyValue
AttributeKeyReceiver = types.AttributeKeyReceiver AttributeKeyRefundReceiver = types.AttributeKeyRefundReceiver
AttributeKeyValue = types.AttributeKeyValue AttributeKeyRefundValue = types.AttributeKeyRefundValue
AttributeKeyRefundReceiver = types.AttributeKeyRefundReceiver AttributeKeyAckSuccess = types.AttributeKeyAckSuccess
AttributeKeyRefundValue = types.AttributeKeyRefundValue AttributeKeyAckError = types.AttributeKeyAckError
AttributeKeyAckSuccess = types.AttributeKeyAckSuccess ModuleName = types.ModuleName
AttributeKeyAckError = types.AttributeKeyAckError StoreKey = types.StoreKey
ModuleName = types.ModuleName RouterKey = types.RouterKey
StoreKey = types.StoreKey QuerierRoute = types.QuerierRoute
RouterKey = types.RouterKey
QuerierRoute = types.QuerierRoute
) )
var ( var (
@ -38,8 +36,7 @@ var (
RegisterInterfaces = types.RegisterInterfaces RegisterInterfaces = types.RegisterInterfaces
// variable aliases // variable aliases
ModuleCdc = types.ModuleCdc ModuleCdc = types.ModuleCdc
AttributeValueCategory = types.AttributeValueCategory
) )
type ( type (

View File

@ -3,6 +3,7 @@ package cli
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
) )
@ -10,8 +11,11 @@ import (
// GetQueryCmd returns the query commands for IBC fungible token transfer // GetQueryCmd returns the query commands for IBC fungible token transfer
func GetQueryCmd(cdc *codec.Codec, queryRoute string) *cobra.Command { func GetQueryCmd(cdc *codec.Codec, queryRoute string) *cobra.Command {
ics20TransferQueryCmd := &cobra.Command{ ics20TransferQueryCmd := &cobra.Command{
Use: "transfer", Use: "ibc-transfer",
Short: "IBC fungible token transfer query subcommands", Short: "IBC fungible token transfer query subcommands",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
} }
ics20TransferQueryCmd.AddCommand(flags.GetCommands( ics20TransferQueryCmd.AddCommand(flags.GetCommands(
@ -24,8 +28,11 @@ func GetQueryCmd(cdc *codec.Codec, queryRoute string) *cobra.Command {
// GetTxCmd returns the transaction commands for IBC fungible token transfer // GetTxCmd returns the transaction commands for IBC fungible token transfer
func GetTxCmd(cdc *codec.Codec) *cobra.Command { func GetTxCmd(cdc *codec.Codec) *cobra.Command {
ics20TransferTxCmd := &cobra.Command{ ics20TransferTxCmd := &cobra.Command{
Use: "transfer", Use: "ibc-transfer",
Short: "IBC fungible token transfer transaction subcommands", Short: "IBC fungible token transfer transaction subcommands",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
} }
ics20TransferTxCmd.AddCommand(flags.PostCommands( ics20TransferTxCmd.AddCommand(flags.PostCommands(

View File

@ -22,10 +22,10 @@ func GetCmdQueryNextSequence(cdc *codec.Codec, queryRoute string) *cobra.Command
Long: strings.TrimSpace(fmt.Sprintf(`Query an IBC channel end Long: strings.TrimSpace(fmt.Sprintf(`Query an IBC channel end
Example: Example:
$ %s query ibc channel next-recv [port-id] [channel-id] $ %s query ibc-transfer next-recv [port-id] [channel-id]
`, version.ClientName), `, version.ClientName),
), ),
Example: fmt.Sprintf("%s query ibc channel next-recv [port-id] [channel-id]", version.ClientName), Example: fmt.Sprintf("%s query ibc-transfer next-recv [port-id] [channel-id]", version.ClientName),
Args: cobra.ExactArgs(2), Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := client.NewContext().WithCodec(cdc) clientCtx := client.NewContext().WithCodec(cdc)

View File

@ -2,36 +2,33 @@ package cli
import ( import (
"bufio" "bufio"
"strconv" "fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/version"
authclient "github.com/cosmos/cosmos-sdk/x/auth/client" authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/ibc-transfer/types" "github.com/cosmos/cosmos-sdk/x/ibc-transfer/types"
) )
// IBC transfer flags const (
var ( flagTimeoutHeight = "timeout-height"
FlagNode1 = "node1" flagTimeoutTimestamp = "timeout-timestamp"
FlagNode2 = "node2"
FlagFrom1 = "from1"
FlagFrom2 = "from2"
FlagChainID2 = "chain-id2"
FlagSequence = "packet-sequence"
FlagTimeout = "timeout"
) )
// GetTransferTxCmd returns the command to create a NewMsgTransfer transaction // GetTransferTxCmd returns the command to create a NewMsgTransfer transaction
func GetTransferTxCmd(cdc *codec.Codec) *cobra.Command { func GetTransferTxCmd(cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "transfer [src-port] [src-channel] [dest-height] [receiver] [amount]", Use: "transfer [src-port] [src-channel] [receiver] [amount]",
Short: "Transfer fungible token through IBC", Short: "Transfer a fungible token through IBC",
Args: cobra.ExactArgs(5), Example: fmt.Sprintf("%s tx ibc-transfer transfer [src-port] [src-channel] [receiver] [amount]", version.ClientName),
Args: cobra.ExactArgs(4),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
inBuf := bufio.NewReader(cmd.InOrStdin()) inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := authtypes.NewTxBuilderFromCLI(inBuf).WithTxEncoder(authclient.GetTxEncoder(cdc)) txBldr := authtypes.NewTxBuilderFromCLI(inBuf).WithTxEncoder(authclient.GetTxEncoder(cdc))
@ -40,18 +37,19 @@ func GetTransferTxCmd(cdc *codec.Codec) *cobra.Command {
sender := clientCtx.GetFromAddress() sender := clientCtx.GetFromAddress()
srcPort := args[0] srcPort := args[0]
srcChannel := args[1] srcChannel := args[1]
destHeight, err := strconv.Atoi(args[2]) receiver := args[2]
coins, err := sdk.ParseCoins(args[3])
if err != nil { if err != nil {
return err return err
} }
// parse coin trying to be sent timeoutHeight := viper.GetUint64(flagTimeoutHeight)
coins, err := sdk.ParseCoins(args[4]) timeoutTimestamp := viper.GetUint64(flagTimeoutHeight)
if err != nil {
return err
}
msg := types.NewMsgTransfer(srcPort, srcChannel, uint64(destHeight), coins, sender, args[3]) msg := types.NewMsgTransfer(
srcPort, srcChannel, coins, sender, receiver, timeoutHeight, timeoutTimestamp,
)
if err := msg.ValidateBasic(); err != nil { if err := msg.ValidateBasic(); err != nil {
return err return err
} }
@ -59,5 +57,7 @@ func GetTransferTxCmd(cdc *codec.Codec) *cobra.Command {
return authclient.GenerateOrBroadcastMsgs(clientCtx, txBldr, []sdk.Msg{msg}) return authclient.GenerateOrBroadcastMsgs(clientCtx, txBldr, []sdk.Msg{msg})
}, },
} }
cmd.Flags().Uint64(flagTimeoutHeight, types.DefaultAbsolutePacketTimeoutHeight, "Absolute timeout block height. The timeout is disabled when set to 0.")
cmd.Flags().Uint64(flagTimeoutTimestamp, types.DefaultAbsolutePacketTimeoutTimestamp, "Absolute timeout timestamp in nanoseconds. The timeout is disabled when set to 0.")
return cmd return cmd
} }

View File

@ -21,8 +21,9 @@ func RegisterRoutes(clientCtx client.Context, r *mux.Router) {
// TransferTxReq defines the properties of a transfer tx request's body. // TransferTxReq defines the properties of a transfer tx request's body.
type TransferTxReq struct { type TransferTxReq struct {
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
DestHeight uint64 `json:"dest_height" yaml:"dest_height"` Amount sdk.Coins `json:"amount" yaml:"amount"`
Amount sdk.Coins `json:"amount" yaml:"amount"` Receiver string `json:"receiver" yaml:"receiver"`
Receiver string `json:"receiver" yaml:"receiver"` TimeoutHeight uint64 `json:"timeout_height" yaml:"timeout_height"`
TimeoutTimestamp uint64 `json:"timeout_timestamp" yaml:"timeout_timestamp"`
} }

View File

@ -56,10 +56,11 @@ func transferHandlerFn(clientCtx client.Context) http.HandlerFunc {
msg := types.NewMsgTransfer( msg := types.NewMsgTransfer(
portID, portID,
channelID, channelID,
req.DestHeight,
req.Amount, req.Amount,
fromAddr, fromAddr,
req.Receiver, req.Receiver,
req.TimeoutHeight,
req.TimeoutTimestamp,
) )
if err := msg.ValidateBasic(); err != nil { if err := msg.ValidateBasic(); err != nil {

View File

@ -22,7 +22,7 @@ func NewHandler(k Keeper) sdk.Handler {
// See createOutgoingPacket in spec:https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#packet-relay // See createOutgoingPacket in spec:https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#packet-relay
func handleMsgTransfer(ctx sdk.Context, k Keeper, msg *MsgTransfer) (*sdk.Result, error) { func handleMsgTransfer(ctx sdk.Context, k Keeper, msg *MsgTransfer) (*sdk.Result, error) {
if err := k.SendTransfer( if err := k.SendTransfer(
ctx, msg.SourcePort, msg.SourceChannel, msg.DestinationHeight, msg.Amount, msg.Sender, msg.Receiver, ctx, msg.SourcePort, msg.SourceChannel, msg.Amount, msg.Sender, msg.Receiver, msg.TimeoutHeight, msg.TimeoutTimestamp,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
@ -32,7 +32,7 @@ func handleMsgTransfer(ctx sdk.Context, k Keeper, msg *MsgTransfer) (*sdk.Result
ctx.EventManager().EmitEvent( ctx.EventManager().EmitEvent(
sdk.NewEvent( sdk.NewEvent(
sdk.EventTypeMessage, sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, AttributeValueCategory), sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName),
sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender.String()), sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender.String()),
sdk.NewAttribute(AttributeKeyReceiver, msg.Receiver), sdk.NewAttribute(AttributeKeyReceiver, msg.Receiver),
), ),

View File

@ -79,7 +79,7 @@ func (suite *HandlerTestSuite) TestHandleMsgTransfer() {
suite.Require().Nil(err, "transfer module could not claim capability") suite.Require().Nil(err, "transfer module could not claim capability")
ctx := suite.chainA.GetContext() ctx := suite.chainA.GetContext()
msg := transfer.NewMsgTransfer(testPort1, testChannel1, 10, testPrefixedCoins2, testAddr1, testAddr2.String()) msg := transfer.NewMsgTransfer(testPort1, testChannel1, testPrefixedCoins2, testAddr1, testAddr2.String(), 110, 0)
res, err := handler(ctx, msg) res, err := handler(ctx, msg)
suite.Require().Error(err) suite.Require().Error(err)
suite.Require().Nil(res, "%+v", res) // channel does not exist suite.Require().Nil(res, "%+v", res) // channel does not exist
@ -105,14 +105,14 @@ func (suite *HandlerTestSuite) TestHandleMsgTransfer() {
suite.Require().NotNil(res, "%+v", res) // successfully executed suite.Require().NotNil(res, "%+v", res) // successfully executed
// test when the source is false // test when the source is false
msg = transfer.NewMsgTransfer(testPort1, testChannel1, 10, testPrefixedCoins2, testAddr1, testAddr2.String()) msg = transfer.NewMsgTransfer(testPort1, testChannel1, testPrefixedCoins2, testAddr1, testAddr2.String(), 110, 0)
_ = suite.chainA.App.BankKeeper.SetBalances(ctx, testAddr1, testPrefixedCoins2) _ = suite.chainA.App.BankKeeper.SetBalances(ctx, testAddr1, testPrefixedCoins2)
res, err = handler(ctx, msg) res, err = handler(ctx, msg)
suite.Require().Error(err) suite.Require().Error(err)
suite.Require().Nil(res, "%+v", res) // incorrect denom prefix suite.Require().Nil(res, "%+v", res) // incorrect denom prefix
msg = transfer.NewMsgTransfer(testPort1, testChannel1, 10, testPrefixedCoins1, testAddr1, testAddr2.String()) msg = transfer.NewMsgTransfer(testPort1, testChannel1, testPrefixedCoins1, testAddr1, testAddr2.String(), 110, 0)
suite.chainA.App.BankKeeper.SetSupply(ctx, bank.NewSupply(testPrefixedCoins1)) suite.chainA.App.BankKeeper.SetSupply(ctx, bank.NewSupply(testPrefixedCoins1))
_ = suite.chainA.App.BankKeeper.SetBalances(ctx, testAddr1, testPrefixedCoins1) _ = suite.chainA.App.BankKeeper.SetBalances(ctx, testAddr1, testPrefixedCoins1)

View File

@ -16,17 +16,7 @@ import (
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
) )
const ( // Keeper defines the IBC fungible transfer keeper
// DefaultPacketTimeoutHeight is the default packet timeout height relative
// to the current block height. The timeout is disabled when set to 0.
DefaultPacketTimeoutHeight = 1000 // NOTE: in blocks
// DefaultPacketTimeoutTimestamp is the default packet timeout timestamp relative
// to the current block timestamp. The timeout is disabled when set to 0.
DefaultPacketTimeoutTimestamp = 0 // NOTE: in nanoseconds
)
// Keeper defines the IBC transfer keeper
type Keeper struct { type Keeper struct {
storeKey sdk.StoreKey storeKey sdk.StoreKey
cdc codec.Marshaler cdc codec.Marshaler
@ -63,7 +53,7 @@ func NewKeeper(
// Logger returns a module-specific logger. // Logger returns a module-specific logger.
func (k Keeper) Logger(ctx sdk.Context) log.Logger { func (k Keeper) Logger(ctx sdk.Context) log.Logger {
return ctx.Logger().With("module", fmt.Sprintf("x/%s/%s", host.ModuleName, types.ModuleName)) return ctx.Logger().With("module", fmt.Sprintf("x/%s-%s", host.ModuleName, types.ModuleName))
} }
// GetTransferAccount returns the ICS20 - transfers ModuleAccount // GetTransferAccount returns the ICS20 - transfers ModuleAccount

View File

@ -24,10 +24,11 @@ func (k Keeper) SendTransfer(
ctx sdk.Context, ctx sdk.Context,
sourcePort, sourcePort,
sourceChannel string, sourceChannel string,
destHeight uint64,
amount sdk.Coins, amount sdk.Coins,
sender sdk.AccAddress, sender sdk.AccAddress,
receiver string, receiver string,
timeoutHeight,
timeoutTimestamp uint64,
) error { ) error {
sourceChannelEnd, found := k.channelKeeper.GetChannel(ctx, sourcePort, sourceChannel) sourceChannelEnd, found := k.channelKeeper.GetChannel(ctx, sourcePort, sourceChannel)
if !found { if !found {
@ -44,10 +45,12 @@ func (k Keeper) SendTransfer(
channeltypes.ErrSequenceSendNotFound, channeltypes.ErrSequenceSendNotFound,
"source port: %s, source channel: %s", sourcePort, sourceChannel, "source port: %s, source channel: %s", sourcePort, sourceChannel,
) )
} }
return k.createOutgoingPacket(ctx, sequence, sourcePort, sourceChannel, destinationPort, destinationChannel, destHeight, amount, sender, receiver) return k.createOutgoingPacket(
ctx, sequence, sourcePort, sourceChannel, destinationPort, destinationChannel,
amount, sender, receiver, timeoutHeight, timeoutTimestamp,
)
} }
// See spec for this function: https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#packet-relay // See spec for this function: https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#packet-relay
@ -56,10 +59,10 @@ func (k Keeper) createOutgoingPacket(
seq uint64, seq uint64,
sourcePort, sourceChannel, sourcePort, sourceChannel,
destinationPort, destinationChannel string, destinationPort, destinationChannel string,
destHeight uint64,
amount sdk.Coins, amount sdk.Coins,
sender sdk.AccAddress, sender sdk.AccAddress,
receiver string, receiver string,
timeoutHeight, timeoutTimestamp uint64,
) error { ) error {
channelCap, ok := k.scopedKeeper.GetCapability(ctx, host.ChannelCapabilityPath(sourcePort, sourceChannel)) channelCap, ok := k.scopedKeeper.GetCapability(ctx, host.ChannelCapabilityPath(sourcePort, sourceChannel))
if !ok { if !ok {
@ -138,8 +141,8 @@ func (k Keeper) createOutgoingPacket(
sourceChannel, sourceChannel,
destinationPort, destinationPort,
destinationChannel, destinationChannel,
destHeight+DefaultPacketTimeoutHeight, timeoutHeight,
DefaultPacketTimeoutTimestamp, timeoutTimestamp,
) )
return k.channelKeeper.SendPacket(ctx, channelCap, packet) return k.channelKeeper.SendPacket(ctx, channelCap, packet)

View File

@ -93,7 +93,7 @@ func (suite *KeeperTestSuite) TestSendTransfer() {
tc.malleate() tc.malleate()
err = suite.chainA.App.TransferKeeper.SendTransfer( err = suite.chainA.App.TransferKeeper.SendTransfer(
suite.chainA.GetContext(), testPort1, testChannel1, 100, tc.amount, testAddr1, testAddr2.String(), suite.chainA.GetContext(), testPort1, testChannel1, tc.amount, testAddr1, testAddr2.String(), 110, 0,
) )
if tc.expPass { if tc.expPass {

View File

@ -304,7 +304,7 @@ func (am AppModule) OnRecvPacket(
ctx.EventManager().EmitEvent( ctx.EventManager().EmitEvent(
sdk.NewEvent( sdk.NewEvent(
EventTypePacket, EventTypePacket,
sdk.NewAttribute(sdk.AttributeKeyModule, AttributeValueCategory), sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName),
sdk.NewAttribute(AttributeKeyReceiver, data.Receiver), sdk.NewAttribute(AttributeKeyReceiver, data.Receiver),
sdk.NewAttribute(AttributeKeyValue, data.Amount.String()), sdk.NewAttribute(AttributeKeyValue, data.Amount.String()),
), ),
@ -336,7 +336,7 @@ func (am AppModule) OnAcknowledgementPacket(
ctx.EventManager().EmitEvent( ctx.EventManager().EmitEvent(
sdk.NewEvent( sdk.NewEvent(
EventTypePacket, EventTypePacket,
sdk.NewAttribute(sdk.AttributeKeyModule, AttributeValueCategory), sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName),
sdk.NewAttribute(AttributeKeyReceiver, data.Receiver), sdk.NewAttribute(AttributeKeyReceiver, data.Receiver),
sdk.NewAttribute(AttributeKeyValue, data.Amount.String()), sdk.NewAttribute(AttributeKeyValue, data.Amount.String()),
sdk.NewAttribute(AttributeKeyAckSuccess, fmt.Sprintf("%t", ack.Success)), sdk.NewAttribute(AttributeKeyAckSuccess, fmt.Sprintf("%t", ack.Success)),
@ -375,7 +375,7 @@ func (am AppModule) OnTimeoutPacket(
EventTypeTimeout, EventTypeTimeout,
sdk.NewAttribute(AttributeKeyRefundReceiver, data.Sender), sdk.NewAttribute(AttributeKeyRefundReceiver, data.Sender),
sdk.NewAttribute(AttributeKeyRefundValue, data.Amount.String()), sdk.NewAttribute(AttributeKeyRefundValue, data.Amount.String()),
sdk.NewAttribute(sdk.AttributeKeyModule, AttributeValueCategory), sdk.NewAttribute(sdk.AttributeKeyModule, ModuleName),
), ),
) )

View File

@ -23,11 +23,11 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) {
var ( var (
amino = codec.New() amino = codec.New()
// ModuleCdc references the global x/transfer module codec. Note, the codec // ModuleCdc references the global x/ibc-transfer module codec. Note, the codec
// should ONLY be used in certain instances of tests and for JSON encoding as Amino // should ONLY be used in certain instances of tests and for JSON encoding as Amino
// is still used for that purpose. // is still used for that purpose.
// //
// The actual codec used for serialization should be provided to x/transfer and // The actual codec used for serialization should be provided to x/ibc-transfer and
// defined at the application level. // defined at the application level.
ModuleCdc = codec.NewHybridCodec(amino, cdctypes.NewInterfaceRegistry()) ModuleCdc = codec.NewHybridCodec(amino, cdctypes.NewInterfaceRegistry())
) )

View File

@ -1,11 +1,5 @@
package types package types
import (
"fmt"
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
)
// IBC transfer events // IBC transfer events
const ( const (
EventTypeTimeout = "timeout" EventTypeTimeout = "timeout"
@ -19,8 +13,3 @@ const (
AttributeKeyAckSuccess = "success" AttributeKeyAckSuccess = "success"
AttributeKeyAckError = "error" AttributeKeyAckError = "error"
) )
// IBC transfer events vars
var (
AttributeValueCategory = fmt.Sprintf("%s_%s", host.ModuleName, ModuleName)
)

View File

@ -13,15 +13,18 @@ const (
// NewMsgTransfer creates a new MsgTransfer instance // NewMsgTransfer creates a new MsgTransfer instance
func NewMsgTransfer( func NewMsgTransfer(
sourcePort, sourceChannel string, destHeight uint64, amount sdk.Coins, sender sdk.AccAddress, receiver string, sourcePort, sourceChannel string,
amount sdk.Coins, sender sdk.AccAddress, receiver string,
timeoutHeight, timeoutTimestamp uint64,
) *MsgTransfer { ) *MsgTransfer {
return &MsgTransfer{ return &MsgTransfer{
SourcePort: sourcePort, SourcePort: sourcePort,
SourceChannel: sourceChannel, SourceChannel: sourceChannel,
DestinationHeight: destHeight, Amount: amount,
Amount: amount, Sender: sender,
Sender: sender, Receiver: receiver,
Receiver: receiver, TimeoutHeight: timeoutHeight,
TimeoutTimestamp: timeoutTimestamp,
} }
} }
@ -35,7 +38,8 @@ func (MsgTransfer) Type() string {
return TypeMsgTransfer return TypeMsgTransfer
} }
// ValidateBasic implements sdk.Msg // ValidateBasic performs a basic check of the MsgTransfer fields.
// NOTE: timeout height and timestamp values can be 0 to disable the timeout.
func (msg MsgTransfer) ValidateBasic() error { func (msg MsgTransfer) ValidateBasic() error {
if err := host.PortIdentifierValidator(msg.SourcePort); err != nil { if err := host.PortIdentifierValidator(msg.SourcePort); err != nil {
return sdkerrors.Wrap(err, "invalid source port ID") return sdkerrors.Wrap(err, "invalid source port ID")
@ -44,10 +48,10 @@ func (msg MsgTransfer) ValidateBasic() error {
return sdkerrors.Wrap(err, "invalid source channel ID") return sdkerrors.Wrap(err, "invalid source channel ID")
} }
if !msg.Amount.IsAllPositive() { if !msg.Amount.IsAllPositive() {
return sdkerrors.ErrInsufficientFunds return sdkerrors.Wrap(sdkerrors.ErrInsufficientFunds, msg.Amount.String())
} }
if !msg.Amount.IsValid() { if !msg.Amount.IsValid() {
return sdkerrors.ErrInvalidCoins return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String())
} }
if msg.Sender.Empty() { if msg.Sender.Empty() {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing sender address") return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing sender address")

View File

@ -34,14 +34,14 @@ var (
// TestMsgTransferRoute tests Route for MsgTransfer // TestMsgTransferRoute tests Route for MsgTransfer
func TestMsgTransferRoute(t *testing.T) { func TestMsgTransferRoute(t *testing.T) {
msg := NewMsgTransfer(validPort, validChannel, 10, coins, addr1, addr2) msg := NewMsgTransfer(validPort, validChannel, coins, addr1, addr2, 10, 0)
require.Equal(t, RouterKey, msg.Route()) require.Equal(t, RouterKey, msg.Route())
} }
// TestMsgTransferType tests Type for MsgTransfer // TestMsgTransferType tests Type for MsgTransfer
func TestMsgTransferType(t *testing.T) { func TestMsgTransferType(t *testing.T) {
msg := NewMsgTransfer(validPort, validChannel, 10, coins, addr1, addr2) msg := NewMsgTransfer(validPort, validChannel, coins, addr1, addr2, 10, 0)
require.Equal(t, "transfer", msg.Type()) require.Equal(t, "transfer", msg.Type())
} }
@ -49,18 +49,18 @@ func TestMsgTransferType(t *testing.T) {
// TestMsgTransferValidation tests ValidateBasic for MsgTransfer // TestMsgTransferValidation tests ValidateBasic for MsgTransfer
func TestMsgTransferValidation(t *testing.T) { func TestMsgTransferValidation(t *testing.T) {
testMsgs := []*MsgTransfer{ testMsgs := []*MsgTransfer{
NewMsgTransfer(validPort, validChannel, 10, coins, addr1, addr2), // valid msg NewMsgTransfer(validPort, validChannel, coins, addr1, addr2, 10, 0), // valid msg
NewMsgTransfer(invalidShortPort, validChannel, 10, coins, addr1, addr2), // too short port id NewMsgTransfer(invalidShortPort, validChannel, coins, addr1, addr2, 10, 0), // too short port id
NewMsgTransfer(invalidLongPort, validChannel, 10, coins, addr1, addr2), // too long port id NewMsgTransfer(invalidLongPort, validChannel, coins, addr1, addr2, 10, 0), // too long port id
NewMsgTransfer(invalidPort, validChannel, 10, coins, addr1, addr2), // port id contains non-alpha NewMsgTransfer(invalidPort, validChannel, coins, addr1, addr2, 10, 0), // port id contains non-alpha
NewMsgTransfer(validPort, invalidShortChannel, 10, coins, addr1, addr2), // too short channel id NewMsgTransfer(validPort, invalidShortChannel, coins, addr1, addr2, 10, 0), // too short channel id
NewMsgTransfer(validPort, invalidLongChannel, 10, coins, addr1, addr2), // too long channel id NewMsgTransfer(validPort, invalidLongChannel, coins, addr1, addr2, 10, 0), // too long channel id
NewMsgTransfer(validPort, invalidChannel, 10, coins, addr1, addr2), // channel id contains non-alpha NewMsgTransfer(validPort, invalidChannel, coins, addr1, addr2, 10, 0), // channel id contains non-alpha
NewMsgTransfer(validPort, validChannel, 10, invalidDenomCoins, addr1, addr2), // invalid amount NewMsgTransfer(validPort, validChannel, invalidDenomCoins, addr1, addr2, 10, 0), // invalid amount
NewMsgTransfer(validPort, validChannel, 10, negativeCoins, addr1, addr2), // amount contains negative coin NewMsgTransfer(validPort, validChannel, negativeCoins, addr1, addr2, 10, 0), // amount contains negative coin
NewMsgTransfer(validPort, validChannel, 10, coins, emptyAddr, addr2), // missing sender address NewMsgTransfer(validPort, validChannel, coins, emptyAddr, addr2, 10, 0), // missing sender address
NewMsgTransfer(validPort, validChannel, 10, coins, addr1, ""), // missing recipient address NewMsgTransfer(validPort, validChannel, coins, addr1, "", 10, 0), // missing recipient address
NewMsgTransfer(validPort, validChannel, 10, sdk.Coins{}, addr1, addr2), // not possitive coin NewMsgTransfer(validPort, validChannel, sdk.Coins{}, addr1, addr2, 10, 0), // not possitive coin
} }
testCases := []struct { testCases := []struct {
@ -93,16 +93,16 @@ func TestMsgTransferValidation(t *testing.T) {
// TestMsgTransferGetSignBytes tests GetSignBytes for MsgTransfer // TestMsgTransferGetSignBytes tests GetSignBytes for MsgTransfer
func TestMsgTransferGetSignBytes(t *testing.T) { func TestMsgTransferGetSignBytes(t *testing.T) {
msg := NewMsgTransfer(validPort, validChannel, 10, coins, addr1, addr2) msg := NewMsgTransfer(validPort, validChannel, coins, addr1, addr2, 110, 10)
res := msg.GetSignBytes() res := msg.GetSignBytes()
expected := `{"type":"cosmos-sdk/MsgTransfer","value":{"amount":[{"amount":"100","denom":"atom"}],"destination_height":"10","receiver":"cosmos1w3jhxarpv3j8yvs7f9y7g","sender":"cosmos1w3jhxarpv3j8yvg4ufs4x","source_channel":"testchannel","source_port":"testportid"}}` expected := `{"type":"cosmos-sdk/MsgTransfer","value":{"amount":[{"amount":"100","denom":"atom"}],"receiver":"cosmos1w3jhxarpv3j8yvs7f9y7g","sender":"cosmos1w3jhxarpv3j8yvg4ufs4x","source_channel":"testchannel","source_port":"testportid","timeout_height":"110","timeout_timestamp":"10"}}`
require.Equal(t, expected, string(res)) require.Equal(t, expected, string(res))
} }
// TestMsgTransferGetSigners tests GetSigners for MsgTransfer // TestMsgTransferGetSigners tests GetSigners for MsgTransfer
func TestMsgTransferGetSigners(t *testing.T) { func TestMsgTransferGetSigners(t *testing.T) {
msg := NewMsgTransfer(validPort, validChannel, 10, coins, addr1, addr2) msg := NewMsgTransfer(validPort, validChannel, coins, addr1, addr2, 10, 0)
res := msg.GetSigners() res := msg.GetSigners()
expected := "[746573746164647231]" expected := "[746573746164647231]"

View File

@ -1,10 +1,30 @@
package types package types
import ( import (
"strings"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
) )
const (
// DefaultRelativePacketTimeoutHeight is the default packet timeout height (in blocks) relative
// to the current block height. The timeout is disabled when set to 0.
DefaultRelativePacketTimeoutHeight = 1000
// DefaultRelativePacketTimeoutTimestamp is the default packet timeout timestamp (in nanoseconds)
// relative to the current block timestamp. The timeout is disabled when set to 0.
DefaultRelativePacketTimeoutTimestamp = 0
// DefaultAbsolutePacketTimeoutHeight is the default packet timeout in blocks.
// The timeout is disabled when set to 0.
DefaultAbsolutePacketTimeoutHeight = 0
// DefaultAbsolutePacketTimeoutTimestamp is the default packet timeout timestamp (in nanoseconds)
// relative to the current block timestamp. The timeout is disabled when set to 0.
DefaultAbsolutePacketTimeoutTimestamp = 0
)
// NewFungibleTokenPacketData contructs a new FungibleTokenPacketData instance // NewFungibleTokenPacketData contructs a new FungibleTokenPacketData instance
func NewFungibleTokenPacketData( func NewFungibleTokenPacketData(
amount sdk.Coins, sender, receiver string) FungibleTokenPacketData { amount sdk.Coins, sender, receiver string) FungibleTokenPacketData {
@ -18,16 +38,16 @@ func NewFungibleTokenPacketData(
// ValidateBasic is used for validating the token transfer // ValidateBasic is used for validating the token transfer
func (ftpd FungibleTokenPacketData) ValidateBasic() error { func (ftpd FungibleTokenPacketData) ValidateBasic() error {
if !ftpd.Amount.IsAllPositive() { if !ftpd.Amount.IsAllPositive() {
return sdkerrors.ErrInsufficientFunds return sdkerrors.Wrap(sdkerrors.ErrInsufficientFunds, ftpd.Amount.String())
} }
if !ftpd.Amount.IsValid() { if !ftpd.Amount.IsValid() {
return sdkerrors.ErrInvalidCoins return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, ftpd.Amount.String())
} }
if ftpd.Sender == "" { if strings.TrimSpace(ftpd.Sender) == "" {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing sender address") return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be blank")
} }
if ftpd.Receiver == "" { if strings.TrimSpace(ftpd.Receiver) == "" {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing receiver address") return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "receiver address cannot be blank")
} }
return nil return nil
} }

View File

@ -32,14 +32,18 @@ type MsgTransfer struct {
SourcePort string `protobuf:"bytes,1,opt,name=source_port,json=sourcePort,proto3" json:"source_port,omitempty" yaml:"source_port"` SourcePort string `protobuf:"bytes,1,opt,name=source_port,json=sourcePort,proto3" json:"source_port,omitempty" yaml:"source_port"`
// the channel by which the packet will be sent // the channel by which the packet will be sent
SourceChannel string `protobuf:"bytes,2,opt,name=source_channel,json=sourceChannel,proto3" json:"source_channel,omitempty" yaml:"source_channel"` SourceChannel string `protobuf:"bytes,2,opt,name=source_channel,json=sourceChannel,proto3" json:"source_channel,omitempty" yaml:"source_channel"`
// the current height of the destination chain
DestinationHeight uint64 `protobuf:"varint,3,opt,name=destination_height,json=destinationHeight,proto3" json:"destination_height,omitempty" yaml:"destination_height"`
// the tokens to be transferred // the tokens to be transferred
Amount github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,4,rep,name=amount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount"` Amount github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,3,rep,name=amount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount"`
// the sender address // the sender address
Sender github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,5,opt,name=sender,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"sender,omitempty"` Sender github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,4,opt,name=sender,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"sender,omitempty"`
// the recipient address on the destination chain // the recipient address on the destination chain
Receiver string `protobuf:"bytes,6,opt,name=receiver,proto3" json:"receiver,omitempty"` Receiver string `protobuf:"bytes,5,opt,name=receiver,proto3" json:"receiver,omitempty"`
// Timeout height relative to the current block height.
// The timeout is disabled when set to 0.
TimeoutHeight uint64 `protobuf:"varint,6,opt,name=timeout_height,json=timeoutHeight,proto3" json:"timeout_height,omitempty" yaml:"timeout_height"`
// Timeout timestamp (in nanoseconds) relative to the current block timestamp.
// The timeout is disabled when set to 0.
TimeoutTimestamp uint64 `protobuf:"varint,7,opt,name=timeout_timestamp,json=timeoutTimestamp,proto3" json:"timeout_timestamp,omitempty" yaml:"timeout_timestamp"`
} }
func (m *MsgTransfer) Reset() { *m = MsgTransfer{} } func (m *MsgTransfer) Reset() { *m = MsgTransfer{} }
@ -89,13 +93,6 @@ func (m *MsgTransfer) GetSourceChannel() string {
return "" return ""
} }
func (m *MsgTransfer) GetDestinationHeight() uint64 {
if m != nil {
return m.DestinationHeight
}
return 0
}
func (m *MsgTransfer) GetAmount() github_com_cosmos_cosmos_sdk_types.Coins { func (m *MsgTransfer) GetAmount() github_com_cosmos_cosmos_sdk_types.Coins {
if m != nil { if m != nil {
return m.Amount return m.Amount
@ -117,6 +114,20 @@ func (m *MsgTransfer) GetReceiver() string {
return "" return ""
} }
func (m *MsgTransfer) GetTimeoutHeight() uint64 {
if m != nil {
return m.TimeoutHeight
}
return 0
}
func (m *MsgTransfer) GetTimeoutTimestamp() uint64 {
if m != nil {
return m.TimeoutTimestamp
}
return 0
}
// FungibleTokenPacketData defines a struct for the packet payload // FungibleTokenPacketData defines a struct for the packet payload
// See FungibleTokenPacketData spec: https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures // See FungibleTokenPacketData spec: https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures
type FungibleTokenPacketData struct { type FungibleTokenPacketData struct {
@ -246,37 +257,39 @@ func init() {
func init() { proto.RegisterFile("x/ibc-transfer/types/types.proto", fileDescriptor_36db19b72d57f809) } func init() { proto.RegisterFile("x/ibc-transfer/types/types.proto", fileDescriptor_36db19b72d57f809) }
var fileDescriptor_36db19b72d57f809 = []byte{ var fileDescriptor_36db19b72d57f809 = []byte{
// 480 bytes of a gzipped FileDescriptorProto // 498 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x53, 0xc1, 0x6e, 0xd3, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x53, 0x41, 0x8b, 0xd3, 0x40,
0x10, 0x8d, 0x49, 0x1b, 0xca, 0x06, 0x90, 0xba, 0x40, 0x71, 0x23, 0x61, 0x47, 0x3e, 0x20, 0x5f, 0x14, 0x6e, 0xec, 0x6e, 0x77, 0x9d, 0xba, 0xe2, 0x8e, 0xba, 0x8e, 0x45, 0x92, 0x92, 0x83, 0xe4,
0x62, 0x13, 0x38, 0x20, 0x71, 0x22, 0x2e, 0x42, 0x20, 0x40, 0xaa, 0xac, 0x9c, 0x90, 0x50, 0xb4, 0xd2, 0xc4, 0xea, 0x41, 0xf0, 0x64, 0xbb, 0x22, 0x2e, 0x22, 0x2c, 0xa1, 0x27, 0x41, 0x4a, 0x3a,
0x59, 0x0f, 0xf6, 0xca, 0xf1, 0x6e, 0xb4, 0xbb, 0x0e, 0xcd, 0x5f, 0xf0, 0x01, 0x7c, 0x01, 0xe2, 0x79, 0x26, 0x21, 0xcd, 0x4c, 0x98, 0x99, 0xd4, 0xed, 0xbf, 0xf0, 0x77, 0x88, 0x3f, 0x64, 0x8f,
0x43, 0x7a, 0xec, 0x91, 0x93, 0x41, 0xc9, 0x1f, 0xe4, 0xc8, 0x09, 0xd5, 0x76, 0x4a, 0xa0, 0x11, 0x7b, 0x14, 0x84, 0x28, 0xed, 0x3f, 0xe8, 0xd1, 0x93, 0x34, 0x49, 0x6b, 0x8b, 0x45, 0xbc, 0xec,
0xe2, 0xc2, 0xc5, 0xf6, 0x9b, 0x79, 0xf3, 0x3c, 0x6f, 0x76, 0x16, 0x75, 0x4f, 0x7c, 0x36, 0xa6, 0x25, 0x93, 0xef, 0xbd, 0xef, 0x7d, 0xc9, 0xf7, 0x31, 0x0f, 0xb5, 0x2f, 0x9c, 0x68, 0x44, 0x3b,
0x3d, 0x2d, 0x09, 0x57, 0xef, 0x41, 0xfa, 0x7a, 0x3e, 0x05, 0x55, 0x3d, 0xbd, 0xa9, 0x14, 0x5a, 0x4a, 0x78, 0x4c, 0x7e, 0x04, 0xe1, 0xa8, 0x69, 0x0a, 0xb2, 0x7c, 0xda, 0xa9, 0xe0, 0x8a, 0x63,
0x60, 0x93, 0x0a, 0x95, 0x09, 0x35, 0x52, 0x51, 0xea, 0x9d, 0x78, 0x6b, 0xa2, 0x37, 0xeb, 0x77, 0x42, 0xb9, 0x4c, 0xb8, 0x1c, 0x4a, 0x3f, 0xb6, 0x2f, 0xec, 0x15, 0xd1, 0x9e, 0x74, 0x5b, 0x8f,
0xee, 0xeb, 0x84, 0xc9, 0x68, 0x34, 0x25, 0x52, 0xcf, 0xfd, 0x92, 0xec, 0xc7, 0x22, 0x16, 0xbf, 0x55, 0x18, 0x09, 0x7f, 0x98, 0x7a, 0x42, 0x4d, 0x9d, 0x82, 0xec, 0x04, 0x3c, 0xe0, 0x7f, 0xde,
0xbe, 0x2a, 0x85, 0xce, 0xfe, 0x25, 0x51, 0xe7, 0x53, 0x13, 0xb5, 0xdf, 0xa8, 0x78, 0x58, 0xab, 0x4a, 0x85, 0xd6, 0xf1, 0x5f, 0xa2, 0xe6, 0xf7, 0x3a, 0x6a, 0xbe, 0x93, 0xc1, 0xa0, 0x52, 0xc3,
0xe1, 0xc7, 0xa8, 0xad, 0x44, 0x2e, 0x29, 0x8c, 0xa6, 0x42, 0x6a, 0xd3, 0xe8, 0x1a, 0xee, 0xb5, 0xcf, 0x51, 0x53, 0xf2, 0x4c, 0x50, 0x18, 0xa6, 0x5c, 0x28, 0xa2, 0xb5, 0x35, 0xeb, 0x66, 0xff,
0xe0, 0x60, 0x55, 0xd8, 0x78, 0x4e, 0xb2, 0xc9, 0x13, 0x67, 0x23, 0xe9, 0x84, 0xa8, 0x42, 0xc7, 0x64, 0x91, 0x1b, 0x78, 0xea, 0x25, 0xe3, 0x17, 0xe6, 0x46, 0xd3, 0x74, 0x51, 0x89, 0xce, 0xb9,
0x42, 0x6a, 0xfc, 0x14, 0xdd, 0xac, 0x73, 0x34, 0x21, 0x9c, 0xc3, 0xc4, 0xbc, 0x52, 0xd6, 0x1e, 0x50, 0xf8, 0x25, 0xba, 0x5d, 0xf5, 0x68, 0xe8, 0x31, 0x06, 0x63, 0x72, 0xa3, 0x98, 0x7d, 0xb8,
0xae, 0x0a, 0xfb, 0xce, 0x6f, 0xb5, 0x75, 0xde, 0x09, 0x6f, 0x54, 0x81, 0xa3, 0x0a, 0xe3, 0xd7, 0xc8, 0x8d, 0xfb, 0x5b, 0xb3, 0x55, 0xdf, 0x74, 0x8f, 0xca, 0xc2, 0x69, 0x89, 0xf1, 0x07, 0xd4,
0x08, 0x47, 0xa0, 0x34, 0xe3, 0x44, 0x33, 0xc1, 0x47, 0x09, 0xb0, 0x38, 0xd1, 0x66, 0xb3, 0x6b, 0xf0, 0x12, 0x9e, 0x31, 0x45, 0xea, 0xed, 0xba, 0xd5, 0x7c, 0x7a, 0xd7, 0xde, 0x30, 0x3c, 0xe9,
0xb8, 0x3b, 0xc1, 0xbd, 0x55, 0x61, 0x1f, 0x56, 0x2a, 0x97, 0x39, 0x4e, 0xb8, 0xbf, 0x11, 0x7c, 0xda, 0xa7, 0x3c, 0x62, 0xfd, 0x27, 0x97, 0xb9, 0x51, 0xfb, 0xf2, 0xc3, 0xb0, 0x82, 0x48, 0x85,
0x51, 0xc6, 0xf0, 0x3b, 0xd4, 0x22, 0x99, 0xc8, 0xb9, 0x36, 0x77, 0xba, 0x4d, 0xb7, 0xfd, 0xf0, 0xd9, 0xc8, 0xa6, 0x3c, 0x71, 0x4a, 0x5a, 0x75, 0x74, 0xa4, 0x1f, 0x57, 0x0e, 0x97, 0x03, 0xd2,
0x96, 0xb7, 0x31, 0xbe, 0x59, 0xdf, 0x3b, 0x12, 0x8c, 0x07, 0x0f, 0x4e, 0x0b, 0xbb, 0xf1, 0xf9, 0xad, 0x44, 0xf1, 0x19, 0x6a, 0x48, 0x60, 0x3e, 0x08, 0xb2, 0xd7, 0xd6, 0xac, 0x5b, 0xfd, 0xee,
0x9b, 0xed, 0xc6, 0x4c, 0x27, 0xf9, 0xd8, 0xa3, 0x22, 0xf3, 0x2b, 0x5a, 0xfd, 0xea, 0xa9, 0x28, 0xaf, 0xdc, 0xe8, 0xfc, 0x87, 0x4a, 0x8f, 0xd2, 0x9e, 0xef, 0x0b, 0x90, 0xd2, 0xad, 0x04, 0x70,
0xad, 0xe7, 0x75, 0x5e, 0xa0, 0xc2, 0x5a, 0x14, 0xbf, 0x44, 0x2d, 0x05, 0x3c, 0x02, 0x69, 0xee, 0x0b, 0x1d, 0x0a, 0xa0, 0x10, 0x4d, 0x40, 0x90, 0xfd, 0xa5, 0x4b, 0x77, 0x8d, 0x97, 0x39, 0xa8,
0x76, 0x0d, 0xf7, 0x7a, 0xd0, 0xff, 0x51, 0xd8, 0xbd, 0x7f, 0x50, 0x19, 0x50, 0x3a, 0x88, 0x22, 0x28, 0x01, 0x9e, 0xa9, 0x61, 0x08, 0x51, 0x10, 0x2a, 0xd2, 0x68, 0x6b, 0xd6, 0xde, 0x66, 0x0e,
0x09, 0x4a, 0x85, 0xb5, 0x00, 0xee, 0xa0, 0x3d, 0x09, 0x14, 0xd8, 0x0c, 0xa4, 0xd9, 0x3a, 0x9f, 0xdb, 0x7d, 0xd3, 0x3d, 0xaa, 0x0a, 0x6f, 0x0a, 0x8c, 0xcf, 0xd0, 0xf1, 0x8a, 0xb1, 0x3c, 0xa5,
0x59, 0x78, 0x81, 0x9d, 0x2f, 0x06, 0xba, 0xfb, 0x3c, 0xe7, 0x31, 0x1b, 0x4f, 0x60, 0x28, 0x52, 0xf2, 0x92, 0x94, 0x1c, 0x14, 0x22, 0x8f, 0x16, 0xb9, 0x41, 0xb6, 0x45, 0xd6, 0x14, 0xd3, 0xbd,
0xe0, 0xc7, 0x84, 0xa6, 0xa0, 0x9f, 0x11, 0x4d, 0x36, 0x1c, 0x1a, 0xff, 0xc3, 0xe1, 0xc1, 0x85, 0x53, 0xd5, 0x06, 0xeb, 0xd2, 0x57, 0x0d, 0x3d, 0x78, 0x9d, 0xb1, 0x20, 0x1a, 0x8d, 0x61, 0xc0,
0xc3, 0xf2, 0x20, 0xb7, 0xb6, 0xdb, 0xfc, 0xa3, 0xdd, 0x21, 0x72, 0xb6, 0x74, 0x3b, 0xa0, 0x29, 0x63, 0x60, 0xe7, 0x1e, 0x8d, 0x41, 0xbd, 0xf2, 0x94, 0xb7, 0x11, 0xb7, 0x76, 0x1d, 0x71, 0x9f,
0x17, 0x1f, 0x26, 0x10, 0xc5, 0x90, 0x01, 0xd7, 0xd8, 0x44, 0x57, 0x55, 0x4e, 0x29, 0x28, 0x55, 0xac, 0xe3, 0x2e, 0xee, 0xc1, 0xce, 0xec, 0xea, 0xdb, 0xd9, 0x99, 0x03, 0x64, 0xee, 0xf8, 0xdb,
0xee, 0xd7, 0x5e, 0xb8, 0x86, 0xf8, 0x36, 0xda, 0x05, 0x29, 0xc5, 0xfa, 0x97, 0x15, 0x08, 0x5e, 0x1e, 0x8d, 0x19, 0xff, 0x34, 0x06, 0x3f, 0x80, 0x04, 0x98, 0xc2, 0x04, 0x1d, 0xc8, 0x8c, 0x52,
0x9d, 0x2e, 0x2c, 0xe3, 0x6c, 0x61, 0x19, 0xdf, 0x17, 0x96, 0xf1, 0x71, 0x69, 0x35, 0xce, 0x96, 0x90, 0xb2, 0xb8, 0x9e, 0x87, 0xee, 0x0a, 0xe2, 0x7b, 0x68, 0x1f, 0x84, 0xe0, 0xab, 0x4f, 0x96,
0x56, 0xe3, 0xeb, 0xd2, 0x6a, 0xbc, 0xed, 0xff, 0xd5, 0xd5, 0xb6, 0x1b, 0x35, 0x6e, 0x95, 0x7b, 0xa0, 0xff, 0xf6, 0x72, 0xa6, 0x6b, 0x57, 0x33, 0x5d, 0xfb, 0x39, 0xd3, 0xb5, 0xcf, 0x73, 0xbd,
0xff, 0xe8, 0x67, 0x00, 0x00, 0x00, 0xff, 0xff, 0x39, 0x62, 0x70, 0xeb, 0x70, 0x03, 0x00, 0x00, 0x76, 0x35, 0xd7, 0x6b, 0xdf, 0xe6, 0x7a, 0xed, 0x7d, 0xf7, 0x9f, 0xae, 0x76, 0x2d, 0xe4, 0xa8,
0x51, 0xac, 0xcd, 0xb3, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x83, 0xf7, 0x16, 0x2f, 0xaf, 0x03,
0x00, 0x00,
} }
func (m *MsgTransfer) Marshal() (dAtA []byte, err error) { func (m *MsgTransfer) Marshal() (dAtA []byte, err error) {
@ -299,19 +312,29 @@ func (m *MsgTransfer) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if m.TimeoutTimestamp != 0 {
i = encodeVarintTypes(dAtA, i, uint64(m.TimeoutTimestamp))
i--
dAtA[i] = 0x38
}
if m.TimeoutHeight != 0 {
i = encodeVarintTypes(dAtA, i, uint64(m.TimeoutHeight))
i--
dAtA[i] = 0x30
}
if len(m.Receiver) > 0 { if len(m.Receiver) > 0 {
i -= len(m.Receiver) i -= len(m.Receiver)
copy(dAtA[i:], m.Receiver) copy(dAtA[i:], m.Receiver)
i = encodeVarintTypes(dAtA, i, uint64(len(m.Receiver))) i = encodeVarintTypes(dAtA, i, uint64(len(m.Receiver)))
i-- i--
dAtA[i] = 0x32 dAtA[i] = 0x2a
} }
if len(m.Sender) > 0 { if len(m.Sender) > 0 {
i -= len(m.Sender) i -= len(m.Sender)
copy(dAtA[i:], m.Sender) copy(dAtA[i:], m.Sender)
i = encodeVarintTypes(dAtA, i, uint64(len(m.Sender))) i = encodeVarintTypes(dAtA, i, uint64(len(m.Sender)))
i-- i--
dAtA[i] = 0x2a dAtA[i] = 0x22
} }
if len(m.Amount) > 0 { if len(m.Amount) > 0 {
for iNdEx := len(m.Amount) - 1; iNdEx >= 0; iNdEx-- { for iNdEx := len(m.Amount) - 1; iNdEx >= 0; iNdEx-- {
@ -324,14 +347,9 @@ func (m *MsgTransfer) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i = encodeVarintTypes(dAtA, i, uint64(size)) i = encodeVarintTypes(dAtA, i, uint64(size))
} }
i-- i--
dAtA[i] = 0x22 dAtA[i] = 0x1a
} }
} }
if m.DestinationHeight != 0 {
i = encodeVarintTypes(dAtA, i, uint64(m.DestinationHeight))
i--
dAtA[i] = 0x18
}
if len(m.SourceChannel) > 0 { if len(m.SourceChannel) > 0 {
i -= len(m.SourceChannel) i -= len(m.SourceChannel)
copy(dAtA[i:], m.SourceChannel) copy(dAtA[i:], m.SourceChannel)
@ -465,9 +483,6 @@ func (m *MsgTransfer) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovTypes(uint64(l)) n += 1 + l + sovTypes(uint64(l))
} }
if m.DestinationHeight != 0 {
n += 1 + sovTypes(uint64(m.DestinationHeight))
}
if len(m.Amount) > 0 { if len(m.Amount) > 0 {
for _, e := range m.Amount { for _, e := range m.Amount {
l = e.Size() l = e.Size()
@ -482,6 +497,12 @@ func (m *MsgTransfer) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovTypes(uint64(l)) n += 1 + l + sovTypes(uint64(l))
} }
if m.TimeoutHeight != 0 {
n += 1 + sovTypes(uint64(m.TimeoutHeight))
}
if m.TimeoutTimestamp != 0 {
n += 1 + sovTypes(uint64(m.TimeoutTimestamp))
}
return n return n
} }
@ -624,25 +645,6 @@ func (m *MsgTransfer) Unmarshal(dAtA []byte) error {
m.SourceChannel = string(dAtA[iNdEx:postIndex]) m.SourceChannel = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
case 3: case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field DestinationHeight", wireType)
}
m.DestinationHeight = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTypes
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.DestinationHeight |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 4:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType)
} }
@ -676,7 +678,7 @@ func (m *MsgTransfer) Unmarshal(dAtA []byte) error {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
case 5: case 4:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType)
} }
@ -710,7 +712,7 @@ func (m *MsgTransfer) Unmarshal(dAtA []byte) error {
m.Sender = []byte{} m.Sender = []byte{}
} }
iNdEx = postIndex iNdEx = postIndex
case 6: case 5:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Receiver", wireType) return fmt.Errorf("proto: wrong wireType = %d for field Receiver", wireType)
} }
@ -742,6 +744,44 @@ func (m *MsgTransfer) Unmarshal(dAtA []byte) error {
} }
m.Receiver = string(dAtA[iNdEx:postIndex]) m.Receiver = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
case 6:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field TimeoutHeight", wireType)
}
m.TimeoutHeight = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTypes
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.TimeoutHeight |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 7:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field TimeoutTimestamp", wireType)
}
m.TimeoutTimestamp = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTypes
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.TimeoutTimestamp |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipTypes(dAtA[iNdEx:]) skippy, err := skipTypes(dAtA[iNdEx:])

View File

@ -17,21 +17,23 @@ message MsgTransfer {
string source_channel = 2 [ string source_channel = 2 [
(gogoproto.moretags) = "yaml:\"source_channel\"" (gogoproto.moretags) = "yaml:\"source_channel\""
]; ];
// the current height of the destination chain
uint64 destination_height = 3 [
(gogoproto.moretags) = "yaml:\"destination_height\""
];
// the tokens to be transferred // the tokens to be transferred
repeated cosmos_sdk.v1.Coin amount = 4 [ repeated cosmos_sdk.v1.Coin amount = 3 [
(gogoproto.nullable) = false, (gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins" (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
]; ];
// the sender address // the sender address
bytes sender = 5 [ bytes sender = 4 [
(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"
]; ];
// the recipient address on the destination chain // the recipient address on the destination chain
string receiver = 6; string receiver = 5;
// Timeout height relative to the current block height.
// The timeout is disabled when set to 0.
uint64 timeout_height = 6 [(gogoproto.moretags) = "yaml:\"timeout_height\""];
// Timeout timestamp (in nanoseconds) relative to the current block timestamp.
// The timeout is disabled when set to 0.
uint64 timeout_timestamp = 7 [(gogoproto.moretags) = "yaml:\"timeout_timestamp\""];
} }
// FungibleTokenPacketData defines a struct for the packet payload // FungibleTokenPacketData defines a struct for the packet payload

View File

@ -33,13 +33,11 @@ const flagTrustLevel = "trust-level"
// in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#create // in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#create
func GetCmdCreateClient(cdc *codec.Codec) *cobra.Command { func GetCmdCreateClient(cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "create [client-id] [path/to/consensus_state.json] [trusting_period] [unbonding_period] [max_clock_drift]", Use: "create [client-id] [path/to/consensus_state.json] [trusting_period] [unbonding_period] [max_clock_drift]",
Short: "create new tendermint client", Short: "create new tendermint client",
Long: "create new tendermint client. Trust level can be a fraction (eg: '1/3') or 'default'", Long: "create new tendermint client. Trust level can be a fraction (eg: '1/3') or 'default'",
Example: fmt.Sprintf( Example: fmt.Sprintf("%s tx ibc %s create [client-id] [path/to/consensus_state.json] [trusting_period] [unbonding_period] [max_clock_drift] --trust-level default --from node0 --home ../node0/<app>cli --chain-id $CID", version.ClientName, ibctmtypes.SubModuleName),
"%s tx ibc %s create [client-id] [path/to/consensus_state.json] [trusting_period] [unbonding_period] [max_clock_drift] --trust-level default --from node0 --home ../node0/<app>cli --chain-id $CID", Args: cobra.ExactArgs(5),
version.ClientName, ibctmtypes.SubModuleName),
Args: cobra.ExactArgs(5),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
inBuf := bufio.NewReader(cmd.InOrStdin()) inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := authtypes.NewTxBuilderFromCLI(inBuf).WithTxEncoder(authclient.GetTxEncoder(cdc)) txBldr := authtypes.NewTxBuilderFromCLI(inBuf).WithTxEncoder(authclient.GetTxEncoder(cdc))

View File

@ -40,11 +40,11 @@ in the SDK's `x/ibc` module:
* [ICS 003 - Connection Semantics](https://github.com/cosmos/ics/blob/master/spec/ics-003-connection-semantics): Implemented in [`x/ibc/03-connection`](https://github.com/cosmos/x/ibc/03-connection) * [ICS 003 - Connection Semantics](https://github.com/cosmos/ics/blob/master/spec/ics-003-connection-semantics): Implemented in [`x/ibc/03-connection`](https://github.com/cosmos/x/ibc/03-connection)
* [ICS 004 - Channel and Packet Semantics](https://github.com/cosmos/ics/blob/master/spec/ics-004-channel-and-packet-semantics): Implemented in [`x/ibc/04-channel`](https://github.com/cosmos/x/ibc/04-channel) * [ICS 004 - Channel and Packet Semantics](https://github.com/cosmos/ics/blob/master/spec/ics-004-channel-and-packet-semantics): Implemented in [`x/ibc/04-channel`](https://github.com/cosmos/x/ibc/04-channel)
* [ICS 005 - Port Allocation](https://github.com/cosmos/ics/blob/master/spec/ics-005-port-allocation): Implemented in [`x/ibc/05-port`](https://github.com/cosmos/x/ibc/05-port) * [ICS 005 - Port Allocation](https://github.com/cosmos/ics/blob/master/spec/ics-005-port-allocation): Implemented in [`x/ibc/05-port`](https://github.com/cosmos/x/ibc/05-port)
* [ICS 006 - Solo Machine Client](https://github.com/cosmos/ics/blob/master/spec/ics-006-solo-machine-client): To be implemented in [`x/ibc/06-solo`](https://github.com/cosmos/x/ibc/06-solo) * [ICS 006 - Solo Machine Client](https://github.com/cosmos/ics/blob/master/spec/ics-006-solo-machine-client): Implemented in [`x/ibc/06-solomachine`](https://github.com/cosmos/x/ibc/06-solomachine)
* [ICS 007 - Tendermint Client](https://github.com/cosmos/ics/blob/master/spec/ics-007-tendermint-client): Implemented in [`x/ibc/07-tendermint`](https://github.com/cosmos/x/ibc/07-tendermint) * [ICS 007 - Tendermint Client](https://github.com/cosmos/ics/blob/master/spec/ics-007-tendermint-client): Implemented in [`x/ibc/07-tendermint`](https://github.com/cosmos/x/ibc/07-tendermint)
* [ICS 009 - Loopback Client](https://github.com/cosmos/ics/blob/master/spec/ics-009-loopback-client): To be implemented in [`x/ibc/09-loopback`](https://github.com/cosmos/x/ibc/09-loopback) * [ICS 009 - Loopback Client](https://github.com/cosmos/ics/blob/master/spec/ics-009-loopback-client): Implemented in [`x/ibc/09-localhost`](https://github.com/cosmos/x/ibc/09-localhost)
* [ICS 018- Relayer Algorithms](https://github.com/cosmos/ics/tree/master/spec/ics-018-relayer-algorithms): Implemented in it's own [relayer repository](https://github.com/cosmos/relayer) * [ICS 018- Relayer Algorithms](https://github.com/cosmos/ics/tree/master/spec/ics-018-relayer-algorithms): Implemented in it's own [relayer repository](https://github.com/cosmos/relayer)
* [ICS 020 - Fungible Token Transfer](https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer): Implemented in [`x/transfer`](https://github.com/cosmos/x/transfer) * [ICS 020 - Fungible Token Transfer](https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer): Implemented in [`x/ibc-transfer`](https://github.com/cosmos/x/ibc-transfer)
* [ICS 023 - Vector Commitments](https://github.com/cosmos/ics/tree/master/spec/ics-023-vector-commitments): Implemented in [`x/ibc/23-commitment`](https://github.com/cosmos/x/ibc/23-commitment) * [ICS 023 - Vector Commitments](https://github.com/cosmos/ics/tree/master/spec/ics-023-vector-commitments): Implemented in [`x/ibc/23-commitment`](https://github.com/cosmos/x/ibc/23-commitment)
* [ICS 024 - Host Requirements](https://github.com/cosmos/ics/tree/master/spec/ics-024-host-requirements): Implemented in [`x/ibc/24-host`](https://github.com/cosmos/x/ibc/24-host) * [ICS 024 - Host Requirements](https://github.com/cosmos/ics/tree/master/spec/ics-024-host-requirements): Implemented in [`x/ibc/24-host`](https://github.com/cosmos/x/ibc/24-host)
* [ICS 025 - Handler Interface](https://github.com/cosmos/ics/tree/master/spec/ics-025-handler-interface): Handler interfaces are implemented at the top level in `x/ibc/handler.go`, * [ICS 025 - Handler Interface](https://github.com/cosmos/ics/tree/master/spec/ics-025-handler-interface): Handler interfaces are implemented at the top level in `x/ibc/handler.go`,
@ -75,35 +75,37 @@ the SDK modules, please check this [document](../../../docs/building-modules/str
prerequisite reading. prerequisite reading.
For ease of auditing, every Interchain Standard has been developed in its own For ease of auditing, every Interchain Standard has been developed in its own
package. The following tree describes the architecture of the directories within package. The development team separated the IBC TAO (Transport, Authentication, Ordering) ICS specifications from the IBC application level
the IBC module: specification. The following tree describes the architecture of the directories that
the `ibc` (TAO) and `ibc-transfer` ([ICS20](https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer)) modules:
```shell ```shell
x/ibc x/
├── 02-client/ ├── ibc/
├── 03-connection/ │ ├── 02-client/
├── 04-channel/ │ ├── 03-connection/
├── 05-port/ │ ├── 04-channel/
├── 06-solo/ │ ├── 05-port/
├── 07-tendermint/ │ ├── 06-solo/
├── 09-loopback/ │ ├── 07-tendermint/
├── 20-transfer/ │ ├── 09-localhost/
├── 23-commitment/ │ ├── 23-commitment/
├── 24-host/ │ ├── 24-host/
├── ante │ ├── ante
│   └── ante.go │ │ └── ante.go
├── client │ ├── client
│   ├── cli │  │ ├── cli
│   │   └── cli.go │  │ │   └── cli.go
│   └── rest │  │ └── rest
│   └── rest.go │  │ └── rest.go
├── keeper │ ├── keeper
│   ├── keeper.go │  │ ├── keeper.go
│   └── querier.go │  │ └── querier.go
├── types │ ├── types
│   ├── errors.go │ │   ├── errors.go
│   └── keys.go │ │   └── keys.go
├── alias.go │ ├── alias.go
├── handler.go │ ├── handler.go
└── module.go │ └── module.go
└── ibc-transfer/
``` ```