Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adding authz support for ICS-20 MsgTransfer #2795

Merged
merged 46 commits into from
Dec 19, 2022

Conversation

zmanian
Copy link
Member

@zmanian zmanian commented Nov 20, 2022

Authz grant for ics-20 transfers

This PR introduces an authz grant for ICS-20 transfers.

it enables restricting transfers to only specified channels and addresses.


Before we can merge this PR, please make sure that all the following items have been
checked off. If any of the checklist items are not applicable, please leave them but
write a little note why.

  • Targeted PR against correct branch (see CONTRIBUTING.md).
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
  • Code follows the module structure standards.
  • Wrote unit and integration tests.
  • Updated relevant documentation (docs/) or specification (x/<module>/spec/).
  • Added relevant godoc comments.
  • Provide a commit message to be used for the changelog entry in the PR description for review.
  • Re-reviewed Files changed in the Github PR explorer.
  • Review Codecov Report in the comment section below once CI passes.

Copy link
Contributor

@crodriguezvega crodriguezvega left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for adding, @zmanian! This actually will close #2431, which was requested some time ago.

Even though the unit tests look great, I think it would be nice to add some integration/e2e tests.

Please let us know if you would be interested in collaborating on the PR with us. Maybe @jonathanjmak would also be interested. We can then discuss a way to work together and take this to the finish line.

And we need also a changelog entry :) (I would say under Features).

repeated cosmos.base.v1beta1.Coin spend_limit = 3
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
// allowed addresses to be sent via transfer message
repeated string allowed_addresses = 4;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a nit, but maybe we could use allow_list, which is the same name the SDK uses in send authorization? Just to keep terminology a bit consistent...

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, allow_list is probably more consistent terminology. It would be useful to mention in the protodoc that this is an allow list of receiver addresses.

modules/apps/transfer/types/transfer_authz.go Outdated Show resolved Hide resolved
return sdk.MsgTypeURL(&MsgTransfer{})
}

