Skip to content

Commit

Permalink
Backport 1.13: Restricted Marker Transfer IBC (#1167)
Browse files Browse the repository at this point in the history
* Restricted marker transfer over ibc (#1158)

* initial setup of the ibc transfer

* Update proto to reuse ibc transfer

* remove telemetry

* wire in ibc send

* Add tx command for ibc transfer

* add todo for tx command

* moving to ibc-testing tag.

* Fixes to cli and msg server.

* changing signer of ibc message.

* setup ibc transfer keeper before marker keeper

* refactor ibc-transfer command, setup first test for ibc-transfer cli

* add a few more cli tests

* Updating proto comments.

* Add change log entry

* add spec

* add msg test

* update ibc-go tag

Co-authored-by: arnabmitra <arnabmitra.mitra@gmail.com>

* Re-add a changelog entry that I accidentally added in a different PR then erroneously deleted in the last conflict resolution. But since it's already in release/v1.13.x, might as well leave it.

Co-authored-by: Carlton Hanna <nullpointer0x00@gmail.com>
Co-authored-by: arnabmitra <arnabmitra.mitra@gmail.com>
  • Loading branch information
3 people authored Oct 20, 2022
1 parent ac924e2 commit 9e5a70a
Show file tree
Hide file tree
Showing 20 changed files with 1,004 additions and 147 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ Ref: https://keepachangelog.com/en/1.0.0/

## Unreleased

### Features

* Add restricted marker transfer over ibc support [#1136](https://github.com/provenance-io/provenance/issues/1136)

### Improvements

* Updated name restrictions documentation [#808](https://github.com/provenance-io/provenance/issues/808)
Expand Down
26 changes: 13 additions & 13 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,12 +433,24 @@ func New(

app.GroupKeeper = groupkeeper.NewKeeper(keys[group.StoreKey], appCodec, app.BaseApp.MsgServiceRouter(), app.AccountKeeper, group.DefaultConfig())

// Create IBC Keeper
app.IBCKeeper = ibckeeper.NewKeeper(
appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper,
)

// Create Transfer Keepers
app.TransferKeeper = ibctransferkeeper.NewKeeper(
appCodec, keys[ibctransfertypes.StoreKey], app.GetSubspace(ibctransfertypes.ModuleName),
app.IBCKeeper.ChannelKeeper, app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper,
app.AccountKeeper, app.BankKeeper, scopedTransferKeeper,
)

app.MetadataKeeper = metadatakeeper.NewKeeper(
appCodec, keys[metadatatypes.StoreKey], app.GetSubspace(metadatatypes.ModuleName), app.AccountKeeper, app.AuthzKeeper,
)

app.MarkerKeeper = markerkeeper.NewKeeper(
appCodec, keys[markertypes.StoreKey], app.GetSubspace(markertypes.ModuleName), app.AccountKeeper, app.BankKeeper, app.AuthzKeeper, app.FeeGrantKeeper, keys[banktypes.StoreKey],
appCodec, keys[markertypes.StoreKey], app.GetSubspace(markertypes.ModuleName), app.AccountKeeper, app.BankKeeper, app.AuthzKeeper, app.FeeGrantKeeper, app.TransferKeeper, keys[banktypes.StoreKey],
)

app.NameKeeper = namekeeper.NewKeeper(
Expand All @@ -449,18 +461,6 @@ func New(
appCodec, keys[attributetypes.StoreKey], app.GetSubspace(attributetypes.ModuleName), app.AccountKeeper, app.NameKeeper,
)

// Create IBC Keeper
app.IBCKeeper = ibckeeper.NewKeeper(
appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper,
)

// Create Transfer Keepers
app.TransferKeeper = ibctransferkeeper.NewKeeper(
appCodec, keys[ibctransfertypes.StoreKey], app.GetSubspace(ibctransfertypes.ModuleName),
app.IBCKeeper.ChannelKeeper, app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper,
app.AccountKeeper, app.BankKeeper, scopedTransferKeeper,
)

pioMessageRouter := MessageRouterFunc(func(msg sdk.Msg) baseapp.MsgServiceHandler {
return pioMsgFeesRouter.Handler(msg)
})
Expand Down
29 changes: 29 additions & 0 deletions docs/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@
- [MsgFinalizeResponse](#provenance.marker.v1.MsgFinalizeResponse)
- [MsgGrantAllowanceRequest](#provenance.marker.v1.MsgGrantAllowanceRequest)
- [MsgGrantAllowanceResponse](#provenance.marker.v1.MsgGrantAllowanceResponse)
- [MsgIbcTransferRequest](#provenance.marker.v1.MsgIbcTransferRequest)
- [MsgIbcTransferResponse](#provenance.marker.v1.MsgIbcTransferResponse)
- [MsgMintRequest](#provenance.marker.v1.MsgMintRequest)
- [MsgMintResponse](#provenance.marker.v1.MsgMintResponse)
- [MsgSetDenomMetadataRequest](#provenance.marker.v1.MsgSetDenomMetadataRequest)
Expand Down Expand Up @@ -2117,6 +2119,32 @@ MsgGrantAllowanceResponse defines the Msg/GrantAllowanceResponse response type.



<a name="provenance.marker.v1.MsgIbcTransferRequest"></a>

### MsgIbcTransferRequest
MsgIbcTransferRequest defines the Msg/IbcTransfer request type for markers.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `transfer` | [ibc.applications.transfer.v1.MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) | | |
| `administrator` | [string](#string) | | |






<a name="provenance.marker.v1.MsgIbcTransferResponse"></a>

### MsgIbcTransferResponse
MsgIbcTransferResponse defines the Msg/IbcTransfer response type






<a name="provenance.marker.v1.MsgMintRequest"></a>

### MsgMintRequest
Expand Down Expand Up @@ -2249,6 +2277,7 @@ Msg defines the Marker Msg service.
| `Withdraw` | [MsgWithdrawRequest](#provenance.marker.v1.MsgWithdrawRequest) | [MsgWithdrawResponse](#provenance.marker.v1.MsgWithdrawResponse) | Withdraw | |
| `AddMarker` | [MsgAddMarkerRequest](#provenance.marker.v1.MsgAddMarkerRequest) | [MsgAddMarkerResponse](#provenance.marker.v1.MsgAddMarkerResponse) | AddMarker | |
| `Transfer` | [MsgTransferRequest](#provenance.marker.v1.MsgTransferRequest) | [MsgTransferResponse](#provenance.marker.v1.MsgTransferResponse) | Transfer marker denominated coin between accounts | |
| `IbcTransfer` | [MsgIbcTransferRequest](#provenance.marker.v1.MsgIbcTransferRequest) | [MsgIbcTransferResponse](#provenance.marker.v1.MsgIbcTransferResponse) | Transfer over ibc any marker(including restricted markers) between ibc accounts. The relayer is still needed to accomplish ibc middleware relays. | |
| `SetDenomMetadata` | [MsgSetDenomMetadataRequest](#provenance.marker.v1.MsgSetDenomMetadataRequest) | [MsgSetDenomMetadataResponse](#provenance.marker.v1.MsgSetDenomMetadataResponse) | Allows Denom Metadata (see bank module) to be set for the Marker's Denom | |
| `GrantAllowance` | [MsgGrantAllowanceRequest](#provenance.marker.v1.MsgGrantAllowanceRequest) | [MsgGrantAllowanceResponse](#provenance.marker.v1.MsgGrantAllowanceResponse) | GrantAllowance grants fee allowance to the grantee on the granter's account with the provided expiration time. | |

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,4 @@ replace github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0
replace github.com/CosmWasm/wasmd => github.com/provenance-io/wasmd v0.29.0-pio-1

// TODO: Required for IBC Transfer Module. Remove this when they patch it to include our changes. https://github.com/provenance-io/provenance/issues/1100
replace github.com/cosmos/ibc-go/v5 => github.com/provenance-io/ibc-go/v5 v5.0.0-pio-1
replace github.com/cosmos/ibc-go/v5 => github.com/provenance-io/ibc-go/v5 v5.0.0-pio-2
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -861,8 +861,8 @@ github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0ua
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/provenance-io/cosmos-sdk v0.46.2-pio-1 h1:rN69vWW+bXlpbVoQDgM40uu24eYRTsz0LJDamlaLkj0=
github.com/provenance-io/cosmos-sdk v0.46.2-pio-1/go.mod h1:B1ddM4dmTaSd06CMzFJ5jeJ+sS9TbVpEtsLrL2YUJK4=
github.com/provenance-io/ibc-go/v5 v5.0.0-pio-1 h1:gNL9Kw8ckFCE+d5jmCiuLcnDHpkbayfRSl71hIY7HRA=
github.com/provenance-io/ibc-go/v5 v5.0.0-pio-1/go.mod h1:Wqsguq98Iuns8tgTv8+xaGYbC+Q8zJfbpjzT6IgMJbs=
github.com/provenance-io/ibc-go/v5 v5.0.0-pio-2 h1:c8JQupz4x+TyI6iYfJS/UCP8Kfl03PkV65Ivpg8OdE8=
github.com/provenance-io/ibc-go/v5 v5.0.0-pio-2/go.mod h1:Wqsguq98Iuns8tgTv8+xaGYbC+Q8zJfbpjzT6IgMJbs=
github.com/provenance-io/wasmd v0.29.0-pio-1 h1:vH7tyRf+SjZl/jHBnmcXaXtWpGenfDa6in2yKdREnEs=
github.com/provenance-io/wasmd v0.29.0-pio-1/go.mod h1:7GcVWVZIP2hmXuDJEFkofF3P1Ax48foYmknQvl0H8dU=
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
Expand Down
16 changes: 16 additions & 0 deletions proto/provenance/marker/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";
import "cosmos/bank/v1beta1/bank.proto";
import "ibc/applications/transfer/v1/tx.proto";
import "provenance/marker/v1/marker.proto";
import "provenance/marker/v1/accessgrant.proto";

Expand Down Expand Up @@ -38,6 +39,9 @@ service Msg {
rpc AddMarker(MsgAddMarkerRequest) returns (MsgAddMarkerResponse);
// Transfer marker denominated coin between accounts
rpc Transfer(MsgTransferRequest) returns (MsgTransferResponse);
// Transfer over ibc any marker(including restricted markers) between ibc accounts.
// The relayer is still needed to accomplish ibc middleware relays.
rpc IbcTransfer(MsgIbcTransferRequest) returns (MsgIbcTransferResponse);
// Allows Denom Metadata (see bank module) to be set for the Marker's Denom
rpc SetDenomMetadata(MsgSetDenomMetadataRequest) returns (MsgSetDenomMetadataResponse);
// GrantAllowance grants fee allowance to the grantee on the granter's
Expand Down Expand Up @@ -169,6 +173,18 @@ message MsgTransferRequest {
// MsgTransferResponse defines the Msg/Transfer response type
message MsgTransferResponse {}

// MsgIbcTransferRequest defines the Msg/IbcTransfer request type for markers.
message MsgIbcTransferRequest {
ibc.applications.transfer.v1.MsgTransfer transfer = 1 [
(gogoproto.nullable) = false,
(gogoproto.customtype) = "github.com/cosmos/ibc-go/v5/modules/apps/transfer/types.MsgTransfer"
];
string administrator = 2;
}

// MsgIbcTransferResponse defines the Msg/IbcTransfer response type
message MsgIbcTransferResponse {}

// MsgSetDenomMetadataRequest defines the Msg/SetDenomMetadata request type
message MsgSetDenomMetadataRequest {
cosmos.bank.v1beta1.Metadata metadata = 1
Expand Down
76 changes: 76 additions & 0 deletions x/marker/client/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,82 @@ func (s *IntegrationTestSuite) TestMarkerTxCommands() {
}
}

func (s *IntegrationTestSuite) TestMarkerIbcTransfer() {
testCases := []struct {
name string
srcPort string
srcChannel string
sender string
receiver string
amount string
flagPacketTimeoutHeight string
flagPacketTimeoutTimestamp string
flagAbsoluteTimeouts string
expectedErr string
}{
{
name: "should fail on invalid coin",
srcPort: "port",
srcChannel: "channel",
sender: "sender",
receiver: "receiver",
amount: "not-a-valid-coin-amount",
expectedErr: "invalid decimal coin expression: not-a-valid-coin-amount",
},
{
name: "should fail on invalid packet timeout height",
srcPort: "port",
srcChannel: "channel",
sender: "sender",
receiver: "receiver",
amount: "10jackthecat",
flagPacketTimeoutHeight: "invalidtimeoutheight",
expectedErr: "expected height string format: {revision}-{height}. Got: invalidtimeoutheight: invalid height",
},
{
name: "should fail on parsing absolute timeouts boolean",
srcPort: "port",
srcChannel: "channel",
sender: "sender",
receiver: "receiver",
amount: "10jackthecat",
flagAbsoluteTimeouts: "not-a-bool",
expectedErr: `invalid argument "not-a-bool" for "--absolute-timeouts" flag: strconv.ParseBool: parsing "not-a-bool": invalid syntax`,
},
}

for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
clientCtx := s.testnet.Validators[0].ClientCtx
args := []string{
tc.srcPort,
tc.srcChannel,
tc.sender,
tc.receiver,
tc.amount,
}
args = append(args, []string{fmt.Sprintf("--%s=%s", flags.FlagFrom, s.testnet.Validators[0].Address.String()),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
}...)
if len(tc.flagPacketTimeoutHeight) > 0 {
args = append(args, fmt.Sprintf("--%s=%s", markercli.FlagPacketTimeoutHeight, tc.flagPacketTimeoutHeight))
}
if len(tc.flagAbsoluteTimeouts) > 0 {
args = append(args, fmt.Sprintf("--%s=%s", markercli.FlagAbsoluteTimeouts, tc.flagAbsoluteTimeouts))
}
_, err := clitestutil.ExecTestCLICmd(clientCtx, markercli.GetIbcTransferTxCmd(), args)
if len(tc.expectedErr) > 0 {
s.Assert().EqualError(err, tc.expectedErr)
} else {
s.Assert().NoError(err, tc.name)
}
})
}
}

func (s *IntegrationTestSuite) TestMarkerAuthzTxCommands() {
testCases := []struct {
name string
Expand Down
106 changes: 106 additions & 0 deletions x/marker/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cli

import (
"encoding/json"
"errors"
"fmt"
"strings"
"time"
Expand All @@ -21,6 +22,9 @@ import (
"github.com/cosmos/cosmos-sdk/x/feegrant"
govtypesv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"

clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
channelutils "github.com/cosmos/ibc-go/v5/modules/core/04-channel/client/utils"

"github.com/spf13/cobra"
)

Expand All @@ -34,6 +38,9 @@ const (
FlagPeriodLimit = "period-limit"
FlagSpendLimit = "spend-limit"
FlagAllowedMsgs = "allowed-messages"
FlagPacketTimeoutHeight = "packet-timeout-height"
FlagPacketTimeoutTimestamp = "packet-timeout-timestamp"
FlagAbsoluteTimeouts = "absolute-timeouts"
)

// NewTxCmd returns the top-level command for marker CLI transactions.
Expand Down Expand Up @@ -61,6 +68,7 @@ func NewTxCmd() *cobra.Command {
GetCmdGrantAuthorization(),
GetCmdRevokeAuthorization(),
GetCmdFeeGrant(),
GetIbcTransferTxCmd(),
)
return txCmd
}
Expand Down Expand Up @@ -532,6 +540,104 @@ func GetNewTransferCmd() *cobra.Command {
return cmd
}

// TODO: refactor usage comments to be provenance specific
// GetIbcTransferTxCmd returns the command to create a GetIbcTransferTxCmd transaction
func GetIbcTransferTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "ibc-transfer [src-port] [src-channel] [sender] [receiver] [amount]",
Short: "Transfer a restricted marker token through IBC",
Long: strings.TrimSpace(`Transfer a restricted marker through IBC. Timeouts can be specified
as absolute or relative using the "absolute-timeouts" flag. Timeout height can be set by passing in the height string
in the form {revision}-{height} using the "packet-timeout-height" flag. Relative timeout height is added to the block
height queried from the latest consensus state corresponding to the counterparty channel. Relative timeout timestamp
is added to the greater value of the local clock time and the block timestamp queried from the latest consensus state
corresponding to the counterparty channel. Any timeout set to 0 is disabled.`),
Example: fmt.Sprintf("%s tx marker ibc-transfer [src-port] [src-channel] [receiver] [amount]", version.AppName),
Args: cobra.ExactArgs(5),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
sourcePort := args[0]
sourceChannel := args[1]
sender := args[2]
receiver := args[3]
token, err := sdk.ParseCoinNormalized(args[4])
if err != nil {
return err
}

timeoutHeightStr, err := cmd.Flags().GetString(FlagPacketTimeoutHeight)
if err != nil {
return err
}
timeoutHeight, err := clienttypes.ParseHeight(timeoutHeightStr)
if err != nil {
return err
}

timeoutTimestamp, err := cmd.Flags().GetUint64(FlagPacketTimeoutTimestamp)
if err != nil {
return err
}

absoluteTimeouts, err := cmd.Flags().GetBool(FlagAbsoluteTimeouts)
if err != nil {
return err
}

// if the timeouts are not absolute, retrieve latest block height and block timestamp
// for the consensus state connected to the destination port/channel
if !absoluteTimeouts {
consensusState, height, _, err := channelutils.QueryLatestConsensusState(clientCtx, sourcePort, sourceChannel)
if err != nil {
return err
}

if !timeoutHeight.IsZero() {
absoluteHeight := height
absoluteHeight.RevisionNumber += timeoutHeight.RevisionNumber
absoluteHeight.RevisionHeight += timeoutHeight.RevisionHeight
timeoutHeight = absoluteHeight
}

if timeoutTimestamp != 0 {
// use local clock time as reference time if it is later than the
// consensus state timestamp of the counter party chain, otherwise
// still use consensus state timestamp as reference
now := time.Now().UnixNano()
consensusStateTimestamp := consensusState.GetTimestamp()
if now > 0 {
now := uint64(now)
if now > consensusStateTimestamp {
timeoutTimestamp = now + timeoutTimestamp
} else {
timeoutTimestamp = consensusStateTimestamp + timeoutTimestamp
}
} else {
return errors.New("local clock time is not greater than Jan 1st, 1970 12:00 AM")
}
}
}
msg := types.NewIbcMsgTransferRequest(
clientCtx.GetFromAddress().String(),
sourcePort, sourceChannel,
token, sender, receiver,
timeoutHeight, timeoutTimestamp,
)
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

cmd.Flags().String(FlagPacketTimeoutHeight, "0-1000", "Packet timeout block height. The timeout is disabled when set to 0-0.")
cmd.Flags().Uint64(FlagPacketTimeoutTimestamp, uint64((time.Duration(10) * time.Minute).Nanoseconds()), "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)

return cmd
}

func GetCmdGrantAuthorization() *cobra.Command {
cmd := &cobra.Command{
Use: "grant-authz [grantee] [authorization_type]",
Expand Down
3 changes: 3 additions & 0 deletions x/marker/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
case *types.MsgTransferRequest:
res, err := msgServer.Transfer(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
case *types.MsgIbcTransferRequest:
res, err := msgServer.IbcTransfer(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)

case *types.MsgSetDenomMetadataRequest:
res, err := msgServer.SetDenomMetadata(sdk.WrapSDKContext(ctx), msg)
Expand Down
Loading

0 comments on commit 9e5a70a

Please sign in to comment.