-
Notifications
You must be signed in to change notification settings - Fork 626
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
feat: adding authz support for ICS-20 MsgTransfer
#2795
Conversation
Create an authz grant that resricts to transfers to specific addresses and channels.
There was a problem hiding this 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; |
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
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.
return sdk.MsgTypeURL(&MsgTransfer{}) | ||
} | ||
|
||
func IsAllowedAddress(receiver string, allowedAddrs []string) bool { |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, Allocation
works!
toAddr = sdk.AccAddress("_______to________") | ||
) | ||
|
||
func TestTransferAuthorization(t *testing.T) { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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
).
There was a problem hiding this comment.
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?
There was a problem hiding this 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 |
There was a problem hiding this comment.
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?
There was a problem hiding this 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") |
There was a problem hiding this comment.
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?
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")
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") |
There was a problem hiding this comment.
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
return authz.AcceptResponse{}, sdkerrors.ErrInvalidType.Wrap("type mismatch") | |
return authz.AcceptResponse{}, sdkerrors.Wrap(sdkerrors.ErrInvalidType, "type mismatch") |
toAddr = sdk.AccAddress("_______to________") | ||
) | ||
|
||
func TestTransferAuthorization(t *testing.T) { |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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!
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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?
MsgTransfer
* update README to reflect new website * pr comment
… solo machine client state definition, removes all solo machine consensus states and removes the localhost client. (cosmos#2824)
…ate release line to ibc-go >= v1.x.x. (cosmos#2897)
* 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
Thank yo very much for starting this feature, @zmanian. We will continue now opening new PRs against the feature branch. |
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.
docs/
) or specification (x/<module>/spec/
).godoc
comments.Files changed
in the Github PR explorer.Codecov Report
in the comment section below once CI passes.