func IsAllowedAddress(receiver string, allowedAddrs []string) bool {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this function can be made private.

import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";

message PortChannelAmount {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just thinking of some alternative names... Maybe Allocation (since that's the field name used in TransferAuthorization) or Allowance?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, Allocation works!

modules/apps/transfer/types/transfer_authz.go Show resolved Hide resolved
modules/apps/transfer/types/transfer_authz.go Show resolved Hide resolved
toAddr = sdk.AccAddress("_______to________")
)

func TestTransferAuthorization(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be nice to create a set of table tests for the different cases tested here. What do you think, @colin-axner?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree!

)

// NewTransferAuthorization creates a new TransferAuthorization object.
func NewTransferAuthorization(sourcePorts, sourceChannels []string, spendLimits []sdk.Coins, allowedAddrs [][]string) *TransferAuthorization {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing each input as an individual slice opens up the possibility of mismatch in the length of the slices. We should handle that situation... or maybe something better would be to accept as input a slice of PortChannelAmount that the caller has already initialized with the desired values (I guess in this case we would need to make a copy of the slice, since it might be modified in Accept).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to suggest using varargs. I think it makes a flexible/clean API.

func NewTransferAuthorization(allocations ...Allocation) *TransferAuthorization {
	return &TransferAuthorization{
		Allocations: allocations,
	}
}

I don't understand why we would need to make any copies? If TransferAuthorization is modified in Accept, an Update is returned to authz in the AcceptResponse, right?

Copy link

@jonathanjmak jonathanjmak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a few small comments

context: #2431 (comment)

@@ -0,0 +1,105 @@
package types

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small nit here as well, but can we name it transfer_authorization.go so it's similar to this?

modules/apps/transfer/types/transfer_authz.go Show resolved Hide resolved
Copy link
Member

@damiannolan damiannolan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work! Thanks for getting this started and apologies for the delay getting around to review.

Left some nits and suggestions! It looks like the tests should be updated to include the memo field arg in NewMsgTransfer. I imagine the fork was likely out of date.

Would be great to see an e2e test with this, I can add one in a follow up PR.
Also happy to help out in pushing this forward!

edit: I've renamed the PR title as it's used by default when merging a squash commit, we use this to parse changelog entries using conventional commits.

@@ -14,4 +14,5 @@ var (
ErrSendDisabled = sdkerrors.Register(ModuleName, 7, "fungible token transfers from this chain are disabled")
ErrReceiveDisabled = sdkerrors.Register(ModuleName, 8, "fungible token transfers to this chain are disabled")
ErrMaxTransferChannels = sdkerrors.Register(ModuleName, 9, "max transfer channels")
ErrDuplicateEntry = sdkerrors.Register(ModuleName, 10, "duplicated entry")
Copy link
Member

@damiannolan damiannolan Dec 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the moment this error is being returned directly from ValidateBasic with no additional information.
As a user I would see something like: failed to execute message; message types.MsgTransfer: duplicated entry returned from authz

Since this error is specific to x/authz functionality should we consider renaming to something like ErrInvalidAuthorization and then we can reuse and wrap as necessary?

Suggested change
ErrDuplicateEntry = sdkerrors.Register(ModuleName, 10, "duplicated entry")
ErrInvalidAuthorization = sdkerrors.Register(ModuleName, 10, "invalid transfer authorization")

We could then return the following and the user would see: failed to execute message; message types.MsgTransfer: invalid transfer authorization: duplicate entry in allow list cosmos1...

return sdkerrors.Wrapf(ErrInvalidAuthorization, "duplicate entry in allow list %s")

modules/apps/transfer/types/transfer_authz.go Outdated Show resolved Hide resolved
func (a TransferAuthorization) Accept(ctx sdk.Context, msg sdk.Msg) (authz.AcceptResponse, error) {
mTransfer, ok := msg.(*MsgTransfer)
if !ok {
return authz.AcceptResponse{}, sdkerrors.ErrInvalidType.Wrap("type mismatch")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: in ibc-go we normally structure sdk error returns like below. see example

Suggested change
return authz.AcceptResponse{}, sdkerrors.ErrInvalidType.Wrap("type mismatch")
return authz.AcceptResponse{}, sdkerrors.Wrap(sdkerrors.ErrInvalidType, "type mismatch")

modules/apps/transfer/types/transfer_authz.go Outdated Show resolved Hide resolved
modules/apps/transfer/types/transfer_authz.go Outdated Show resolved Hide resolved
toAddr = sdk.AccAddress("_______to________")
)

func TestTransferAuthorization(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree!

import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";

message PortChannelAmount {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, Allocation works!

@@ -0,0 +1,30 @@
syntax = "proto3";

package ibc.applications.transfer.v2;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This proto file could live in ibc.applications.transfer.v1 but its not required.
The v2 protos were added to support an updated FungibleTokenPacketData. Happy to leave it here.

"golang.org/x/exp/slices"
)

const gasCostPerIteration = uint64(10)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surprising that x/authz doesn't provide a default const out of the box!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha... 🤔

)

// NewTransferAuthorization creates a new TransferAuthorization object.
func NewTransferAuthorization(sourcePorts, sourceChannels []string, spendLimits []sdk.Coins, allowedAddrs [][]string) *TransferAuthorization {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to suggest using varargs. I think it makes a flexible/clean API.

func NewTransferAuthorization(allocations ...Allocation) *TransferAuthorization {
	return &TransferAuthorization{
		Allocations: allocations,
	}
}

I don't understand why we would need to make any copies? If TransferAuthorization is modified in Accept, an Update is returned to authz in the AcceptResponse, right?

@damiannolan damiannolan changed the title Authz grant for ICS-20 IBC transfers feat: adding authz support for ICS-20 MsgTransfer Dec 15, 2022
Carlos Rodriguez and others added 25 commits December 19, 2022 09:47
* update chainconfig

* update to commit fixing broadcastTx

* update to use SDK default cointype 118

* update so relayer tag isn't required
* add test for automatic migration of solomachine clientstate version

* add clientID generation functions

* update godoc

* update sprintf message
…onsensus state via the client state `Initialize` method (cosmos#2936)

* set the initial client and consensus state via the client state Initialize method. update godocs

* updating godocs

* updating migration doc

* updating light client guide docs for Initialize method

* updating migration doc

* Apply suggestions from code review

Co-authored-by: Charly <charly@interchain.io>

* Update docs/ibc/light-clients/client-state.md

Co-authored-by: Carlos Rodriguez <carlos@interchain.io>

* adding tests to lightclients

* updating 02-client tests

Co-authored-by: Charly <charly@interchain.io>
Co-authored-by: Carlos Rodriguez <carlos@interchain.io>
* update compatibility tests

* compatibility tests for v4.3.x

* adding tags to tests

* Skip e2e if test matrix does not exist (cosmos#2949)

Co-authored-by: Carlos Rodriguez <carlos@interchain.io>
Co-authored-by: Cian Hatton <cian@interchain.io>
Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 3 to 4.
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](goreleaser/goreleaser-action@v3...v4)

---
updated-dependencies:
- dependency-name: goreleaser/goreleaser-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Carlos Rodriguez <carlos@interchain.io>
* removing solomachine header sequence

* removing commented out code in validate basic
@zmanian zmanian requested a review from tmsdkeys as a code owner December 19, 2022 17:56
@zmanian zmanian changed the base branch from main to feat/authz-ics20 December 19, 2022 17:57
@crodriguezvega crodriguezvega merged commit d1b8a69 into cosmos:feat/authz-ics20 Dec 19, 2022
@crodriguezvega
Copy link
Contributor

Thank yo very much for starting this feature, @zmanian. We will continue now opening new PRs against the feature branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done 🥳
Development

Successfully merging this pull request may close these issues.

10 participants