Skip to content

Commit

Permalink
merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
colin-axner committed Jan 14, 2022
2 parents b9bdd13 + e2693b0 commit 8529bfb
Show file tree
Hide file tree
Showing 15 changed files with 2,303 additions and 1,291 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2021 COSMOS
Copyright (c) 2022 COSMOS

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
5 changes: 5 additions & 0 deletions docs/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ module.exports = {
directory: false,
path: "/app_modules/interchain-accounts/integration.html"
},
{
title: "Authentication module development",
directory: false,
path: "/app_modules/interchain-accounts/ica_auth.html"
},
]
},
]
Expand Down
7 changes: 6 additions & 1 deletion docs/app_modules/interchain-accounts/ica_auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,12 @@ packetData := icatypes.InterchainAccountPacketData{
Data: data,
}

_, err = keeper.icaControllerKeeper.TrySendTx(ctx, chanCap, p, packetData)
// Obtain timeout timestamp
// An appropriate timeout timestamp must be determined based on the usage of the interchain account.
// If the packet times out, the channel will be closed requiring a new channel to be created
timeoutTimestamp := obtainTimeoutTimestamp()

_, err = keeper.icaControllerKeeper.TrySendTx(ctx, chanCap, p, packetData, timeoutTimestamp)
```

The data within an `InterchainAccountPacketData` must be serialized using a format supported by the host chain.
Expand Down
2 changes: 1 addition & 1 deletion docs/ibc/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -903,7 +903,7 @@ https://github.com/cosmos/ibc/tree/master/spec/app/ics-020-fungible-token-transf
| `sender` | [string](#string) | | the sender address |
| `receiver` | [string](#string) | | the recipient address on the destination chain |
| `timeout_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Timeout height relative to the current block height. The timeout is disabled when set to 0. |
| `timeout_timestamp` | [uint64](#uint64) | | Timeout timestamp (in nanoseconds) relative to the current block timestamp. The timeout is disabled when set to 0. |
| `timeout_timestamp` | [uint64](#uint64) | | Timeout timestamp in absolute nanoseconds since unix epoch. The timeout is disabled when set to 0. |



Expand Down
3,456 changes: 2,189 additions & 1,267 deletions docs/package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"author": "",
"license": "ISC",
"dependencies": {
"markdown-it": ">=12.3.2",
"glob-parent": "^5.1.2",
"vue": "^2.6.14",
"vuepress-theme-cosmos": "^1.0.182"
Expand Down
20 changes: 12 additions & 8 deletions modules/apps/27-interchain-accounts/controller/keeper/relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ import (
channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types"
)

// TrySendTx takes in a transaction from an authentication module and attempts to send the packet
// if the base application has the capability to send on the provided portID
func (k Keeper) TrySendTx(ctx sdk.Context, chanCap *capabilitytypes.Capability, portID string, icaPacketData icatypes.InterchainAccountPacketData) (uint64, error) {
// TrySendTx takes pre-built packet data containing messages to be executed on the host chain from an authentication module and attempts to send the packet.
// The packet sequence for the outgoing packet is returned as a result.
// If the base application has the capability to send on the provided portID. An appropriate
// absolute timeoutTimestamp must be provided. If the packet is timed out, the channel will be closed.
// In the case of channel closure, a new channel may be reopened to reconnect to the host chain.
func (k Keeper) TrySendTx(ctx sdk.Context, chanCap *capabilitytypes.Capability, portID string, icaPacketData icatypes.InterchainAccountPacketData, timeoutTimestamp uint64) (uint64, error) {
// Check for the active channel
activeChannelID, found := k.GetActiveChannelID(ctx, portID)
if !found {
Expand All @@ -27,7 +30,11 @@ func (k Keeper) TrySendTx(ctx sdk.Context, chanCap *capabilitytypes.Capability,
destinationPort := sourceChannelEnd.GetCounterparty().GetPortID()
destinationChannel := sourceChannelEnd.GetCounterparty().GetChannelID()

return k.createOutgoingPacket(ctx, portID, activeChannelID, destinationPort, destinationChannel, chanCap, icaPacketData)
if uint64(ctx.BlockTime().UnixNano()) >= timeoutTimestamp {
return 0, icatypes.ErrInvalidTimeoutTimestamp
}

return k.createOutgoingPacket(ctx, portID, activeChannelID, destinationPort, destinationChannel, chanCap, icaPacketData, timeoutTimestamp)
}

func (k Keeper) createOutgoingPacket(
Expand All @@ -38,6 +45,7 @@ func (k Keeper) createOutgoingPacket(
destinationChannel string,
chanCap *capabilitytypes.Capability,
icaPacketData icatypes.InterchainAccountPacketData,
timeoutTimestamp uint64,
) (uint64, error) {
if err := icaPacketData.ValidateBasic(); err != nil {
return 0, sdkerrors.Wrap(err, "invalid interchain account packet data")
Expand All @@ -49,10 +57,6 @@ func (k Keeper) createOutgoingPacket(
return 0, sdkerrors.Wrapf(channeltypes.ErrSequenceSendNotFound, "failed to retrieve next sequence send for channel %s on port %s", sourceChannel, sourcePort)
}

// timeoutTimestamp is set to be a max number here so that we never recieve a timeout
// ics-27-1 uses ordered channels which can close upon recieving a timeout, which is an undesired effect
const timeoutTimestamp = ^uint64(0) >> 1 // Shift the unsigned bit to satisfy hermes relayer timestamp conversion

packet := channeltypes.NewPacket(
icaPacketData.GetBytes(),
sequence,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import (

func (suite *KeeperTestSuite) TestTrySendTx() {
var (
path *ibctesting.Path
packetData icatypes.InterchainAccountPacketData
chanCap *capabilitytypes.Capability
path *ibctesting.Path
packetData icatypes.InterchainAccountPacketData
chanCap *capabilitytypes.Capability
timeoutTimestamp uint64
)

testCases := []struct {
Expand Down Expand Up @@ -114,13 +115,38 @@ func (suite *KeeperTestSuite) TestTrySendTx() {
},
false,
},
{
"timeout timestamp is not in the future",
func() {
interchainAccountAddr, found := suite.chainA.GetSimApp().ICAControllerKeeper.GetInterchainAccountAddress(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID)
suite.Require().True(found)

msg := &banktypes.MsgSend{
FromAddress: interchainAccountAddr,
ToAddress: suite.chainB.SenderAccount.GetAddress().String(),
Amount: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))),
}

data, err := icatypes.SerializeCosmosTx(suite.chainB.GetSimApp().AppCodec(), []sdk.Msg{msg})
suite.Require().NoError(err)

packetData = icatypes.InterchainAccountPacketData{
Type: icatypes.EXECUTE_TX,
Data: data,
}

timeoutTimestamp = uint64(suite.chainA.GetContext().BlockTime().UnixNano())
},
false,
},
}

for _, tc := range testCases {
tc := tc

suite.Run(tc.msg, func() {
suite.SetupTest() // reset
suite.SetupTest() // reset
timeoutTimestamp = ^uint64(0) // default

path = NewICAPath(suite.chainA, suite.chainB)
suite.coordinator.SetupConnections(path)
Expand All @@ -134,7 +160,7 @@ func (suite *KeeperTestSuite) TestTrySendTx() {

tc.malleate() // malleate mutates test data

_, err = suite.chainA.GetSimApp().ICAControllerKeeper.TrySendTx(suite.chainA.GetContext(), chanCap, path.EndpointA.ChannelConfig.PortID, packetData)
_, err = suite.chainA.GetSimApp().ICAControllerKeeper.TrySendTx(suite.chainA.GetContext(), chanCap, path.EndpointA.ChannelConfig.PortID, packetData, timeoutTimestamp)

if tc.expPass {
suite.Require().NoError(err)
Expand Down
8 changes: 4 additions & 4 deletions modules/apps/27-interchain-accounts/types/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ var (
// DefaultMaxAddrLength defines the default maximum character length used in validation of addresses
var DefaultMaxAddrLength = 128

// IsValidAddr defines a regular expression to check if the provided string consists of
// strictly alphanumeric characters
var IsValidAddr = regexp.MustCompile("^[a-zA-Z0-9]*$").MatchString
// isValidAddr defines a regular expression to check if the provided string consists of
// strictly alphanumeric characters and is non empty.
var isValidAddr = regexp.MustCompile("^[a-zA-Z0-9]+$").MatchString

// InterchainAccountI wraps the authtypes.AccountI interface
type InterchainAccountI interface {
Expand All @@ -48,7 +48,7 @@ func GenerateAddress(moduleAccAddr sdk.AccAddress, portID string) sdk.AccAddress
// ValidateAccountAddress performs basic validation of interchain account addresses, enforcing constraints
// on address length and character set
func ValidateAccountAddress(addr string) error {
if !IsValidAddr(addr) || len(addr) == 0 || len(addr) > DefaultMaxAddrLength {
if !isValidAddr(addr) || len(addr) > DefaultMaxAddrLength {
return sdkerrors.Wrapf(
ErrInvalidAccountAddress,
"address must contain strictly alphanumeric characters, not exceeding %d characters in length",
Expand Down
46 changes: 46 additions & 0 deletions modules/apps/27-interchain-accounts/types/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,52 @@ func (suite *TypesTestSuite) TestGenerateAddress() {
suite.Require().NotEmpty(accAddr)
}

func (suite *TypesTestSuite) TestValidateAccountAddress() {
testCases := []struct {
name string
address string
expPass bool
}{
{
"success",
TestOwnerAddress,
true,
},
{
"success with single character",
"a",
true,
},
{
"empty string",
"",
false,
},
{
"only spaces",
" ",
false,
},
{
"address is too long",
ibctesting.LongString,
false,
},
}

for _, tc := range testCases {
suite.Run(tc.name, func() {
err := types.ValidateAccountAddress(tc.address)

if tc.expPass {
suite.Require().NoError(err, tc.name)
} else {
suite.Require().Error(err, tc.name)
}
})
}
}

func (suite *TypesTestSuite) TestInterchainAccount() {
pubkey := secp256k1.GenPrivKey().PubKey()
addr := sdk.AccAddress(pubkey.Address())
Expand Down
3 changes: 2 additions & 1 deletion modules/apps/27-interchain-accounts/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ var (
ErrUnsupported = sdkerrors.Register(ModuleName, 13, "interchain account does not support this action")
ErrInvalidControllerPort = sdkerrors.Register(ModuleName, 14, "invalid controller port")
ErrInvalidHostPort = sdkerrors.Register(ModuleName, 15, "invalid host port")
ErrInvalidCodec = sdkerrors.Register(ModuleName, 16, "codec is not supported")
ErrInvalidTimeoutTimestamp = sdkerrors.Register(ModuleName, 16, "timeout timestamp must be in the future")
ErrInvalidCodec = sdkerrors.Register(ModuleName, 17, "codec is not supported")
)
2 changes: 1 addition & 1 deletion modules/apps/transfer/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ corresponding to the counterparty channel. Any timeout set to 0 is disabled.`),
}

cmd.Flags().String(flagPacketTimeoutHeight, types.DefaultRelativePacketTimeoutHeight, "Packet timeout block height. The timeout is disabled when set to 0-0.")
cmd.Flags().Uint64(flagPacketTimeoutTimestamp, types.DefaultRelativePacketTimeoutTimestamp, "Packet timeout timestamp in nanoseconds. Default is 10 minutes. The timeout is disabled when set to 0.")
cmd.Flags().Uint64(flagPacketTimeoutTimestamp, types.DefaultRelativePacketTimeoutTimestamp, "Packet timeout timestamp in nanoseconds from now. Default is 10 minutes. The timeout is disabled when set to 0.")
cmd.Flags().Bool(flagAbsoluteTimeouts, false, "Timeout flags are used as absolute timeouts.")
flags.AddTxFlagsToCmd(cmd)

Expand Down
2 changes: 1 addition & 1 deletion modules/apps/transfer/types/tx.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion proto/ibc/applications/transfer/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ message MsgTransfer {
// The timeout is disabled when set to 0.
ibc.core.client.v1.Height timeout_height = 6
[(gogoproto.moretags) = "yaml:\"timeout_height\"", (gogoproto.nullable) = false];
// Timeout timestamp (in nanoseconds) relative to the current block timestamp.
// Timeout timestamp in absolute nanoseconds since unix epoch.
// The timeout is disabled when set to 0.
uint64 timeout_timestamp = 7 [(gogoproto.moretags) = "yaml:\"timeout_timestamp\""];
}
Expand Down
2 changes: 2 additions & 0 deletions testing/values.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ const (
// used for testing proposals
Title = "title"
Description = "description"

LongString = "LoremipsumdolorsitameconsecteturadipiscingeliseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliquUtenimadminimveniamquisnostrudexercitationullamcolaborisnisiutaliquipexeacommodoconsequDuisauteiruredolorinreprehenderitinvoluptateelitsseillumoloreufugiatnullaariaturEcepteurintoccaectupidatatonroidentuntnulpauifficiaeseruntmollitanimidestlaborum"
)

var (
Expand Down

0 comments on commit 8529bfb

Please sign in to comment.